Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_hir_analysis/src/coherence/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
10 changes: 10 additions & 0 deletions compiler/rustc_hir_analysis/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
17 changes: 16 additions & 1 deletion compiler/rustc_trait_selection/src/traits/misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand All @@ -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> {
Expand Down Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
@@ -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

Original file line number Diff line number Diff line change
@@ -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))]
Copy link
Copy Markdown
Contributor Author

@zedddie zedddie Apr 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure now, should it go into const-generics/adt_const_params or its fine as it is in min 🧐

View changes since the review

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

min is ok :3

#![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() {}
Loading