use front::map as ast_map;
use front::map::blocks::FnLikeNode;
use middle::cstore::{self, CrateStore, InlinedItem};
-use middle::{def, infer, subst, traits};
+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};
use util::num::ToPrimitive;
use util::nodemap::NodeMap;
+use graphviz::IntoCow;
use syntax::{ast, abi};
use rustc_front::hir::Expr;
use rustc_front::hir;
use syntax::ptr::P;
use syntax::codemap;
-use std::borrow::{Cow, IntoCow};
-use std::num::wrapping::OverflowingOps;
+use std::borrow::Cow;
use std::cmp::Ordering;
use std::collections::hash_map::Entry::Vacant;
use std::hash;
use std::{i8, i16, i32, i64, u8, u16, u32, u64};
use std::rc::Rc;
-fn lookup_const<'a>(tcx: &'a ty::ctxt, e: &Expr) -> Option<&'a Expr> {
- let opt_def = tcx.def_map.borrow().get(&e.id).map(|d| d.full_def());
- match opt_def {
- Some(def::DefConst(def_id)) |
- Some(def::DefAssociatedConst(def_id)) => {
- lookup_const_by_id(tcx, def_id, Some(e.id))
- }
- Some(def::DefVariant(enum_def, variant_def, _)) => {
- lookup_variant_by_id(tcx, enum_def, variant_def)
- }
- _ => None
- }
-}
-
fn lookup_variant_by_id<'a>(tcx: &'a ty::ctxt,
enum_def: DefId,
variant_def: DefId)
}
}
+/// * `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.
+///
+/// `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.
pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: &'a ty::ctxt<'tcx>,
def_id: DefId,
- maybe_ref_id: Option<ast::NodeId>)
+ maybe_ref_id: Option<ast::NodeId>,
+ param_substs: Option<&'tcx subst::Substs<'tcx>>)
-> Option<&'tcx Expr> {
if let Some(node_id) = tcx.map.as_local_node_id(def_id) {
match tcx.map.find(node_id) {
Some(ref_id) => {
let trait_id = tcx.trait_of_item(def_id)
.unwrap();
- let substs = tcx.node_id_item_substs(ref_id)
- .substs;
+ 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)
}
// a trait-associated const if the caller gives us
// the expression that refers to it.
Some(ref_id) => {
- let substs = tcx.node_id_item_substs(ref_id)
- .substs;
+ 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).map(|e| e.id)
}
entry.insert(def);
}
let path = match def.full_def() {
- def::DefStruct(def_id) => def_to_path(tcx, def_id),
- def::DefVariant(_, variant_did, _) => def_to_path(tcx, variant_did),
- def::DefFn(..) => return P(hir::Pat {
+ Def::Struct(def_id) => def_to_path(tcx, def_id),
+ Def::Variant(_, variant_did) => def_to_path(tcx, variant_did),
+ Def::Fn(..) => return P(hir::Pat {
id: expr.id,
node: hir::PatLit(P(expr.clone())),
span: span,
hir::ExprPath(_, ref path) => {
let opt_def = tcx.def_map.borrow().get(&expr.id).map(|d| d.full_def());
match opt_def {
- Some(def::DefStruct(..)) =>
+ Some(Def::Struct(..)) =>
hir::PatStruct(path.clone(), hir::HirVec::new(), false),
- Some(def::DefVariant(..)) =>
+ Some(Def::Variant(..)) =>
hir::PatEnum(path.clone(), None),
- _ => {
- match lookup_const(tcx, expr) {
- Some(actual) => return const_expr_to_pat(tcx, actual, span),
- _ => unreachable!()
- }
- }
+ Some(Def::Const(def_id)) |
+ Some(Def::AssociatedConst(def_id)) => {
+ let expr = lookup_const_by_id(tcx, def_id, Some(expr.id), None).unwrap();
+ return const_expr_to_pat(tcx, expr, span);
+ },
+ _ => unreachable!(),
}
}
None
};
let (const_expr, const_ty) = match opt_def {
- Some(def::DefConst(def_id)) => {
+ Some(Def::Const(def_id)) => {
if let Some(node_id) = tcx.map.as_local_node_id(def_id) {
match tcx.map.find(node_id) {
Some(ast_map::NodeItem(it)) => match it.node {
_ => (None, None)
}
} else {
- (lookup_const_by_id(tcx, def_id, Some(e.id)), None)
+ (lookup_const_by_id(tcx, def_id, Some(e.id), None), None)
}
}
- Some(def::DefAssociatedConst(def_id)) => {
+ Some(Def::AssociatedConst(def_id)) => {
if let Some(node_id) = tcx.map.as_local_node_id(def_id) {
match tcx.impl_or_trait_item(def_id).container() {
ty::TraitContainer(trait_id) => match tcx.map.find(node_id) {
},
}
} else {
- (lookup_const_by_id(tcx, def_id, Some(e.id)), None)
+ (lookup_const_by_id(tcx, def_id, Some(e.id), None), None)
}
}
- Some(def::DefVariant(enum_def, variant_def, _)) => {
+ Some(Def::Variant(enum_def, variant_def)) => {
(lookup_variant_by_id(tcx, enum_def, variant_def), None)
}
- Some(def::DefStruct(_)) => {
+ Some(Def::Struct(..)) => {
return Ok(ConstVal::Struct(e.id))
}
- Some(def::DefLocal(_, id)) => {
- debug!("DefLocal({:?}): {:?}", id, fn_args);
+ Some(Def::Local(_, id)) => {
+ debug!("Def::Local({:?}): {:?}", id, fn_args);
if let Some(val) = fn_args.and_then(|args| args.get(&id)) {
return Ok(val.clone());
} else {
(None, None)
}
},
- Some(def::DefMethod(id)) | Some(def::DefFn(id, _)) => return Ok(Function(id)),
+ Some(Def::Method(id)) | Some(Def::Fn(id)) => return Ok(Function(id)),
_ => (None, None)
};
let const_expr = match const_expr {
rcvr_substs: subst::Substs<'tcx>)
-> Option<&'tcx Expr>
{
- let subst::SeparateVecsPerParamSpace {
- types: rcvr_type,
- selfs: rcvr_self,
- fns: _,
- } = rcvr_substs.types.split();
- let trait_substs =
- subst::Substs::erased(subst::VecPerParamSpace::new(rcvr_type,
- rcvr_self,
- Vec::new()));
- let trait_substs = tcx.mk_substs(trait_substs);
- debug!("resolve_trait_associated_const: trait_substs={:?}",
- trait_substs);
- let trait_ref = ty::Binder(ty::TraitRef { def_id: trait_id,
- substs: trait_substs });
+ let trait_ref = ty::Binder(
+ rcvr_substs.erase_regions().to_trait_ref(tcx, trait_id)
+ );
+ debug!("resolve_trait_associated_const: trait_ref={:?}",
+ trait_ref);
tcx.populate_implementations_for_trait_if_necessary(trait_ref.def_id());
- let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, false);
+ let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
let mut selcx = traits::SelectionContext::new(&infcx);
let obligation = traits::Obligation::new(traits::ObligationCause::dummy(),
Ok(None) => {
return None
}
- Err(e) => {
- tcx.sess.span_bug(ti.span,
- &format!("Encountered error `{:?}` when trying \
- to select an implementation for \
- constant trait item reference.",
- e))
+ Err(_) => {
+ return None
}
};
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),
+ Some(ic) => lookup_const_by_id(tcx, ic.def_id, None, None),
None => match ti.node {
hir::ConstTraitItem(_, Some(ref expr)) => Some(&*expr),
_ => None,