|
1 | 1 | use rustc_ast_pretty::pprust; |
2 | | -use rustc_data_structures::{fx::FxIndexMap,fx::FxIndexSet, sync::Lrc}; |
| 2 | +use rustc_data_structures::fx::{FxIndexMap,FxIndexSet}; |
3 | 3 | use rustc_errors::{Diag,LintDiagnostic,MultiSpan}; |
4 | 4 | use rustc_feature::{Features,GateIssue}; |
5 | 5 | use rustc_hir::HirId; |
@@ -31,7 +31,7 @@ use crate::errors::{ |
31 | 31 | OverruledAttributeSub,RequestedLevel,UnknownToolInScopedLint,UnsupportedGroup, |
32 | 32 | }; |
33 | 33 | usecrate::fluent_generated as fluent; |
34 | | -usecrate::late::{unerased_lint_store,name_without_tool}; |
| 34 | +usecrate::late::{unerased_lint_store/*name_without_tool*/}; |
35 | 35 | usecrate::lints::{ |
36 | 36 | DeprecatedLintName,DeprecatedLintNameFromCommandLine,IgnoredUnlessCrateSpecified, |
37 | 37 | OverruledAttributeLint,RemovedLint,RemovedLintFromCommandLine,RenamedLint, |
@@ -115,34 +115,41 @@ impl LintLevelSets { |
115 | 115 | } |
116 | 116 | } |
117 | 117 |
|
118 | | -/// Walk the whole crate collecting nodes where lint levels change |
119 | | -/// (e.g. `#[allow]` attributes), and joins that list with the warn-by-default |
120 | | -/// (and not allowed in the crate) and CLI lints. The returned value is a tuple |
121 | | -/// of 1. The lints that will emit (or at least, should run), and 2. |
122 | | -/// The lints that are allowed at the crate level and will not emit. |
123 | | -pubfnlints_that_can_emit(tcx:TyCtxt<'_>,():()) -> Lrc<(FxIndexSet<String>,FxIndexSet<String>)>{ |
124 | | -letmut visitor = LintLevelMinimum::new(tcx); |
125 | | - visitor.process_opts(); |
126 | | - tcx.hir().walk_attributes(&mut visitor); |
127 | | - |
| 118 | +fnlints_that_dont_need_to_run(tcx:TyCtxt<'_>,():()) -> FxIndexSet<LintId>{ |
128 | 119 | let store = unerased_lint_store(&tcx.sess); |
129 | 120 |
|
130 | | -let lint_groups = store.get_lint_groups(); |
131 | | -for group in lint_groups { |
132 | | -let binding = group.0.to_lowercase(); |
133 | | -let group_name = name_without_tool(&binding).to_string(); |
134 | | -if visitor.lints_that_actually_run.contains(&group_name){ |
135 | | -for lint in group.1{ |
136 | | - visitor.lints_that_actually_run.insert(name_without_tool(&lint.to_string()).to_string()); |
137 | | -} |
138 | | -}elseif visitor.lints_allowed.contains(&group_name){ |
139 | | -for lint in&group.1{ |
140 | | - visitor.lints_allowed.insert(name_without_tool(&lint.to_string()).to_string()); |
| 121 | +let dont_need_to_run:FxIndexSet<LintId> = store |
| 122 | +.get_lints() |
| 123 | +.into_iter() |
| 124 | +.filter_map(|lint| { |
| 125 | +if !lint.loadbearing && lint.default_level(tcx.sess.edition()) == Level::Allow{ |
| 126 | +Some(LintId::of(lint)) |
| 127 | +}else{ |
| 128 | +None |
141 | 129 | } |
142 | | -} |
143 | | -} |
| 130 | +}) |
| 131 | +.collect(); |
144 | 132 |
|
145 | | -Lrc::new((visitor.lints_that_actually_run, visitor.lints_allowed)) |
| 133 | +letmut visitor = LintLevelMaximum{ tcx, dont_need_to_run }; |
| 134 | + visitor.process_opts(); |
| 135 | + tcx.hir().walk_attributes(&mut visitor); |
| 136 | + |
| 137 | +// let lint_groups = store.get_lint_groups(); |
| 138 | +// for group in lint_groups { |
| 139 | +// let binding = group.0.to_lowercase(); |
| 140 | +// let group_name = name_without_tool(&binding).to_string(); |
| 141 | +// if visitor.lints_that_actually_run.contains(&group_name) { |
| 142 | +// for lint in group.1 { |
| 143 | +// visitor.lints_that_actually_run.insert(name_without_tool(&lint.to_string()).to_string()); |
| 144 | +// } |
| 145 | +// } else if visitor.lints_allowed.contains(&group_name) { |
| 146 | +// for lint in &group.1 { |
| 147 | +// visitor.lints_allowed.insert(name_without_tool(&lint.to_string()).to_string()); |
| 148 | +// } |
| 149 | +// } |
| 150 | +// } |
| 151 | + |
| 152 | + visitor.dont_need_to_run |
146 | 153 | } |
147 | 154 |
|
148 | 155 | #[instrument(level = "trace", skip(tcx), ret)] |
@@ -336,82 +343,112 @@ impl<'tcx> Visitor<'tcx> for LintLevelsBuilder<'_, LintLevelQueryMap<'tcx>> { |
336 | 343 | /// |
337 | 344 | /// E.g., if a crate has a global #![allow(lint)] attribute, but a single item |
338 | 345 | /// uses #[warn(lint)], this visitor will set that lint level as `Warn` |
339 | | -structLintLevelMinimum<'tcx>{ |
| 346 | +structLintLevelMaximum<'tcx>{ |
340 | 347 | tcx:TyCtxt<'tcx>, |
341 | 348 | /// The actual list of detected lints. |
342 | | -lints_that_actually_run:FxIndexSet<String>, |
343 | | -lints_allowed:FxIndexSet<String>, |
| 349 | +dont_need_to_run:FxIndexSet<LintId>, |
344 | 350 | } |
345 | 351 |
|
346 | | -impl<'tcx>LintLevelMinimum<'tcx>{ |
347 | | -pubfnnew(tcx:TyCtxt<'tcx>) -> Self{ |
348 | | -letmut lints_that_actually_run = FxIndexSet::default(); |
349 | | - lints_that_actually_run.reserve(230); |
350 | | -letmut lints_allowed = FxIndexSet::default(); |
351 | | - lints_allowed.reserve(100); |
352 | | -Self{ |
353 | | - tcx, |
354 | | -// That magic number is the current number of lints + some more for possible future lints |
355 | | - lints_that_actually_run, |
356 | | - lints_allowed, |
357 | | -} |
358 | | -} |
359 | | - |
| 352 | +impl<'tcx>LintLevelMaximum<'tcx>{ |
360 | 353 | fnprocess_opts(&mutself){ |
361 | | -for(lint, level)in&self.tcx.sess.opts.lint_opts{ |
362 | | -if*level == Level::Allow{ |
363 | | -self.lints_allowed.insert(lint.clone()); |
364 | | -}else{ |
365 | | -self.lints_that_actually_run.insert(lint.to_string()); |
| 354 | +let store = unerased_lint_store(self.tcx.sess); |
| 355 | +for(lint_group, level)in&self.tcx.sess.opts.lint_opts{ |
| 356 | +if*level != Level::Allow{ |
| 357 | +letOk(lints) = store.find_lints(lint_group)else{ |
| 358 | +return; |
| 359 | +}; |
| 360 | +for lint in lints { |
| 361 | +self.dont_need_to_run.swap_remove(&lint); |
| 362 | +} |
366 | 363 | } |
367 | 364 | } |
368 | 365 | } |
369 | 366 | } |
370 | 367 |
|
371 | | -impl<'tcx>Visitor<'tcx>forLintLevelMinimum<'tcx>{ |
| 368 | +impl<'tcx>Visitor<'tcx>forLintLevelMaximum<'tcx>{ |
372 | 369 | typeNestedFilter = nested_filter::All; |
373 | 370 |
|
374 | 371 | fnnested_visit_map(&mutself) -> Self::Map{ |
375 | 372 | self.tcx.hir() |
376 | 373 | } |
377 | 374 |
|
378 | 375 | fnvisit_attribute(&mutself,attribute:&'tcx ast::Attribute){ |
379 | | -ifletSome(meta) = attribute.meta(){ |
380 | | -if[sym::warn, sym::deny, sym::forbid, sym::expect] |
381 | | -.iter() |
382 | | -.any(|kind| meta.has_name(*kind)) |
383 | | -{ |
| 376 | +matchLevel::from_attr(attribute){ |
| 377 | +Some( |
| 378 | +Level::Warn |
| 379 | + | Level::Deny |
| 380 | + | Level::Forbid |
| 381 | + | Level::Expect(..) |
| 382 | + | Level::ForceWarn(..), |
| 383 | +) => { |
| 384 | +let store = unerased_lint_store(self.tcx.sess); |
| 385 | +letSome(meta) = attribute.meta()else{return}; |
384 | 386 | // SAFETY: Lint attributes are always a metalist inside a |
385 | 387 | // metalist (even with just one lint). |
386 | | -for meta_list in meta.meta_item_list().unwrap(){ |
387 | | -// If it's a tool lint (e.g. clippy::my_clippy_lint) |
388 | | -iflet ast::NestedMetaItem::MetaItem(meta_item) = meta_list { |
389 | | -if meta_item.path.segments.len() == 1{ |
390 | | -self.lints_that_actually_run.insert( |
391 | | -// SAFETY: Lint attributes can only have literals |
392 | | - meta_list.ident().unwrap().name.as_str().to_string(), |
393 | | -); |
394 | | -}else{ |
395 | | -self.lints_that_actually_run |
396 | | -.insert(meta_item.path.segments[1].ident.name.as_str().to_string()); |
397 | | -} |
398 | | -} |
399 | | -} |
400 | | -// We handle #![allow]s differently, as these remove checking rather than adding. |
401 | | -}elseif meta.has_name(sym::allow) |
402 | | - && let ast::AttrStyle::Inner = attribute.style |
403 | | -{ |
404 | | -for meta_list in meta.meta_item_list().unwrap(){ |
405 | | -// If it's a tool lint (e.g. clippy::my_clippy_lint) |
406 | | -iflet ast::NestedMetaItem::MetaItem(meta_item) = meta_list { |
407 | | -if meta_item.path.segments.len() == 1{ |
408 | | -self.lints_allowed.insert(meta_list.name_or_empty().as_str().to_string()); |
409 | | -}else{ |
410 | | -self.lints_allowed |
411 | | -.insert(meta_item.path.segments[1].ident.name.as_str().to_string()); |
412 | | -} |
| 388 | +letSome(meta_item_list) = meta.meta_item_list()else{return}; |
| 389 | + |
| 390 | +for meta_list in meta_item_list { |
| 391 | +// Convert Path to String |
| 392 | +letSome(meta_item) = meta_list.meta_item()else{return}; |
| 393 | +let ident:&str = &meta_item |
| 394 | +.path |
| 395 | +.segments |
| 396 | +.iter() |
| 397 | +.map(|segment| segment.ident.as_str()) |
| 398 | +.collect::<Vec<&str>>() |
| 399 | +.join("::"); |
| 400 | +letOk(lints) = store.find_lints( |
| 401 | +// SAFETY: Lint attributes can only have literals |
| 402 | + ident, |
| 403 | +)else{ |
| 404 | +return; |
| 405 | +}; |
| 406 | +for lint in lints { |
| 407 | +self.dont_need_to_run.swap_remove(&lint); |
413 | 408 | } |
| 409 | +// // If it's a tool lint (e.g. clippy::my_clippy_lint) |
| 410 | +// if let ast::NestedMetaItem::MetaItem(meta_item) = meta_list { |
| 411 | +// if meta_item.path.segments.len() == 1 { |
| 412 | +// let Ok(lints) = store.find_lints( |
| 413 | +// // SAFETY: Lint attributes can only have literals |
| 414 | +// meta_list.ident().unwrap().name.as_str(), |
| 415 | +// ) else { |
| 416 | +// return; |
| 417 | +// }; |
| 418 | +// for lint in lints { |
| 419 | +// dbg!("LINT REMOVED", &lint); |
| 420 | +// self.dont_need_to_run.swap_remove(&lint); |
| 421 | +// } |
| 422 | +// } else { |
| 423 | +// let Ok(lints) = store.find_lints( |
| 424 | +// // SAFETY: Lint attributes can only have literals |
| 425 | +// meta_item.path.segments[1].ident.name.as_str(), |
| 426 | +// ) else { |
| 427 | +// return; |
| 428 | +// }; |
| 429 | +// for lint in lints { |
| 430 | +// dbg!("LINT REMOVED", &lint); |
| 431 | +// self.dont_need_to_run.swap_remove(&lint); |
| 432 | +// } |
| 433 | +// } |
414 | 434 | } |
| 435 | +// We handle #![allow]s differently, as these remove checking rather than adding. |
| 436 | +}// Some(Level::Allow) if ast::AttrStyle::Inner == attribute.style => { |
| 437 | +// for meta_list in meta.meta_item_list().unwrap() { |
| 438 | +// // If it's a tool lint (e.g. clippy::my_clippy_lint) |
| 439 | +// if let ast::NestedMetaItem::MetaItem(meta_item) = meta_list { |
| 440 | +// if meta_item.path.segments.len() == 1 { |
| 441 | +// self.lints_allowed |
| 442 | +// .insert(meta_list.name_or_empty().as_str().to_string()); |
| 443 | +// } else { |
| 444 | +// self.lints_allowed |
| 445 | +// .insert(meta_item.path.segments[1].ident.name.as_str().to_string()); |
| 446 | +// } |
| 447 | +// } |
| 448 | +// } |
| 449 | +// } |
| 450 | + _ => { |
| 451 | +return; |
415 | 452 | } |
416 | 453 | } |
417 | 454 | } |
@@ -1047,8 +1084,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> { |
1047 | 1084 | } |
1048 | 1085 |
|
1049 | 1086 | pub(crate)fnprovide(providers:&mutProviders){ |
1050 | | -*providers = |
1051 | | -Providers{ shallow_lint_levels_on, lints_that_can_emit, ..*providers }; |
| 1087 | +*providers = Providers{ shallow_lint_levels_on, lints_that_dont_need_to_run, ..*providers }; |
1052 | 1088 | } |
1053 | 1089 |
|
1054 | 1090 | pub(crate)fnparse_lint_and_tool_name(lint_name:&str) -> (Option<Symbol>,&str){ |
|
0 commit comments