@@ -3953,6 +3953,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
39533953 // Avoid recording definition of `A::B` in `<T as A>::B::C`.
39543954 self . r . record_partial_res ( node_id, partial_res) ;
39553955 self . resolve_elided_lifetimes_in_path ( partial_res, path, source, path_span) ;
3956+ self . lint_unused_qualifications ( path, ns, finalize) ;
39563957 }
39573958
39583959 partial_res
@@ -4145,39 +4146,6 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
41454146 PathResult :: Indeterminate => bug ! ( "indeterminate path result in resolve_qpath" ) ,
41464147 } ;
41474148
4148- if path. iter ( ) . all ( |seg| !seg. ident . span . from_expansion ( ) ) {
4149- let end_pos =
4150- path. iter ( ) . position ( |seg| seg. has_generic_args ) . map_or ( path. len ( ) , |pos| pos + 1 ) ;
4151- let unqualified =
4152- path[ ..end_pos] . iter ( ) . enumerate ( ) . skip ( 1 ) . rev ( ) . find_map ( |( i, seg) | {
4153- // Preserve the current namespace for the final path segment, but use the type
4154- // namespace for all preceding segments
4155- //
4156- // e.g. for `std::env::args` check the `ValueNS` for `args` but the `TypeNS` for
4157- // `std` and `env`
4158- //
4159- // If the final path segment is beyond `end_pos` all the segments to check will
4160- // use the type namespace
4161- let ns = if i + 1 == path. len ( ) { ns } else { TypeNS } ;
4162- let res = self . r . partial_res_map . get ( & seg. id ?) ?. full_res ( ) ?;
4163- let binding = self . resolve_ident_in_lexical_scope ( seg. ident , ns, None , None ) ?;
4164-
4165- ( res == binding. res ( ) ) . then_some ( seg)
4166- } ) ;
4167-
4168- if let Some ( unqualified) = unqualified {
4169- self . r . lint_buffer . buffer_lint_with_diagnostic (
4170- lint:: builtin:: UNUSED_QUALIFICATIONS ,
4171- finalize. node_id ,
4172- finalize. path_span ,
4173- "unnecessary qualification" ,
4174- lint:: BuiltinLintDiag :: UnusedQualifications {
4175- removal_span : finalize. path_span . until ( unqualified. ident . span ) ,
4176- } ,
4177- ) ;
4178- }
4179- }
4180-
41814149 Ok ( Some ( result) )
41824150 }
41834151
@@ -4656,6 +4624,42 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
46564624 self . r . doc_link_traits_in_scope = doc_link_traits_in_scope;
46574625 }
46584626 }
4627+
4628+ fn lint_unused_qualifications ( & mut self , path : & [ Segment ] , ns : Namespace , finalize : Finalize ) {
4629+ if path. iter ( ) . any ( |seg| seg. ident . span . from_expansion ( ) ) {
4630+ return ;
4631+ }
4632+
4633+ let end_pos =
4634+ path. iter ( ) . position ( |seg| seg. has_generic_args ) . map_or ( path. len ( ) , |pos| pos + 1 ) ;
4635+ let unqualified = path[ ..end_pos] . iter ( ) . enumerate ( ) . skip ( 1 ) . rev ( ) . find_map ( |( i, seg) | {
4636+ // Preserve the current namespace for the final path segment, but use the type
4637+ // namespace for all preceding segments
4638+ //
4639+ // e.g. for `std::env::args` check the `ValueNS` for `args` but the `TypeNS` for
4640+ // `std` and `env`
4641+ //
4642+ // If the final path segment is beyond `end_pos` all the segments to check will
4643+ // use the type namespace
4644+ let ns = if i + 1 == path. len ( ) { ns } else { TypeNS } ;
4645+ let res = self . r . partial_res_map . get ( & seg. id ?) ?. full_res ( ) ?;
4646+ let binding = self . resolve_ident_in_lexical_scope ( seg. ident , ns, None , None ) ?;
4647+
4648+ ( res == binding. res ( ) ) . then_some ( seg)
4649+ } ) ;
4650+
4651+ if let Some ( unqualified) = unqualified {
4652+ self . r . lint_buffer . buffer_lint_with_diagnostic (
4653+ lint:: builtin:: UNUSED_QUALIFICATIONS ,
4654+ finalize. node_id ,
4655+ finalize. path_span ,
4656+ "unnecessary qualification" ,
4657+ lint:: BuiltinLintDiag :: UnusedQualifications {
4658+ removal_span : path[ 0 ] . ident . span . until ( unqualified. ident . span ) ,
4659+ } ,
4660+ ) ;
4661+ }
4662+ }
46594663}
46604664
46614665/// Walks the whole crate in DFS order, visiting each item, counting the declared number of
0 commit comments