use middle::cstore::{self, CrateStore, InlinedItem};
use middle::{infer, subst, traits};
use middle::def::Def;
-use middle::subst::Subst;
use middle::def_id::DefId;
use middle::pat_util::def_to_path;
use middle::ty::{self, Ty, TyCtxt};
}
/// * `def_id` is the id of the constant.
-/// * `maybe_ref_id` is the id of the expr referencing the constant.
-/// * `param_substs` is the monomorphization substitution for the expression.
+/// * `substs` is the monomorphized substitutions for the expression.
///
-/// `maybe_ref_id` and `param_substs` are optional and are used for
-/// finding substitutions in associated constants. This generally
-/// happens in late/trans const evaluation.
+/// `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: &'a TyCtxt<'tcx>,
def_id: DefId,
- maybe_ref_id: Option<ast::NodeId>,
- param_substs: Option<&'tcx subst::Substs<'tcx>>)
+ substs: Option<subst::Substs<'tcx>>)
-> Option<(&'tcx Expr, Option<ty::Ty<'tcx>>)> {
if let Some(node_id) = tcx.map.as_local_node_id(def_id) {
match tcx.map.find(node_id) {
},
Some(ast_map::NodeTraitItem(ti)) => match ti.node {
hir::ConstTraitItem(_, _) => {
- match maybe_ref_id {
- // If we have a trait item, and we know the expression
- // that's the source of the obligation to resolve it,
+ if let Some(substs) = substs {
+ // If we have a trait item and the substitutions for it,
// `resolve_trait_associated_const` will select an impl
// or the default.
- Some(ref_id) => {
- let trait_id = tcx.trait_of_item(def_id)
- .unwrap();
- let mut substs = tcx.node_id_item_substs(ref_id)
- .substs;
- if let Some(param_substs) = param_substs {
- substs = substs.subst(tcx, param_substs);
- }
- resolve_trait_associated_const(tcx, ti, trait_id, substs)
- }
+ let trait_id = tcx.trait_of_item(def_id).unwrap();
+ resolve_trait_associated_const(tcx, ti, trait_id, substs)
+ } else {
// Technically, without knowing anything about the
// expression that generates the obligation, we could
// still return the default if there is one. However,
// it's safer to return `None` than to return some value
// that may differ from what you would get from
// correctly selecting an impl.
- None => None
+ None
}
}
_ => None
}
None => {}
}
- let mut used_ref_id = false;
+ let mut used_substs = false;
let expr_ty = match tcx.sess.cstore.maybe_get_item_ast(tcx, def_id) {
cstore::FoundAst::Found(&InlinedItem::Item(ref item)) => match item.node {
hir::ItemConst(ref ty, ref const_expr) => {
},
cstore::FoundAst::Found(&InlinedItem::TraitItem(trait_id, ref ti)) => match ti.node {
hir::ConstTraitItem(_, _) => {
- used_ref_id = true;
- match maybe_ref_id {
+ used_substs = true;
+ if let Some(substs) = substs {
// 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 expression that refers to it.
- Some(ref_id) => {
- let mut substs = tcx.node_id_item_substs(ref_id)
- .substs;
- if let Some(param_substs) = param_substs {
- substs = substs.subst(tcx, param_substs);
- }
- resolve_trait_associated_const(tcx, ti, trait_id, substs)
- }
- None => None
+ // the substitutions for the reference to it.
+ resolve_trait_associated_const(tcx, ti, trait_id, substs)
+ } else {
+ None
}
}
_ => None
},
_ => None
};
- // If we used the reference expression, particularly to choose an impl
+ // If we used the substitutions, particularly to choose an impl
// of a trait-associated const, don't cache that, because the next
// lookup with the same def_id may yield a different result.
- if !used_ref_id {
+ if !used_substs {
tcx.extern_const_statics
.borrow_mut()
.insert(def_id, expr_ty.map(|(e, t)| (e.id, t)));
PatKind::Path(path.clone()),
Some(Def::Const(def_id)) |
Some(Def::AssociatedConst(def_id)) => {
- let (expr, _ty) = lookup_const_by_id(tcx, def_id, Some(expr.id), None).unwrap();
+ let substs = Some(tcx.node_id_item_substs(expr.id).substs);
+ let (expr, _ty) = lookup_const_by_id(tcx, def_id, substs).unwrap();
return const_expr_to_pat(tcx, expr, span);
},
_ => unreachable!(),
match opt_def {
Def::Const(def_id) |
Def::AssociatedConst(def_id) => {
- let maybe_ref_id = if let ExprTypeChecked = ty_hint {
- Some(e.id)
+ let substs = if let ExprTypeChecked = ty_hint {
+ Some(tcx.node_id_item_substs(e.id).substs)
} else {
None
};
- if let Some((e, ty)) = lookup_const_by_id(tcx, def_id, maybe_ref_id, None) {
+ if let Some((e, ty)) = lookup_const_by_id(tcx, def_id, substs) {
let item_hint = match ty {
Some(ty) => ty_hint.checked_or(ty),
None => ty_hint,
traits::VtableImpl(ref impl_data) => {
match tcx.associated_consts(impl_data.impl_def_id)
.iter().find(|ic| ic.name == ti.name) {
- Some(ic) => lookup_const_by_id(tcx, ic.def_id, None, None),
+ Some(ic) => lookup_const_by_id(tcx, ic.def_id, None),
None => match ti.node {
hir::ConstTraitItem(ref ty, Some(ref expr)) => {
Some((&*expr, ast_ty_to_prim_ty(tcx, ty)))
use llvm::{ConstFCmp, ConstICmp, SetLinkage, SetUnnamedAddr};
use llvm::{InternalLinkage, ValueRef, Bool, True};
use middle::const_qualif::ConstQualif;
-use middle::cstore::LOCAL_CRATE;
use middle::const_eval::{self, ConstEvalErr};
use middle::def::Def;
use middle::def_id::DefId;
use rustc::front::map as hir_map;
-use trans::{abi, adt, closure, debuginfo, expr, inline, machine};
+use trans::{abi, adt, closure, debuginfo, expr, machine};
use trans::base::{self, exported_name, imported_name, push_ctxt};
use trans::callee::Callee;
use trans::collector::{self, TransItem};
ref_expr: &hir::Expr,
param_substs: &'tcx Substs<'tcx>)
-> &'tcx hir::Expr {
- let def_id = inline::maybe_instantiate_inline(ccx, def_id);
-
- if def_id.krate != LOCAL_CRATE {
- ccx.sess().span_bug(ref_expr.span,
- "cross crate constant could not be inlined");
- }
-
- match const_eval::lookup_const_by_id(ccx.tcx(), def_id, Some(ref_expr.id), Some(param_substs)) {
+ let substs = ccx.tcx().node_id_item_substs(ref_expr.id).substs;
+ let substs = monomorphize::apply_param_substs(ccx.tcx(),
+ param_substs,
+ &substs.erase_regions());
+ match const_eval::lookup_const_by_id(ccx.tcx(), def_id, Some(substs)) {
Some((ref expr, _ty)) => expr,
None => {
ccx.sess().span_bug(ref_expr.span, "constant item not found")