Skip to content

Commit 23de823

Browse files
committed
Auto merge of rust-lang#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 rust-lang#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 rust-lang#41394 by fixing rust-lang#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

+2-2
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

+6-3
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

+6-5
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

+5-5
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

+2-1
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

+27-5
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

+21-4
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
}

0 commit comments

Comments
 (0)