Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide structured suggestion for unconstrained generic constant #122802

Merged
merged 1 commit into from
Mar 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3538,12 +3538,39 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
let mut err =
self.dcx().struct_span_err(span, "unconstrained generic constant");
let const_span = self.tcx.def_span(uv.def);

let const_ty = self.tcx.type_of(uv.def).instantiate(self.tcx, uv.args);
let cast = if const_ty != self.tcx.types.usize { " as usize" } else { "" };
let msg = "try adding a `where` bound";
match self.tcx.sess.source_map().span_to_snippet(const_span) {
Ok(snippet) => err.help(format!(
"try adding a `where` bound using this expression: `where [(); {snippet}]:`"
)),
_ => err.help("consider adding a `where` bound using this expression"),
};
Ok(snippet) => {
let code = format!("[(); {snippet}{cast}]:");
let def_id = if let ObligationCauseCode::CompareImplItemObligation {
trait_item_def_id,
..
} = obligation.cause.code()
{
trait_item_def_id.as_local()
} else {
Some(obligation.cause.body_id)
};
if let Some(def_id) = def_id
&& let Some(generics) = self.tcx.hir().get_generics(def_id)
{
err.span_suggestion_verbose(
generics.tail_span_for_predicate_suggestion(),
msg,
format!("{} {code}", generics.add_where_or_trailing_comma()),
Applicability::MaybeIncorrect,
);
} else {
err.help(format!("{msg}: where {code}"));
};
}
_ => {
err.help(msg);
}
};
Ok(err)
}
ty::ConstKind::Expr(_) => {
Expand Down
5 changes: 4 additions & 1 deletion tests/ui/const-generics/const-argument-if-length.full.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ error: unconstrained generic constant
LL | pad: [u8; is_zst::<T>()],
| ^^^^^^^^^^^^^^^^^^^
|
= help: try adding a `where` bound using this expression: `where [(); is_zst::<T>()]:`
help: try adding a `where` bound
|
LL | pub struct AtLeastByte<T: ?Sized> where [(); is_zst::<T>()]: {
| ++++++++++++++++++++++++++

error[E0277]: the size for values of type `T` cannot be known at compilation time
--> $DIR/const-argument-if-length.rs:16:12
Expand Down
10 changes: 8 additions & 2 deletions tests/ui/const-generics/defaults/generic-expr-default.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,21 @@ error: unconstrained generic constant
LL | pub fn needs_evaluatable_bound<const N1: usize>() -> Foo<N1> {
| ^^^^^^^
|
= help: try adding a `where` bound using this expression: `where [(); { N + 1 }]:`
help: try adding a `where` bound
|
LL | pub fn needs_evaluatable_bound<const N1: usize>() -> Foo<N1> where [(); { N + 1 }]: {
| ++++++++++++++++++++++

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

error: aborting due to 2 previous errors

5 changes: 4 additions & 1 deletion tests/ui/const-generics/ensure_is_evaluatable.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ error: unconstrained generic constant
LL | bar()
| ^^^^^
|
= help: try adding a `where` bound using this expression: `where [(); N + 1]:`
note: required by a bound in `bar`
--> $DIR/ensure_is_evaluatable.rs:15:10
|
Expand All @@ -13,6 +12,10 @@ LL | fn bar<const N: usize>() -> [(); N]
LL | where
LL | [(); N + 1]:,
| ^^^^^ required by this bound in `bar`
help: try adding a `where` bound
|
LL | [(); M + 1]:, [(); N + 1]:
| ~~~~~~~~~~~~~~

error: aborting due to 1 previous error

5 changes: 4 additions & 1 deletion tests/ui/const-generics/fn_with_two_const_inputs.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ error: unconstrained generic constant
LL | bar()
| ^^^^^
|
= help: try adding a `where` bound using this expression: `where [(); N + 1]:`
note: required by a bound in `bar`
--> $DIR/fn_with_two_const_inputs.rs:18:10
|
Expand All @@ -13,6 +12,10 @@ LL | fn bar<const N: usize>() -> [(); N]
LL | where
LL | [(); N + 1]:,
| ^^^^^ required by this bound in `bar`
help: try adding a `where` bound
|
LL | [(); both(N + 1, M + 1)]:, [(); N + 1]:
| ~~~~~~~~~~~~~~

error: aborting due to 1 previous error

Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//@ run-rustfix
#![feature(generic_const_exprs)]
#![allow(incomplete_features, dead_code)]

struct Evaluatable<const N: u128> {}

struct Foo<const N: u8>([u8; N as usize])
//~^ ERROR unconstrained generic constant
where
Evaluatable<{N as u128}>:, [(); N as usize]:;
//~^ HELP try adding a `where` bound

struct Foo2<const N: u8>(Evaluatable::<{N as u128}>) where Evaluatable<{N as usize as u128 }>:, [(); {N as u128} as usize]:;
//~^ ERROR unconstrained generic constant
//~| HELP try adding a `where` bound

struct Bar<const N: u8>([u8; (N + 2) as usize]) where [(); (N + 1) as usize]:, [(); (N + 2) as usize]:;
//~^ ERROR unconstrained generic constant
//~| HELP try adding a `where` bound

fn main() {}
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
//@ run-rustfix
#![feature(generic_const_exprs)]
#![allow(incomplete_features)]
#![allow(incomplete_features, dead_code)]

struct Evaluatable<const N: u128> {}

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

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

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

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

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

error: unconstrained generic constant
--> $DIR/abstract-const-as-cast-2.rs:16:25
--> $DIR/abstract-const-as-cast-2.rs:17:25
|
LL | struct Bar<const N: u8>([u8; (N + 2) as usize]) where [(); (N + 1) as usize]:;
| ^^^^^^^^^^^^^^^^^^^^^^
|
= help: try adding a `where` bound using this expression: `where [(); (N + 2) as usize]:`
help: try adding a `where` bound
|
LL | struct Bar<const N: u8>([u8; (N + 2) as usize]) where [(); (N + 1) as usize]:, [(); (N + 2) as usize]:;
| +++++++++++++++++++++++++

error: aborting due to 3 previous errors

Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ error: unconstrained generic constant
LL | assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as u128 }>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: try adding a `where` bound using this expression: `where [(); { O as u128 }]:`
note: required for `HasCastInTraitImpl<{ N + 1 }, { N as u128 }>` to implement `Trait`
--> $DIR/abstract-const-as-cast-3.rs:8:22
|
Expand All @@ -15,6 +14,10 @@ note: required by a bound in `use_trait_impl::assert_impl`
|
LL | fn assert_impl<T: Trait>() {}
| ^^^^^ required by this bound in `assert_impl`
help: try adding a `where` bound
|
LL | EvaluatableU128<{N as u128}>:, [(); { O as u128 } as usize]: {
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

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

error[E0308]: mismatched types
--> $DIR/abstract-const-as-cast-3.rs:20:5
Expand Down Expand Up @@ -96,7 +102,6 @@ error: unconstrained generic constant
LL | assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as u128 }>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: try adding a `where` bound using this expression: `where [(); { O as u128 }]:`
note: required for `HasCastInTraitImpl<{ N + 1 }, { N as u128 }>` to implement `Trait`
--> $DIR/abstract-const-as-cast-3.rs:8:22
|
Expand All @@ -107,6 +112,10 @@ note: required by a bound in `use_trait_impl_2::assert_impl`
|
LL | fn assert_impl<T: Trait>() {}
| ^^^^^ required by this bound in `assert_impl`
help: try adding a `where` bound
|
LL | EvaluatableU128<{N as _}>:, [(); { O as u128 } as usize]: {
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

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

error[E0308]: mismatched types
--> $DIR/abstract-const-as-cast-3.rs:38:5
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ error: unconstrained generic constant
LL | bar::<{ N as usize as usize }>();
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= help: try adding a `where` bound using this expression: `where [(); { N as usize as usize }]:`
help: try adding a `where` bound
|
LL | fn foo<const N: u8>(a: [(); N as usize]) where [(); { N as usize as usize }]: {
| ++++++++++++++++++++++++++++++++++++

error: aborting due to 1 previous error

Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ error: unconstrained generic constant
LL | struct ArithArrayLen<const N: usize>([u32; 0 + N]);
| ^^^^^^^^^^^^
|
= help: try adding a `where` bound using this expression: `where [(); 0 + N]:`
help: try adding a `where` bound
|
LL | struct ArithArrayLen<const N: usize>([u32; 0 + N]) where [(); 0 + N]:;
| ++++++++++++++++++

error: overly complex generic constant
--> $DIR/array-size-in-generic-struct-param.rs:23:15
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ error: unconstrained generic constant
LL | bar::<{ T::ASSOC }>();
| ^^^^^^^^^^^^
|
= help: try adding a `where` bound using this expression: `where [(); { T::ASSOC }]:`
help: try adding a `where` bound
|
LL | fn foo<T: Trait, U: Trait>() where [(); U::ASSOC]:, [(); { T::ASSOC }]: {
| ~~~~~~~~~~~~~~~~~~~~~

error: aborting due to 1 previous error

Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ error: unconstrained generic constant
LL | foo::<_, L>([(); L + 1 + L]);
| ^^^^^^^^^
|
= help: try adding a `where` bound using this expression: `where [(); L + 1 + L]:`
help: try adding a `where` bound
|
LL | [(); (L - 1) + 1 + L]:, [(); L + 1 + L]:
| ~~~~~~~~~~~~~~~~~~

error: unconstrained generic constant
--> $DIR/issue_114151.rs:17:17
Expand All @@ -34,11 +37,6 @@ LL | foo::<_, L>([(); L + 1 + L]);
| |
| required by a bound introduced by this call
|
= help: try adding a `where` bound using this expression: `where [(); {
{
N
}
}]:`
note: required by a bound in `foo`
--> $DIR/issue_114151.rs:5:13
|
Expand All @@ -51,6 +49,14 @@ LL | | N
LL | | }
LL | | }],
| |_____^ required by this bound in `foo`
help: try adding a `where` bound
|
LL ~ [(); (L - 1) + 1 + L]:, [(); {
LL + {
LL + N
LL + }
LL + }]:
|

error: unconstrained generic constant `L + 1 + L`
--> $DIR/issue_114151.rs:17:5
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ error: unconstrained generic constant
LL | Bar::<{ make_generic(N, 1_u8 == 0_u8) }>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: try adding a `where` bound using this expression: `where [(); { make_generic(N, 1_u8 == 0_u8) }]:`
help: try adding a `where` bound
|
LL | fn foo<const N: usize>() -> Bar<{ make_generic(N, true == false) }> where [(); { make_generic(N, 1_u8 == 0_u8) } as usize]: {
| +++++++++++++++++++++++++++++++++++++++++++++++++++++++

error: aborting due to 2 previous errors

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ error: unconstrained generic constant
LL | [(); (1_u8 as usize) + N]
| ^^^^^^^^^^^^^^^^^^^
|
= help: try adding a `where` bound using this expression: `where [(); (1_u8 as usize) + N]:`
help: try adding a `where` bound
|
LL | fn foo<const N: usize>() -> [(); (true as usize) + N] where [(); (1_u8 as usize) + N]: {
| ++++++++++++++++++++++++++++++++

error: aborting due to 2 previous errors

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ error: unconstrained generic constant
LL | foo::<_, L>([(); L + 1 + L]);
| ^^^^^^^^^
|
= help: try adding a `where` bound using this expression: `where [(); L + 1 + L]:`
help: try adding a `where` bound
|
LL | [(); (L - 1) + 1 + L]:, [(); L + 1 + L]:
| ~~~~~~~~~~~~~~~~~~

error: aborting due to 2 previous errors

Expand Down
Loading
Loading