Skip to content

Commit fbb4d60

Browse files
committed
Fix issues with unrelated to delegation spans
1 parent f687046 commit fbb4d60

8 files changed

Lines changed: 57 additions & 53 deletions

compiler/rustc_ast_lowering/src/delegation.rs

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -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

compiler/rustc_ast_lowering/src/item.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -591,7 +591,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
591591
hir::ItemKind::Macro(ident, macro_def, macro_kinds)
592592
}
593593
ItemKind::Delegation(box delegation) => {
594-
let delegation_results = self.lower_delegation(delegation, id);
594+
let delegation_results = self.lower_delegation(delegation, id, span);
595595
hir::ItemKind::Fn {
596596
sig: delegation_results.sig,
597597
ident: delegation_results.ident,
@@ -1091,7 +1091,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
10911091
(*ident, generics, kind, ty.is_some())
10921092
}
10931093
AssocItemKind::Delegation(box delegation) => {
1094-
let delegation_results = self.lower_delegation(delegation, i.id);
1094+
let delegation_results = self.lower_delegation(delegation, i.id, i.span);
10951095
let item_kind = hir::TraitItemKind::Fn(
10961096
delegation_results.sig,
10971097
hir::TraitFn::Provided(delegation_results.body_id),
@@ -1284,7 +1284,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
12841284
)
12851285
}
12861286
AssocItemKind::Delegation(box delegation) => {
1287-
let delegation_results = self.lower_delegation(delegation, i.id);
1287+
let delegation_results = self.lower_delegation(delegation, i.id, i.span);
12881288
(
12891289
delegation.ident,
12901290
(

tests/ui/delegation/generics/def-id-isnt-local-ice-143498.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,7 @@ impl X {
2222
reuse< std::fmt::Debug as Iterator >::*;
2323
//~^ ERROR: expected method or associated constant, found associated type `Iterator::Item`
2424
//~| ERROR: expected a type, found a trait
25+
//~| ERROR: method takes at most 1 generic argument but 2 generic arguments were supplied
2526
}
2627

2728
fn main() {}
28-
29-
// FIXME(fn_delegation): don't propagate synthetic generic params.
30-
//~? ERROR: method takes at most 1 generic argument but 2 generic arguments were supplied
31-
//~? ERROR: method takes at most 1 generic argument but 2 generic arguments were supplied

tests/ui/delegation/generics/def-id-isnt-local-ice-143498.stderr

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,24 +22,17 @@ LL | reuse< dyn std::fmt::Debug as Iterator >::*;
2222
| +++
2323

2424
error[E0107]: method takes at most 1 generic argument but 2 generic arguments were supplied
25-
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
25+
--> $DIR/def-id-isnt-local-ice-143498.rs:22:5
2626
|
27-
= note: expected at most 1 generic argument
28-
|
29-
= note: help: remove the unnecessary generic argument
30-
|
31-
= note: `impl Trait` cannot be explicitly specified as a generic argument
32-
33-
error[E0107]: method takes at most 1 generic argument but 2 generic arguments were supplied
34-
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
35-
|
36-
= note: expected at most 1 generic argument
37-
|
38-
= note: help: remove the unnecessary generic argument
27+
LL | reuse< std::fmt::Debug as Iterator >::*;
28+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
29+
| |
30+
| expected at most 1 generic argument
31+
| help: remove the unnecessary generic argument
3932
|
4033
= note: `impl Trait` cannot be explicitly specified as a generic argument
4134

42-
error: aborting due to 5 previous errors
35+
error: aborting due to 4 previous errors
4336

4437
Some errors have detailed explanations: E0107, E0425, E0575, E0782.
4538
For more information about an error, try `rustc --explain E0107`.

tests/ui/delegation/generics/def-path-hash-collision-ice-153410.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,7 @@ impl Iterator {
2222
reuse< < <for<'a> fn()>::Output>::Item as Iterator>::*;
2323
//~^ ERROR: expected method or associated constant, found associated type `Iterator::Item`
2424
//~| ERROR: ambiguous associated type
25+
//~| ERROR: method takes at most 1 generic argument but 2 generic arguments were supplied
2526
}
2627

2728
fn main() {}
28-
29-
// FIXME(fn_delegation): don't propagate synthetic generic params.
30-
//~? ERROR: method takes at most 1 generic argument but 2 generic arguments were supplied
31-
//~? ERROR: method takes at most 1 generic argument but 2 generic arguments were supplied

tests/ui/delegation/generics/def-path-hash-collision-ice-153410.stderr

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -35,24 +35,17 @@ LL + reuse< < <fn() as IntoFuture>::Output>::Item as Iterator>::*;
3535
|
3636

3737
error[E0107]: method takes at most 1 generic argument but 2 generic arguments were supplied
38-
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
38+
--> $DIR/def-path-hash-collision-ice-153410.rs:22:5
3939
|
40-
= note: expected at most 1 generic argument
41-
|
42-
= note: help: remove the unnecessary generic argument
43-
|
44-
= note: `impl Trait` cannot be explicitly specified as a generic argument
45-
46-
error[E0107]: method takes at most 1 generic argument but 2 generic arguments were supplied
47-
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
48-
|
49-
= note: expected at most 1 generic argument
50-
|
51-
= note: help: remove the unnecessary generic argument
40+
LL | reuse< < <for<'a> fn()>::Output>::Item as Iterator>::*;
41+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
42+
| |
43+
| expected at most 1 generic argument
44+
| help: remove the unnecessary generic argument
5245
|
5346
= note: `impl Trait` cannot be explicitly specified as a generic argument
5447

55-
error: aborting due to 5 previous errors
48+
error: aborting due to 4 previous errors
5649

5750
Some errors have detailed explanations: E0107, E0223, E0575, E0782.
5851
For more information about an error, try `rustc --explain E0107`.

tests/ui/delegation/impl-reuse-negative-traits.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
trait Trait {
66
fn foo(&self);
7-
//~^ ERROR negative impls cannot have any items [E0749]
87
}
98

109
struct S;
@@ -15,5 +14,6 @@ impl Trait for S {
1514
struct F(S);
1615

1716
reuse impl !Trait for F { &self.0 }
17+
//~^ ERROR negative impls cannot have any items [E0749]
1818

1919
fn main() {}

tests/ui/delegation/impl-reuse-negative-traits.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error[E0749]: negative impls cannot have any items
2-
--> $DIR/impl-reuse-negative-traits.rs:6:8
2+
--> $DIR/impl-reuse-negative-traits.rs:16:1
33
|
4-
LL | fn foo(&self);
5-
| ^^^
4+
LL | reuse impl !Trait for F { &self.0 }
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66

77
error: aborting due to 1 previous error
88

0 commit comments

Comments
 (0)