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

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

Merged
merged 1 commit into from
Sep 29, 2023
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
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
Loading