@@ -154,8 +154,26 @@ impl<'hir> LoweringContext<'_, 'hir> {
154154 & mut self ,
155155 delegation : & Delegation ,
156156 item_id : NodeId ,
157+ item_span : Span ,
157158 ) -> DelegationResults < ' hir > {
158- let span = self . lower_span ( delegation. path . segments . last ( ) . unwrap ( ) . ident . span ) ;
159+ let last_seg_span = self . lower_span ( delegation. path . segments . last ( ) . unwrap ( ) . ident . span ) ;
160+ let item_span = self . lower_span ( item_span) ;
161+
162+ // Check if the span of the last segment is contained in item span. The span of last segment
163+ // may refer to completely different entity, for example when we do a glob reuse we
164+ // generate segments (in `rustc_expand::expand::build_single_delegations`),
165+ // and during `rustc_resolve::macros::glob_delegation_suffixes` we generate
166+ // suffixes, where identifiers that are used in generated segment
167+ // use spans of the original functions from trait,
168+ // thus those spans can point either to local or external
169+ // trait functions. This `span` is also used for diagnostics purposes, so we want it to point
170+ // to delegation, not to the random trait function, so we perform this check here.
171+ // We could have added similar check in `rustc_resolve::macros::glob_delegation_suffixes`
172+ // (i.e. create ident with span related to ast path of delegation, not the original trait item),
173+ // or in `rustc_expand::expand::build_single_delegations`,
174+ // however it will break `impl-reuse-pass` test and checking span here seems to be good solution,
175+ // as bad spans may come from different places in future.
176+ let span = if item_span. contains ( last_seg_span) { last_seg_span } else { item_span } ;
159177
160178 // Delegation can be unresolved in illegal places such as function bodies in extern blocks (see #151356)
161179 let ids = if let Some ( delegation_info) =
@@ -651,7 +669,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
651669
652670 // FIXME(fn_delegation): proper support for parent generics propagation
653671 // in method call scenario.
654- let segment = self . process_segment ( item_id, span, & segment, & mut generics. child , false ) ;
672+ let segment = self . process_segment ( item_id, span, & segment, & mut generics. child , true ) ;
655673 let segment = self . arena . alloc ( segment) ;
656674
657675 self . arena . alloc ( hir:: Expr {
@@ -677,14 +695,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
677695
678696 new_path. segments = self . arena . alloc_from_iter (
679697 new_path. segments . iter ( ) . enumerate ( ) . map ( |( idx, segment) | {
680- let mut process_segment = |result, add_lifetimes | {
681- self . process_segment ( item_id, span, segment, result, add_lifetimes )
698+ let mut process_segment = |result, is_child | {
699+ self . process_segment ( item_id, span, segment, result, is_child )
682700 } ;
683701
684702 if idx + 2 == len {
685- process_segment ( & mut generics. parent , true )
703+ process_segment ( & mut generics. parent , false )
686704 } else if idx + 1 == len {
687- process_segment ( & mut generics. child , false )
705+ process_segment ( & mut generics. child , true )
688706 } else {
689707 segment. clone ( )
690708 }
@@ -695,7 +713,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
695713 }
696714 hir:: QPath :: TypeRelative ( ty, segment) => {
697715 let segment =
698- self . process_segment ( item_id, span, segment, & mut generics. child , false ) ;
716+ self . process_segment ( item_id, span, segment, & mut generics. child , true ) ;
699717
700718 hir:: QPath :: TypeRelative ( ty, self . arena . alloc ( segment) )
701719 }
@@ -723,17 +741,17 @@ impl<'hir> LoweringContext<'_, 'hir> {
723741 span : Span ,
724742 segment : & hir:: PathSegment < ' hir > ,
725743 result : & mut GenericsGenerationResult < ' hir > ,
726- add_lifetimes : bool ,
744+ is_child_segment : bool ,
727745 ) -> hir:: PathSegment < ' hir > {
728746 let details = result. generics . args_propagation_details ( ) ;
729747
730748 // The first condition is needed when there is SelfAndUserSpecified case,
731749 // we don't want to propagate generics params in this situation.
732- let segment = if details. should_propagate
750+ let mut segment = if details. should_propagate
733751 && let Some ( args) = result
734752 . generics
735753 . into_hir_generics ( self , item_id, span)
736- . into_generic_args ( self , add_lifetimes , span)
754+ . into_generic_args ( self , !is_child_segment , span)
737755 {
738756 hir:: PathSegment { args : Some ( args) , ..segment. clone ( ) }
739757 } else {
@@ -744,6 +762,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
744762 result. args_segment_id = Some ( segment. hir_id ) ;
745763 }
746764
765+ // Update segment ident span if it is not contained in delegation span, see comment
766+ // in `lower_delegation` function in this file.
767+ if is_child_segment && !span. contains ( segment. ident . span ) {
768+ segment. ident . span = span;
769+ }
770+
747771 segment
748772 }
749773
0 commit comments