Skip to content

Commit

Permalink
Rollup merge of rust-lang#116253 - asquared31415:adt_const_params_fea…
Browse files Browse the repository at this point in the history
…ture, r=compiler-errors

Make `adt_const_params` feature suggestion consistent with other features and improve when it is emitted

Makes the suggestion to add `adt_const_params` formatted like every other feature gate (notably this makes it such that the playground recognizes it). Additionally improves the situations in which that help is emitted so that it's only emitted when the type would be valid or the type *could* be valid (using a slightly incorrect heuristic that favors suggesting the feature over not) instead of, for example, implying that adding the feature would allow the use of `String`.

Also adds the "the only supported types are integers, `bool` and `char`" note to the errors on fn and raw pointers.

r? `@compiler-errors`
  • Loading branch information
matthiaskrgr committed Sep 29, 2023
2 parents 92234f9 + b53a1b3 commit 95262e4
Show file tree
Hide file tree
Showing 40 changed files with 254 additions and 84 deletions.
89 changes: 57 additions & 32 deletions compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
use rustc_trait_selection::traits::misc::{
type_allowed_to_implement_const_param_ty, ConstParamTyImplementationError,
};
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
use rustc_trait_selection::traits::{
Expand Down Expand Up @@ -865,43 +868,65 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
);
});
} else {
let err_ty_str;
let mut is_ptr = true;

let err = match ty.kind() {
let diag = match ty.kind() {
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Error(_) => None,
ty::FnPtr(_) => Some("function pointers"),
ty::RawPtr(_) => Some("raw pointers"),
_ => {
is_ptr = false;
err_ty_str = format!("`{ty}`");
Some(err_ty_str.as_str())
}
ty::FnPtr(_) => Some(tcx.sess.struct_span_err(
hir_ty.span,
"using function pointers as const generic parameters is forbidden",
)),
ty::RawPtr(_) => Some(tcx.sess.struct_span_err(
hir_ty.span,
"using raw pointers as const generic parameters is forbidden",
)),
_ => Some(tcx.sess.struct_span_err(
hir_ty.span,
format!("`{}` is forbidden as the type of a const generic parameter", ty),
)),
};

if let Some(unsupported_type) = err {
if is_ptr {
tcx.sess.span_err(
hir_ty.span,
format!(
"using {unsupported_type} as const generic parameters is forbidden",
),
);
} else {
let mut err = tcx.sess.struct_span_err(
hir_ty.span,
format!(
"{unsupported_type} is forbidden as the type of a const generic parameter",
),
);
err.note("the only supported types are integers, `bool` and `char`");
if tcx.sess.is_nightly_build() {
err.help(
"more complex types are supported with `#![feature(adt_const_params)]`",
);
if let Some(mut diag) = diag {
diag.note("the only supported types are integers, `bool` and `char`");

let cause = ObligationCause::misc(hir_ty.span, param.def_id);
let may_suggest_feature = match type_allowed_to_implement_const_param_ty(
tcx,
tcx.param_env(param.def_id),
ty,
cause,
) {
// Can never implement `ConstParamTy`, don't suggest anything.
Err(ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed) => false,
// May be able to implement `ConstParamTy`. Only emit the feature help
// if the type is local, since the user may be able to fix the local type.
Err(ConstParamTyImplementationError::InfrigingFields(..)) => {
fn ty_is_local(ty: Ty<'_>) -> bool {
match ty.kind() {
ty::Adt(adt_def, ..) => adt_def.did().is_local(),
// Arrays and slices use the inner type's `ConstParamTy`.
ty::Array(ty, ..) => ty_is_local(*ty),
ty::Slice(ty) => ty_is_local(*ty),
// `&` references use the inner type's `ConstParamTy`.
// `&mut` are not supported.
ty::Ref(_, ty, ast::Mutability::Not) => ty_is_local(*ty),
// Say that a tuple is local if any of its components are local.
// This is not strictly correct, but it's likely that the user can fix the local component.
ty::Tuple(tys) => tys.iter().any(|ty| ty_is_local(ty)),
_ => false,
}
}

ty_is_local(ty)
}
err.emit();
// Implments `ConstParamTy`, suggest adding the feature to enable.
Ok(..) => true,
};
if may_suggest_feature && tcx.sess.is_nightly_build() {
diag.help(
"add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types",
);
}

diag.emit();
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Test that when adt_const_params is not enabled, we suggest adding the feature only when
// it would be possible for the type to be used as a const generic or when it's likely
// possible for the user to fix their type to be used.

// Can never be used as const generics.
fn uwu_0<const N: &'static mut ()>() {}
//~^ ERROR: forbidden as the type of a const generic

// Needs the feature but can be used, so suggest adding the feature.
fn owo_0<const N: &'static u32>() {}
//~^ ERROR: forbidden as the type of a const generic
//~^^ HELP: add `#![feature(adt_const_params)]`

// Can only be used in const generics with changes.
struct Meow {
meow: u8,
}

fn meow_0<const N: Meow>() {}
//~^ ERROR: forbidden as the type of a const generic
//~^^ HELP: add `#![feature(adt_const_params)]`
fn meow_1<const N: &'static Meow>() {}
//~^ ERROR: forbidden as the type of a const generic
//~^^ HELP: add `#![feature(adt_const_params)]`
fn meow_2<const N: [Meow; 100]>() {}
//~^ ERROR: forbidden as the type of a const generic
//~^^ HELP: add `#![feature(adt_const_params)]`
fn meow_3<const N: (Meow, u8)>() {}
//~^ ERROR: forbidden as the type of a const generic
//~^^ HELP: add `#![feature(adt_const_params)]`

// This is suboptimal that it thinks it can be used
// but better to suggest the feature to the user.
fn meow_4<const N: (Meow, String)>() {}
//~^ ERROR: forbidden as the type of a const generic
//~^^ HELP: add `#![feature(adt_const_params)]`

// Non-local ADT that does not impl `ConstParamTy`
fn nya_0<const N: String>() {}
//~^ ERROR: forbidden as the type of a const generic
fn nya_1<const N: Vec<u32>>() {}
//~^ ERROR: forbidden as the type of a const generic

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
error: `&'static mut ()` is forbidden as the type of a const generic parameter
--> $DIR/suggest_feature_only_when_possible.rs:6:19
|
LL | fn uwu_0<const N: &'static mut ()>() {}
| ^^^^^^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`

error: `&'static u32` is forbidden as the type of a const generic parameter
--> $DIR/suggest_feature_only_when_possible.rs:10:19
|
LL | fn owo_0<const N: &'static u32>() {}
| ^^^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types

error: `Meow` is forbidden as the type of a const generic parameter
--> $DIR/suggest_feature_only_when_possible.rs:19:20
|
LL | fn meow_0<const N: Meow>() {}
| ^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types

error: `&'static Meow` is forbidden as the type of a const generic parameter
--> $DIR/suggest_feature_only_when_possible.rs:22:20
|
LL | fn meow_1<const N: &'static Meow>() {}
| ^^^^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types

error: `[Meow; 100]` is forbidden as the type of a const generic parameter
--> $DIR/suggest_feature_only_when_possible.rs:25:20
|
LL | fn meow_2<const N: [Meow; 100]>() {}
| ^^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types

error: `(Meow, u8)` is forbidden as the type of a const generic parameter
--> $DIR/suggest_feature_only_when_possible.rs:28:20
|
LL | fn meow_3<const N: (Meow, u8)>() {}
| ^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types

error: `(Meow, String)` is forbidden as the type of a const generic parameter
--> $DIR/suggest_feature_only_when_possible.rs:34:20
|
LL | fn meow_4<const N: (Meow, String)>() {}
| ^^^^^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types

error: `String` is forbidden as the type of a const generic parameter
--> $DIR/suggest_feature_only_when_possible.rs:39:19
|
LL | fn nya_0<const N: String>() {}
| ^^^^^^
|
= note: the only supported types are integers, `bool` and `char`

error: `Vec<u32>` is forbidden as the type of a const generic parameter
--> $DIR/suggest_feature_only_when_possible.rs:41:19
|
LL | fn nya_1<const N: Vec<u32>>() {}
| ^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`

error: aborting due to 9 previous errors

10 changes: 5 additions & 5 deletions tests/ui/const-generics/const-param-elided-lifetime.min.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ LL | struct A<const N: &u8>;
| ^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: more complex types are supported with `#![feature(adt_const_params)]`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types

error: `&u8` is forbidden as the type of a const generic parameter
--> $DIR/const-param-elided-lifetime.rs:14:15
Expand All @@ -44,7 +44,7 @@ LL | impl<const N: &u8> A<N> {
| ^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: more complex types are supported with `#![feature(adt_const_params)]`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types

error: `&u8` is forbidden as the type of a const generic parameter
--> $DIR/const-param-elided-lifetime.rs:22:15
Expand All @@ -53,7 +53,7 @@ LL | impl<const N: &u8> B for A<N> {}
| ^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: more complex types are supported with `#![feature(adt_const_params)]`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types

error: `&u8` is forbidden as the type of a const generic parameter
--> $DIR/const-param-elided-lifetime.rs:26:17
Expand All @@ -62,7 +62,7 @@ LL | fn bar<const N: &u8>() {}
| ^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: more complex types are supported with `#![feature(adt_const_params)]`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types

error: `&u8` is forbidden as the type of a const generic parameter
--> $DIR/const-param-elided-lifetime.rs:17:21
Expand All @@ -71,7 +71,7 @@ LL | fn foo<const M: &u8>(&self) {}
| ^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: more complex types are supported with `#![feature(adt_const_params)]`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types

error: aborting due to 10 previous errors

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ LL | pub struct Dependent<const N: usize, const X: [u8; N]>([(); N]);
| ^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: more complex types are supported with `#![feature(adt_const_params)]`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types

error: `[u8; N]` is forbidden as the type of a const generic parameter
--> $DIR/const-param-type-depends-on-const-param.rs:15:35
Expand All @@ -30,7 +30,7 @@ LL | pub struct SelfDependent<const N: [u8; N]>;
| ^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: more complex types are supported with `#![feature(adt_const_params)]`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types

error: aborting due to 4 previous errors

Expand Down
1 change: 0 additions & 1 deletion tests/ui/const-generics/float-generic.simple.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ LL | fn foo<const F: f32>() {}
| ^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: more complex types are supported with `#![feature(adt_const_params)]`

error: aborting due to previous error

4 changes: 4 additions & 0 deletions tests/ui/const-generics/fn-const-param-call.min.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,16 @@ error: using function pointers as const generic parameters is forbidden
|
LL | struct Wrapper<const F: fn() -> u32>;
| ^^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`

error: using function pointers as const generic parameters is forbidden
--> $DIR/fn-const-param-call.rs:13:15
|
LL | impl<const F: fn() -> u32> Wrapper<F> {
| ^^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`

error: aborting due to 2 previous errors

2 changes: 2 additions & 0 deletions tests/ui/const-generics/fn-const-param-infer.min.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ error: using function pointers as const generic parameters is forbidden
|
LL | struct Checked<const F: fn(usize) -> bool>;
| ^^^^^^^^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`

error: aborting due to previous error

Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ LL | struct B<const CFG: Config> {
| ^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: more complex types are supported with `#![feature(adt_const_params)]`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types

error: aborting due to 3 previous errors

Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ LL | trait Trait<const S: &'static str> {}
| ^^^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: more complex types are supported with `#![feature(adt_const_params)]`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types

error: aborting due to 2 previous errors

2 changes: 1 addition & 1 deletion tests/ui/const-generics/issues/issue-56445-1.min.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ LL | struct Bug<'a, const S: &'a str>(PhantomData<&'a ()>);
| ^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: more complex types are supported with `#![feature(adt_const_params)]`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types

error: aborting due to 2 previous errors

Expand Down
2 changes: 1 addition & 1 deletion tests/ui/const-generics/issues/issue-62878.min.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ LL | fn foo<const N: usize, const A: [u8; N]>() {}
| ^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: more complex types are supported with `#![feature(adt_const_params)]`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types

error: aborting due to 2 previous errors

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ LL | fn test<const T: &'static dyn A>() {
| ^^^^^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: more complex types are supported with `#![feature(adt_const_params)]`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types

error: aborting due to previous error

2 changes: 1 addition & 1 deletion tests/ui/const-generics/issues/issue-68615-adt.min.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ LL | struct Const<const V: [usize; 0]> {}
| ^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: more complex types are supported with `#![feature(adt_const_params)]`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types

error: aborting due to previous error

Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ LL | struct Foo<const V: [usize; 0] > {}
| ^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= help: more complex types are supported with `#![feature(adt_const_params)]`
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types

error: aborting due to previous error

Loading

0 comments on commit 95262e4

Please sign in to comment.