diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index a559211e5d467..5b4ef693e5ee4 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -577,6 +577,9 @@ declare_features! ( (unstable, marker_trait_attr, "1.30.0", Some(29864)), /// Enable mgca `type const` syntax before expansion. (incomplete, mgca_type_const_syntax, "1.95.0", Some(132980)), + /// Allows additional const parameter types, such as [u8; 10] or user defined types. + /// User defined types must not have fields more private than the type itself. + (unstable, min_adt_const_params, "CURRENT_RUSTC_VERSION", Some(154042)), /// Enables the generic const args MVP (only bare paths, not arbitrary computation). (incomplete, min_generic_const_args, "1.84.0", Some(132980)), /// A minimal, sound subset of specialization intended to be used by the diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 96d0a56f901ad..52cb061177c1f 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -842,7 +842,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &ty::GenericParamDef) -> Result<(), Er let span = tcx.def_span(param.def_id); let def_id = param.def_id.expect_local(); - if tcx.features().adt_const_params() { + if tcx.features().adt_const_params() || tcx.features().min_adt_const_params() { enter_wf_checking_ctxt(tcx, tcx.local_parent(def_id), |wfcx| { wfcx.register_bound( ObligationCause::new(span, def_id, ObligationCauseCode::ConstParam(ty)), diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index abd5c024ef79c..61453e5328d5f 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -184,6 +184,26 @@ fn visit_implementation_of_const_param_ty(checker: &Checker<'_>) -> Result<(), E return Ok(()); } + if !tcx.features().adt_const_params() { + match *self_type.kind() { + ty::Adt(adt, _) if adt.is_struct() => { + let struct_vis = tcx.visibility(adt.did()); + for variant in adt.variants() { + for field in &variant.fields { + if !field.vis.is_at_least(struct_vis, tcx) { + let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span; + return Err(tcx + .dcx() + .emit_err(errors::ConstParamTyFieldVisMismatch { span })); + } + } + } + } + + _ => {} + } + } + let cause = traits::ObligationCause::misc(DUMMY_SP, impl_did); match type_allowed_to_implement_const_param_ty(tcx, param_env, self_type, cause) { Ok(()) => Ok(()), diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index fcd4cb938bf73..c55b9e384c55b 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -317,6 +317,14 @@ pub(crate) struct ConstParamTyImplOnNonAdt { pub span: Span, } +#[derive(Diagnostic)] +#[diag("the trait `ConstParamTy` may not be implemented for this struct")] +pub(crate) struct ConstParamTyFieldVisMismatch { + #[primary_span] + #[label("struct fields are less visible than the struct")] + pub span: Span, +} + #[derive(Diagnostic)] #[diag("at least one trait is required for an object type", code = E0224)] pub(crate) struct TraitObjectDeclaredWithNoTraits { diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index cf048231bd607..8512a4b93e863 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1773,7 +1773,8 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { // const generics. Of course, `Struct` and `Enum` may contain ty params, too, but the // benefits of including them here outweighs the small number of false positives. Some(Res::Def(DefKind::Struct | DefKind::Enum, _)) - if self.r.tcx.features().adt_const_params() => + if self.r.tcx.features().adt_const_params() + || self.r.tcx.features().min_adt_const_params() => { Applicability::MaybeIncorrect } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 738c9b975fd00..5ca5d79bd940e 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1241,6 +1241,7 @@ symbols! { meta_sized, metadata_type, mgca_type_const_syntax, + min_adt_const_params, min_const_fn, min_const_generics, min_const_unsafe_fn, diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index c79e8fc4060c1..688371ff808ab 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -1088,7 +1088,7 @@ pub trait ConstParamTy_: StructuralPartialEq + Eq {} /// Derive macro generating an impl of the trait `ConstParamTy`. #[rustc_builtin_macro] #[allow_internal_unstable(const_param_ty_trait)] -#[unstable(feature = "adt_const_params", issue = "95174")] +#[unstable(feature = "min_adt_const_params", issue = "154042", implied_by = "adt_const_params")] pub macro ConstParamTy($item:item) { /* compiler built-in */ } diff --git a/tests/ui/const-generics/min_adt_const_params/const_param_ty-on-adt-without-adt-gate.rs b/tests/ui/const-generics/min_adt_const_params/const_param_ty-on-adt-without-adt-gate.rs new file mode 100644 index 0000000000000..9b5c62c412995 --- /dev/null +++ b/tests/ui/const-generics/min_adt_const_params/const_param_ty-on-adt-without-adt-gate.rs @@ -0,0 +1,17 @@ +//! Ensure we enforce `min_adt_const_params` rules on any adt `ConstParamTy_` +//! implementation unless `adt_const_params` feature is used. +#![allow(incomplete_features)] +#![feature(const_param_ty_trait)] + +use std::marker::ConstParamTy_; + +#[derive(PartialEq, Eq)] +pub struct Fumo { + cirno: i32, + pub(crate) reimu: i32 +} + +impl ConstParamTy_ for Fumo {} + //~^ ERROR: the trait `ConstParamTy` may not be implemented for this struct + +fn main() {} diff --git a/tests/ui/const-generics/min_adt_const_params/const_param_ty-on-adt-without-adt-gate.stderr b/tests/ui/const-generics/min_adt_const_params/const_param_ty-on-adt-without-adt-gate.stderr new file mode 100644 index 0000000000000..784c6f0937d8a --- /dev/null +++ b/tests/ui/const-generics/min_adt_const_params/const_param_ty-on-adt-without-adt-gate.stderr @@ -0,0 +1,8 @@ +error: the trait `ConstParamTy` may not be implemented for this struct + --> $DIR/const_param_ty-on-adt-without-adt-gate.rs:14:24 + | +LL | impl ConstParamTy_ for Fumo {} + | ^^^^ struct fields are less visible than the struct + +error: aborting due to 1 previous error + diff --git a/tests/ui/const-generics/min_adt_const_params/min_adt_const_params-gate-fail.rs b/tests/ui/const-generics/min_adt_const_params/min_adt_const_params-gate-fail.rs new file mode 100644 index 0000000000000..bb18a3314f4c6 --- /dev/null +++ b/tests/ui/const-generics/min_adt_const_params/min_adt_const_params-gate-fail.rs @@ -0,0 +1,35 @@ +//! Ensure min_adt_const_params enforce +//! struct's visibility on its fields +#![allow(incomplete_features)] +#![feature(min_adt_const_params)] +#![feature(const_param_ty_trait)] + +use std::marker::ConstParamTy_; + +#[derive(PartialEq, Eq)] +pub struct Meowl { + pub public: i32, + private: i32 +} + +#[derive(PartialEq, Eq)] +pub struct Meowl2 { + pub a: i32, + pub b: i32 +} + +#[derive(PartialEq, Eq)] +pub(crate) struct Meowl3 { + pub(crate) a: i32, + pub b: i32 +} + +impl ConstParamTy_ for Meowl {} + //~^ ERROR the trait `ConstParamTy` may not be implemented for this struct +impl ConstParamTy_ for Meowl2 {} +impl ConstParamTy_ for Meowl3 {} + +fn something() {} +fn something2() {} + +fn main() {} diff --git a/tests/ui/const-generics/min_adt_const_params/min_adt_const_params-gate-fail.stderr b/tests/ui/const-generics/min_adt_const_params/min_adt_const_params-gate-fail.stderr new file mode 100644 index 0000000000000..fec610f061c20 --- /dev/null +++ b/tests/ui/const-generics/min_adt_const_params/min_adt_const_params-gate-fail.stderr @@ -0,0 +1,8 @@ +error: the trait `ConstParamTy` may not be implemented for this struct + --> $DIR/min_adt_const_params-gate-fail.rs:27:24 + | +LL | impl ConstParamTy_ for Meowl {} + | ^^^^^ struct fields are less visible than the struct + +error: aborting due to 1 previous error + diff --git a/tests/ui/const-generics/min_adt_const_params/min_adt_const_params-gate.rs b/tests/ui/const-generics/min_adt_const_params/min_adt_const_params-gate.rs new file mode 100644 index 0000000000000..e33f5b0fac99b --- /dev/null +++ b/tests/ui/const-generics/min_adt_const_params/min_adt_const_params-gate.rs @@ -0,0 +1,18 @@ +// gate-test-min_adt_const_params +//@run-pass +#![feature(min_adt_const_params, const_param_ty_trait)] +#![allow(incomplete_features, dead_code)] + +use std::marker::ConstParamTy_; + +#[derive(PartialEq, Eq)] +pub struct Meowl { + pub public: i32, + pub also_public: i32 +} + +impl ConstParamTy_ for Meowl {} + +fn meoow() {} + +fn main() {} diff --git a/tests/ui/const-generics/min_adt_const_params/type-field-more-visible-than-type.rs b/tests/ui/const-generics/min_adt_const_params/type-field-more-visible-than-type.rs new file mode 100644 index 0000000000000..cedec86675f3e --- /dev/null +++ b/tests/ui/const-generics/min_adt_const_params/type-field-more-visible-than-type.rs @@ -0,0 +1,12 @@ +//@run-pass +#![feature(min_adt_const_params)] + +use std::marker::ConstParamTy; + +#[derive(ConstParamTy, Eq, PartialEq)] +#[allow(dead_code)] +struct Foo { + pub field: u32, +} + +fn main() {}