@@ -3954,6 +3954,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
39543954 // Avoid recording definition of `A::B` in `<T as A>::B::C`.
39553955 self . r . record_partial_res ( node_id, partial_res) ;
39563956 self . resolve_elided_lifetimes_in_path ( partial_res, path, source, path_span) ;
3957+ self . lint_unused_qualifications ( path, ns, finalize) ;
39573958 }
39583959
39593960 partial_res
@@ -4165,39 +4166,6 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
41654166 PathResult :: Indeterminate => bug ! ( "indeterminate path result in resolve_qpath" ) ,
41664167 } ;
41674168
4168- if path. iter ( ) . all ( |seg| !seg. ident . span . from_expansion ( ) ) {
4169- let end_pos =
4170- path. iter ( ) . position ( |seg| seg. has_generic_args ) . map_or ( path. len ( ) , |pos| pos + 1 ) ;
4171- let unqualified =
4172- path[ ..end_pos] . iter ( ) . enumerate ( ) . skip ( 1 ) . rev ( ) . find_map ( |( i, seg) | {
4173- // Preserve the current namespace for the final path segment, but use the type
4174- // namespace for all preceding segments
4175- //
4176- // e.g. for `std::env::args` check the `ValueNS` for `args` but the `TypeNS` for
4177- // `std` and `env`
4178- //
4179- // If the final path segment is beyond `end_pos` all the segments to check will
4180- // use the type namespace
4181- let ns = if i + 1 == path. len ( ) { ns } else { TypeNS } ;
4182- let res = self . r . partial_res_map . get ( & seg. id ?) ?. full_res ( ) ?;
4183- let binding = self . resolve_ident_in_lexical_scope ( seg. ident , ns, None , None ) ?;
4184-
4185- ( res == binding. res ( ) ) . then_some ( seg)
4186- } ) ;
4187-
4188- if let Some ( unqualified) = unqualified {
4189- self . r . lint_buffer . buffer_lint_with_diagnostic (
4190- lint:: builtin:: UNUSED_QUALIFICATIONS ,
4191- finalize. node_id ,
4192- finalize. path_span ,
4193- "unnecessary qualification" ,
4194- lint:: BuiltinLintDiag :: UnusedQualifications {
4195- removal_span : finalize. path_span . until ( unqualified. ident . span ) ,
4196- } ,
4197- ) ;
4198- }
4199- }
4200-
42014169 Ok ( Some ( result) )
42024170 }
42034171
@@ -4676,6 +4644,42 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
46764644 self . r . doc_link_traits_in_scope = doc_link_traits_in_scope;
46774645 }
46784646 }
4647+
4648+ fn lint_unused_qualifications ( & mut self , path : & [ Segment ] , ns : Namespace , finalize : Finalize ) {
4649+ if path. iter ( ) . any ( |seg| seg. ident . span . from_expansion ( ) ) {
4650+ return ;
4651+ }
4652+
4653+ let end_pos =
4654+ path. iter ( ) . position ( |seg| seg. has_generic_args ) . map_or ( path. len ( ) , |pos| pos + 1 ) ;
4655+ let unqualified = path[ ..end_pos] . iter ( ) . enumerate ( ) . skip ( 1 ) . rev ( ) . find_map ( |( i, seg) | {
4656+ // Preserve the current namespace for the final path segment, but use the type
4657+ // namespace for all preceding segments
4658+ //
4659+ // e.g. for `std::env::args` check the `ValueNS` for `args` but the `TypeNS` for
4660+ // `std` and `env`
4661+ //
4662+ // If the final path segment is beyond `end_pos` all the segments to check will
4663+ // use the type namespace
4664+ let ns = if i + 1 == path. len ( ) { ns } else { TypeNS } ;
4665+ let res = self . r . partial_res_map . get ( & seg. id ?) ?. full_res ( ) ?;
4666+ let binding = self . resolve_ident_in_lexical_scope ( seg. ident , ns, None , None ) ?;
4667+
4668+ ( res == binding. res ( ) ) . then_some ( seg)
4669+ } ) ;
4670+
4671+ if let Some ( unqualified) = unqualified {
4672+ self . r . lint_buffer . buffer_lint_with_diagnostic (
4673+ lint:: builtin:: UNUSED_QUALIFICATIONS ,
4674+ finalize. node_id ,
4675+ finalize. path_span ,
4676+ "unnecessary qualification" ,
4677+ lint:: BuiltinLintDiag :: UnusedQualifications {
4678+ removal_span : path[ 0 ] . ident . span . until ( unqualified. ident . span ) ,
4679+ } ,
4680+ ) ;
4681+ }
4682+ }
46794683}
46804684
46814685/// Walks the whole crate in DFS order, visiting each item, counting the declared number of
0 commit comments