rustc: make the const-eval cache polymorphic.
This commit is contained in:
parent
a94124488a
commit
e22873d912
@ -97,7 +97,7 @@ pub enum DepNode<D: Clone + Debug> {
|
||||
TypeckBodiesKrate,
|
||||
TypeckTables(D),
|
||||
UsedTraitImports(D),
|
||||
MonomorphicConstEval(D),
|
||||
ConstEval(D),
|
||||
|
||||
// The set of impls for a given trait. Ultimately, it would be
|
||||
// nice to get more fine-grained here (e.g., to include a
|
||||
@ -233,7 +233,7 @@ pub fn map_def<E, OP>(&self, mut op: OP) -> Option<DepNode<E>>
|
||||
InherentImpls(ref d) => op(d).map(InherentImpls),
|
||||
TypeckTables(ref d) => op(d).map(TypeckTables),
|
||||
UsedTraitImports(ref d) => op(d).map(UsedTraitImports),
|
||||
MonomorphicConstEval(ref d) => op(d).map(MonomorphicConstEval),
|
||||
ConstEval(ref d) => op(d).map(ConstEval),
|
||||
TraitImpls(ref d) => op(d).map(TraitImpls),
|
||||
TraitItems(ref d) => op(d).map(TraitItems),
|
||||
ReprHints(ref d) => op(d).map(ReprHints),
|
||||
|
@ -227,7 +227,8 @@ pub fn eval_length(tcx: TyCtxt,
|
||||
{
|
||||
let count_expr = &tcx.hir.body(count).value;
|
||||
let count_def_id = tcx.hir.body_owner_def_id(count);
|
||||
match ty::queries::monomorphic_const_eval::get(tcx, count_expr.span, count_def_id) {
|
||||
let substs = Substs::empty();
|
||||
match ty::queries::const_eval::get(tcx, count_expr.span, (count_def_id, substs)) {
|
||||
Ok(Integral(Usize(count))) => {
|
||||
let val = count.as_u64(tcx.sess.target.uint_type);
|
||||
assert_eq!(val as usize as u64, val);
|
||||
|
@ -249,8 +249,8 @@ fn retrace_path(&self,
|
||||
fn load_macro(&self, did: DefId, sess: &Session) -> LoadedMacro;
|
||||
|
||||
// misc. metadata
|
||||
fn maybe_get_item_body<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
|
||||
-> Option<&'tcx hir::Body>;
|
||||
fn item_body<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
|
||||
-> &'tcx hir::Body;
|
||||
fn item_body_nested_bodies(&self, def: DefId) -> BTreeMap<hir::BodyId, hir::Body>;
|
||||
fn const_is_rvalue_promotable_to_static(&self, def: DefId) -> bool;
|
||||
|
||||
@ -399,9 +399,9 @@ fn item_children(&self, did: DefId) -> Vec<def::Export> { bug!("item_children")
|
||||
fn load_macro(&self, did: DefId, sess: &Session) -> LoadedMacro { bug!("load_macro") }
|
||||
|
||||
// misc. metadata
|
||||
fn maybe_get_item_body<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
|
||||
-> Option<&'tcx hir::Body> {
|
||||
bug!("maybe_get_item_body")
|
||||
fn item_body<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
|
||||
-> &'tcx hir::Body {
|
||||
bug!("item_body")
|
||||
}
|
||||
fn item_body_nested_bodies(&self, def: DefId) -> BTreeMap<hir::BodyId, hir::Body> {
|
||||
bug!("item_body_nested_bodies")
|
||||
|
@ -16,6 +16,7 @@
|
||||
use mir;
|
||||
use session::CompileResult;
|
||||
use ty::{self, CrateInherentImpls, Ty, TyCtxt};
|
||||
use ty::subst::Substs;
|
||||
use util::nodemap::NodeSet;
|
||||
|
||||
use rustc_data_structures::indexed_vec::IndexVec;
|
||||
@ -74,6 +75,15 @@ fn default_span(&self, tcx: TyCtxt) -> Span {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Key for (DefId, &'tcx Substs<'tcx>) {
|
||||
fn map_crate(&self) -> CrateNum {
|
||||
self.0.krate
|
||||
}
|
||||
fn default_span(&self, tcx: TyCtxt) -> Span {
|
||||
self.0.default_span(tcx)
|
||||
}
|
||||
}
|
||||
|
||||
trait Value<'tcx>: Sized {
|
||||
fn from_cycle_error<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Self;
|
||||
}
|
||||
@ -217,6 +227,13 @@ fn describe(_: TyCtxt, _: CrateNum) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> QueryDescription for queries::const_eval<'tcx> {
|
||||
fn describe(tcx: TyCtxt, (def_id, _): (DefId, &'tcx Substs<'tcx>)) -> String {
|
||||
format!("const-evaluating `{}`",
|
||||
tcx.item_path_str(def_id))
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! define_maps {
|
||||
(<$tcx:tt>
|
||||
$($(#[$attr:meta])*
|
||||
@ -446,16 +463,17 @@ fn default() -> Self {
|
||||
/// (Defined only for LOCAL_CRATE)
|
||||
pub crate_inherent_impls_overlap_check: crate_inherent_impls_dep_node(CrateNum) -> (),
|
||||
|
||||
/// Results of evaluating monomorphic constants embedded in
|
||||
/// other items, such as enum variant explicit discriminants.
|
||||
pub monomorphic_const_eval: MonomorphicConstEval(DefId) -> const_val::EvalResult<'tcx>,
|
||||
/// Results of evaluating const items or constants embedded in
|
||||
/// other items (such as enum variant explicit discriminants).
|
||||
pub const_eval: const_eval_dep_node((DefId, &'tcx Substs<'tcx>))
|
||||
-> const_val::EvalResult<'tcx>,
|
||||
|
||||
/// Performs the privacy check and computes "access levels".
|
||||
pub privacy_access_levels: PrivacyAccessLevels(CrateNum) -> Rc<AccessLevels>,
|
||||
|
||||
pub reachable_set: reachability_dep_node(CrateNum) -> Rc<NodeSet>,
|
||||
|
||||
pub mir_shims: mir_shim(ty::InstanceDef<'tcx>) -> &'tcx RefCell<mir::Mir<'tcx>>
|
||||
pub mir_shims: mir_shim_dep_node(ty::InstanceDef<'tcx>) -> &'tcx RefCell<mir::Mir<'tcx>>
|
||||
}
|
||||
|
||||
fn coherent_trait_dep_node((_, def_id): (CrateNum, DefId)) -> DepNode<DefId> {
|
||||
@ -470,10 +488,14 @@ fn reachability_dep_node(_: CrateNum) -> DepNode<DefId> {
|
||||
DepNode::Reachability
|
||||
}
|
||||
|
||||
fn mir_shim(instance: ty::InstanceDef) -> DepNode<DefId> {
|
||||
fn mir_shim_dep_node(instance: ty::InstanceDef) -> DepNode<DefId> {
|
||||
instance.dep_node()
|
||||
}
|
||||
|
||||
fn typeck_item_bodies_dep_node(_: CrateNum) -> DepNode<DefId> {
|
||||
DepNode::TypeckBodiesKrate
|
||||
}
|
||||
|
||||
fn const_eval_dep_node((def_id, _): (DefId, &Substs)) -> DepNode<DefId> {
|
||||
DepNode::ConstEval(def_id)
|
||||
}
|
||||
|
@ -1701,7 +1701,8 @@ pub fn discriminants(&'a self, tcx: TyCtxt<'a, 'gcx, 'tcx>)
|
||||
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 queries::monomorphic_const_eval::get(tcx, DUMMY_SP, expr_did) {
|
||||
let substs = Substs::empty();
|
||||
match queries::const_eval::get(tcx, DUMMY_SP, (expr_did, substs)) {
|
||||
Ok(ConstVal::Integral(v)) => {
|
||||
discr = v;
|
||||
}
|
||||
@ -1733,7 +1734,8 @@ pub fn discriminant_for_variant(&self,
|
||||
explicit_index -= distance;
|
||||
}
|
||||
ty::VariantDiscr::Explicit(expr_did) => {
|
||||
match queries::monomorphic_const_eval::get(tcx, DUMMY_SP, expr_did) {
|
||||
let substs = Substs::empty();
|
||||
match queries::const_eval::get(tcx, DUMMY_SP, (expr_did, substs)) {
|
||||
Ok(ConstVal::Integral(v)) => {
|
||||
explicit_value = v;
|
||||
break;
|
||||
|
@ -75,83 +75,34 @@ fn lookup_variant_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
///
|
||||
/// `substs` is optional and is used for associated constants.
|
||||
/// This generally happens in late/trans const evaluation.
|
||||
pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
def_id: DefId,
|
||||
substs: &'tcx Substs<'tcx>)
|
||||
-> Option<(&'tcx Expr,
|
||||
&'a ty::TypeckTables<'tcx>)> {
|
||||
pub fn lookup_const_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
def_id: DefId,
|
||||
substs: &'tcx Substs<'tcx>)
|
||||
-> Option<(DefId, &'tcx Substs<'tcx>)> {
|
||||
if let Some(node_id) = tcx.hir.as_local_node_id(def_id) {
|
||||
match tcx.hir.find(node_id) {
|
||||
None => None,
|
||||
Some(hir_map::NodeItem(&hir::Item {
|
||||
node: hir::ItemConst(_, body), ..
|
||||
})) |
|
||||
Some(hir_map::NodeImplItem(&hir::ImplItem {
|
||||
node: hir::ImplItemKind::Const(_, body), ..
|
||||
})) => {
|
||||
Some((&tcx.hir.body(body).value,
|
||||
tcx.item_tables(def_id)))
|
||||
Some(hir_map::NodeTraitItem(_)) => {
|
||||
// If we have a trait item and the substitutions for it,
|
||||
// `resolve_trait_associated_const` will select an impl
|
||||
// or the default.
|
||||
resolve_trait_associated_const(tcx, def_id, substs)
|
||||
}
|
||||
Some(hir_map::NodeTraitItem(ti)) => match ti.node {
|
||||
hir::TraitItemKind::Const(_, default) => {
|
||||
// If we have a trait item and the substitutions for it,
|
||||
// `resolve_trait_associated_const` will select an impl
|
||||
// or the default.
|
||||
let trait_id = tcx.hir.get_parent(node_id);
|
||||
let trait_id = tcx.hir.local_def_id(trait_id);
|
||||
let default_value = default.map(|body| {
|
||||
(&tcx.hir.body(body).value,
|
||||
tcx.item_tables(def_id))
|
||||
});
|
||||
resolve_trait_associated_const(tcx, def_id, default_value, trait_id, substs)
|
||||
}
|
||||
_ => None
|
||||
},
|
||||
Some(_) => None
|
||||
_ => Some((def_id, substs))
|
||||
}
|
||||
} else {
|
||||
let expr_and_tables = tcx.sess.cstore.maybe_get_item_body(tcx, def_id).map(|body| {
|
||||
(&body.value, tcx.item_tables(def_id))
|
||||
});
|
||||
match tcx.sess.cstore.describe_def(def_id) {
|
||||
Some(Def::AssociatedConst(_)) => {
|
||||
let trait_id = tcx.sess.cstore.trait_of_item(def_id);
|
||||
// As mentioned in the comments above for in-crate
|
||||
// constants, we only try to find the expression for a
|
||||
// trait-associated const if the caller gives us the
|
||||
// substitutions for the reference to it.
|
||||
if let Some(trait_id) = trait_id {
|
||||
resolve_trait_associated_const(tcx, def_id, expr_and_tables,
|
||||
trait_id, substs)
|
||||
if tcx.sess.cstore.trait_of_item(def_id).is_some() {
|
||||
resolve_trait_associated_const(tcx, def_id, substs)
|
||||
} else {
|
||||
expr_and_tables
|
||||
Some((def_id, substs))
|
||||
}
|
||||
},
|
||||
Some(Def::Const(..)) => expr_and_tables,
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn lookup_const_fn_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
|
||||
-> Option<(&'tcx hir::Body, &'a ty::TypeckTables<'tcx>)>
|
||||
{
|
||||
if let Some(node_id) = tcx.hir.as_local_node_id(def_id) {
|
||||
FnLikeNode::from_node(tcx.hir.get(node_id)).and_then(|fn_like| {
|
||||
if fn_like.constness() == hir::Constness::Const {
|
||||
Some((tcx.hir.body(fn_like.body()),
|
||||
tcx.item_tables(def_id)))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
} else {
|
||||
if tcx.sess.cstore.is_const_fn(def_id) {
|
||||
tcx.sess.cstore.maybe_get_item_body(tcx, def_id).map(|body| {
|
||||
(body, tcx.item_tables(def_id))
|
||||
})
|
||||
} else {
|
||||
None
|
||||
_ => Some((def_id, substs))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -357,21 +308,15 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
|
||||
match cx.tables.qpath_def(qpath, e.id) {
|
||||
Def::Const(def_id) |
|
||||
Def::AssociatedConst(def_id) => {
|
||||
if let Some((expr, tables)) = lookup_const_by_id(tcx, def_id, substs) {
|
||||
let cx = ConstContext::with_tables(tcx, tables);
|
||||
match cx.eval(expr) {
|
||||
Ok(val) => val,
|
||||
Err(ConstEvalErr { kind: TypeckError, .. }) => {
|
||||
signal!(e, TypeckError);
|
||||
}
|
||||
Err(err) => {
|
||||
debug!("bad reference: {:?}, {:?}", err.description(), err.span);
|
||||
signal!(e, ErroneousReferencedConstant(box err))
|
||||
},
|
||||
}
|
||||
} else {
|
||||
signal!(e, TypeckError);
|
||||
}
|
||||
match ty::queries::const_eval::get(tcx, e.span, (def_id, substs)) {
|
||||
Ok(val) => val,
|
||||
Err(ConstEvalErr { kind: TypeckError, .. }) => {
|
||||
signal!(e, TypeckError);
|
||||
}
|
||||
Err(err) => {
|
||||
debug!("bad reference: {:?}, {:?}", err.description(), err.span);
|
||||
signal!(e, ErroneousReferencedConstant(box err))
|
||||
},
|
||||
},
|
||||
Def::VariantCtor(variant_def, ..) => {
|
||||
if let Some((expr, tables)) = lookup_variant_by_id(tcx, variant_def) {
|
||||
@ -407,14 +352,27 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
|
||||
}
|
||||
}
|
||||
hir::ExprCall(ref callee, ref args) => {
|
||||
let (did, substs) = match cx.eval(callee)? {
|
||||
Function(did, substs) => (did, substs),
|
||||
Struct(_) => signal!(e, UnimplementedConstVal("tuple struct constructors")),
|
||||
let (def_id, substs) = match cx.eval(callee)? {
|
||||
Function(def_id, substs) => (def_id, substs),
|
||||
callee => signal!(e, CallOn(callee)),
|
||||
};
|
||||
let (body, tables) = match lookup_const_fn_by_id(tcx, did) {
|
||||
Some(x) => x,
|
||||
None => signal!(e, NonConstPath),
|
||||
|
||||
let body = if let Some(node_id) = tcx.hir.as_local_node_id(def_id) {
|
||||
if let Some(fn_like) = FnLikeNode::from_node(tcx.hir.get(node_id)) {
|
||||
if fn_like.constness() == hir::Constness::Const {
|
||||
tcx.hir.body(fn_like.body())
|
||||
} else {
|
||||
signal!(e, TypeckError)
|
||||
}
|
||||
} else {
|
||||
signal!(e, TypeckError)
|
||||
}
|
||||
} else {
|
||||
if tcx.sess.cstore.is_const_fn(def_id) {
|
||||
tcx.sess.cstore.item_body(tcx, def_id)
|
||||
} else {
|
||||
signal!(e, TypeckError)
|
||||
}
|
||||
};
|
||||
|
||||
let arg_defs = body.arguments.iter().map(|arg| match arg.pat.node {
|
||||
@ -434,7 +392,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
|
||||
debug!("const call({:?})", call_args);
|
||||
let callee_cx = ConstContext {
|
||||
tcx: tcx,
|
||||
tables: tables,
|
||||
tables: tcx.item_tables(def_id),
|
||||
substs: substs,
|
||||
fn_args: Some(call_args)
|
||||
};
|
||||
@ -532,19 +490,16 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn resolve_trait_associated_const<'a, 'tcx: 'a>(
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
trait_item_id: DefId,
|
||||
default_value: Option<(&'tcx Expr, &'a ty::TypeckTables<'tcx>)>,
|
||||
trait_id: DefId,
|
||||
rcvr_substs: &'tcx Substs<'tcx>
|
||||
) -> Option<(&'tcx Expr, &'a ty::TypeckTables<'tcx>)>
|
||||
{
|
||||
let trait_ref = ty::Binder(ty::TraitRef::new(trait_id, rcvr_substs));
|
||||
fn resolve_trait_associated_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
def_id: DefId,
|
||||
substs: &'tcx Substs<'tcx>)
|
||||
-> Option<(DefId, &'tcx Substs<'tcx>)> {
|
||||
let trait_item = tcx.associated_item(def_id);
|
||||
let trait_id = trait_item.container.id();
|
||||
let trait_ref = ty::Binder(ty::TraitRef::new(trait_id, substs));
|
||||
debug!("resolve_trait_associated_const: trait_ref={:?}",
|
||||
trait_ref);
|
||||
|
||||
tcx.populate_implementations_for_trait_if_necessary(trait_id);
|
||||
tcx.infer_ctxt((), Reveal::UserFacing).enter(|infcx| {
|
||||
let mut selcx = traits::SelectionContext::new(&infcx);
|
||||
let obligation = traits::Obligation::new(traits::ObligationCause::dummy(),
|
||||
@ -569,12 +524,20 @@ fn resolve_trait_associated_const<'a, 'tcx: 'a>(
|
||||
// when constructing the inference context above.
|
||||
match selection {
|
||||
traits::VtableImpl(ref impl_data) => {
|
||||
let name = tcx.associated_item(trait_item_id).name;
|
||||
let name = trait_item.name;
|
||||
let ac = tcx.associated_items(impl_data.impl_def_id)
|
||||
.find(|item| item.kind == ty::AssociatedKind::Const && item.name == name);
|
||||
match ac {
|
||||
Some(ic) => lookup_const_by_id(tcx, ic.def_id, Substs::empty()),
|
||||
None => default_value,
|
||||
// FIXME(eddyb) Use proper Instance resolution to
|
||||
// get the correct Substs returned from here.
|
||||
Some(ic) => Some((ic.def_id, Substs::empty())),
|
||||
None => {
|
||||
if trait_item.defaultness.has_value() {
|
||||
Some((def_id, substs))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
@ -796,21 +759,35 @@ pub fn compare_lit_exprs(&self,
|
||||
|
||||
pub fn provide(providers: &mut Providers) {
|
||||
*providers = Providers {
|
||||
monomorphic_const_eval,
|
||||
const_eval,
|
||||
..*providers
|
||||
};
|
||||
}
|
||||
|
||||
fn monomorphic_const_eval<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
def_id: DefId)
|
||||
-> EvalResult<'tcx> {
|
||||
let cx = ConstContext::with_tables(tcx, tcx.item_tables(def_id));
|
||||
fn const_eval<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
(def_id, substs): (DefId, &'tcx Substs<'tcx>))
|
||||
-> EvalResult<'tcx> {
|
||||
let (def_id, substs) = if let Some(resolved) = lookup_const_by_id(tcx, def_id, substs) {
|
||||
resolved
|
||||
} else {
|
||||
return Err(ConstEvalErr {
|
||||
span: tcx.def_span(def_id),
|
||||
kind: TypeckError
|
||||
});
|
||||
};
|
||||
|
||||
let cx = ConstContext {
|
||||
tcx,
|
||||
tables: tcx.item_tables(def_id),
|
||||
substs: substs,
|
||||
fn_args: None
|
||||
};
|
||||
|
||||
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()
|
||||
tcx.sess.cstore.item_body(tcx, def_id)
|
||||
};
|
||||
cx.eval(&body.value)
|
||||
}
|
||||
|
@ -587,11 +587,16 @@ fn lower_path(&mut self,
|
||||
let substs = self.tables.node_id_item_substs(id)
|
||||
.unwrap_or_else(|| tcx.intern_substs(&[]));
|
||||
match eval::lookup_const_by_id(tcx, def_id, substs) {
|
||||
Some((const_expr, const_tables)) => {
|
||||
Some((def_id, _substs)) => {
|
||||
// Enter the inlined constant's tables temporarily.
|
||||
let old_tables = self.tables;
|
||||
self.tables = const_tables;
|
||||
let pat = self.lower_const_expr(const_expr, pat_id, span);
|
||||
self.tables = tcx.item_tables(def_id);
|
||||
let body = if let Some(id) = tcx.hir.as_local_node_id(def_id) {
|
||||
tcx.hir.body(tcx.hir.body_owned_by(id))
|
||||
} else {
|
||||
tcx.sess.cstore.item_body(tcx, def_id)
|
||||
};
|
||||
let pat = self.lower_const_expr(&body.value, pat_id, span);
|
||||
self.tables = old_tables;
|
||||
return pat;
|
||||
}
|
||||
|
@ -420,19 +420,18 @@ fn load_macro(&self, id: DefId, sess: &Session) -> LoadedMacro {
|
||||
})
|
||||
}
|
||||
|
||||
fn maybe_get_item_body<'a, 'tcx>(&self,
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
def_id: DefId)
|
||||
-> Option<&'tcx hir::Body>
|
||||
{
|
||||
fn item_body<'a, 'tcx>(&self,
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
def_id: DefId)
|
||||
-> &'tcx hir::Body {
|
||||
if let Some(cached) = tcx.hir.get_inlined_body(def_id) {
|
||||
return Some(cached);
|
||||
return cached;
|
||||
}
|
||||
|
||||
self.dep_graph.read(DepNode::MetaData(def_id));
|
||||
debug!("maybe_get_item_body({}): inlining item", tcx.item_path_str(def_id));
|
||||
debug!("item_body({}): inlining item", tcx.item_path_str(def_id));
|
||||
|
||||
self.get_crate_data(def_id.krate).maybe_get_item_body(tcx, def_id.index)
|
||||
self.get_crate_data(def_id.krate).item_body(tcx, def_id.index)
|
||||
}
|
||||
|
||||
fn item_body_nested_bodies(&self, def: DefId) -> BTreeMap<hir::BodyId, hir::Body> {
|
||||
|
@ -750,16 +750,15 @@ pub fn each_child_of_item<F>(&self, id: DefIndex, mut callback: F)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn maybe_get_item_body(&self,
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
id: DefIndex)
|
||||
-> Option<&'tcx hir::Body> {
|
||||
if self.is_proc_macro(id) { return None; }
|
||||
self.entry(id).ast.map(|ast| {
|
||||
let def_id = self.local_def_id(id);
|
||||
let body = ast.decode(self).body.decode(self);
|
||||
tcx.hir.intern_inlined_body(def_id, body)
|
||||
})
|
||||
pub fn item_body(&self,
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
id: DefIndex)
|
||||
-> &'tcx hir::Body {
|
||||
assert!(!self.is_proc_macro(id));
|
||||
let ast = self.entry(id).ast.unwrap();
|
||||
let def_id = self.local_def_id(id);
|
||||
let body = ast.decode(self).body.decode(self);
|
||||
tcx.hir.intern_inlined_body(def_id, body)
|
||||
}
|
||||
|
||||
pub fn item_body_tables(&self,
|
||||
|
@ -593,7 +593,8 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||
hir::ExprRepeat(ref v, count) => {
|
||||
let c = &cx.tcx.hir.body(count).value;
|
||||
let def_id = cx.tcx.hir.body_owner_def_id(count);
|
||||
let count = match ty::queries::monomorphic_const_eval::get(cx.tcx, c.span, def_id) {
|
||||
let substs = Substs::empty();
|
||||
let count = match ty::queries::const_eval::get(cx.tcx, c.span, (def_id, substs)) {
|
||||
Ok(ConstVal::Integral(ConstInt::Usize(u))) => u,
|
||||
Ok(other) => bug!("constant evaluation of repeat count yielded {:?}", other),
|
||||
Err(s) => cx.fatal_const_eval_err(&s, c.span, "expression")
|
||||
|
@ -555,7 +555,8 @@ fn convert_enum_variant_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
let wrapped_discr = prev_discr.map_or(initial, |d| d.wrap_incr());
|
||||
prev_discr = Some(if let Some(e) = variant.node.disr_expr {
|
||||
let expr_did = tcx.hir.local_def_id(e.node_id);
|
||||
let result = ty::queries::monomorphic_const_eval::get(tcx, variant.span, expr_did);
|
||||
let substs = Substs::empty();
|
||||
let result = ty::queries::const_eval::get(tcx, variant.span, (expr_did, substs));
|
||||
|
||||
// enum variant evaluation happens before the global constant check
|
||||
// so we need to report the real error
|
||||
|
@ -487,7 +487,7 @@ fn nested(&self, state: &mut hir::print::State, nested: hir::print::Nested)
|
||||
}
|
||||
|
||||
fn print_inlined_const(cx: &DocContext, did: DefId) -> String {
|
||||
let body = cx.tcx.sess.cstore.maybe_get_item_body(cx.tcx, did).unwrap();
|
||||
let body = cx.tcx.sess.cstore.item_body(cx.tcx, did);
|
||||
let inlined = InlinedConst {
|
||||
nested_bodies: cx.tcx.sess.cstore.item_body_nested_bodies(did)
|
||||
};
|
||||
|
@ -17,6 +17,4 @@ fn f(x: usize) -> usize {
|
||||
fn main() {
|
||||
let _ = [0; f(2)];
|
||||
//~^ ERROR calls in constants are limited to constant functions
|
||||
//~| ERROR constant evaluation error [E0080]
|
||||
//~| non-constant path in constant expression
|
||||
}
|
||||
|
@ -28,10 +28,6 @@ pub struct Vector<T, D: Dim> {
|
||||
fn main() {
|
||||
let array: [usize; Dim3::dim()]
|
||||
//~^ ERROR calls in constants are limited to constant functions
|
||||
//~| ERROR constant evaluation error
|
||||
//~| non-constant path in constant expression
|
||||
= [0; Dim3::dim()];
|
||||
//~^ ERROR calls in constants are limited to constant functions
|
||||
//~| ERROR constant evaluation error
|
||||
//~| non-constant path in constant expression
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user