Skip to content

Commit 38feebd

Browse files
committed
Split part of adt_const_params into unsized_const_params
1 parent fd94759 commit 38feebd

File tree

132 files changed

+848
-476
lines changed

Some content is hidden

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

132 files changed

+848
-476
lines changed

compiler/rustc_builtin_macros/src/deriving/bounds.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ 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_),
4242
skip_path_as_bound: false,
4343
needs_copy_as_bound_if_packed: false,
4444
additional_bounds: vec![ty::Ty::Path(path_std!(cmp::Eq))],

compiler/rustc_feature/src/unstable.rs

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

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

+57-20
Original file line numberDiff line numberDiff line change
@@ -934,12 +934,43 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(),
934934
ty,
935935
tcx.require_lang_item(LangItem::ConstParamTy, Some(hir_ty.span)),
936936
);
937-
wfcx.register_bound(
938-
ObligationCause::new(hir_ty.span, param.def_id, ObligationCauseCode::Misc),
939-
wfcx.param_env,
940-
ty,
941-
tcx.require_lang_item(LangItem::Sized, Some(hir_ty.span)),
942-
);
937+
if !tcx.features().unsized_const_parameters {
938+
let cause = ObligationCause::new(
939+
hir_ty.span,
940+
param.def_id,
941+
ObligationCauseCode::Misc,
942+
);
943+
944+
wfcx.register_bound(
945+
cause.clone(),
946+
wfcx.param_env,
947+
ty,
948+
tcx.require_lang_item(LangItem::Sized, Some(hir_ty.span)),
949+
);
950+
951+
// FIXME(unsized_const_parameters): Just remove the `ConstParamTy` impl on references
952+
// and make `const N: [u8]` work then we can get rid of this.
953+
if let Ok(ty) = wfcx.structurally_normalize(&cause, wfcx.param_env, ty)
954+
&& let ty::Ref(..) = ty.kind()
955+
{
956+
let mut diag = tcx.dcx().struct_span_err(
957+
hir_ty.span,
958+
"references are forbidden as the type of const generic parameters",
959+
);
960+
diag.note("only types that implement `ConstParamTy` are permitted");
961+
962+
tcx.disabled_nightly_features(
963+
&mut diag,
964+
Some(param.hir_id),
965+
[(
966+
" references to implement the `ConstParamTy` trait".into(),
967+
sym::unsized_const_parameters,
968+
)],
969+
);
970+
971+
return Err(diag.emit());
972+
}
973+
}
943974
Ok(())
944975
})
945976
} else {
@@ -962,6 +993,8 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(),
962993
diag.note("the only supported types are integers, `bool` and `char`");
963994

964995
let cause = ObligationCause::misc(hir_ty.span, param.def_id);
996+
let adt_const_params_feature_string =
997+
" more complex and user defined types".to_string();
965998
let may_suggest_feature = match type_allowed_to_implement_const_param_ty(
966999
tcx,
9671000
tcx.param_env(param.def_id),
@@ -971,9 +1004,17 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(),
9711004
// Can never implement `ConstParamTy`, don't suggest anything.
9721005
Err(
9731006
ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed
974-
| ConstParamTyImplementationError::InvalidInnerTyOfBuiltinTy(..)
975-
| ConstParamTyImplementationError::TypeNotSized,
976-
) => false,
1007+
| ConstParamTyImplementationError::InvalidInnerTyOfBuiltinTy(..),
1008+
) => None,
1009+
Err(ConstParamTyImplementationError::UnsizedConstParamsFeatureRequired) => {
1010+
Some(vec![
1011+
(adt_const_params_feature_string, sym::adt_const_params),
1012+
(
1013+
" references to implement the `ConstParamTy` trait".into(),
1014+
sym::unsized_const_parameters,
1015+
),
1016+
])
1017+
}
9771018
// May be able to implement `ConstParamTy`. Only emit the feature help
9781019
// if the type is local, since the user may be able to fix the local type.
9791020
Err(ConstParamTyImplementationError::InfrigingFields(..)) => {
@@ -993,20 +1034,16 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(),
9931034
}
9941035
}
9951036

996-
ty_is_local(ty)
1037+
ty_is_local(ty).then_some(vec![(
1038+
adt_const_params_feature_string,
1039+
sym::adt_const_params,
1040+
)])
9971041
}
9981042
// Implments `ConstParamTy`, suggest adding the feature to enable.
999-
Ok(..) => true,
1043+
Ok(..) => Some(vec![(adt_const_params_feature_string, sym::adt_const_params)]),
10001044
};
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-
);
1045+
if let Some(features) = may_suggest_feature {
1046+
tcx.disabled_nightly_features(&mut diag, Some(param.hir_id), features);
10101047
}
10111048

10121049
Err(diag.emit())

compiler/rustc_hir_analysis/src/coherence/builtin.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ fn visit_implementation_of_const_param_ty(checker: &Checker<'_>) -> Result<(), E
162162
span,
163163
))
164164
}
165-
Err(ConstParamTyImplementationError::TypeNotSized) => {
165+
Err(ConstParamTyImplementationError::UnsizedConstParamsFeatureRequired) => {
166166
let span = tcx.hir().expect_item(impl_did).expect_impl().self_ty.span;
167167
Err(tcx.dcx().emit_err(errors::ConstParamTyImplOnUnsized { span }))
168168
}

compiler/rustc_span/src/symbol.rs

+2
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,
@@ -2000,6 +2001,7 @@ symbols! {
20002001
unsafe_no_drop_flag,
20012002
unsafe_pin_internals,
20022003
unsize,
2004+
unsized_const_parameters,
20032005
unsized_fn_params,
20042006
unsized_locals,
20052007
unsized_tuple_coercion,

compiler/rustc_trait_selection/src/traits/misc.rs

+19-9
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,
@@ -91,7 +92,7 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
9192
self_type: Ty<'tcx>,
9293
parent_cause: ObligationCause<'tcx>,
9394
) -> Result<(), ConstParamTyImplementationError<'tcx>> {
94-
{
95+
if !tcx.features().unsized_const_parameters {
9596
// Check for sizedness before recursing into ADT fields so that if someone tries to write:
9697
// ```rust
9798
// #[derive(ConstParamTy)]
@@ -110,7 +111,7 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
110111
);
111112

112113
if !ocx.select_all_or_error().is_empty() {
113-
return Err(ConstParamTyImplementationError::TypeNotSized);
114+
return Err(ConstParamTyImplementationError::UnsizedConstParamsFeatureRequired);
114115
}
115116
};
116117

@@ -121,14 +122,23 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
121122
// - Have structural equality
122123
ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Char => return Ok(()),
123124

124-
ty::Ref(..) => return Err(ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed),
125+
// Handle types gated under `feature(unsized_const_parameters)`
126+
// FIXME(unsized_const_parameters): Make `const N: [u8]` work then forbid references
127+
ty::Slice(inner_ty) | ty::Ref(_, inner_ty, Mutability::Not)
128+
if tcx.features().unsized_const_parameters =>
129+
{
130+
vec![inner_ty]
131+
}
132+
ty::Str if tcx.features().unsized_const_parameters => {
133+
vec![Ty::new_slice(tcx, tcx.types.u8)]
134+
}
135+
ty::Str | ty::Slice(..) | ty::Ref(_, _, Mutability::Not) => {
136+
return Err(ConstParamTyImplementationError::UnsizedConstParamsFeatureRequired);
137+
}
125138

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],
129-
// `str` morally acts like a newtype around `[u8]`
130-
ty::Str => vec![Ty::new_slice(tcx, tcx.types.u8)],
139+
ty::Array(inner_ty, _) => vec![inner_ty],
131140

141+
// `str` morally acts like a newtype around `[u8]`
132142
ty::Tuple(inner_tys) => inner_tys.into_iter().collect(),
133143

134144
ty::Adt(adt, args) if adt.is_enum() || adt.is_struct() => {

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_parameters)]
251252
#![feature(unsized_fn_params)]
252253
#![feature(with_negative_coherence)]
253254
// tidy-alphabetical-end

library/core/src/marker.rs

+15-15
Original file line numberDiff line numberDiff line change
@@ -975,13 +975,17 @@ pub trait PointerLike {}
975975
/// that all fields are also `ConstParamTy`, which implies that recursively, all fields
976976
/// are `StructuralPartialEq`.
977977
#[lang = "const_param_ty"]
978-
#[unstable(feature = "adt_const_params", issue = "95174")]
978+
#[unstable(feature = "unsized_const_parameters", issue = "95174")]
979979
#[diagnostic::on_unimplemented(message = "`{Self}` can't be used as a const parameter type")]
980980
#[allow(multiple_supertrait_upcastable)]
981-
pub trait ConstParamTy: StructuralPartialEq + Eq {}
981+
// We name this differently than the derive macro so that the `adt_const_params` can
982+
// be used independently of `unsized_const_parameters` without requiring a full path
983+
// to the derive macro every time it is used. This should be renamed on stabilization.
984+
pub trait ConstParamTy_: StructuralPartialEq + Eq {}
982985

983986
/// Derive macro generating an impl of the trait `ConstParamTy`.
984987
#[rustc_builtin_macro]
988+
#[allow_internal_unstable(unsized_const_parameters)]
985989
#[unstable(feature = "adt_const_params", issue = "95174")]
986990
pub macro ConstParamTy($item:item) {
987991
/* compiler built-in */
@@ -990,26 +994,22 @@ pub macro ConstParamTy($item:item) {
990994
// FIXME(adt_const_params): handle `ty::FnDef`/`ty::Closure`
991995
marker_impls! {
992996
#[unstable(feature = "adt_const_params", issue = "95174")]
993-
ConstParamTy for
997+
ConstParamTy_ for
994998
usize, u8, u16, u32, u64, u128,
995999
isize, i8, i16, i32, i64, i128,
9961000
bool,
9971001
char,
9981002
(),
999-
{T: ConstParamTy, const N: usize} [T; N],
1003+
{T: ConstParamTy_, const N: usize} [T; N],
10001004
}
10011005

1002-
#[unstable(feature = "adt_const_params", issue = "95174")]
1003-
#[rustc_reservation_impl = "types that are not `Sized` are not supported as the type of a const generic parameter"]
1004-
impl<T> ConstParamTy for [T] {}
1005-
1006-
#[unstable(feature = "adt_const_params", issue = "95174")]
1007-
#[rustc_reservation_impl = "types that are not `Sized` are not supported as the type of a const generic parameter"]
1008-
impl ConstParamTy for str {}
1009-
1010-
#[unstable(feature = "adt_const_params", issue = "95174")]
1011-
#[rustc_reservation_impl = "references are not supported as the type of a const generic parameter"]
1012-
impl<T: ?Sized> ConstParamTy for &T {}
1006+
marker_impls! {
1007+
#[unstable(feature = "unsized_const_parameters", issue = "95174")]
1008+
ConstParamTy_ for
1009+
str,
1010+
{T: ConstParamTy_} [T],
1011+
{T: ConstParamTy_ + ?Sized} &T,
1012+
}
10131013

10141014
/// A common trait implemented by all function pointers.
10151015
#[unstable(

library/core/src/mem/transmutability.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::marker::ConstParamTy;
1+
use crate::marker::ConstParamTy_;
22

33
/// Are values of a type transmutable into values of another type?
44
///
@@ -39,7 +39,7 @@ pub struct Assume {
3939
}
4040

4141
#[unstable(feature = "transmutability", issue = "99571")]
42-
impl ConstParamTy for Assume {}
42+
impl ConstParamTy_ for Assume {}
4343

4444
impl Assume {
4545
/// Do not assume that *you* have ensured any safety properties are met.

library/core/src/tuple.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// See core/src/primitive_docs.rs for documentation.
22

33
use crate::cmp::Ordering::{self, *};
4-
use crate::marker::ConstParamTy;
4+
use crate::marker::ConstParamTy_;
55
use crate::marker::StructuralPartialEq;
66

77
// Recursive macro for implementing n-ary tuple functions and operations
@@ -50,7 +50,7 @@ macro_rules! tuple_impls {
5050
maybe_tuple_doc! {
5151
$($T)+ @
5252
#[unstable(feature = "structural_match", issue = "31434")]
53-
impl<$($T: ConstParamTy),+> ConstParamTy for ($($T,)+)
53+
impl<$($T: ConstParamTy_),+> ConstParamTy_ for ($($T,)+)
5454
{}
5555
}
5656

tests/crashes/119299.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,24 @@
22
#![feature(adt_const_params)]
33
#![allow(incomplete_features)]
44

5-
use std::marker::ConstParamTy;
5+
use std::marker::ConstParamTy_;
66

77
#[derive(Eq, PartialEq)]
88
struct ConstStrU(*const u8, usize);
99

10-
impl ConstParamTy for &'static ConstStrU {}
10+
impl ConstParamTy_ for &'static ConstStrU {}
1111

1212
impl ConstStrU {
13-
const fn from_bytes(bytes: &'static [u8]) -> Self {
14-
Self(bytes.as_ptr(), bytes.len())
15-
}
13+
const fn from_bytes(bytes: &'static [u8]) -> Self {
14+
Self(bytes.as_ptr(), bytes.len())
15+
}
1616
}
1717

1818
const fn chars_s<const S: &'static ConstStrU>() -> [char; 3] {
19-
['a','b','c']
19+
['a', 'b', 'c']
2020
}
2121

2222
fn main() {
23-
const A: &'static ConstStrU = &ConstStrU::from_bytes(b"abc");
24-
chars_s::<A>();
23+
const A: &'static ConstStrU = &ConstStrU::from_bytes(b"abc");
24+
chars_s::<A>();
2525
}

tests/mir-opt/issue_99325.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// skip-filecheck
22
// EMIT_MIR_FOR_EACH_BIT_WIDTH
33

4-
#![feature(adt_const_params)]
4+
#![feature(adt_const_params, unsized_const_parameters)]
55
#![allow(incomplete_features)]
66

77
pub fn function_with_bytes<const BYTES: &'static [u8; 4]>() -> &'static [u8] {

tests/ui/coherence/negative-coherence/regions-in-canonical.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
//@ check-pass
22

3-
#![feature(adt_const_params)]
4-
//~^ WARN the feature `adt_const_params` is incomplete
3+
#![feature(adt_const_params, unsized_const_parameters)]
4+
//~^ WARN the feature `unsized_const_parameters` is incomplete
55
#![feature(with_negative_coherence, negative_impls)]
66

77
pub trait A<const K: &'static str> {}
88
pub trait C {}
99

10-
1110
struct W<T>(T);
1211

1312
// Negative coherence:

0 commit comments

Comments
 (0)