Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 23de823

Browse files
committedApr 23, 2017
Auto merge of #41408 - eddyb:poly-const-eval, r=arielb1
rustc: generalize monomorphic_const_eval to polymorphic constants. With the addition of `Substs` to the query key, we can now evaluate *and cache* polymorphic constants. Fixes #23898 by replacing the crippled explicit-discriminant-only local-crate-only `lookup_variant_by_id` with `ConstVal::Variant` which can describe variants irrespective of their discriminant. Fixes #41394 by fixing #23898 (for the original testcase) and by not looping past the first discriminant.
2 parents a941244 + 8054377 commit 23de823

File tree

23 files changed

+331
-219
lines changed

23 files changed

+331
-219
lines changed
 

‎src/librustc/dep_graph/dep_node.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ pub enum DepNode<D: Clone + Debug> {
9797
TypeckBodiesKrate,
9898
TypeckTables(D),
9999
UsedTraitImports(D),
100-
MonomorphicConstEval(D),
100+
ConstEval(D),
101101

102102
// The set of impls for a given trait. Ultimately, it would be
103103
// nice to get more fine-grained here (e.g., to include a
@@ -233,7 +233,7 @@ impl<D: Clone + Debug> DepNode<D> {
233233
InherentImpls(ref d) => op(d).map(InherentImpls),
234234
TypeckTables(ref d) => op(d).map(TypeckTables),
235235
UsedTraitImports(ref d) => op(d).map(UsedTraitImports),
236-
MonomorphicConstEval(ref d) => op(d).map(MonomorphicConstEval),
236+
ConstEval(ref d) => op(d).map(ConstEval),
237237
TraitImpls(ref d) => op(d).map(TraitImpls),
238238
TraitItems(ref d) => op(d).map(TraitItems),
239239
ReprHints(ref d) => op(d).map(ReprHints),

‎src/librustc/ich/impls_ty.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,12 @@ for ::middle::const_val::ConstVal<'tcx> {
273273
ConstVal::Bool(value) => {
274274
value.hash_stable(hcx, hasher);
275275
}
276+
ConstVal::Char(value) => {
277+
value.hash_stable(hcx, hasher);
278+
}
279+
ConstVal::Variant(def_id) => {
280+
def_id.hash_stable(hcx, hasher);
281+
}
276282
ConstVal::Function(def_id, substs) => {
277283
def_id.hash_stable(hcx, hasher);
278284
substs.hash_stable(hcx, hasher);
@@ -296,9 +302,6 @@ for ::middle::const_val::ConstVal<'tcx> {
296302
value.hash_stable(hcx, hasher);
297303
times.hash_stable(hcx, hasher);
298304
}
299-
ConstVal::Char(value) => {
300-
value.hash_stable(hcx, hasher);
301-
}
302305
}
303306
}
304307
}

‎src/librustc/middle/const_val.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,13 @@ pub enum ConstVal<'tcx> {
3838
Str(InternedString),
3939
ByteStr(Rc<Vec<u8>>),
4040
Bool(bool),
41+
Char(char),
42+
Variant(DefId),
4143
Function(DefId, &'tcx Substs<'tcx>),
4244
Struct(BTreeMap<ast::Name, ConstVal<'tcx>>),
4345
Tuple(Vec<ConstVal<'tcx>>),
4446
Array(Vec<ConstVal<'tcx>>),
4547
Repeat(Box<ConstVal<'tcx>>, u64),
46-
Char(char),
4748
}
4849

4950
impl<'tcx> ConstVal<'tcx> {
@@ -54,12 +55,13 @@ impl<'tcx> ConstVal<'tcx> {
5455
Str(_) => "string literal",
5556
ByteStr(_) => "byte string literal",
5657
Bool(_) => "boolean",
58+
Char(..) => "char",
59+
Variant(_) => "enum variant",
5760
Struct(_) => "struct",
5861
Tuple(_) => "tuple",
5962
Function(..) => "function definition",
6063
Array(..) => "array",
6164
Repeat(..) => "repeat",
62-
Char(..) => "char",
6365
}
6466
}
6567

@@ -85,7 +87,6 @@ pub enum ErrKind<'tcx> {
8587
MissingStructField,
8688
NegateOn(ConstVal<'tcx>),
8789
NotOn(ConstVal<'tcx>),
88-
CallOn(ConstVal<'tcx>),
8990

9091
NonConstPath,
9192
UnimplementedConstVal(&'static str),
@@ -145,7 +146,6 @@ impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> {
145146
CannotCast => simple!("can't cast this type"),
146147
NegateOn(ref const_val) => simple!("negate on {}", const_val.description()),
147148
NotOn(ref const_val) => simple!("not on {}", const_val.description()),
148-
CallOn(ref const_val) => simple!("call on {}", const_val.description()),
149149

150150
MissingStructField => simple!("nonexistent struct field"),
151151
NonConstPath => simple!("non-constant path in constant expression"),
@@ -227,7 +227,8 @@ pub fn eval_length(tcx: TyCtxt,
227227
{
228228
let count_expr = &tcx.hir.body(count).value;
229229
let count_def_id = tcx.hir.body_owner_def_id(count);
230-
match ty::queries::monomorphic_const_eval::get(tcx, count_expr.span, count_def_id) {
230+
let substs = Substs::empty();
231+
match ty::queries::const_eval::get(tcx, count_expr.span, (count_def_id, substs)) {
231232
Ok(Integral(Usize(count))) => {
232233
let val = count.as_u64(tcx.sess.target.uint_type);
233234
assert_eq!(val as usize as u64, val);

‎src/librustc/middle/cstore.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -249,8 +249,8 @@ pub trait CrateStore {
249249
fn load_macro(&self, did: DefId, sess: &Session) -> LoadedMacro;
250250

251251
// misc. metadata
252-
fn maybe_get_item_body<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
253-
-> Option<&'tcx hir::Body>;
252+
fn item_body<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
253+
-> &'tcx hir::Body;
254254
fn item_body_nested_bodies(&self, def: DefId) -> BTreeMap<hir::BodyId, hir::Body>;
255255
fn const_is_rvalue_promotable_to_static(&self, def: DefId) -> bool;
256256

@@ -399,9 +399,9 @@ impl CrateStore for DummyCrateStore {
399399
fn load_macro(&self, did: DefId, sess: &Session) -> LoadedMacro { bug!("load_macro") }
400400

401401
// misc. metadata
402-
fn maybe_get_item_body<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
403-
-> Option<&'tcx hir::Body> {
404-
bug!("maybe_get_item_body")
402+
fn item_body<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
403+
-> &'tcx hir::Body {
404+
bug!("item_body")
405405
}
406406
fn item_body_nested_bodies(&self, def: DefId) -> BTreeMap<hir::BodyId, hir::Body> {
407407
bug!("item_body_nested_bodies")

‎src/librustc/mir/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1307,10 +1307,11 @@ fn fmt_const_val<W: Write>(fmt: &mut W, const_val: &ConstVal) -> fmt::Result {
13071307
write!(fmt, "b\"{}\"", escaped)
13081308
}
13091309
Bool(b) => write!(fmt, "{:?}", b),
1310+
Char(c) => write!(fmt, "{:?}", c),
1311+
Variant(def_id) |
13101312
Function(def_id, _) => write!(fmt, "{}", item_path_str(def_id)),
13111313
Struct(_) | Tuple(_) | Array(_) | Repeat(..) =>
13121314
bug!("ConstVal `{:?}` should not be in MIR", const_val),
1313-
Char(c) => write!(fmt, "{:?}", c),
13141315
}
13151316
}
13161317

‎src/librustc/ty/maps.rs

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use middle::privacy::AccessLevels;
1616
use mir;
1717
use session::CompileResult;
1818
use ty::{self, CrateInherentImpls, Ty, TyCtxt};
19+
use ty::subst::Substs;
1920
use util::nodemap::NodeSet;
2021

2122
use rustc_data_structures::indexed_vec::IndexVec;
@@ -74,6 +75,15 @@ impl Key for (CrateNum, DefId) {
7475
}
7576
}
7677

78+
impl<'tcx> Key for (DefId, &'tcx Substs<'tcx>) {
79+
fn map_crate(&self) -> CrateNum {
80+
self.0.krate
81+
}
82+
fn default_span(&self, tcx: TyCtxt) -> Span {
83+
self.0.default_span(tcx)
84+
}
85+
}
86+
7787
trait Value<'tcx>: Sized {
7888
fn from_cycle_error<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Self;
7989
}
@@ -217,6 +227,13 @@ impl<'tcx> QueryDescription for queries::reachable_set<'tcx> {
217227
}
218228
}
219229

230+
impl<'tcx> QueryDescription for queries::const_eval<'tcx> {
231+
fn describe(tcx: TyCtxt, (def_id, _): (DefId, &'tcx Substs<'tcx>)) -> String {
232+
format!("const-evaluating `{}`",
233+
tcx.item_path_str(def_id))
234+
}
235+
}
236+
220237
macro_rules! define_maps {
221238
(<$tcx:tt>
222239
$($(#[$attr:meta])*
@@ -446,16 +463,17 @@ define_maps! { <'tcx>
446463
/// (Defined only for LOCAL_CRATE)
447464
pub crate_inherent_impls_overlap_check: crate_inherent_impls_dep_node(CrateNum) -> (),
448465

449-
/// Results of evaluating monomorphic constants embedded in
450-
/// other items, such as enum variant explicit discriminants.
451-
pub monomorphic_const_eval: MonomorphicConstEval(DefId) -> const_val::EvalResult<'tcx>,
466+
/// Results of evaluating const items or constants embedded in
467+
/// other items (such as enum variant explicit discriminants).
468+
pub const_eval: const_eval_dep_node((DefId, &'tcx Substs<'tcx>))
469+
-> const_val::EvalResult<'tcx>,
452470

453471
/// Performs the privacy check and computes "access levels".
454472
pub privacy_access_levels: PrivacyAccessLevels(CrateNum) -> Rc<AccessLevels>,
455473

456474
pub reachable_set: reachability_dep_node(CrateNum) -> Rc<NodeSet>,
457475

458-
pub mir_shims: mir_shim(ty::InstanceDef<'tcx>) -> &'tcx RefCell<mir::Mir<'tcx>>
476+
pub mir_shims: mir_shim_dep_node(ty::InstanceDef<'tcx>) -> &'tcx RefCell<mir::Mir<'tcx>>
459477
}
460478

461479
fn coherent_trait_dep_node((_, def_id): (CrateNum, DefId)) -> DepNode<DefId> {
@@ -470,10 +488,14 @@ fn reachability_dep_node(_: CrateNum) -> DepNode<DefId> {
470488
DepNode::Reachability
471489
}
472490

473-
fn mir_shim(instance: ty::InstanceDef) -> DepNode<DefId> {
491+
fn mir_shim_dep_node(instance: ty::InstanceDef) -> DepNode<DefId> {
474492
instance.dep_node()
475493
}
476494

477495
fn typeck_item_bodies_dep_node(_: CrateNum) -> DepNode<DefId> {
478496
DepNode::TypeckBodiesKrate
479497
}
498+
499+
fn const_eval_dep_node((def_id, _): (DefId, &Substs)) -> DepNode<DefId> {
500+
DepNode::ConstEval(def_id)
501+
}

‎src/librustc/ty/mod.rs

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1693,6 +1693,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
16931693
}
16941694
}
16951695

1696+
#[inline]
16961697
pub fn discriminants(&'a self, tcx: TyCtxt<'a, 'gcx, 'tcx>)
16971698
-> impl Iterator<Item=ConstInt> + 'a {
16981699
let repr_type = self.repr.discr_type();
@@ -1701,11 +1702,18 @@ impl<'a, 'gcx, 'tcx> AdtDef {
17011702
self.variants.iter().map(move |v| {
17021703
let mut discr = prev_discr.map_or(initial, |d| d.wrap_incr());
17031704
if let VariantDiscr::Explicit(expr_did) = v.discr {
1704-
match queries::monomorphic_const_eval::get(tcx, DUMMY_SP, expr_did) {
1705+
let substs = Substs::empty();
1706+
match queries::const_eval::get(tcx, DUMMY_SP, (expr_did, substs)) {
17051707
Ok(ConstVal::Integral(v)) => {
17061708
discr = v;
17071709
}
1708-
_ => {}
1710+
err => {
1711+
if !expr_did.is_local() {
1712+
span_bug!(tcx.def_span(expr_did),
1713+
"variant discriminant evaluation succeeded \
1714+
in its crate but failed locally: {:?}", err);
1715+
}
1716+
}
17091717
}
17101718
}
17111719
prev_discr = Some(discr);
@@ -1733,12 +1741,21 @@ impl<'a, 'gcx, 'tcx> AdtDef {
17331741
explicit_index -= distance;
17341742
}
17351743
ty::VariantDiscr::Explicit(expr_did) => {
1736-
match queries::monomorphic_const_eval::get(tcx, DUMMY_SP, expr_did) {
1744+
let substs = Substs::empty();
1745+
match queries::const_eval::get(tcx, DUMMY_SP, (expr_did, substs)) {
17371746
Ok(ConstVal::Integral(v)) => {
17381747
explicit_value = v;
17391748
break;
17401749
}
1741-
_ => {
1750+
err => {
1751+
if !expr_did.is_local() {
1752+
span_bug!(tcx.def_span(expr_did),
1753+
"variant discriminant evaluation succeeded \
1754+
in its crate but failed locally: {:?}", err);
1755+
}
1756+
if explicit_index == 0 {
1757+
break;
1758+
}
17421759
explicit_index -= 1;
17431760
}
17441761
}

‎src/librustc_const_eval/eval.rs

Lines changed: 115 additions & 149 deletions
Large diffs are not rendered by default.

‎src/librustc_const_eval/pattern.rs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ fn print_const_val(value: &ConstVal, f: &mut fmt::Formatter) -> fmt::Result {
116116
ConstVal::ByteStr(ref b) => write!(f, "{:?}", &b[..]),
117117
ConstVal::Bool(b) => write!(f, "{:?}", b),
118118
ConstVal::Char(c) => write!(f, "{:?}", c),
119+
ConstVal::Variant(_) |
119120
ConstVal::Struct(_) |
120121
ConstVal::Tuple(_) |
121122
ConstVal::Function(..) |
@@ -587,11 +588,16 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> {
587588
let substs = self.tables.node_id_item_substs(id)
588589
.unwrap_or_else(|| tcx.intern_substs(&[]));
589590
match eval::lookup_const_by_id(tcx, def_id, substs) {
590-
Some((const_expr, const_tables)) => {
591+
Some((def_id, _substs)) => {
591592
// Enter the inlined constant's tables temporarily.
592593
let old_tables = self.tables;
593-
self.tables = const_tables;
594-
let pat = self.lower_const_expr(const_expr, pat_id, span);
594+
self.tables = tcx.item_tables(def_id);
595+
let body = if let Some(id) = tcx.hir.as_local_node_id(def_id) {
596+
tcx.hir.body(tcx.hir.body_owned_by(id))
597+
} else {
598+
tcx.sess.cstore.item_body(tcx, def_id)
599+
};
600+
let pat = self.lower_const_expr(&body.value, pat_id, span);
595601
self.tables = old_tables;
596602
return pat;
597603
}
@@ -615,7 +621,12 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> {
615621
let const_cx = eval::ConstContext::with_tables(self.tcx.global_tcx(), self.tables);
616622
match const_cx.eval(expr) {
617623
Ok(value) => {
618-
PatternKind::Constant { value: value }
624+
if let ConstVal::Variant(def_id) = value {
625+
let ty = self.tables.expr_ty(expr);
626+
self.lower_variant_or_leaf(Def::Variant(def_id), ty, vec![])
627+
} else {
628+
PatternKind::Constant { value: value }
629+
}
619630
}
620631
Err(e) => {
621632
self.errors.push(PatternError::ConstEval(e));

‎src/librustc_metadata/cstore_impl.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -420,19 +420,18 @@ impl CrateStore for cstore::CStore {
420420
})
421421
}
422422

423-
fn maybe_get_item_body<'a, 'tcx>(&self,
424-
tcx: TyCtxt<'a, 'tcx, 'tcx>,
425-
def_id: DefId)
426-
-> Option<&'tcx hir::Body>
427-
{
423+
fn item_body<'a, 'tcx>(&self,
424+
tcx: TyCtxt<'a, 'tcx, 'tcx>,
425+
def_id: DefId)
426+
-> &'tcx hir::Body {
428427
if let Some(cached) = tcx.hir.get_inlined_body(def_id) {
429-
return Some(cached);
428+
return cached;
430429
}
431430

432431
self.dep_graph.read(DepNode::MetaData(def_id));
433-
debug!("maybe_get_item_body({}): inlining item", tcx.item_path_str(def_id));
432+
debug!("item_body({}): inlining item", tcx.item_path_str(def_id));
434433

435-
self.get_crate_data(def_id.krate).maybe_get_item_body(tcx, def_id.index)
434+
self.get_crate_data(def_id.krate).item_body(tcx, def_id.index)
436435
}
437436

438437
fn item_body_nested_bodies(&self, def: DefId) -> BTreeMap<hir::BodyId, hir::Body> {

‎src/librustc_metadata/decoder.rs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -750,16 +750,15 @@ impl<'a, 'tcx> CrateMetadata {
750750
}
751751
}
752752

753-
pub fn maybe_get_item_body(&self,
754-
tcx: TyCtxt<'a, 'tcx, 'tcx>,
755-
id: DefIndex)
756-
-> Option<&'tcx hir::Body> {
757-
if self.is_proc_macro(id) { return None; }
758-
self.entry(id).ast.map(|ast| {
759-
let def_id = self.local_def_id(id);
760-
let body = ast.decode(self).body.decode(self);
761-
tcx.hir.intern_inlined_body(def_id, body)
762-
})
753+
pub fn item_body(&self,
754+
tcx: TyCtxt<'a, 'tcx, 'tcx>,
755+
id: DefIndex)
756+
-> &'tcx hir::Body {
757+
assert!(!self.is_proc_macro(id));
758+
let ast = self.entry(id).ast.unwrap();
759+
let def_id = self.local_def_id(id);
760+
let body = ast.decode(self).body.decode(self);
761+
tcx.hir.intern_inlined_body(def_id, body)
763762
}
764763

765764
pub fn item_body_tables(&self,

‎src/librustc_mir/hair/cx/expr.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -593,7 +593,8 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
593593
hir::ExprRepeat(ref v, count) => {
594594
let c = &cx.tcx.hir.body(count).value;
595595
let def_id = cx.tcx.hir.body_owner_def_id(count);
596-
let count = match ty::queries::monomorphic_const_eval::get(cx.tcx, c.span, def_id) {
596+
let substs = Substs::empty();
597+
let count = match ty::queries::const_eval::get(cx.tcx, c.span, (def_id, substs)) {
597598
Ok(ConstVal::Integral(ConstInt::Usize(u))) => u,
598599
Ok(other) => bug!("constant evaluation of repeat count yielded {:?}", other),
599600
Err(s) => cx.fatal_const_eval_err(&s, c.span, "expression")

‎src/librustc_trans/mir/constant.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -100,15 +100,13 @@ impl<'tcx> Const<'tcx> {
100100
ConstVal::Integral(ref i) => return Const::from_constint(ccx, i),
101101
ConstVal::Str(ref v) => C_str_slice(ccx, v.clone()),
102102
ConstVal::ByteStr(ref v) => consts::addr_of(ccx, C_bytes(ccx, v), 1, "byte_str"),
103+
ConstVal::Char(c) => C_integral(Type::char(ccx), c as u64, false),
104+
ConstVal::Function(..) => C_null(type_of::type_of(ccx, ty)),
105+
ConstVal::Variant(_) |
103106
ConstVal::Struct(_) | ConstVal::Tuple(_) |
104107
ConstVal::Array(..) | ConstVal::Repeat(..) => {
105108
bug!("MIR must not use `{:?}` (aggregates are expanded to MIR rvalues)", cv)
106109
}
107-
ConstVal::Function(..) => {
108-
let llty = type_of::type_of(ccx, ty);
109-
return Const::new(C_null(llty), ty);
110-
}
111-
ConstVal::Char(c) => C_integral(Type::char(ccx), c as u64, false),
112110
};
113111

114112
assert!(!ty.has_erasable_regions());

‎src/librustc_typeck/collect.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -555,7 +555,8 @@ fn convert_enum_variant_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
555555
let wrapped_discr = prev_discr.map_or(initial, |d| d.wrap_incr());
556556
prev_discr = Some(if let Some(e) = variant.node.disr_expr {
557557
let expr_did = tcx.hir.local_def_id(e.node_id);
558-
let result = ty::queries::monomorphic_const_eval::get(tcx, variant.span, expr_did);
558+
let substs = Substs::empty();
559+
let result = ty::queries::const_eval::get(tcx, variant.span, (expr_did, substs));
559560

560561
// enum variant evaluation happens before the global constant check
561562
// so we need to report the real error

‎src/librustdoc/clean/inline.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -487,7 +487,7 @@ impl hir::print::PpAnn for InlinedConst {
487487
}
488488

489489
fn print_inlined_const(cx: &DocContext, did: DefId) -> String {
490-
let body = cx.tcx.sess.cstore.maybe_get_item_body(cx.tcx, did).unwrap();
490+
let body = cx.tcx.sess.cstore.item_body(cx.tcx, did);
491491
let inlined = InlinedConst {
492492
nested_bodies: cx.tcx.sess.cstore.item_body_nested_bodies(did)
493493
};

‎src/test/compile-fail/const-call.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,4 @@ fn f(x: usize) -> usize {
1717
fn main() {
1818
let _ = [0; f(2)];
1919
//~^ ERROR calls in constants are limited to constant functions
20-
//~| ERROR constant evaluation error [E0080]
21-
//~| non-constant path in constant expression
2220
}

‎src/test/compile-fail/const-pattern-not-const-evaluable.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,22 @@
1010

1111
#![feature(const_fn)]
1212

13+
#[derive(PartialEq, Eq)]
1314
enum Cake {
1415
BlackForest,
1516
Marmor,
1617
}
1718
use Cake::*;
1819

19-
const BOO: (Cake, Cake) = (Marmor, BlackForest);
20+
struct Pair<A, B>(A, B);
21+
22+
const BOO: Pair<Cake, Cake> = Pair(Marmor, BlackForest);
2023
//~^ ERROR: constant evaluation error [E0080]
21-
//~| unimplemented constant expression: enum variants
24+
//~| unimplemented constant expression: tuple struct constructors
2225
const FOO: Cake = BOO.1;
2326

2427
const fn foo() -> Cake {
2528
Marmor
26-
//~^ ERROR: constant evaluation error [E0080]
27-
//~| unimplemented constant expression: enum variants
2829
}
2930

3031
const WORKS: Cake = Marmor;
@@ -34,7 +35,7 @@ const GOO: Cake = foo();
3435
fn main() {
3536
match BlackForest {
3637
FOO => println!("hi"), //~ NOTE: for pattern here
37-
GOO => println!("meh"), //~ NOTE: for pattern here
38+
GOO => println!("meh"),
3839
WORKS => println!("möp"),
3940
_ => println!("bye"),
4041
}

‎src/test/compile-fail/issue-39559.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,6 @@ pub struct Vector<T, D: Dim> {
2828
fn main() {
2929
let array: [usize; Dim3::dim()]
3030
//~^ ERROR calls in constants are limited to constant functions
31-
//~| ERROR constant evaluation error
32-
//~| non-constant path in constant expression
3331
= [0; Dim3::dim()];
3432
//~^ ERROR calls in constants are limited to constant functions
35-
//~| ERROR constant evaluation error
36-
//~| non-constant path in constant expression
3733
}

‎src/test/compile-fail/issue-41394.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
enum Foo {
12+
A = "" + 1
13+
//~^ ERROR binary operation `+` cannot be applied to type `&'static str`
14+
}
15+
16+
enum Bar {
17+
A = Foo::A as isize
18+
}
19+
20+
fn main() {}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![crate_type = "lib"]
12+
13+
#[repr(u32)]
14+
pub enum Foo {
15+
Foo = Private::Variant as u32
16+
}
17+
18+
#[repr(u8)]
19+
enum Private {
20+
Variant = 42
21+
}
22+
23+
#[inline(always)]
24+
pub fn foo() -> Foo {
25+
Foo::Foo
26+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(const_fn)]
12+
13+
#[derive(PartialEq, Eq)]
14+
enum Cake {
15+
BlackForest,
16+
Marmor,
17+
}
18+
use Cake::*;
19+
20+
const BOO: (Cake, Cake) = (Marmor, BlackForest);
21+
const FOO: Cake = BOO.1;
22+
23+
const fn foo() -> Cake {
24+
Marmor
25+
}
26+
27+
const WORKS: Cake = Marmor;
28+
29+
const GOO: Cake = foo();
30+
31+
fn main() {
32+
match BlackForest {
33+
FOO => println!("hi"),
34+
GOO => println!("meh"),
35+
WORKS => println!("möp"),
36+
_ => println!("bye"),
37+
}
38+
}

‎src/test/compile-fail/non-constant-enum-for-vec-repeat.rs renamed to ‎src/test/run-pass/issue-23898.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,10 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
// Note: This test is checking that we forbid a coding pattern that
12-
// Issue #5873 explicitly wants to allow.
11+
// Note: This test was used to demonstrate #5873 (now #23898).
1312

1413
enum State { ST_NULL, ST_WHITESPACE }
1514

1615
fn main() {
1716
[State::ST_NULL; (State::ST_WHITESPACE as usize)];
18-
//~^ ERROR constant evaluation error
19-
//~| unimplemented constant expression: enum variants
2017
}

‎src/test/run-pass/issue-41394.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// aux-build:issue-41394.rs
12+
13+
extern crate issue_41394 as lib;
14+
15+
fn main() {
16+
assert_eq!(lib::foo() as u32, 42);
17+
}

0 commit comments

Comments
 (0)
Please sign in to comment.