Skip to content

Commit dda2372

Browse files
committed
Auto merge of #122802 - estebank:unconstrained-generic-const, r=Nadrieril
Provide structured suggestion for unconstrained generic constant ``` error: unconstrained generic constant --> $DIR/const-argument-if-length.rs:18:10 | LL | pad: [u8; is_zst::<T>()], | ^^^^^^^^^^^^^^^^^^^ | help: try adding a `where` bound | LL | pub struct AtLeastByte<T: ?Sized> where [(); is_zst::<T>()]: { | ++++++++++++++++++++++++++ ``` Detect when the constant expression isn't `usize` and suggest casting: ``` error: unconstrained generic constant --> f300.rs:6:10 | 6 | bb::<{!N}>(); | ^^^^ -Ztrack-diagnostics: created at compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs:3539:36 | help: try adding a `where` bound | 5 | fn b<const N: bool>() where [(); {!N} as usize]: { | ++++++++++++++++++++++++++ ``` Fix #122395.
2 parents 42198bf + 6b24fdf commit dda2372

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+351
-111
lines changed

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

+32-5
Original file line numberDiff line numberDiff line change
@@ -3536,12 +3536,39 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
35363536
let mut err =
35373537
self.dcx().struct_span_err(span, "unconstrained generic constant");
35383538
let const_span = self.tcx.def_span(uv.def);
3539+
3540+
let const_ty = self.tcx.type_of(uv.def).instantiate(self.tcx, uv.args);
3541+
let cast = if const_ty != self.tcx.types.usize { " as usize" } else { "" };
3542+
let msg = "try adding a `where` bound";
35393543
match self.tcx.sess.source_map().span_to_snippet(const_span) {
3540-
Ok(snippet) => err.help(format!(
3541-
"try adding a `where` bound using this expression: `where [(); {snippet}]:`"
3542-
)),
3543-
_ => err.help("consider adding a `where` bound using this expression"),
3544-
};
3544+
Ok(snippet) => {
3545+
let code = format!("[(); {snippet}{cast}]:");
3546+
let def_id = if let ObligationCauseCode::CompareImplItemObligation {
3547+
trait_item_def_id,
3548+
..
3549+
} = obligation.cause.code()
3550+
{
3551+
trait_item_def_id.as_local()
3552+
} else {
3553+
Some(obligation.cause.body_id)
3554+
};
3555+
if let Some(def_id) = def_id
3556+
&& let Some(generics) = self.tcx.hir().get_generics(def_id)
3557+
{
3558+
err.span_suggestion_verbose(
3559+
generics.tail_span_for_predicate_suggestion(),
3560+
msg,
3561+
format!("{} {code}", generics.add_where_or_trailing_comma()),
3562+
Applicability::MaybeIncorrect,
3563+
);
3564+
} else {
3565+
err.help(format!("{msg}: where {code}"));
3566+
};
3567+
}
3568+
_ => {
3569+
err.help(msg);
3570+
}
3571+
};
35453572
Ok(err)
35463573
}
35473574
ty::ConstKind::Expr(_) => {

tests/ui/const-generics/const-argument-if-length.full.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ error: unconstrained generic constant
44
LL | pad: [u8; is_zst::<T>()],
55
| ^^^^^^^^^^^^^^^^^^^
66
|
7-
= help: try adding a `where` bound using this expression: `where [(); is_zst::<T>()]:`
7+
help: try adding a `where` bound
8+
|
9+
LL | pub struct AtLeastByte<T: ?Sized> where [(); is_zst::<T>()]: {
10+
| ++++++++++++++++++++++++++
811

912
error[E0277]: the size for values of type `T` cannot be known at compilation time
1013
--> $DIR/const-argument-if-length.rs:16:12

tests/ui/const-generics/defaults/generic-expr-default.stderr

+8-2
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,21 @@ error: unconstrained generic constant
44
LL | pub fn needs_evaluatable_bound<const N1: usize>() -> Foo<N1> {
55
| ^^^^^^^
66
|
7-
= help: try adding a `where` bound using this expression: `where [(); { N + 1 }]:`
7+
help: try adding a `where` bound
8+
|
9+
LL | pub fn needs_evaluatable_bound<const N1: usize>() -> Foo<N1> where [(); { N + 1 }]: {
10+
| ++++++++++++++++++++++
811

912
error: unconstrained generic constant
1013
--> $DIR/generic-expr-default.rs:14:58
1114
|
1215
LL | fn needs_evaluatable_bound_alias<T, const N: usize>() -> FooAlias<N>
1316
| ^^^^^^^^^^^
1417
|
15-
= help: try adding a `where` bound using this expression: `where [(); { N + 1 }]:`
18+
help: try adding a `where` bound
19+
|
20+
LL | fn needs_evaluatable_bound_alias<T, const N: usize>() -> FooAlias<N> where [(); { N + 1 }]:
21+
| ++++++++++++++++++++++
1622

1723
error: aborting due to 2 previous errors
1824

tests/ui/const-generics/ensure_is_evaluatable.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ error: unconstrained generic constant
44
LL | bar()
55
| ^^^^^
66
|
7-
= help: try adding a `where` bound using this expression: `where [(); N + 1]:`
87
note: required by a bound in `bar`
98
--> $DIR/ensure_is_evaluatable.rs:15:10
109
|
@@ -13,6 +12,10 @@ LL | fn bar<const N: usize>() -> [(); N]
1312
LL | where
1413
LL | [(); N + 1]:,
1514
| ^^^^^ required by this bound in `bar`
15+
help: try adding a `where` bound
16+
|
17+
LL | [(); M + 1]:, [(); N + 1]:
18+
| ~~~~~~~~~~~~~~
1619

1720
error: aborting due to 1 previous error
1821

tests/ui/const-generics/fn_with_two_const_inputs.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ error: unconstrained generic constant
44
LL | bar()
55
| ^^^^^
66
|
7-
= help: try adding a `where` bound using this expression: `where [(); N + 1]:`
87
note: required by a bound in `bar`
98
--> $DIR/fn_with_two_const_inputs.rs:18:10
109
|
@@ -13,6 +12,10 @@ LL | fn bar<const N: usize>() -> [(); N]
1312
LL | where
1413
LL | [(); N + 1]:,
1514
| ^^^^^ required by this bound in `bar`
15+
help: try adding a `where` bound
16+
|
17+
LL | [(); both(N + 1, M + 1)]:, [(); N + 1]:
18+
| ~~~~~~~~~~~~~~
1619

1720
error: aborting due to 1 previous error
1821

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//@ run-rustfix
2+
#![feature(generic_const_exprs)]
3+
#![allow(incomplete_features, dead_code)]
4+
5+
struct Evaluatable<const N: u128> {}
6+
7+
struct Foo<const N: u8>([u8; N as usize])
8+
//~^ ERROR unconstrained generic constant
9+
where
10+
Evaluatable<{N as u128}>:, [(); N as usize]:;
11+
//~^ HELP try adding a `where` bound
12+
13+
struct Foo2<const N: u8>(Evaluatable::<{N as u128}>) where Evaluatable<{N as usize as u128 }>:, [(); {N as u128} as usize]:;
14+
//~^ ERROR unconstrained generic constant
15+
//~| HELP try adding a `where` bound
16+
17+
struct Bar<const N: u8>([u8; (N + 2) as usize]) where [(); (N + 1) as usize]:, [(); (N + 2) as usize]:;
18+
//~^ ERROR unconstrained generic constant
19+
//~| HELP try adding a `where` bound
20+
21+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,21 @@
1+
//@ run-rustfix
12
#![feature(generic_const_exprs)]
2-
#![allow(incomplete_features)]
3+
#![allow(incomplete_features, dead_code)]
34

45
struct Evaluatable<const N: u128> {}
56

67
struct Foo<const N: u8>([u8; N as usize])
7-
//~^ Error: unconstrained generic constant
8-
//~| help: try adding a `where` bound using this expression: `where [(); N as usize]:`
8+
//~^ ERROR unconstrained generic constant
99
where
1010
Evaluatable<{N as u128}>:;
11+
//~^ HELP try adding a `where` bound
1112

1213
struct Foo2<const N: u8>(Evaluatable::<{N as u128}>) where Evaluatable<{N as usize as u128 }>:;
13-
//~^ Error: unconstrained generic constant
14-
//~| help: try adding a `where` bound using this expression: `where [(); {N as u128}]:`
14+
//~^ ERROR unconstrained generic constant
15+
//~| HELP try adding a `where` bound
1516

1617
struct Bar<const N: u8>([u8; (N + 2) as usize]) where [(); (N + 1) as usize]:;
17-
//~^ Error: unconstrained generic constant
18-
//~| help: try adding a `where` bound using this expression: `where [(); (N + 2) as usize]:`
18+
//~^ ERROR unconstrained generic constant
19+
//~| HELP try adding a `where` bound
1920

2021
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,35 @@
11
error: unconstrained generic constant
2-
--> $DIR/abstract-const-as-cast-2.rs:6:25
2+
--> $DIR/abstract-const-as-cast-2.rs:7:25
33
|
44
LL | struct Foo<const N: u8>([u8; N as usize])
55
| ^^^^^^^^^^^^^^^^
66
|
7-
= help: try adding a `where` bound using this expression: `where [(); N as usize]:`
7+
help: try adding a `where` bound
8+
|
9+
LL | Evaluatable<{N as u128}>:, [(); N as usize]:;
10+
| +++++++++++++++++++
811

912
error: unconstrained generic constant
10-
--> $DIR/abstract-const-as-cast-2.rs:12:26
13+
--> $DIR/abstract-const-as-cast-2.rs:13:26
1114
|
1215
LL | struct Foo2<const N: u8>(Evaluatable::<{N as u128}>) where Evaluatable<{N as usize as u128 }>:;
1316
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
1417
|
15-
= help: try adding a `where` bound using this expression: `where [(); {N as u128}]:`
18+
help: try adding a `where` bound
19+
|
20+
LL | struct Foo2<const N: u8>(Evaluatable::<{N as u128}>) where Evaluatable<{N as usize as u128 }>:, [(); {N as u128} as usize]:;
21+
| +++++++++++++++++++++++++++++
1622

1723
error: unconstrained generic constant
18-
--> $DIR/abstract-const-as-cast-2.rs:16:25
24+
--> $DIR/abstract-const-as-cast-2.rs:17:25
1925
|
2026
LL | struct Bar<const N: u8>([u8; (N + 2) as usize]) where [(); (N + 1) as usize]:;
2127
| ^^^^^^^^^^^^^^^^^^^^^^
2228
|
23-
= help: try adding a `where` bound using this expression: `where [(); (N + 2) as usize]:`
29+
help: try adding a `where` bound
30+
|
31+
LL | struct Bar<const N: u8>([u8; (N + 2) as usize]) where [(); (N + 1) as usize]:, [(); (N + 2) as usize]:;
32+
| +++++++++++++++++++++++++
2433

2534
error: aborting due to 3 previous errors
2635

tests/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.stderr

+16-4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ error: unconstrained generic constant
44
LL | assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as u128 }>>();
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66
|
7-
= help: try adding a `where` bound using this expression: `where [(); { O as u128 }]:`
87
note: required for `HasCastInTraitImpl<{ N + 1 }, { N as u128 }>` to implement `Trait`
98
--> $DIR/abstract-const-as-cast-3.rs:8:22
109
|
@@ -15,6 +14,10 @@ note: required by a bound in `use_trait_impl::assert_impl`
1514
|
1615
LL | fn assert_impl<T: Trait>() {}
1716
| ^^^^^ required by this bound in `assert_impl`
17+
help: try adding a `where` bound
18+
|
19+
LL | EvaluatableU128<{N as u128}>:, [(); { O as u128 } as usize]: {
20+
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1821

1922
error[E0308]: mismatched types
2023
--> $DIR/abstract-const-as-cast-3.rs:17:5
@@ -36,7 +39,6 @@ error: unconstrained generic constant
3639
LL | assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as _ }>>();
3740
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3841
|
39-
= help: try adding a `where` bound using this expression: `where [(); { O as u128 }]:`
4042
note: required for `HasCastInTraitImpl<{ N + 1 }, { N as _ }>` to implement `Trait`
4143
--> $DIR/abstract-const-as-cast-3.rs:8:22
4244
|
@@ -47,6 +49,10 @@ note: required by a bound in `use_trait_impl::assert_impl`
4749
|
4850
LL | fn assert_impl<T: Trait>() {}
4951
| ^^^^^ required by this bound in `assert_impl`
52+
help: try adding a `where` bound
53+
|
54+
LL | EvaluatableU128<{N as u128}>:, [(); { O as u128 } as usize]: {
55+
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5056

5157
error[E0308]: mismatched types
5258
--> $DIR/abstract-const-as-cast-3.rs:20:5
@@ -96,7 +102,6 @@ error: unconstrained generic constant
96102
LL | assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as u128 }>>();
97103
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
98104
|
99-
= help: try adding a `where` bound using this expression: `where [(); { O as u128 }]:`
100105
note: required for `HasCastInTraitImpl<{ N + 1 }, { N as u128 }>` to implement `Trait`
101106
--> $DIR/abstract-const-as-cast-3.rs:8:22
102107
|
@@ -107,6 +112,10 @@ note: required by a bound in `use_trait_impl_2::assert_impl`
107112
|
108113
LL | fn assert_impl<T: Trait>() {}
109114
| ^^^^^ required by this bound in `assert_impl`
115+
help: try adding a `where` bound
116+
|
117+
LL | EvaluatableU128<{N as _}>:, [(); { O as u128 } as usize]: {
118+
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
110119

111120
error[E0308]: mismatched types
112121
--> $DIR/abstract-const-as-cast-3.rs:35:5
@@ -128,7 +137,6 @@ error: unconstrained generic constant
128137
LL | assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as _ }>>();
129138
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
130139
|
131-
= help: try adding a `where` bound using this expression: `where [(); { O as u128 }]:`
132140
note: required for `HasCastInTraitImpl<{ N + 1 }, { N as _ }>` to implement `Trait`
133141
--> $DIR/abstract-const-as-cast-3.rs:8:22
134142
|
@@ -139,6 +147,10 @@ note: required by a bound in `use_trait_impl_2::assert_impl`
139147
|
140148
LL | fn assert_impl<T: Trait>() {}
141149
| ^^^^^ required by this bound in `assert_impl`
150+
help: try adding a `where` bound
151+
|
152+
LL | EvaluatableU128<{N as _}>:, [(); { O as u128 } as usize]: {
153+
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
142154

143155
error[E0308]: mismatched types
144156
--> $DIR/abstract-const-as-cast-3.rs:38:5

tests/ui/const-generics/generic_const_exprs/abstract-consts-as-cast-5.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ error: unconstrained generic constant
44
LL | bar::<{ N as usize as usize }>();
55
| ^^^^^^^^^^^^^^^^^^^^^^^
66
|
7-
= help: try adding a `where` bound using this expression: `where [(); { N as usize as usize }]:`
7+
help: try adding a `where` bound
8+
|
9+
LL | fn foo<const N: u8>(a: [(); N as usize]) where [(); { N as usize as usize }]: {
10+
| ++++++++++++++++++++++++++++++++++++
811

912
error: aborting due to 1 previous error
1013

tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ error: unconstrained generic constant
44
LL | struct ArithArrayLen<const N: usize>([u32; 0 + N]);
55
| ^^^^^^^^^^^^
66
|
7-
= help: try adding a `where` bound using this expression: `where [(); 0 + N]:`
7+
help: try adding a `where` bound
8+
|
9+
LL | struct ArithArrayLen<const N: usize>([u32; 0 + N]) where [(); 0 + N]:;
10+
| ++++++++++++++++++
811

912
error: overly complex generic constant
1013
--> $DIR/array-size-in-generic-struct-param.rs:23:15

tests/ui/const-generics/generic_const_exprs/assoc_const_unification/doesnt_unify_evaluatable.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ error: unconstrained generic constant
44
LL | bar::<{ T::ASSOC }>();
55
| ^^^^^^^^^^^^
66
|
7-
= help: try adding a `where` bound using this expression: `where [(); { T::ASSOC }]:`
7+
help: try adding a `where` bound
8+
|
9+
LL | fn foo<T: Trait, U: Trait>() where [(); U::ASSOC]:, [(); { T::ASSOC }]: {
10+
| ~~~~~~~~~~~~~~~~~~~~~
811

912
error: aborting due to 1 previous error
1013

tests/ui/const-generics/generic_const_exprs/const_kind_expr/issue_114151.stderr

+12-6
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@ error: unconstrained generic constant
2424
LL | foo::<_, L>([(); L + 1 + L]);
2525
| ^^^^^^^^^
2626
|
27-
= help: try adding a `where` bound using this expression: `where [(); L + 1 + L]:`
27+
help: try adding a `where` bound
28+
|
29+
LL | [(); (L - 1) + 1 + L]:, [(); L + 1 + L]:
30+
| ~~~~~~~~~~~~~~~~~~
2831

2932
error: unconstrained generic constant
3033
--> $DIR/issue_114151.rs:17:17
@@ -34,11 +37,6 @@ LL | foo::<_, L>([(); L + 1 + L]);
3437
| |
3538
| required by a bound introduced by this call
3639
|
37-
= help: try adding a `where` bound using this expression: `where [(); {
38-
{
39-
N
40-
}
41-
}]:`
4240
note: required by a bound in `foo`
4341
--> $DIR/issue_114151.rs:5:13
4442
|
@@ -51,6 +49,14 @@ LL | | N
5149
LL | | }
5250
LL | | }],
5351
| |_____^ required by this bound in `foo`
52+
help: try adding a `where` bound
53+
|
54+
LL ~ [(); (L - 1) + 1 + L]:, [(); {
55+
LL + {
56+
LL + N
57+
LL + }
58+
LL + }]:
59+
|
5460

5561
error: unconstrained generic constant `L + 1 + L`
5662
--> $DIR/issue_114151.rs:17:5

tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_binop_arg_tys.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@ error: unconstrained generic constant
1313
LL | Bar::<{ make_generic(N, 1_u8 == 0_u8) }>
1414
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1515
|
16-
= help: try adding a `where` bound using this expression: `where [(); { make_generic(N, 1_u8 == 0_u8) }]:`
16+
help: try adding a `where` bound
17+
|
18+
LL | fn foo<const N: usize>() -> Bar<{ make_generic(N, true == false) }> where [(); { make_generic(N, 1_u8 == 0_u8) } as usize]: {
19+
| +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1720

1821
error: aborting due to 2 previous errors
1922

tests/ui/const-generics/generic_const_exprs/const_kind_expr/relate_cast_arg_ty.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@ error: unconstrained generic constant
1313
LL | [(); (1_u8 as usize) + N]
1414
| ^^^^^^^^^^^^^^^^^^^
1515
|
16-
= help: try adding a `where` bound using this expression: `where [(); (1_u8 as usize) + N]:`
16+
help: try adding a `where` bound
17+
|
18+
LL | fn foo<const N: usize>() -> [(); (true as usize) + N] where [(); (1_u8 as usize) + N]: {
19+
| ++++++++++++++++++++++++++++++++
1720

1821
error: aborting due to 2 previous errors
1922

tests/ui/const-generics/generic_const_exprs/const_kind_expr/wf_obligation.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@ error: unconstrained generic constant
1313
LL | foo::<_, L>([(); L + 1 + L]);
1414
| ^^^^^^^^^
1515
|
16-
= help: try adding a `where` bound using this expression: `where [(); L + 1 + L]:`
16+
help: try adding a `where` bound
17+
|
18+
LL | [(); (L - 1) + 1 + L]:, [(); L + 1 + L]:
19+
| ~~~~~~~~~~~~~~~~~~
1720

1821
error: aborting due to 2 previous errors
1922

0 commit comments

Comments
 (0)