Skip to content

Commit 2c29f0c

Browse files
committed
typeck/wfcheck: require that explicit enum discriminants const-evaluate succesfully.
1 parent 50c63e4 commit 2c29f0c

File tree

1 file changed

+35
-2
lines changed

1 file changed

+35
-2
lines changed

src/librustc_typeck/check/wfcheck.rs

+35-2
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,23 @@ fn check_type_defn<'tcx, F>(
411411
ObligationCauseCode::MiscObligation,
412412
)
413413
}
414+
415+
// Explicit `enum` discriminant values must const-evaluate successfully.
416+
if let Some(discr_def_id) = variant.explicit_discr {
417+
let discr_substs =
418+
InternalSubsts::identity_for_item(fcx.tcx, discr_def_id.to_def_id());
419+
420+
let cause = traits::ObligationCause::new(
421+
fcx.tcx.def_span(discr_def_id),
422+
fcx.body_id,
423+
traits::MiscObligation,
424+
);
425+
fcx.register_predicate(traits::Obligation::new(
426+
cause,
427+
fcx.param_env,
428+
ty::Predicate::ConstEvaluatable(discr_def_id.to_def_id(), discr_substs),
429+
));
430+
}
414431
}
415432

416433
check_where_clauses(tcx, fcx, item.span, def_id.to_def_id(), None);
@@ -1287,8 +1304,14 @@ impl ParItemLikeVisitor<'tcx> for CheckTypeWellFormedVisitor<'tcx> {
12871304
///////////////////////////////////////////////////////////////////////////
12881305
// ADT
12891306

1307+
// FIXME(eddyb) replace this with getting fields/discriminants through `ty::AdtDef`.
12901308
struct AdtVariant<'tcx> {
1309+
/// Types of fields in the variant, that must be well-formed.
12911310
fields: Vec<AdtField<'tcx>>,
1311+
1312+
/// Explicit discriminant of this variant (e.g. `A = 123`),
1313+
/// that must evaluate to a constant value.
1314+
explicit_discr: Option<LocalDefId>,
12921315
}
12931316

12941317
struct AdtField<'tcx> {
@@ -1297,6 +1320,7 @@ struct AdtField<'tcx> {
12971320
}
12981321

12991322
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1323+
// FIXME(eddyb) replace this with getting fields through `ty::AdtDef`.
13001324
fn non_enum_variant(&self, struct_def: &hir::VariantData<'_>) -> AdtVariant<'tcx> {
13011325
let fields = struct_def
13021326
.fields()
@@ -1309,11 +1333,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13091333
AdtField { ty: field_ty, span: field.span }
13101334
})
13111335
.collect();
1312-
AdtVariant { fields }
1336+
AdtVariant { fields, explicit_discr: None }
13131337
}
13141338

13151339
fn enum_variants(&self, enum_def: &hir::EnumDef<'_>) -> Vec<AdtVariant<'tcx>> {
1316-
enum_def.variants.iter().map(|variant| self.non_enum_variant(&variant.data)).collect()
1340+
enum_def
1341+
.variants
1342+
.iter()
1343+
.map(|variant| AdtVariant {
1344+
fields: self.non_enum_variant(&variant.data).fields,
1345+
explicit_discr: variant
1346+
.disr_expr
1347+
.map(|explicit_discr| self.tcx.hir().local_def_id(explicit_discr.hir_id)),
1348+
})
1349+
.collect()
13171350
}
13181351

13191352
fn impl_implied_bounds(&self, impl_def_id: DefId, span: Span) -> Vec<Ty<'tcx>> {

0 commit comments

Comments
 (0)