Rollup merge of #155675 - zedddie:disallow-non_exhaustive-adt-const-params, r=BoxyUwU

Disallow non_exhaustive structs and enums with non_exhaustive variants from implementing `ConstParamTy`

tracking issue rust-lang/rust#154042

r? BoxyUwU
This commit is contained in:
Jonathan Brouwer
2026-04-27 19:54:48 +02:00
committed by GitHub
6 changed files with 86 additions and 1 deletions
@@ -911,6 +911,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &ty::GenericParamDef) -> Result<(), Er
// Can never implement `ConstParamTy`, don't suggest anything.
Err(
ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed
| ConstParamTyImplementationError::NonExhaustive(..)
| ConstParamTyImplementationError::InvalidInnerTyOfBuiltinTy(..),
) => None,
Err(ConstParamTyImplementationError::UnsizedConstParamsFeatureRequired) => {
@@ -221,6 +221,12 @@ fn visit_implementation_of_const_param_ty(checker: &Checker<'_>) -> Result<(), E
let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
Err(tcx.dcx().emit_err(errors::ConstParamTyImplOnNonAdt { span }))
}
Err(ConstParamTyImplementationError::NonExhaustive(attr_span)) => {
let defn_span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
Err(tcx
.dcx()
.emit_err(errors::ConstParamTyImplOnNonExhaustive { defn_span, attr_span }))
}
Err(ConstParamTyImplementationError::InvalidInnerTyOfBuiltinTy(infringing_tys)) => {
let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
Err(infringing_fields_error(
+10
View File
@@ -317,6 +317,16 @@ pub(crate) struct ConstParamTyImplOnNonAdt {
pub span: Span,
}
#[derive(Diagnostic)]
#[diag("the trait `ConstParamTy` may not be implemented for this type")]
pub(crate) struct ConstParamTyImplOnNonExhaustive {
#[primary_span]
#[label("non exhaustive const params are forbidden")]
pub defn_span: Span,
#[label("caused by this attribute")]
pub attr_span: Span,
}
#[derive(Diagnostic)]
#[diag("the trait `ConstParamTy` may not be implemented for this struct")]
pub(crate) struct ConstParamTyFieldVisMismatch {
@@ -4,8 +4,9 @@ use hir::LangItem;
use rustc_ast::Mutability;
use rustc_hir as hir;
use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
use rustc_middle::bug;
use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt, TypeVisitableExt, TypingMode, Unnormalized};
use rustc_span::sym;
use rustc_span::{Span, sym};
use crate::regions::InferCtxtRegionExt;
use crate::traits::{self, FulfillmentError, Obligation, ObligationCause};
@@ -22,6 +23,7 @@ pub enum ConstParamTyImplementationError<'tcx> {
InvalidInnerTyOfBuiltinTy(Vec<(Ty<'tcx>, InfringingFieldsReason<'tcx>)>),
InfrigingFields(Vec<(&'tcx ty::FieldDef, Ty<'tcx>, InfringingFieldsReason<'tcx>)>),
NotAnAdtOrBuiltinAllowed,
NonExhaustive(Span),
}
pub enum InfringingFieldsReason<'tcx> {
@@ -124,6 +126,19 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
ty::Tuple(inner_tys) => inner_tys.into_iter().collect(),
ty::Adt(adt, args) if adt.is_enum() || adt.is_struct() => {
if !tcx.features().adt_const_params() {
for variant in adt.variants() {
if variant.is_field_list_non_exhaustive() {
let attr_span = match hir::find_attr!(tcx, variant.def_id, hir::attrs::AttributeKind::NonExhaustive(span) => *span)
{
Some(sp) => sp,
None => bug!("non_exhaustive variant missing NonExhaustive attribute"),
};
return Err(ConstParamTyImplementationError::NonExhaustive(attr_span));
}
}
}
all_fields_implement_trait(
tcx,
param_env,
@@ -0,0 +1,23 @@
error: the trait `ConstParamTy` may not be implemented for this type
--> $DIR/forbid-non_exhaustive-const-param-ty.rs:13:12
|
LL | #[non_exhaustive]
| ----------------- caused by this attribute
LL | #[derive(PartialEq, Eq, ConstParamTy)]
| ------------ in this derive macro expansion
LL | pub struct Miow;
| ^^^^ non exhaustive const params are forbidden
error: the trait `ConstParamTy` may not be implemented for this type
--> $DIR/forbid-non_exhaustive-const-param-ty.rs:17:10
|
LL | #[derive(PartialEq, Eq, ConstParamTy)]
| ------------ in this derive macro expansion
LL | pub enum Enumiow {
| ^^^^^^^ non exhaustive const params are forbidden
LL |
LL | #[non_exhaustive] NonExhaustiveThingie,
| ----------------- caused by this attribute
error: aborting due to 2 previous errors
@@ -0,0 +1,30 @@
//! Ensure that non exhaustive structs and enums with non exhaustive variants
//! aren't allowed to implement ConstParamTy under min_adt_const_params feature
//@ revisions: full min
//@[full] check-pass
#![cfg_attr(min, feature(min_adt_const_params))]
#![cfg_attr(full, feature(adt_const_params))]
#![allow(incomplete_features)]
use std::marker::ConstParamTy;
#[non_exhaustive]
#[derive(PartialEq, Eq, ConstParamTy)]
pub struct Miow;
//[min]~^ ERROR: the trait `ConstParamTy` may not be implemented for this type
#[derive(PartialEq, Eq, ConstParamTy)]
pub enum Enumiow {
//[min]~^ ERROR: the trait `ConstParamTy` may not be implemented for this type
#[non_exhaustive] NonExhaustiveThingie,
ExhaustiveThingie,
}
#[non_exhaustive]
#[derive(PartialEq, Eq, ConstParamTy)]
pub enum EnumiowButFine {
ExhaustiveThingie,
AlsoExhaustiveThingie,
}
fn main() {}