Skip to content

Commit 094e976

Browse files
committed
1 parent 9fb91aa commit 094e976

File tree

8 files changed

+105
-28
lines changed

8 files changed

+105
-28
lines changed

compiler/rustc_resolve/src/check_unused.rs

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,23 @@ use crate::imports::ImportKind;
2727
use crate::module_to_string;
2828
use crate::Resolver;
2929

30-
use crate::NameBindingKind;
30+
use crate::{LexicalScopeBinding, NameBindingKind};
3131
use rustc_ast as ast;
3232
use rustc_ast::visit::{self, Visitor};
3333
use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
3434
use rustc_data_structures::unord::UnordSet;
3535
use rustc_errors::{pluralize, MultiSpan};
3636
use rustc_hir::def::{DefKind, Res};
37-
use rustc_session::lint::builtin::{MACRO_USE_EXTERN_CRATE, UNUSED_EXTERN_CRATES, UNUSED_IMPORTS};
37+
use rustc_session::lint::builtin::{
38+
MACRO_USE_EXTERN_CRATE, UNUSED_EXTERN_CRATES, UNUSED_IMPORTS, UNUSED_QUALIFICATIONS,
39+
};
3840
use rustc_session::lint::BuiltinLintDiag;
41+
use rustc_span::symbol::sym;
3942
use rustc_span::symbol::{kw, Ident};
4043
use rustc_span::{Span, DUMMY_SP};
44+
use thin_vec::ThinVec;
4145

46+
#[derive(Debug)]
4247
struct UnusedImport {
4348
use_tree: ast::UseTree,
4449
use_tree_id: ast::NodeId,
@@ -494,6 +499,39 @@ impl Resolver<'_, '_> {
494499
}
495500

496501
let unused_imports = visitor.unused_imports;
502+
503+
// The lint fixes for unused_import and unnecessary_qualification may conflict.
504+
// Deleting both unused imports and unnecessary segments of an item may result
505+
// in the item not being found.
506+
for v in &self.potentially_unnecessary_qualification {
507+
if let LexicalScopeBinding::Item(name_binding) = v.binding
508+
&& let NameBindingKind::Import { binding: _, import } = name_binding.kind
509+
&& let Some(unused_import) = unused_imports.get(&import.root_id)
510+
&& let Some(id) = import.id()
511+
&& unused_import.unused.contains(&id)
512+
{
513+
let def_id = self.local_def_id(id);
514+
if let Some(attr) = tcx.get_attr(def_id, sym::allow) {
515+
debug!("surechen attr:{:?}", attr);
516+
for item in attr.meta_item_list().unwrap_or_else(ThinVec::new) {
517+
debug!("surechen item:{:?}", item);
518+
if !item.has_name(sym::unused_imports) {
519+
debug!("surechen yes item:{:?}", item);
520+
continue;
521+
}
522+
}
523+
}
524+
}
525+
526+
self.lint_buffer.buffer_lint_with_diagnostic(
527+
UNUSED_QUALIFICATIONS,
528+
v.finalize.node_id,
529+
v.finalize.path_span,
530+
"unnecessary qualification",
531+
BuiltinLintDiag::UnusedQualifications { removal_span: v.span },
532+
);
533+
}
534+
497535
let mut check_redundant_imports = FxIndexSet::default();
498536
for module in self.arenas.local_modules().iter() {
499537
for (_key, resolution) in self.resolutions(*module).borrow().iter() {

compiler/rustc_resolve/src/imports.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1352,6 +1352,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
13521352
target_bindings[ns].get(),
13531353
) {
13541354
Ok(other_binding) => {
1355+
debug!(
1356+
"surechen check_for_redundant_imports other_binding:{:?}",
1357+
other_binding
1358+
);
1359+
debug!("surechen check_for_redundant_imports binding:{:?}", binding);
13551360
is_redundant =
13561361
binding.res() == other_binding.res() && !other_binding.is_ambiguity();
13571362
if is_redundant {

compiler/rustc_resolve/src/late.rs

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,14 @@ impl MaybeExported<'_> {
580580
}
581581
}
582582

583+
/// Used for recording UnnecessaryQualification.
584+
#[derive(Debug)]
585+
pub(crate) struct UnnecessaryQualification<'a> {
586+
pub binding: LexicalScopeBinding<'a>,
587+
pub finalize: Finalize,
588+
pub span: Span,
589+
}
590+
583591
#[derive(Default)]
584592
struct DiagMetadata<'ast> {
585593
/// The current trait's associated items' ident, used for diagnostic suggestions.
@@ -4653,20 +4661,15 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
46534661
let ns = if i + 1 == path.len() { ns } else { TypeNS };
46544662
let res = self.r.partial_res_map.get(&seg.id?)?.full_res()?;
46554663
let binding = self.resolve_ident_in_lexical_scope(seg.ident, ns, None, None)?;
4656-
4657-
(res == binding.res()).then_some(seg)
4664+
(res == binding.clone().res()).then_some((seg, binding))
46584665
});
46594666

46604667
if let Some(unqualified) = unqualified {
4661-
self.r.lint_buffer.buffer_lint_with_diagnostic(
4662-
lint::builtin::UNUSED_QUALIFICATIONS,
4663-
finalize.node_id,
4664-
finalize.path_span,
4665-
"unnecessary qualification",
4666-
lint::BuiltinLintDiag::UnusedQualifications {
4667-
removal_span: path[0].ident.span.until(unqualified.ident.span),
4668-
},
4669-
);
4668+
self.r.potentially_unnecessary_qualification.push(UnnecessaryQualification {
4669+
binding: unqualified.1,
4670+
finalize: finalize,
4671+
span: path[0].ident.span.until(unqualified.0.ident.span),
4672+
});
46704673
}
46714674
}
46724675
}

compiler/rustc_resolve/src/lib.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ use std::fmt;
6868

6969
use diagnostics::{ImportSuggestion, LabelSuggestion, Suggestion};
7070
use imports::{Import, ImportData, ImportKind, NameResolution};
71-
use late::{HasGenericParams, PathSource, PatternSource};
71+
use late::{HasGenericParams, PathSource, PatternSource, UnnecessaryQualification};
7272
use macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef};
7373

7474
use crate::effective_visibilities::EffectiveVisibilitiesVisitor;
@@ -372,7 +372,7 @@ impl<'a> From<&'a ast::PathSegment> for Segment {
372372
/// This refers to the thing referred by a name. The difference between `Res` and `Item` is that
373373
/// items are visible in their whole block, while `Res`es only from the place they are defined
374374
/// forward.
375-
#[derive(Debug)]
375+
#[derive(Debug, Clone)]
376376
enum LexicalScopeBinding<'a> {
377377
Item(NameBinding<'a>),
378378
Res(Res),
@@ -1105,6 +1105,8 @@ pub struct Resolver<'a, 'tcx> {
11051105

11061106
potentially_unused_imports: Vec<Import<'a>>,
11071107

1108+
potentially_unnecessary_qualification: Vec<UnnecessaryQualification<'a>>,
1109+
11081110
/// Table for mapping struct IDs into struct constructor IDs,
11091111
/// it's not used during normal resolution, only for better error reporting.
11101112
/// Also includes of list of each fields visibility
@@ -1464,6 +1466,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
14641466
local_macro_def_scopes: FxHashMap::default(),
14651467
name_already_seen: FxHashMap::default(),
14661468
potentially_unused_imports: Vec::new(),
1469+
potentially_unnecessary_qualification: Default::default(),
14671470
struct_constructors: Default::default(),
14681471
unused_macros: Default::default(),
14691472
unused_macro_rules: Default::default(),

tests/ui/lint/lint-qualification.fixed

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ fn main() {
2121
//~^ ERROR: unnecessary qualification
2222
//~| ERROR: unnecessary qualification
2323

24-
use std::fmt;
25-
let _: fmt::Result = Ok(()); //~ ERROR: unnecessary qualification
24+
//~ ERROR: unused import: `std::fmt`
25+
let _: std::fmt::Result = Ok(()); // issue #121999
2626

2727
let _ = <bool as Default>::default(); // issue #121999
2828
//~^ ERROR: unnecessary qualification

tests/ui/lint/lint-qualification.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,9 @@ fn main() {
2121
//~^ ERROR: unnecessary qualification
2222
//~| ERROR: unnecessary qualification
2323

24-
use std::fmt;
25-
let _: std::fmt::Result = Ok(()); //~ ERROR: unnecessary qualification
24+
#[deny(unused_imports)]
25+
use std::fmt; //~ ERROR: unused import: `std::fmt`
26+
let _: std::fmt::Result = Ok(()); // issue #121331
2627

2728
let _ = <bool as ::std::default::Default>::default(); // issue #121999
2829
//~^ ERROR: unnecessary qualification

tests/ui/lint/lint-qualification.stderr

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -75,20 +75,20 @@ LL - let _: std::vec::Vec<String> = std::vec::Vec::<String>::new();
7575
LL + let _: std::vec::Vec<String> = Vec::<String>::new();
7676
|
7777

78-
error: unnecessary qualification
79-
--> $DIR/lint-qualification.rs:25:12
80-
|
81-
LL | let _: std::fmt::Result = Ok(());
82-
| ^^^^^^^^^^^^^^^^
78+
error: unused import: `std::fmt`
79+
--> $DIR/lint-qualification.rs:25:9
8380
|
84-
help: remove the unnecessary path segments
81+
LL | use std::fmt;
82+
| ^^^^^^^^
8583
|
86-
LL - let _: std::fmt::Result = Ok(());
87-
LL + let _: fmt::Result = Ok(());
84+
note: the lint level is defined here
85+
--> $DIR/lint-qualification.rs:24:12
8886
|
87+
LL | #[deny(unused_imports)]
88+
| ^^^^^^^^^^^^^^
8989

9090
error: unnecessary qualification
91-
--> $DIR/lint-qualification.rs:27:13
91+
--> $DIR/lint-qualification.rs:28:13
9292
|
9393
LL | let _ = <bool as ::std::default::Default>::default(); // issue #121999
9494
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//@ run-rustfix
2+
//@ edition:2021
3+
#![deny(unused_qualifications)]
4+
#![feature(coroutines, coroutine_trait)]
5+
6+
use std::ops::{
7+
Coroutine,
8+
CoroutineState::{self, *},
9+
};
10+
use std::pin::Pin;
11+
12+
fn finish<T>(mut amt: usize, mut t: T) -> T::Return
13+
where T: Coroutine<(), Yield = ()> + Unpin,
14+
{
15+
loop {
16+
match Pin::new(&mut t).resume(()) {
17+
CoroutineState::Yielded(()) => amt = amt.checked_sub(1).unwrap(),
18+
CoroutineState::Complete(ret) => {
19+
assert_eq!(amt, 0);
20+
return ret
21+
}
22+
}
23+
}
24+
25+
}
26+
27+
pub fn main() {}

0 commit comments

Comments
 (0)