Skip to content

Commit 95262e4

Browse files
authored
Rollup merge of #116253 - asquared31415:adt_const_params_feature, 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`
2 parents 92234f9 + b53a1b3 commit 95262e4

40 files changed

+254
-84
lines changed

compiler/rustc_hir_analysis/src/check/wfcheck.rs

+57-32
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ use rustc_span::symbol::{sym, Ident, Symbol};
2424
use rustc_span::{Span, DUMMY_SP};
2525
use rustc_target::spec::abi::Abi;
2626
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
27+
use rustc_trait_selection::traits::misc::{
28+
type_allowed_to_implement_const_param_ty, ConstParamTyImplementationError,
29+
};
2730
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
2831
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
2932
use rustc_trait_selection::traits::{
@@ -865,43 +868,65 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
865868
);
866869
});
867870
} else {
868-
let err_ty_str;
869-
let mut is_ptr = true;
870-
871-
let err = match ty.kind() {
871+
let diag = match ty.kind() {
872872
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Error(_) => None,
873-
ty::FnPtr(_) => Some("function pointers"),
874-
ty::RawPtr(_) => Some("raw pointers"),
875-
_ => {
876-
is_ptr = false;
877-
err_ty_str = format!("`{ty}`");
878-
Some(err_ty_str.as_str())
879-
}
873+
ty::FnPtr(_) => Some(tcx.sess.struct_span_err(
874+
hir_ty.span,
875+
"using function pointers as const generic parameters is forbidden",
876+
)),
877+
ty::RawPtr(_) => Some(tcx.sess.struct_span_err(
878+
hir_ty.span,
879+
"using raw pointers as const generic parameters is forbidden",
880+
)),
881+
_ => Some(tcx.sess.struct_span_err(
882+
hir_ty.span,
883+
format!("`{}` is forbidden as the type of a const generic parameter", ty),
884+
)),
880885
};
881886

882-
if let Some(unsupported_type) = err {
883-
if is_ptr {
884-
tcx.sess.span_err(
885-
hir_ty.span,
886-
format!(
887-
"using {unsupported_type} as const generic parameters is forbidden",
888-
),
889-
);
890-
} else {
891-
let mut err = tcx.sess.struct_span_err(
892-
hir_ty.span,
893-
format!(
894-
"{unsupported_type} is forbidden as the type of a const generic parameter",
895-
),
896-
);
897-
err.note("the only supported types are integers, `bool` and `char`");
898-
if tcx.sess.is_nightly_build() {
899-
err.help(
900-
"more complex types are supported with `#![feature(adt_const_params)]`",
901-
);
887+
if let Some(mut diag) = diag {
888+
diag.note("the only supported types are integers, `bool` and `char`");
889+
890+
let cause = ObligationCause::misc(hir_ty.span, param.def_id);
891+
let may_suggest_feature = match type_allowed_to_implement_const_param_ty(
892+
tcx,
893+
tcx.param_env(param.def_id),
894+
ty,
895+
cause,
896+
) {
897+
// Can never implement `ConstParamTy`, don't suggest anything.
898+
Err(ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed) => false,
899+
// May be able to implement `ConstParamTy`. Only emit the feature help
900+
// if the type is local, since the user may be able to fix the local type.
901+
Err(ConstParamTyImplementationError::InfrigingFields(..)) => {
902+
fn ty_is_local(ty: Ty<'_>) -> bool {
903+
match ty.kind() {
904+
ty::Adt(adt_def, ..) => adt_def.did().is_local(),
905+
// Arrays and slices use the inner type's `ConstParamTy`.
906+
ty::Array(ty, ..) => ty_is_local(*ty),
907+
ty::Slice(ty) => ty_is_local(*ty),
908+
// `&` references use the inner type's `ConstParamTy`.
909+
// `&mut` are not supported.
910+
ty::Ref(_, ty, ast::Mutability::Not) => ty_is_local(*ty),
911+
// Say that a tuple is local if any of its components are local.
912+
// This is not strictly correct, but it's likely that the user can fix the local component.
913+
ty::Tuple(tys) => tys.iter().any(|ty| ty_is_local(ty)),
914+
_ => false,
915+
}
916+
}
917+
918+
ty_is_local(ty)
902919
}
903-
err.emit();
920+
// Implments `ConstParamTy`, suggest adding the feature to enable.
921+
Ok(..) => true,
922+
};
923+
if may_suggest_feature && tcx.sess.is_nightly_build() {
924+
diag.help(
925+
"add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types",
926+
);
904927
}
928+
929+
diag.emit();
905930
}
906931
}
907932
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Test that when adt_const_params is not enabled, we suggest adding the feature only when
2+
// it would be possible for the type to be used as a const generic or when it's likely
3+
// possible for the user to fix their type to be used.
4+
5+
// Can never be used as const generics.
6+
fn uwu_0<const N: &'static mut ()>() {}
7+
//~^ ERROR: forbidden as the type of a const generic
8+
9+
// Needs the feature but can be used, so suggest adding the feature.
10+
fn owo_0<const N: &'static u32>() {}
11+
//~^ ERROR: forbidden as the type of a const generic
12+
//~^^ HELP: add `#![feature(adt_const_params)]`
13+
14+
// Can only be used in const generics with changes.
15+
struct Meow {
16+
meow: u8,
17+
}
18+
19+
fn meow_0<const N: Meow>() {}
20+
//~^ ERROR: forbidden as the type of a const generic
21+
//~^^ HELP: add `#![feature(adt_const_params)]`
22+
fn meow_1<const N: &'static Meow>() {}
23+
//~^ ERROR: forbidden as the type of a const generic
24+
//~^^ HELP: add `#![feature(adt_const_params)]`
25+
fn meow_2<const N: [Meow; 100]>() {}
26+
//~^ ERROR: forbidden as the type of a const generic
27+
//~^^ HELP: add `#![feature(adt_const_params)]`
28+
fn meow_3<const N: (Meow, u8)>() {}
29+
//~^ ERROR: forbidden as the type of a const generic
30+
//~^^ HELP: add `#![feature(adt_const_params)]`
31+
32+
// This is suboptimal that it thinks it can be used
33+
// but better to suggest the feature to the user.
34+
fn meow_4<const N: (Meow, String)>() {}
35+
//~^ ERROR: forbidden as the type of a const generic
36+
//~^^ HELP: add `#![feature(adt_const_params)]`
37+
38+
// Non-local ADT that does not impl `ConstParamTy`
39+
fn nya_0<const N: String>() {}
40+
//~^ ERROR: forbidden as the type of a const generic
41+
fn nya_1<const N: Vec<u32>>() {}
42+
//~^ ERROR: forbidden as the type of a const generic
43+
44+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
error: `&'static mut ()` is forbidden as the type of a const generic parameter
2+
--> $DIR/suggest_feature_only_when_possible.rs:6:19
3+
|
4+
LL | fn uwu_0<const N: &'static mut ()>() {}
5+
| ^^^^^^^^^^^^^^^
6+
|
7+
= note: the only supported types are integers, `bool` and `char`
8+
9+
error: `&'static u32` is forbidden as the type of a const generic parameter
10+
--> $DIR/suggest_feature_only_when_possible.rs:10:19
11+
|
12+
LL | fn owo_0<const N: &'static u32>() {}
13+
| ^^^^^^^^^^^^
14+
|
15+
= note: the only supported types are integers, `bool` and `char`
16+
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
17+
18+
error: `Meow` is forbidden as the type of a const generic parameter
19+
--> $DIR/suggest_feature_only_when_possible.rs:19:20
20+
|
21+
LL | fn meow_0<const N: Meow>() {}
22+
| ^^^^
23+
|
24+
= note: the only supported types are integers, `bool` and `char`
25+
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
26+
27+
error: `&'static Meow` is forbidden as the type of a const generic parameter
28+
--> $DIR/suggest_feature_only_when_possible.rs:22:20
29+
|
30+
LL | fn meow_1<const N: &'static Meow>() {}
31+
| ^^^^^^^^^^^^^
32+
|
33+
= note: the only supported types are integers, `bool` and `char`
34+
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
35+
36+
error: `[Meow; 100]` is forbidden as the type of a const generic parameter
37+
--> $DIR/suggest_feature_only_when_possible.rs:25:20
38+
|
39+
LL | fn meow_2<const N: [Meow; 100]>() {}
40+
| ^^^^^^^^^^^
41+
|
42+
= note: the only supported types are integers, `bool` and `char`
43+
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
44+
45+
error: `(Meow, u8)` is forbidden as the type of a const generic parameter
46+
--> $DIR/suggest_feature_only_when_possible.rs:28:20
47+
|
48+
LL | fn meow_3<const N: (Meow, u8)>() {}
49+
| ^^^^^^^^^^
50+
|
51+
= note: the only supported types are integers, `bool` and `char`
52+
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
53+
54+
error: `(Meow, String)` is forbidden as the type of a const generic parameter
55+
--> $DIR/suggest_feature_only_when_possible.rs:34:20
56+
|
57+
LL | fn meow_4<const N: (Meow, String)>() {}
58+
| ^^^^^^^^^^^^^^
59+
|
60+
= note: the only supported types are integers, `bool` and `char`
61+
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
62+
63+
error: `String` is forbidden as the type of a const generic parameter
64+
--> $DIR/suggest_feature_only_when_possible.rs:39:19
65+
|
66+
LL | fn nya_0<const N: String>() {}
67+
| ^^^^^^
68+
|
69+
= note: the only supported types are integers, `bool` and `char`
70+
71+
error: `Vec<u32>` is forbidden as the type of a const generic parameter
72+
--> $DIR/suggest_feature_only_when_possible.rs:41:19
73+
|
74+
LL | fn nya_1<const N: Vec<u32>>() {}
75+
| ^^^^^^^^
76+
|
77+
= note: the only supported types are integers, `bool` and `char`
78+
79+
error: aborting due to 9 previous errors
80+

tests/ui/const-generics/const-param-elided-lifetime.min.stderr

+5-5
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ LL | struct A<const N: &u8>;
3535
| ^^^
3636
|
3737
= note: the only supported types are integers, `bool` and `char`
38-
= help: more complex types are supported with `#![feature(adt_const_params)]`
38+
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
3939

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

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

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

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

7676
error: aborting due to 10 previous errors
7777

tests/ui/const-generics/const-param-type-depends-on-const-param.min.stderr

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

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

3535
error: aborting due to 4 previous errors
3636

tests/ui/const-generics/float-generic.simple.stderr

-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ LL | fn foo<const F: f32>() {}
55
| ^^^
66
|
77
= note: the only supported types are integers, `bool` and `char`
8-
= help: more complex types are supported with `#![feature(adt_const_params)]`
98

109
error: aborting due to previous error
1110

tests/ui/const-generics/fn-const-param-call.min.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,16 @@ error: using function pointers as const generic parameters is forbidden
33
|
44
LL | struct Wrapper<const F: fn() -> u32>;
55
| ^^^^^^^^^^^
6+
|
7+
= note: the only supported types are integers, `bool` and `char`
68

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

1317
error: aborting due to 2 previous errors
1418

tests/ui/const-generics/fn-const-param-infer.min.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ error: using function pointers as const generic parameters is forbidden
33
|
44
LL | struct Checked<const F: fn(usize) -> bool>;
55
| ^^^^^^^^^^^^^^^^^
6+
|
7+
= note: the only supported types are integers, `bool` and `char`
68

79
error: aborting due to previous error
810

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

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

2828
error: aborting due to 3 previous errors
2929

tests/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr

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

1919
error: aborting due to 2 previous errors
2020

tests/ui/const-generics/issues/issue-56445-1.min.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ LL | struct Bug<'a, const S: &'a str>(PhantomData<&'a ()>);
1313
| ^^^^^^^
1414
|
1515
= note: the only supported types are integers, `bool` and `char`
16-
= help: more complex types are supported with `#![feature(adt_const_params)]`
16+
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
1717

1818
error: aborting due to 2 previous errors
1919

tests/ui/const-generics/issues/issue-62878.min.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ LL | fn foo<const N: usize, const A: [u8; N]>() {}
1313
| ^^^^^^^
1414
|
1515
= note: the only supported types are integers, `bool` and `char`
16-
= help: more complex types are supported with `#![feature(adt_const_params)]`
16+
= help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
1717

1818
error: aborting due to 2 previous errors
1919

tests/ui/const-generics/issues/issue-63322-forbid-dyn.min.stderr

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

1010
error: aborting due to previous error
1111

tests/ui/const-generics/issues/issue-68615-adt.min.stderr

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

1010
error: aborting due to previous error
1111

tests/ui/const-generics/issues/issue-68615-array.min.stderr

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

1010
error: aborting due to previous error
1111

0 commit comments

Comments
 (0)