Skip to content

Commit c85bb27

Browse files
committed
Account for trailing comma in removal suggestion
1 parent 2c2f3ed commit c85bb27

File tree

9 files changed

+212
-5
lines changed

9 files changed

+212
-5
lines changed

compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

+26-3
Original file line numberDiff line numberDiff line change
@@ -5100,11 +5100,14 @@ fn point_at_assoc_type_restriction(
51005100
return;
51015101
};
51025102
let name = tcx.item_name(proj.projection_ty.def_id);
5103-
for pred in generics.predicates {
5103+
let mut predicates = generics.predicates.iter().peekable();
5104+
let mut prev: Option<&hir::WhereBoundPredicate<'_>> = None;
5105+
while let Some(pred) = predicates.next() {
51045106
let hir::WherePredicate::BoundPredicate(pred) = pred else {
51055107
continue;
51065108
};
5107-
for bound in pred.bounds {
5109+
let mut bounds = pred.bounds.iter().peekable();
5110+
while let Some(bound) = bounds.next() {
51085111
let Some(trait_ref) = bound.trait_ref() else {
51095112
continue;
51105113
};
@@ -5118,8 +5121,27 @@ fn point_at_assoc_type_restriction(
51185121
&& let hir::QPath::Resolved(None, inner_path) = inner_path
51195122
&& let Res::SelfTyAlias { .. } = inner_path.res
51205123
{
5124+
// The following block is to determine the right span to delete for this bound
5125+
// that will leave valid code after the suggestion is applied.
5126+
let span = if let Some(hir::WherePredicate::BoundPredicate(next)) =
5127+
predicates.peek()
5128+
&& pred.origin == next.origin
5129+
{
5130+
// There's another bound, include the comma for the current one.
5131+
pred.span.until(next.span)
5132+
} else if let Some(prev) = prev
5133+
&& pred.origin == prev.origin
5134+
{
5135+
// Last bound, try to remove the previous comma.
5136+
prev.span.shrink_to_hi().to(pred.span)
5137+
} else if pred.origin == hir::PredicateOrigin::WhereClause {
5138+
pred.span.with_hi(generics.where_clause_span.hi())
5139+
} else {
5140+
pred.span
5141+
};
5142+
51215143
err.span_suggestion_verbose(
5122-
pred.span, // FIXME: include the trailing comma.
5144+
span,
51235145
"associated type for the current `impl` cannot be restricted in `where` \
51245146
clauses, remove this bound",
51255147
"",
@@ -5168,6 +5190,7 @@ fn point_at_assoc_type_restriction(
51685190
);
51695191
}
51705192
}
5193+
prev = Some(pred);
51715194
}
51725195
}
51735196

tests/ui/associated-types/impl-wf-cycle-1.stderr

-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ LL | Self::A: Baz,
2424
help: associated type for the current `impl` cannot be restricted in `where` clauses, remove this bound
2525
|
2626
LL - Self::A: Baz,
27-
LL + ,
2827
|
2928

3029
error: aborting due to 1 previous error

tests/ui/associated-types/impl-wf-cycle-2.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ LL | Self::A: Copy,
2121
help: associated type for the current `impl` cannot be restricted in `where` clauses, remove this bound
2222
|
2323
LL - Self::A: Copy,
24-
LL + ,
24+
LL +
2525
|
2626

2727
error: aborting due to 1 previous error
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// run-rustfix
2+
3+
trait Baz {}
4+
impl Baz for () {}
5+
impl<T> Baz for (T,) {}
6+
7+
trait Fiz {}
8+
impl Fiz for bool {}
9+
10+
trait Grault {
11+
type A;
12+
type B;
13+
}
14+
15+
impl Grault for () {
16+
type A = ();
17+
type B = bool;
18+
}
19+
20+
impl<T> Grault for (T,)
21+
//~^ ERROR overflow evaluating the requirement `<(T,) as Grault>::A == _`
22+
where
23+
T: Grault,
24+
{
25+
type A = ();
26+
type B = bool;
27+
}
28+
29+
fn main() {
30+
let _: <((),) as Grault>::A = ();
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// run-rustfix
2+
3+
trait Baz {}
4+
impl Baz for () {}
5+
impl<T> Baz for (T,) {}
6+
7+
trait Fiz {}
8+
impl Fiz for bool {}
9+
10+
trait Grault {
11+
type A;
12+
type B;
13+
}
14+
15+
impl Grault for () {
16+
type A = ();
17+
type B = bool;
18+
}
19+
20+
impl<T> Grault for (T,)
21+
//~^ ERROR overflow evaluating the requirement `<(T,) as Grault>::A == _`
22+
where
23+
T: Grault,
24+
Self::A: Baz,
25+
{
26+
type A = ();
27+
type B = bool;
28+
}
29+
30+
fn main() {
31+
let _: <((),) as Grault>::A = ();
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _`
2+
--> $DIR/impl-wf-cycle-5.rs:20:1
3+
|
4+
LL | / impl<T> Grault for (T,)
5+
LL | |
6+
LL | | where
7+
LL | | T: Grault,
8+
LL | | Self::A: Baz,
9+
| |_________________^
10+
LL | {
11+
LL | type A = ();
12+
| ------ associated type `<(T,) as Grault>::A` is specified here
13+
|
14+
note: required for `(T,)` to implement `Grault`
15+
--> $DIR/impl-wf-cycle-5.rs:20:9
16+
|
17+
LL | impl<T> Grault for (T,)
18+
| ^^^^^^ ^^^^
19+
...
20+
LL | Self::A: Baz,
21+
| --- unsatisfied trait bound introduced here
22+
help: associated type for the current `impl` cannot be restricted in `where` clauses, remove this bound
23+
|
24+
LL - T: Grault,
25+
LL - Self::A: Baz,
26+
LL + T: Grault,
27+
|
28+
29+
error: aborting due to 1 previous error
30+
31+
For more information about this error, try `rustc --explain E0275`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// run-rustfix
2+
3+
trait Baz {}
4+
impl Baz for () {}
5+
impl<T> Baz for (T,) {}
6+
7+
trait Fiz {}
8+
impl Fiz for bool {}
9+
10+
trait Grault {
11+
type A;
12+
type B;
13+
}
14+
15+
impl Grault for () {
16+
type A = ();
17+
type B = bool;
18+
}
19+
20+
impl<T: Grault> Grault for (T,)
21+
//~^ ERROR overflow evaluating the requirement `<(T,) as Grault>::A == _`
22+
where
23+
24+
{
25+
type A = ();
26+
type B = bool;
27+
}
28+
29+
fn main() {
30+
let _: <((),) as Grault>::A = ();
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// run-rustfix
2+
3+
trait Baz {}
4+
impl Baz for () {}
5+
impl<T> Baz for (T,) {}
6+
7+
trait Fiz {}
8+
impl Fiz for bool {}
9+
10+
trait Grault {
11+
type A;
12+
type B;
13+
}
14+
15+
impl Grault for () {
16+
type A = ();
17+
type B = bool;
18+
}
19+
20+
impl<T: Grault> Grault for (T,)
21+
//~^ ERROR overflow evaluating the requirement `<(T,) as Grault>::A == _`
22+
where
23+
Self::A: Baz,
24+
{
25+
type A = ();
26+
type B = bool;
27+
}
28+
29+
fn main() {
30+
let _: <((),) as Grault>::A = ();
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _`
2+
--> $DIR/impl-wf-cycle-6.rs:20:1
3+
|
4+
LL | / impl<T: Grault> Grault for (T,)
5+
LL | |
6+
LL | | where
7+
LL | | Self::A: Baz,
8+
| |_________________^
9+
LL | {
10+
LL | type A = ();
11+
| ------ associated type `<(T,) as Grault>::A` is specified here
12+
|
13+
note: required for `(T,)` to implement `Grault`
14+
--> $DIR/impl-wf-cycle-6.rs:20:17
15+
|
16+
LL | impl<T: Grault> Grault for (T,)
17+
| ^^^^^^ ^^^^
18+
...
19+
LL | Self::A: Baz,
20+
| --- unsatisfied trait bound introduced here
21+
help: associated type for the current `impl` cannot be restricted in `where` clauses, remove this bound
22+
|
23+
LL - Self::A: Baz,
24+
LL +
25+
|
26+
27+
error: aborting due to 1 previous error
28+
29+
For more information about this error, try `rustc --explain E0275`.

0 commit comments

Comments
 (0)