Skip to content

Commit d0c11bf

Browse files
committed
Split part of adt_const_params into unsized_const_params
1 parent 42cc42b commit d0c11bf

File tree

140 files changed

+1127
-556
lines changed

Some content is hidden

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

140 files changed

+1127
-556
lines changed

compiler/rustc_builtin_macros/src/deriving/bounds.rs

+38-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,44 @@ pub(crate) fn expand_deriving_const_param_ty(
3838
) {
3939
let trait_def = TraitDef {
4040
span,
41-
path: path_std!(marker::ConstParamTy),
41+
path: path_std!(marker::ConstParamTy_),
42+
skip_path_as_bound: false,
43+
needs_copy_as_bound_if_packed: false,
44+
additional_bounds: vec![ty::Ty::Path(path_std!(cmp::Eq))],
45+
supports_unions: false,
46+
methods: Vec::new(),
47+
associated_types: Vec::new(),
48+
is_const,
49+
};
50+
51+
trait_def.expand(cx, mitem, item, push);
52+
53+
let trait_def = TraitDef {
54+
span,
55+
path: path_std!(marker::UnsizedConstParamTy),
56+
skip_path_as_bound: false,
57+
needs_copy_as_bound_if_packed: false,
58+
additional_bounds: vec![ty::Ty::Path(path_std!(cmp::Eq))],
59+
supports_unions: false,
60+
methods: Vec::new(),
61+
associated_types: Vec::new(),
62+
is_const,
63+
};
64+
65+
trait_def.expand(cx, mitem, item, push);
66+
}
67+
68+
pub(crate) fn expand_deriving_unsized_const_param_ty(
69+
cx: &ExtCtxt<'_>,
70+
span: Span,
71+
mitem: &MetaItem,
72+
item: &Annotatable,
73+
push: &mut dyn FnMut(Annotatable),
74+
is_const: bool,
75+
) {
76+
let trait_def = TraitDef {
77+
span,
78+
path: path_std!(marker::UnsizedConstParamTy),
4279
skip_path_as_bound: false,
4380
needs_copy_as_bound_if_packed: false,
4481
additional_bounds: vec![ty::Ty::Path(path_std!(cmp::Eq))],

compiler/rustc_builtin_macros/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
118118
Clone: clone::expand_deriving_clone,
119119
Copy: bounds::expand_deriving_copy,
120120
ConstParamTy: bounds::expand_deriving_const_param_ty,
121+
UnsizedConstParamTy: bounds::expand_deriving_unsized_const_param_ty,
121122
Debug: debug::expand_deriving_debug,
122123
Default: default::expand_deriving_default,
123124
Eq: eq::expand_deriving_eq,

compiler/rustc_error_codes/src/error_codes/E0771.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ allowed.
66
Erroneous code example:
77

88
```compile_fail,E0770
9-
#![feature(adt_const_params)]
9+
#![feature(adt_const_params, unsized_const_params)]
1010
1111
fn function_with_str<'a, const STRING: &'a str>() {} // error!
1212
```
@@ -15,7 +15,7 @@ To fix this issue, the lifetime in the const generic need to be changed to
1515
`'static`:
1616

1717
```
18-
#![feature(adt_const_params)]
18+
#![feature(adt_const_params, unsized_const_params)]
1919
2020
fn function_with_str<const STRING: &'static str>() {} // ok!
2121
```

compiler/rustc_feature/src/unstable.rs

+3
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,9 @@ declare_features! (
630630
(unstable, unsafe_attributes, "1.80.0", Some(123757)),
631631
/// Allows unsafe on extern declarations and safety qualifiers over internal items.
632632
(unstable, unsafe_extern_blocks, "1.80.0", Some(123743)),
633+
/// Allows const generic parameters to be defined with types that
634+
/// are not `Sized`, e.g. `fn foo<const N: [u8]>() {`.
635+
(incomplete, unsized_const_params, "CURRENT_RUSTC_VERSION", Some(95174)),
633636
/// Allows unsized fn parameters.
634637
(internal, unsized_fn_params, "1.49.0", Some(48055)),
635638
/// Allows unsized rvalues at arguments and parameters.

compiler/rustc_hir/src/lang_items.rs

+1
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,7 @@ language_item_table! {
358358
PointerLike, sym::pointer_like, pointer_like, Target::Trait, GenericRequirement::Exact(0);
359359

360360
ConstParamTy, sym::const_param_ty, const_param_ty_trait, Target::Trait, GenericRequirement::Exact(0);
361+
UnsizedConstParamTy, sym::unsized_const_param_ty, unsized_const_param_ty_trait, Target::Trait, GenericRequirement::Exact(0);
361362

362363
Poll, sym::Poll, poll, Target::Enum, GenericRequirement::None;
363364
PollReady, sym::Ready, poll_ready_variant, Target::Variant, GenericRequirement::None;

compiler/rustc_hir_analysis/messages.ftl

+4-4
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,14 @@ hir_analysis_const_impl_for_non_const_trait =
7878
.note = marking a trait with `#[const_trait]` ensures all default method bodies are `const`
7979
.adding = adding a non-const method body in the future would be a breaking change
8080
81-
hir_analysis_const_param_ty_impl_on_unsized =
82-
the trait `ConstParamTy` may not be implemented for this type
83-
.label = type is not `Sized`
84-
8581
hir_analysis_const_param_ty_impl_on_non_adt =
8682
the trait `ConstParamTy` may not be implemented for this type
8783
.label = type is not a structure or enumeration
8884
85+
hir_analysis_const_param_ty_impl_on_unsized =
86+
the trait `ConstParamTy` may not be implemented for this type
87+
.label = type is not `Sized`
88+
8989
hir_analysis_const_specialize = cannot specialize on const impl with non-const impl
9090
9191
hir_analysis_copy_impl_on_non_adt =

compiler/rustc_hir_analysis/src/check/wfcheck.rs

+33-18
Original file line numberDiff line numberDiff line change
@@ -922,7 +922,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(),
922922
} => {
923923
let ty = tcx.type_of(param.def_id).instantiate_identity();
924924

925-
if tcx.features().adt_const_params {
925+
if tcx.features().unsized_const_params {
926926
enter_wf_checking_ctxt(tcx, hir_ty.span, param.def_id, |wfcx| {
927927
wfcx.register_bound(
928928
ObligationCause::new(
@@ -932,13 +932,21 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(),
932932
),
933933
wfcx.param_env,
934934
ty,
935-
tcx.require_lang_item(LangItem::ConstParamTy, Some(hir_ty.span)),
935+
tcx.require_lang_item(LangItem::UnsizedConstParamTy, Some(hir_ty.span)),
936936
);
937+
Ok(())
938+
})
939+
} else if tcx.features().adt_const_params {
940+
enter_wf_checking_ctxt(tcx, hir_ty.span, param.def_id, |wfcx| {
937941
wfcx.register_bound(
938-
ObligationCause::new(hir_ty.span, param.def_id, ObligationCauseCode::Misc),
942+
ObligationCause::new(
943+
hir_ty.span,
944+
param.def_id,
945+
ObligationCauseCode::ConstParam(ty),
946+
),
939947
wfcx.param_env,
940948
ty,
941-
tcx.require_lang_item(LangItem::Sized, Some(hir_ty.span)),
949+
tcx.require_lang_item(LangItem::ConstParamTy, Some(hir_ty.span)),
942950
);
943951
Ok(())
944952
})
@@ -962,18 +970,29 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(),
962970
diag.note("the only supported types are integers, `bool` and `char`");
963971

964972
let cause = ObligationCause::misc(hir_ty.span, param.def_id);
973+
let adt_const_params_feature_string =
974+
" more complex and user defined types".to_string();
965975
let may_suggest_feature = match type_allowed_to_implement_const_param_ty(
966976
tcx,
967977
tcx.param_env(param.def_id),
968978
ty,
979+
LangItem::ConstParamTy,
969980
cause,
970981
) {
971982
// Can never implement `ConstParamTy`, don't suggest anything.
972983
Err(
973984
ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed
974-
| ConstParamTyImplementationError::InvalidInnerTyOfBuiltinTy(..)
975-
| ConstParamTyImplementationError::TypeNotSized,
976-
) => false,
985+
| ConstParamTyImplementationError::InvalidInnerTyOfBuiltinTy(..),
986+
) => None,
987+
Err(ConstParamTyImplementationError::UnsizedConstParamsFeatureRequired) => {
988+
Some(vec![
989+
(adt_const_params_feature_string, sym::adt_const_params),
990+
(
991+
" references to implement the `ConstParamTy` trait".into(),
992+
sym::unsized_const_params,
993+
),
994+
])
995+
}
977996
// May be able to implement `ConstParamTy`. Only emit the feature help
978997
// if the type is local, since the user may be able to fix the local type.
979998
Err(ConstParamTyImplementationError::InfrigingFields(..)) => {
@@ -993,20 +1012,16 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(),
9931012
}
9941013
}
9951014

996-
ty_is_local(ty)
1015+
ty_is_local(ty).then_some(vec![(
1016+
adt_const_params_feature_string,
1017+
sym::adt_const_params,
1018+
)])
9971019
}
9981020
// Implments `ConstParamTy`, suggest adding the feature to enable.
999-
Ok(..) => true,
1021+
Ok(..) => Some(vec![(adt_const_params_feature_string, sym::adt_const_params)]),
10001022
};
1001-
if may_suggest_feature {
1002-
tcx.disabled_nightly_features(
1003-
&mut diag,
1004-
Some(param.hir_id),
1005-
[(
1006-
" more complex and user defined types".to_string(),
1007-
sym::adt_const_params,
1008-
)],
1009-
);
1023+
if let Some(features) = may_suggest_feature {
1024+
tcx.disabled_nightly_features(&mut diag, Some(param.hir_id), features);
10101025
}
10111026

10121027
Err(diag.emit())

compiler/rustc_hir_analysis/src/coherence/builtin.rs

+15-6
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,13 @@ pub(super) fn check_trait<'tcx>(
3636
let checker = Checker { tcx, trait_def_id, impl_def_id, impl_header };
3737
let mut res = checker.check(lang_items.drop_trait(), visit_implementation_of_drop);
3838
res = res.and(checker.check(lang_items.copy_trait(), visit_implementation_of_copy));
39-
res = res.and(
40-
checker.check(lang_items.const_param_ty_trait(), visit_implementation_of_const_param_ty),
41-
);
39+
res = res.and(checker.check(lang_items.const_param_ty_trait(), |checker| {
40+
visit_implementation_of_const_param_ty(checker, LangItem::ConstParamTy)
41+
}));
42+
res = res.and(checker.check(lang_items.unsized_const_param_ty_trait(), |checker| {
43+
visit_implementation_of_const_param_ty(checker, LangItem::UnsizedConstParamTy)
44+
}));
45+
4246
res = res.and(
4347
checker.check(lang_items.coerce_unsized_trait(), visit_implementation_of_coerce_unsized),
4448
);
@@ -122,7 +126,12 @@ fn visit_implementation_of_copy(checker: &Checker<'_>) -> Result<(), ErrorGuaran
122126
}
123127
}
124128

125-
fn visit_implementation_of_const_param_ty(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
129+
fn visit_implementation_of_const_param_ty(
130+
checker: &Checker<'_>,
131+
kind: LangItem,
132+
) -> Result<(), ErrorGuaranteed> {
133+
assert!(matches!(kind, LangItem::ConstParamTy | LangItem::UnsizedConstParamTy));
134+
126135
let tcx = checker.tcx;
127136
let header = checker.impl_header;
128137
let impl_did = checker.impl_def_id;
@@ -136,7 +145,7 @@ fn visit_implementation_of_const_param_ty(checker: &Checker<'_>) -> Result<(), E
136145
}
137146

138147
let cause = traits::ObligationCause::misc(DUMMY_SP, impl_did);
139-
match type_allowed_to_implement_const_param_ty(tcx, param_env, self_type, cause) {
148+
match type_allowed_to_implement_const_param_ty(tcx, param_env, self_type, kind, cause) {
140149
Ok(()) => Ok(()),
141150
Err(ConstParamTyImplementationError::InfrigingFields(fields)) => {
142151
let span = tcx.hir().expect_item(impl_did).expect_impl().self_ty.span;
@@ -162,7 +171,7 @@ fn visit_implementation_of_const_param_ty(checker: &Checker<'_>) -> Result<(), E
162171
span,
163172
))
164173
}
165-
Err(ConstParamTyImplementationError::TypeNotSized) => {
174+
Err(ConstParamTyImplementationError::UnsizedConstParamsFeatureRequired) => {
166175
let span = tcx.hir().expect_item(impl_did).expect_impl().self_ty.span;
167176
Err(tcx.dcx().emit_err(errors::ConstParamTyImplOnUnsized { span }))
168177
}

compiler/rustc_span/src/symbol.rs

+4
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ symbols! {
177177
CoerceUnsized,
178178
Command,
179179
ConstParamTy,
180+
ConstParamTy_,
180181
Context,
181182
Continue,
182183
Copy,
@@ -336,6 +337,7 @@ symbols! {
336337
TyKind,
337338
Unknown,
338339
Unsize,
340+
UnsizedConstParamTy,
339341
Upvars,
340342
Vec,
341343
VecDeque,
@@ -2000,6 +2002,8 @@ symbols! {
20002002
unsafe_no_drop_flag,
20012003
unsafe_pin_internals,
20022004
unsize,
2005+
unsized_const_param_ty,
2006+
unsized_const_params,
20032007
unsized_fn_params,
20042008
unsized_locals,
20052009
unsized_tuple_coercion,

compiler/rustc_trait_selection/src/traits/misc.rs

+23-33
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::regions::InferCtxtRegionExt;
44
use crate::traits::{self, FulfillmentError, ObligationCause};
55

66
use hir::LangItem;
7+
use rustc_ast::Mutability;
78
use rustc_data_structures::fx::FxIndexSet;
89
use rustc_hir as hir;
910
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
@@ -19,7 +20,7 @@ pub enum CopyImplementationError<'tcx> {
1920
}
2021

2122
pub enum ConstParamTyImplementationError<'tcx> {
22-
TypeNotSized,
23+
UnsizedConstParamsFeatureRequired,
2324
InvalidInnerTyOfBuiltinTy(Vec<(Ty<'tcx>, InfringingFieldsReason<'tcx>)>),
2425
InfrigingFields(Vec<(&'tcx ty::FieldDef, Ty<'tcx>, InfringingFieldsReason<'tcx>)>),
2526
NotAnAdtOrBuiltinAllowed,
@@ -79,40 +80,20 @@ pub fn type_allowed_to_implement_copy<'tcx>(
7980
Ok(())
8081
}
8182

82-
/// Checks that the fields of the type (an ADT) all implement `ConstParamTy`.
83+
/// Checks that the fields of the type (an ADT) all implement `(Unsized?)ConstParamTy`.
8384
///
84-
/// If fields don't implement `ConstParamTy`, return an error containing a list of
85+
/// If fields don't implement `(Unsized?)ConstParamTy`, return an error containing a list of
8586
/// those violating fields.
8687
///
8788
/// If it's not an ADT, int ty, `bool` or `char`, returns `Err(NotAnAdtOrBuiltinAllowed)`.
8889
pub fn type_allowed_to_implement_const_param_ty<'tcx>(
8990
tcx: TyCtxt<'tcx>,
9091
param_env: ty::ParamEnv<'tcx>,
9192
self_type: Ty<'tcx>,
93+
lang_item: LangItem,
9294
parent_cause: ObligationCause<'tcx>,
9395
) -> Result<(), ConstParamTyImplementationError<'tcx>> {
94-
{
95-
// Check for sizedness before recursing into ADT fields so that if someone tries to write:
96-
// ```rust
97-
// #[derive(ConstParamTy)]
98-
// struct Foo([u8])
99-
// ```
100-
// They are told that const parameter types must be sized, instead of it saying that
101-
// the trait implementation `[u8]: ConstParamTy` is not satisfied.
102-
let infcx = tcx.infer_ctxt().build();
103-
let ocx = traits::ObligationCtxt::new_with_diagnostics(&infcx);
104-
105-
ocx.register_bound(
106-
parent_cause.clone(),
107-
param_env,
108-
self_type,
109-
tcx.require_lang_item(LangItem::Sized, Some(parent_cause.span)),
110-
);
111-
112-
if !ocx.select_all_or_error().is_empty() {
113-
return Err(ConstParamTyImplementationError::TypeNotSized);
114-
}
115-
};
96+
assert!(matches!(lang_item, LangItem::ConstParamTy | LangItem::UnsizedConstParamTy));
11697

11798
let inner_tys: Vec<_> = match *self_type.kind() {
11899
// Trivially okay as these types are all:
@@ -121,14 +102,23 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
121102
// - Have structural equality
122103
ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Char => return Ok(()),
123104

124-
ty::Ref(..) => return Err(ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed),
105+
// Handle types gated under `feature(unsized_const_params)`
106+
// FIXME(unsized_const_params): Make `const N: [u8]` work then forbid references
107+
ty::Slice(inner_ty) | ty::Ref(_, inner_ty, Mutability::Not)
108+
if lang_item == LangItem::UnsizedConstParamTy =>
109+
{
110+
vec![inner_ty]
111+
}
112+
ty::Str if lang_item == LangItem::UnsizedConstParamTy => {
113+
vec![Ty::new_slice(tcx, tcx.types.u8)]
114+
}
115+
ty::Str | ty::Slice(..) | ty::Ref(_, _, Mutability::Not) => {
116+
return Err(ConstParamTyImplementationError::UnsizedConstParamsFeatureRequired);
117+
}
118+
119+
ty::Array(inner_ty, _) => vec![inner_ty],
125120

126-
// Even if we currently require const params to be `Sized` we may aswell handle them correctly
127-
// here anyway.
128-
ty::Slice(inner_ty) | ty::Array(inner_ty, _) => vec![inner_ty],
129121
// `str` morally acts like a newtype around `[u8]`
130-
ty::Str => vec![Ty::new_slice(tcx, tcx.types.u8)],
131-
132122
ty::Tuple(inner_tys) => inner_tys.into_iter().collect(),
133123

134124
ty::Adt(adt, args) if adt.is_enum() || adt.is_struct() => {
@@ -139,7 +129,7 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
139129
adt,
140130
args,
141131
parent_cause.clone(),
142-
hir::LangItem::ConstParamTy,
132+
lang_item,
143133
)
144134
.map_err(ConstParamTyImplementationError::InfrigingFields)?;
145135

@@ -159,7 +149,7 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
159149
parent_cause.clone(),
160150
param_env,
161151
inner_ty,
162-
tcx.require_lang_item(LangItem::ConstParamTy, Some(parent_cause.span)),
152+
tcx.require_lang_item(lang_item, Some(parent_cause.span)),
163153
);
164154

165155
let errors = ocx.select_all_or_error();

library/core/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,7 @@
248248
#![feature(transparent_unions)]
249249
#![feature(try_blocks)]
250250
#![feature(unboxed_closures)]
251+
#![feature(unsized_const_params)]
251252
#![feature(unsized_fn_params)]
252253
#![feature(with_negative_coherence)]
253254
// tidy-alphabetical-end

0 commit comments

Comments
 (0)