Skip to content

Commit 33a1ed1

Browse files
committed
disallow non_exhaustive structs and enums with non_exhaustive variants from implementing ConstParamTy
1 parent e22c616 commit 33a1ed1

6 files changed

Lines changed: 86 additions & 1 deletion

File tree

compiler/rustc_hir_analysis/src/check/wfcheck.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -911,6 +911,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &ty::GenericParamDef) -> Result<(), Er
911911
// Can never implement `ConstParamTy`, don't suggest anything.
912912
Err(
913913
ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed
914+
| ConstParamTyImplementationError::NonExhaustive(..)
914915
| ConstParamTyImplementationError::InvalidInnerTyOfBuiltinTy(..),
915916
) => None,
916917
Err(ConstParamTyImplementationError::UnsizedConstParamsFeatureRequired) => {

compiler/rustc_hir_analysis/src/coherence/builtin.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,12 @@ fn visit_implementation_of_const_param_ty(checker: &Checker<'_>) -> Result<(), E
221221
let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
222222
Err(tcx.dcx().emit_err(errors::ConstParamTyImplOnNonAdt { span }))
223223
}
224+
Err(ConstParamTyImplementationError::NonExhaustive(attr_span)) => {
225+
let defn_span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
226+
Err(tcx
227+
.dcx()
228+
.emit_err(errors::ConstParamTyImplOnNonExhaustive { defn_span, attr_span }))
229+
}
224230
Err(ConstParamTyImplementationError::InvalidInnerTyOfBuiltinTy(infringing_tys)) => {
225231
let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span;
226232
Err(infringing_fields_error(

compiler/rustc_hir_analysis/src/errors.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,16 @@ pub(crate) struct ConstParamTyImplOnNonAdt {
317317
pub span: Span,
318318
}
319319

320+
#[derive(Diagnostic)]
321+
#[diag("the trait `ConstParamTy` may not be implemented for this type")]
322+
pub(crate) struct ConstParamTyImplOnNonExhaustive {
323+
#[primary_span]
324+
#[label("non exhaustive const params are forbidden")]
325+
pub defn_span: Span,
326+
#[label("caused by this attribute")]
327+
pub attr_span: Span,
328+
}
329+
320330
#[derive(Diagnostic)]
321331
#[diag("the trait `ConstParamTy` may not be implemented for this struct")]
322332
pub(crate) struct ConstParamTyFieldVisMismatch {

compiler/rustc_trait_selection/src/traits/misc.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ use hir::LangItem;
44
use rustc_ast::Mutability;
55
use rustc_hir as hir;
66
use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
7+
use rustc_middle::bug;
78
use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt, TypeVisitableExt, TypingMode, Unnormalized};
8-
use rustc_span::sym;
9+
use rustc_span::{Span, sym};
910

1011
use crate::regions::InferCtxtRegionExt;
1112
use crate::traits::{self, FulfillmentError, Obligation, ObligationCause};
@@ -22,6 +23,7 @@ pub enum ConstParamTyImplementationError<'tcx> {
2223
InvalidInnerTyOfBuiltinTy(Vec<(Ty<'tcx>, InfringingFieldsReason<'tcx>)>),
2324
InfrigingFields(Vec<(&'tcx ty::FieldDef, Ty<'tcx>, InfringingFieldsReason<'tcx>)>),
2425
NotAnAdtOrBuiltinAllowed,
26+
NonExhaustive(Span),
2527
}
2628

2729
pub enum InfringingFieldsReason<'tcx> {
@@ -124,6 +126,19 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>(
124126
ty::Tuple(inner_tys) => inner_tys.into_iter().collect(),
125127

126128
ty::Adt(adt, args) if adt.is_enum() || adt.is_struct() => {
129+
if !tcx.features().adt_const_params() {
130+
for variant in adt.variants() {
131+
if variant.is_field_list_non_exhaustive() {
132+
let attr_span = match hir::find_attr!(tcx, variant.def_id, hir::attrs::AttributeKind::NonExhaustive(span) => *span)
133+
{
134+
Some(sp) => sp,
135+
None => bug!("non_exhaustive variant missing NonExhaustive attribute"),
136+
};
137+
return Err(ConstParamTyImplementationError::NonExhaustive(attr_span));
138+
}
139+
}
140+
}
141+
127142
all_fields_implement_trait(
128143
tcx,
129144
param_env,
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
error: the trait `ConstParamTy` may not be implemented for this type
2+
--> $DIR/forbid-non_exhaustive-const-param-ty.rs:13:12
3+
|
4+
LL | #[non_exhaustive]
5+
| ----------------- caused by this attribute
6+
LL | #[derive(PartialEq, Eq, ConstParamTy)]
7+
| ------------ in this derive macro expansion
8+
LL | pub struct Miow;
9+
| ^^^^ non exhaustive const params are forbidden
10+
11+
error: the trait `ConstParamTy` may not be implemented for this type
12+
--> $DIR/forbid-non_exhaustive-const-param-ty.rs:17:10
13+
|
14+
LL | #[derive(PartialEq, Eq, ConstParamTy)]
15+
| ------------ in this derive macro expansion
16+
LL | pub enum Enumiow {
17+
| ^^^^^^^ non exhaustive const params are forbidden
18+
LL |
19+
LL | #[non_exhaustive] NonExhaustiveThingie,
20+
| ----------------- caused by this attribute
21+
22+
error: aborting due to 2 previous errors
23+
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//! Ensure that non exhaustive structs and enums with non exhaustive variants
2+
//! aren't allowed to implement ConstParamTy under min_adt_const_params feature
3+
//@ revisions: full min
4+
//@[full] check-pass
5+
#![cfg_attr(min, feature(min_adt_const_params))]
6+
#![cfg_attr(full, feature(adt_const_params))]
7+
#![allow(incomplete_features)]
8+
9+
use std::marker::ConstParamTy;
10+
11+
#[non_exhaustive]
12+
#[derive(PartialEq, Eq, ConstParamTy)]
13+
pub struct Miow;
14+
//[min]~^ ERROR: the trait `ConstParamTy` may not be implemented for this type
15+
16+
#[derive(PartialEq, Eq, ConstParamTy)]
17+
pub enum Enumiow {
18+
//[min]~^ ERROR: the trait `ConstParamTy` may not be implemented for this type
19+
#[non_exhaustive] NonExhaustiveThingie,
20+
ExhaustiveThingie,
21+
}
22+
23+
#[non_exhaustive]
24+
#[derive(PartialEq, Eq, ConstParamTy)]
25+
pub enum EnumiowButFine {
26+
ExhaustiveThingie,
27+
AlsoExhaustiveThingie,
28+
}
29+
30+
fn main() {}

0 commit comments

Comments
 (0)