Skip to content

Commit d29a5a1

Browse files
committed
Suggest using type args directly
when they are written wrongly using an equality constraint
1 parent dc2ffa4 commit d29a5a1

File tree

11 files changed

+181
-16
lines changed

11 files changed

+181
-16
lines changed

compiler/rustc_hir_analysis/src/astconv/errors.rs

+14-3
Original file line numberDiff line numberDiff line change
@@ -920,11 +920,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
920920
/// Emits an error regarding forbidden type binding associations
921921
pub fn prohibit_assoc_ty_binding(
922922
tcx: TyCtxt<'_>,
923-
span: Span,
923+
binding: &hir::TypeBinding<'_>,
924924
segment: Option<(&hir::PathSegment<'_>, Span)>,
925925
) {
926-
tcx.dcx().emit_err(AssocTypeBindingNotAllowed {
927-
span,
926+
let mut err = tcx.dcx().create_err(AssocTypeBindingNotAllowed {
927+
span: binding.span,
928928
fn_trait_expansion: if let Some((segment, span)) = segment
929929
&& segment.args().parenthesized == hir::GenericArgsParentheses::ParenSugar
930930
{
@@ -936,6 +936,17 @@ pub fn prohibit_assoc_ty_binding(
936936
None
937937
},
938938
});
939+
940+
if let Some((segment, _)) = segment
941+
&& segment.args().parenthesized == hir::GenericArgsParentheses::No
942+
&& let hir::TypeBindingKind::Equality { term: hir::Term::Ty(ty) } = binding.kind
943+
&& let Ok(ty) = tcx.sess.source_map().span_to_snippet(ty.span)
944+
{
945+
let msg = format!("to use `{ty}` as a generic argument specify it directly");
946+
err.span_suggestion_verbose(binding.span, msg, ty, Applicability::MaybeIncorrect);
947+
}
948+
949+
err.emit();
939950
}
940951

941952
pub(crate) fn fn_trait_to_string(

compiler/rustc_hir_analysis/src/astconv/generics.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,7 @@ pub(crate) fn check_generic_arg_count(
458458
if gen_pos != GenericArgPosition::Type
459459
&& let Some(b) = gen_args.bindings.first()
460460
{
461-
prohibit_assoc_ty_binding(tcx, b.span, None);
461+
prohibit_assoc_ty_binding(tcx, b, None);
462462
}
463463

464464
let explicit_late_bound =

compiler/rustc_hir_analysis/src/astconv/mod.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
290290
ty::BoundConstness::NotConst,
291291
);
292292
if let Some(b) = item_segment.args().bindings.first() {
293-
prohibit_assoc_ty_binding(self.tcx(), b.span, Some((item_segment, span)));
293+
prohibit_assoc_ty_binding(self.tcx(), b, Some((item_segment, span)));
294294
}
295295

296296
args
@@ -599,7 +599,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
599599
);
600600

601601
if let Some(b) = item_segment.args().bindings.first() {
602-
prohibit_assoc_ty_binding(self.tcx(), b.span, Some((item_segment, span)));
602+
prohibit_assoc_ty_binding(self.tcx(), b, Some((item_segment, span)));
603603
}
604604

605605
args
@@ -738,7 +738,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
738738
constness,
739739
);
740740
if let Some(b) = trait_segment.args().bindings.first() {
741-
prohibit_assoc_ty_binding(self.tcx(), b.span, Some((trait_segment, span)));
741+
prohibit_assoc_ty_binding(self.tcx(), b, Some((trait_segment, span)));
742742
}
743743
ty::TraitRef::new(self.tcx(), trait_def_id, generic_args)
744744
}
@@ -1820,7 +1820,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
18201820
for segment in segments {
18211821
// Only emit the first error to avoid overloading the user with error messages.
18221822
if let Some(b) = segment.args().bindings.first() {
1823-
prohibit_assoc_ty_binding(self.tcx(), b.span, None);
1823+
prohibit_assoc_ty_binding(self.tcx(), b, None);
18241824
return true;
18251825
}
18261826
}

tests/ui/associated-type-bounds/issue-102335-ty.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ error[E0229]: associated type bindings are not allowed here
33
|
44
LL | type A: S<C<i32 = u32> = ()>;
55
| ^^^^^^^^^ associated type not allowed here
6+
|
7+
help: to use `u32` as a generic argument specify it directly
8+
|
9+
LL | type A: S<C<u32> = ()>;
10+
| ~~~
611

712
error: aborting due to 1 previous error
813

Original file line numberDiff line numberDiff line change
@@ -1,19 +1,48 @@
11
// Test equality constraints on associated types. Check we get an error when an
2-
// equality constraint is used in a qualified path.
2+
// equality constraint is used outside of type parameter declarations
33

44
pub trait Foo {
55
type A;
66
fn boo(&self) -> <Self as Foo>::A;
77
}
88

99
struct Bar;
10+
struct Qux;
1011

1112
impl Foo for isize {
1213
type A = usize;
1314
fn boo(&self) -> usize { 42 }
1415
}
1516

16-
fn baz<I: Foo>(x: &<I as Foo<A=Bar>>::A) {}
17+
fn baz<I: Foo>(_x: &<I as Foo<A=Bar>>::A) {}
1718
//~^ ERROR associated type bindings are not allowed here
1819

20+
21+
trait Tr1<T1> {
22+
}
23+
24+
impl Tr1<T1 = String> for Bar {
25+
//~^ ERROR associated type bindings are not allowed here
26+
//~| ERROR trait takes 1 generic argument but 0 generic arguments were supplied
27+
}
28+
29+
trait Tr3<T1, T2, T3> {
30+
}
31+
32+
// E0229 is emitted only for the first erroneous equality
33+
// constraint (T2) not for any subequent ones (e.g. T3)
34+
impl Tr3<i32, T2 = Qux, T3 = usize> for Bar {
35+
//~^ ERROR associated type bindings are not allowed here
36+
//~| ERROR trait takes 3 generic arguments but 1 generic argument was supplied
37+
}
38+
39+
40+
struct Generic<T> { _t: T }
41+
42+
impl Tr3<i32, Qux, T3 = Generic<i32>> for Bar {
43+
//~^ ERROR associated type bindings are not allowed here
44+
//~| ERROR trait takes 3 generic arguments but 2 generic arguments were supplied
45+
}
46+
47+
1948
pub fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,100 @@
11
error[E0229]: associated type bindings are not allowed here
2-
--> $DIR/associated-types-eq-2.rs:16:30
2+
--> $DIR/associated-types-eq-2.rs:17:31
33
|
4-
LL | fn baz<I: Foo>(x: &<I as Foo<A=Bar>>::A) {}
5-
| ^^^^^ associated type not allowed here
4+
LL | fn baz<I: Foo>(_x: &<I as Foo<A=Bar>>::A) {}
5+
| ^^^^^ associated type not allowed here
6+
|
7+
help: to use `Bar` as a generic argument specify it directly
8+
|
9+
LL | fn baz<I: Foo>(_x: &<I as Foo<Bar>>::A) {}
10+
| ~~~
11+
12+
error[E0107]: trait takes 1 generic argument but 0 generic arguments were supplied
13+
--> $DIR/associated-types-eq-2.rs:24:6
14+
|
15+
LL | impl Tr1<T1 = String> for Bar {
16+
| ^^^ expected 1 generic argument
17+
|
18+
note: trait defined here, with 1 generic parameter: `T1`
19+
--> $DIR/associated-types-eq-2.rs:21:7
20+
|
21+
LL | trait Tr1<T1> {
22+
| ^^^ --
23+
help: add missing generic argument
24+
|
25+
LL | impl Tr1<T1, T1 = String> for Bar {
26+
| +++
27+
28+
error[E0229]: associated type bindings are not allowed here
29+
--> $DIR/associated-types-eq-2.rs:24:10
30+
|
31+
LL | impl Tr1<T1 = String> for Bar {
32+
| ^^^^^^^^^^^ associated type not allowed here
33+
|
34+
help: to use `String` as a generic argument specify it directly
35+
|
36+
LL | impl Tr1<String> for Bar {
37+
| ~~~~~~
38+
39+
error[E0107]: trait takes 3 generic arguments but 1 generic argument was supplied
40+
--> $DIR/associated-types-eq-2.rs:34:6
41+
|
42+
LL | impl Tr3<i32, T2 = Qux, T3 = usize> for Bar {
43+
| ^^^ --- supplied 1 generic argument
44+
| |
45+
| expected 3 generic arguments
46+
|
47+
note: trait defined here, with 3 generic parameters: `T1`, `T2`, `T3`
48+
--> $DIR/associated-types-eq-2.rs:29:7
49+
|
50+
LL | trait Tr3<T1, T2, T3> {
51+
| ^^^ -- -- --
52+
help: add missing generic arguments
53+
|
54+
LL | impl Tr3<i32, T2, T3, T2 = Qux, T3 = usize> for Bar {
55+
| ++++++++
56+
57+
error[E0229]: associated type bindings are not allowed here
58+
--> $DIR/associated-types-eq-2.rs:34:15
59+
|
60+
LL | impl Tr3<i32, T2 = Qux, T3 = usize> for Bar {
61+
| ^^^^^^^^ associated type not allowed here
62+
|
63+
help: to use `Qux` as a generic argument specify it directly
64+
|
65+
LL | impl Tr3<i32, Qux, T3 = usize> for Bar {
66+
| ~~~
67+
68+
error[E0107]: trait takes 3 generic arguments but 2 generic arguments were supplied
69+
--> $DIR/associated-types-eq-2.rs:42:6
70+
|
71+
LL | impl Tr3<i32, Qux, T3 = Generic<i32>> for Bar {
72+
| ^^^ --- --- supplied 2 generic arguments
73+
| |
74+
| expected 3 generic arguments
75+
|
76+
note: trait defined here, with 3 generic parameters: `T1`, `T2`, `T3`
77+
--> $DIR/associated-types-eq-2.rs:29:7
78+
|
79+
LL | trait Tr3<T1, T2, T3> {
80+
| ^^^ -- -- --
81+
help: add missing generic argument
82+
|
83+
LL | impl Tr3<i32, Qux, T3, T3 = Generic<i32>> for Bar {
84+
| ++++
85+
86+
error[E0229]: associated type bindings are not allowed here
87+
--> $DIR/associated-types-eq-2.rs:42:20
88+
|
89+
LL | impl Tr3<i32, Qux, T3 = Generic<i32>> for Bar {
90+
| ^^^^^^^^^^^^^^^^^ associated type not allowed here
91+
|
92+
help: to use `Generic<i32>` as a generic argument specify it directly
93+
|
94+
LL | impl Tr3<i32, Qux, Generic<i32>> for Bar {
95+
| ~~~~~~~~~~~~
696

7-
error: aborting due to 1 previous error
97+
error: aborting due to 7 previous errors
898

9-
For more information about this error, try `rustc --explain E0229`.
99+
Some errors have detailed explanations: E0107, E0229.
100+
For more information about an error, try `rustc --explain E0107`.

tests/ui/error-codes/E0229.stderr

+13
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ error[E0229]: associated type bindings are not allowed here
33
|
44
LL | fn baz<I>(x: &<I as Foo<A=Bar>>::A) {}
55
| ^^^^^ associated type not allowed here
6+
|
7+
help: to use `Bar` as a generic argument specify it directly
8+
|
9+
LL | fn baz<I>(x: &<I as Foo<Bar>>::A) {}
10+
| ~~~
611

712
error[E0229]: associated type bindings are not allowed here
813
--> $DIR/E0229.rs:13:25
@@ -11,6 +16,10 @@ LL | fn baz<I>(x: &<I as Foo<A=Bar>>::A) {}
1116
| ^^^^^ associated type not allowed here
1217
|
1318
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
19+
help: to use `Bar` as a generic argument specify it directly
20+
|
21+
LL | fn baz<I>(x: &<I as Foo<Bar>>::A) {}
22+
| ~~~
1423

1524
error[E0229]: associated type bindings are not allowed here
1625
--> $DIR/E0229.rs:13:25
@@ -19,6 +28,10 @@ LL | fn baz<I>(x: &<I as Foo<A=Bar>>::A) {}
1928
| ^^^^^ associated type not allowed here
2029
|
2130
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
31+
help: to use `Bar` as a generic argument specify it directly
32+
|
33+
LL | fn baz<I>(x: &<I as Foo<Bar>>::A) {}
34+
| ~~~
2235

2336
error[E0277]: the trait bound `I: Foo` is not satisfied
2437
--> $DIR/E0229.rs:13:15

tests/ui/generic-associated-types/issue-102335-gat.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ error[E0229]: associated type bindings are not allowed here
33
|
44
LL | type A: S<C<(), i32 = ()> = ()>;
55
| ^^^^^^^^ associated type not allowed here
6+
|
7+
help: to use `()` as a generic argument specify it directly
8+
|
9+
LL | type A: S<C<(), ()> = ()>;
10+
| ~~
611

712
error: aborting due to 1 previous error
813

tests/ui/lifetimes/issue-83753-invalid-associated-type-supertrait-hrtb.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ error[E0229]: associated type bindings are not allowed here
33
|
44
LL | fn bar(foo: Foo<Target = usize>) {}
55
| ^^^^^^^^^^^^^^ associated type not allowed here
6+
|
7+
help: to use `usize` as a generic argument specify it directly
8+
|
9+
LL | fn bar(foo: Foo<usize>) {}
10+
| ~~~~~
611

712
error: aborting due to 1 previous error
813

tests/ui/suggestions/issue-85347.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ use std::ops::Deref;
22
trait Foo {
33
type Bar<'a>: Deref<Target = <Self>::Bar<Target = Self>>;
44
//~^ ERROR associated type takes 1 lifetime argument but 0 lifetime arguments were supplied
5-
//~| ERROR associated type bindings are not allowed here
65
//~| HELP add missing
6+
//~| ERROR associated type bindings are not allowed here
7+
//~| HELP to use `Self` as a generic argument specify it directly
78
}
89

910
fn main() {}

tests/ui/suggestions/issue-85347.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ error[E0229]: associated type bindings are not allowed here
1919
|
2020
LL | type Bar<'a>: Deref<Target = <Self>::Bar<Target = Self>>;
2121
| ^^^^^^^^^^^^^ associated type not allowed here
22+
|
23+
help: to use `Self` as a generic argument specify it directly
24+
|
25+
LL | type Bar<'a>: Deref<Target = <Self>::Bar<Self>>;
26+
| ~~~~
2227

2328
error: aborting due to 2 previous errors
2429

0 commit comments

Comments
 (0)