From 6dc21b71cfd8e5246e7953cf64ea5ee6a19ceb3d Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sat, 15 Apr 2017 04:14:44 +0300 Subject: [PATCH] rustc: use monomorphic const_eval for cross-crate enum discriminants. --- src/librustc/ty/mod.rs | 47 ++++++++++- src/librustc_const_eval/eval.rs | 11 ++- src/librustc_driver/driver.rs | 2 + .../persist/dirty_clean.rs | 11 +++ src/librustc_metadata/decoder.rs | 24 ++---- src/librustc_metadata/encoder.rs | 46 +++++++++-- src/librustc_metadata/schema.rs | 13 ++- src/librustc_trans/adt.rs | 20 ++--- src/librustc_trans/disr.rs | 82 ------------------- src/librustc_trans/lib.rs | 2 - src/librustc_trans/mir/constant.rs | 13 +-- src/librustc_trans/mir/rvalue.rs | 6 +- src/librustc_trans/mir/statement.rs | 3 +- src/test/incremental/hashes/enum_defs.rs | 8 +- 14 files changed, 139 insertions(+), 149 deletions(-) delete mode 100644 src/librustc_trans/disr.rs diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 09eacb40aef7e..0b5434f50e830 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1660,7 +1660,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { self.variants.iter().map(move |v| { let mut discr = prev_discr.map_or(initial, |d| d.wrap_incr()); if let VariantDiscr::Explicit(expr_did) = v.discr { - match tcx.maps.monomorphic_const_eval.borrow()[&expr_did] { + match queries::monomorphic_const_eval::get(tcx, DUMMY_SP, expr_did) { Ok(ConstVal::Integral(v)) => { discr = v; } @@ -1673,6 +1673,51 @@ impl<'a, 'gcx, 'tcx> AdtDef { }) } + /// Compute the discriminant value used by a specific variant. + /// Unlike `discriminants`, this is (amortized) constant-time, + /// only doing at most one query for evaluating an explicit + /// discriminant (the last one before the requested variant), + /// assuming there are no constant-evaluation errors there. + pub fn discriminant_for_variant(&self, + tcx: TyCtxt<'a, 'gcx, 'tcx>, + variant_index: usize) + -> ConstInt { + let repr_type = self.repr.discr_type(); + let mut explicit_value = repr_type.initial_discriminant(tcx.global_tcx()); + let mut explicit_index = variant_index; + loop { + match self.variants[explicit_index].discr { + ty::VariantDiscr::Relative(0) => break, + ty::VariantDiscr::Relative(distance) => { + explicit_index -= distance; + } + ty::VariantDiscr::Explicit(expr_did) => { + match queries::monomorphic_const_eval::get(tcx, DUMMY_SP, expr_did) { + Ok(ConstVal::Integral(v)) => { + explicit_value = v; + break; + } + _ => { + explicit_index -= 1; + } + } + } + } + } + let discr = explicit_value.to_u128_unchecked() + .wrapping_add((variant_index - explicit_index) as u128); + match repr_type { + attr::UnsignedInt(ty) => { + ConstInt::new_unsigned_truncating(discr, ty, + tcx.sess.target.uint_type) + } + attr::SignedInt(ty) => { + ConstInt::new_signed_truncating(discr as i128, ty, + tcx.sess.target.int_type) + } + } + } + pub fn destructor(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option { queries::adt_destructor::get(tcx, DUMMY_SP, self.did) } diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index bf8085be31c44..9c5a669bef0d9 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -804,10 +804,13 @@ pub fn provide(providers: &mut Providers) { fn monomorphic_const_eval<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> EvalResult<'tcx> { - ty::queries::mir_const_qualif::get(tcx, DUMMY_SP, def_id); let cx = ConstContext::with_tables(tcx, tcx.item_tables(def_id)); - let id = tcx.hir.as_local_node_id(def_id).unwrap(); - let body = tcx.hir.body_owned_by(id); - cx.eval(&tcx.hir.body(body).value) + let body = if let Some(id) = tcx.hir.as_local_node_id(def_id) { + ty::queries::mir_const_qualif::get(tcx, DUMMY_SP, def_id); + tcx.hir.body(tcx.hir.body_owned_by(id)) + } else { + tcx.sess.cstore.maybe_get_item_body(tcx, def_id).unwrap() + }; + cx.eval(&body.value) } diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index c856ea505ffe8..7632b40ab4f9e 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -900,6 +900,8 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, let mut extern_providers = ty::maps::Providers::default(); cstore::provide(&mut extern_providers); ty::provide_extern(&mut extern_providers); + // FIXME(eddyb) get rid of this once we replace const_eval with miri. + rustc_const_eval::provide(&mut extern_providers); TyCtxt::create_and_enter(sess, local_providers, diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index af5c1f05bd1fc..b73b3e161f9b5 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -266,6 +266,17 @@ impl<'a, 'tcx, 'm> intravisit::Visitor<'tcx> for DirtyCleanMetadataVisitor<'a, ' intravisit::walk_item(self, item); } + fn visit_variant(&mut self, + variant: &'tcx hir::Variant, + generics: &'tcx hir::Generics, + parent_id: ast::NodeId) { + if let Some(e) = variant.node.disr_expr { + self.check_item(e.node_id, variant.span); + } + + intravisit::walk_variant(self, variant, generics, parent_id); + } + fn visit_variant_data(&mut self, variant_data: &'tcx hir::VariantData, _: ast::Name, diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index d2512ff602a84..fac6079529e30 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -511,11 +511,7 @@ impl<'a, 'tcx> CrateMetadata { def } - fn get_variant(&self, - item: &Entry<'tcx>, - index: DefIndex, - tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> (ty::VariantDef, Option) { + fn get_variant(&self, item: &Entry, index: DefIndex) -> ty::VariantDef { let data = match item.kind { EntryKind::Variant(data) | EntryKind::Struct(data, _) | @@ -523,13 +519,7 @@ impl<'a, 'tcx> CrateMetadata { _ => bug!(), }; - if let ty::VariantDiscr::Explicit(def_id) = data.discr { - // The original crate wouldn't have compiled if this is missing. - let result = Ok(data.evaluated_discr.unwrap()); - tcx.maps.monomorphic_const_eval.borrow_mut().insert(def_id, result); - } - - (ty::VariantDef { + ty::VariantDef { did: self.local_def_id(data.struct_ctor.unwrap_or(index)), name: self.item_name(index), fields: item.children.decode(self).map(|index| { @@ -542,7 +532,7 @@ impl<'a, 'tcx> CrateMetadata { }).collect(), discr: data.discr, ctor_kind: data.ctor_kind, - }, data.struct_ctor) + } } pub fn get_adt_def(&self, @@ -561,15 +551,11 @@ impl<'a, 'tcx> CrateMetadata { item.children .decode(self) .map(|index| { - let (variant, struct_ctor) = - self.get_variant(&self.entry(index), index, tcx); - assert_eq!(struct_ctor, None); - variant + self.get_variant(&self.entry(index), index) }) .collect() } else { - let (variant, _struct_ctor) = self.get_variant(&item, item_id, tcx); - vec![variant] + vec![self.get_variant(&item, item_id)] }; let (kind, repr) = match item.kind { EntryKind::Enum(repr) => (ty::AdtKind::Enum, repr), diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 0e204695e8f22..ce9f0a73fe2b8 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -269,12 +269,6 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> { let data = VariantData { ctor_kind: variant.ctor_kind, discr: variant.discr, - evaluated_discr: match variant.discr { - ty::VariantDiscr::Explicit(def_id) => { - ty::queries::monomorphic_const_eval::get(tcx, DUMMY_SP, def_id).ok() - } - ty::VariantDiscr::Relative(_) => None - }, struct_ctor: None, }; @@ -408,7 +402,6 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> { let data = VariantData { ctor_kind: variant.ctor_kind, discr: variant.discr, - evaluated_discr: None, struct_ctor: Some(def_id.index), }; @@ -697,7 +690,6 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> { EntryKind::Struct(self.lazy(&VariantData { ctor_kind: variant.ctor_kind, discr: variant.discr, - evaluated_discr: None, struct_ctor: struct_ctor, }), repr_options) } @@ -708,7 +700,6 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> { EntryKind::Union(self.lazy(&VariantData { ctor_kind: variant.ctor_kind, discr: variant.discr, - evaluated_discr: None, struct_ctor: None, }), repr_options) } @@ -1037,6 +1028,17 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'tcx> { EntryBuilder::encode_info_for_foreign_item, (def_id, ni)); } + fn visit_variant(&mut self, + v: &'tcx hir::Variant, + g: &'tcx hir::Generics, + id: ast::NodeId) { + intravisit::walk_variant(self, v, g, id); + + if let Some(discr) = v.node.disr_expr { + let def_id = self.index.tcx.hir.body_owner_def_id(discr); + self.index.record(def_id, EntryBuilder::encode_info_for_embedded_const, def_id); + } + } fn visit_generics(&mut self, generics: &'tcx hir::Generics) { intravisit::walk_generics(self, generics); self.index.encode_info_for_generics(generics); @@ -1160,6 +1162,32 @@ impl<'a, 'b: 'a, 'tcx: 'b> EntryBuilder<'a, 'b, 'tcx> { } } + fn encode_info_for_embedded_const(&mut self, def_id: DefId) -> Entry<'tcx> { + debug!("EntryBuilder::encode_info_for_embedded_const({:?})", def_id); + let tcx = self.tcx; + let id = tcx.hir.as_local_node_id(def_id).unwrap(); + let body = tcx.hir.body_owned_by(id); + + Entry { + kind: EntryKind::Const(ty::queries::mir_const_qualif::get(tcx, DUMMY_SP, def_id)), + visibility: self.lazy(&ty::Visibility::Public), + span: self.lazy(&tcx.def_span(def_id)), + attributes: LazySeq::empty(), + children: LazySeq::empty(), + stability: None, + deprecation: None, + + ty: Some(self.encode_item_type(def_id)), + inherent_impls: LazySeq::empty(), + variances: LazySeq::empty(), + generics: Some(self.encode_generics(def_id)), + predicates: Some(self.encode_predicates(def_id)), + + ast: Some(self.encode_body(body)), + mir: self.encode_mir(def_id), + } + } + fn encode_attributes(&mut self, attrs: &[ast::Attribute]) -> LazySeq { // NOTE: This must use lazy_seq_from_slice(), not lazy_seq() because // we really on the HashStable specialization for [Attribute] diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 6cd35f1335ed7..2f2e0e125aea5 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -15,7 +15,6 @@ use rustc::hir; use rustc::hir::def::{self, CtorKind}; use rustc::hir::def_id::{DefIndex, DefId}; use rustc::ich::StableHashingContext; -use rustc::middle::const_val::ConstVal; use rustc::middle::cstore::{DepKind, LinkagePreference, NativeLibrary}; use rustc::middle::lang_items; use rustc::mir; @@ -271,9 +270,9 @@ pub enum EntryKind<'tcx> { Type, Enum(ReprOptions), Field, - Variant(Lazy>), - Struct(Lazy>, ReprOptions), - Union(Lazy>, ReprOptions), + Variant(Lazy), + Struct(Lazy, ReprOptions), + Union(Lazy, ReprOptions), Fn(Lazy), ForeignFn(Lazy), Mod(Lazy), @@ -374,20 +373,18 @@ pub struct FnData { impl_stable_hash_for!(struct FnData { constness, arg_names }); #[derive(RustcEncodable, RustcDecodable)] -pub struct VariantData<'tcx> { +pub struct VariantData { pub ctor_kind: CtorKind, pub discr: ty::VariantDiscr, - pub evaluated_discr: Option>, /// If this is a struct's only variant, this /// is the index of the "struct ctor" item. pub struct_ctor: Option, } -impl_stable_hash_for!(struct VariantData<'tcx> { +impl_stable_hash_for!(struct VariantData { ctor_kind, discr, - evaluated_discr, struct_ctor }); diff --git a/src/librustc_trans/adt.rs b/src/librustc_trans/adt.rs index 0fe180253b5b8..87ca410dece0d 100644 --- a/src/librustc_trans/adt.rs +++ b/src/librustc_trans/adt.rs @@ -41,8 +41,6 @@ //! used unboxed and any field can have pointers (including mutable) //! taken to it, implementing them for Rust seems difficult. -use super::Disr; - use std; use llvm::{ValueRef, True, IntEQ, IntNE}; @@ -347,31 +345,31 @@ fn load_discr(bcx: &Builder, ity: layout::Integer, ptr: ValueRef, /// Set the discriminant for a new value of the given case of the given /// representation. -pub fn trans_set_discr<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, t: Ty<'tcx>, val: ValueRef, to: Disr) { +pub fn trans_set_discr<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, t: Ty<'tcx>, val: ValueRef, to: u64) { let l = bcx.ccx.layout_of(t); match *l { layout::CEnum{ discr, min, max, .. } => { - assert_discr_in_range(Disr(min), Disr(max), to); - bcx.store(C_integral(Type::from_integer(bcx.ccx, discr), to.0, true), + assert_discr_in_range(min, max, to); + bcx.store(C_integral(Type::from_integer(bcx.ccx, discr), to, true), val, None); } layout::General{ discr, .. } => { - bcx.store(C_integral(Type::from_integer(bcx.ccx, discr), to.0, true), + bcx.store(C_integral(Type::from_integer(bcx.ccx, discr), to, true), bcx.struct_gep(val, 0), None); } layout::Univariant { .. } | layout::UntaggedUnion { .. } | layout::Vector { .. } => { - assert_eq!(to, Disr(0)); + assert_eq!(to, 0); } layout::RawNullablePointer { nndiscr, .. } => { - if to.0 != nndiscr { + if to != nndiscr { let llptrty = val_ty(val).element_type(); bcx.store(C_null(llptrty), val, None); } } layout::StructWrappedNullablePointer { nndiscr, ref discrfield, ref nonnull, .. } => { - if to.0 != nndiscr { + if to != nndiscr { if target_sets_discr_via_memset(bcx) { // Issue #34427: As workaround for LLVM bug on // ARM, use memset of 0 on whole struct rather @@ -397,7 +395,7 @@ fn target_sets_discr_via_memset<'a, 'tcx>(bcx: &Builder<'a, 'tcx>) -> bool { bcx.sess().target.target.arch == "arm" || bcx.sess().target.target.arch == "aarch64" } -pub fn assert_discr_in_range(min: Disr, max: Disr, discr: Disr) { +pub fn assert_discr_in_range(min: D, max: D, discr: D) { if min <= max { assert!(min <= discr && discr <= max) } else { @@ -415,7 +413,7 @@ fn roundup(x: u64, a: u32) -> u64 { let a = a as u64; ((x + (a - 1)) / a) * a } /// (Not to be confused with `common::const_get_elt`, which operates on /// raw LLVM-level structs and arrays.) pub fn const_get_field<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>, - val: ValueRef, _discr: Disr, + val: ValueRef, ix: usize) -> ValueRef { let l = ccx.layout_of(t); match *l { diff --git a/src/librustc_trans/disr.rs b/src/librustc_trans/disr.rs deleted file mode 100644 index a940faac83877..0000000000000 --- a/src/librustc_trans/disr.rs +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use rustc::middle::const_val::ConstVal; -use rustc::ty::{self, TyCtxt}; -use rustc_const_math::ConstInt; - -#[derive(Debug, Eq, PartialEq, Copy, Clone)] -pub struct Disr(pub u64); - -impl Disr { - pub fn for_variant(tcx: TyCtxt, - def: &ty::AdtDef, - variant_index: usize) -> Self { - let mut explicit_index = variant_index; - let mut explicit_value = Disr(0); - loop { - match def.variants[explicit_index].discr { - ty::VariantDiscr::Relative(0) => break, - ty::VariantDiscr::Relative(distance) => { - explicit_index -= distance; - } - ty::VariantDiscr::Explicit(expr_did) => { - match tcx.maps.monomorphic_const_eval.borrow()[&expr_did] { - Ok(ConstVal::Integral(v)) => { - explicit_value = Disr::from(v); - break; - } - _ => { - explicit_index -= 1; - } - } - } - } - } - let distance = variant_index - explicit_index; - explicit_value.wrapping_add(Disr::from(distance)) - } - - pub fn wrapping_add(self, other: Self) -> Self { - Disr(self.0.wrapping_add(other.0)) - } -} - -impl ::std::ops::BitAnd for Disr { - type Output = Disr; - fn bitand(self, other: Self) -> Self { - Disr(self.0 & other.0) - } -} - -impl From for Disr { - fn from(i: ConstInt) -> Disr { - // FIXME: what if discr has 128 bit discr? - Disr(i.to_u128_unchecked() as u64) - } -} - -impl From for Disr { - fn from(i: usize) -> Disr { - Disr(i as u64) - } -} - -impl PartialOrd for Disr { - fn partial_cmp(&self, other: &Disr) -> Option<::std::cmp::Ordering> { - self.0.partial_cmp(&other.0) - } -} - -impl Ord for Disr { - fn cmp(&self, other: &Disr) -> ::std::cmp::Ordering { - self.0.cmp(&other.0) - } -} diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index c5383fceb8787..be214a0f6143c 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -67,7 +67,6 @@ pub use rustc::lint; pub use rustc::util; pub use base::trans_crate; -pub use disr::Disr; pub mod back { pub use rustc::hir::svh; @@ -118,7 +117,6 @@ mod consts; mod context; mod debuginfo; mod declare; -mod disr; mod glue; mod intrinsic; mod machine; diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index 37d2b1952f494..8bce0cf85c08b 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -22,7 +22,7 @@ use rustc::ty::layout::{self, LayoutTyper}; use rustc::ty::cast::{CastTy, IntTy}; use rustc::ty::subst::{Kind, Substs, Subst}; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; -use {abi, adt, base, Disr, machine}; +use {abi, adt, base, machine}; use callee; use builder::Builder; use common::{self, CrateContext, const_get_elt, val_ty}; @@ -428,7 +428,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { } mir::ProjectionElem::Field(ref field, _) => { let llprojected = adt::const_get_field(self.ccx, tr_base.ty, base.llval, - Disr(0), field.index()); + field.index()); let llextra = if is_sized { ptr::null_mut() } else { @@ -987,13 +987,14 @@ fn trans_const<'a, 'tcx>( layout::CEnum { discr: d, min, max, .. } => { let discr = match *kind { mir::AggregateKind::Adt(adt_def, _, _, _) => { - Disr::for_variant(ccx.tcx(), adt_def, variant_index) + adt_def.discriminant_for_variant(ccx.tcx(), variant_index) + .to_u128_unchecked() as u64 }, - _ => Disr(0), + _ => 0, }; assert_eq!(vals.len(), 0); - adt::assert_discr_in_range(Disr(min), Disr(max), discr); - C_integral(Type::from_integer(ccx, d), discr.0, true) + adt::assert_discr_in_range(min, max, discr); + C_integral(Type::from_integer(ccx, d), discr, true) } layout::General { discr: d, ref variants, .. } => { let variant = &variants[variant_index]; diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs index aa41720d717a7..98e9008f829f6 100644 --- a/src/librustc_trans/mir/rvalue.rs +++ b/src/librustc_trans/mir/rvalue.rs @@ -28,7 +28,6 @@ use type_::Type; use type_of; use tvec; use value::Value; -use Disr; use super::MirContext; use super::constant::const_scalar_checked_binop; @@ -107,9 +106,10 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { mir::Rvalue::Aggregate(ref kind, ref operands) => { match *kind { mir::AggregateKind::Adt(adt_def, variant_index, substs, active_field_index) => { - let disr = Disr::for_variant(bcx.tcx(), adt_def, variant_index); + let discr = adt_def.discriminant_for_variant(bcx.tcx(), variant_index) + .to_u128_unchecked() as u64; let dest_ty = dest.ty.to_ty(bcx.tcx()); - adt::trans_set_discr(&bcx, dest_ty, dest.llval, disr); + adt::trans_set_discr(&bcx, dest_ty, dest.llval, discr); for (i, operand) in operands.iter().enumerate() { let op = self.trans_operand(&bcx, operand); // Do not generate stores and GEPis for zero-sized fields. diff --git a/src/librustc_trans/mir/statement.rs b/src/librustc_trans/mir/statement.rs index 29a0648c8f8f8..52c2afca4748b 100644 --- a/src/librustc_trans/mir/statement.rs +++ b/src/librustc_trans/mir/statement.rs @@ -18,7 +18,6 @@ use builder::Builder; use super::MirContext; use super::LocalRef; use super::super::adt; -use super::super::disr::Disr; impl<'a, 'tcx> MirContext<'a, 'tcx> { pub fn trans_statement(&mut self, @@ -65,7 +64,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { adt::trans_set_discr(&bcx, ty, lvalue_transed.llval, - Disr::from(variant_index)); + variant_index as u64); bcx } mir::StatementKind::StorageLive(ref lvalue) => { diff --git a/src/test/incremental/hashes/enum_defs.rs b/src/test/incremental/hashes/enum_defs.rs index 37c6ef58f5e56..0f734683b60e5 100644 --- a/src/test/incremental/hashes/enum_defs.rs +++ b/src/test/incremental/hashes/enum_defs.rs @@ -27,6 +27,7 @@ #![allow(warnings)] #![feature(rustc_attrs)] +#![feature(stmt_expr_attributes)] #![crate_type="rlib"] @@ -125,9 +126,12 @@ enum EnumChangeValueCStyleVariant0 { enum EnumChangeValueCStyleVariant0 { Variant1, - #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail2")] #[rustc_metadata_clean(cfg="cfail3")] - Variant2 = 22, + Variant2 = + #[rustc_metadata_dirty(cfg="cfail2")] + #[rustc_metadata_clean(cfg="cfail3")] + 22, } #[cfg(cfail1)]