From 7912f94b2db78e69d032b2e6ac47e5e3980d56bd Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Thu, 10 Mar 2016 02:04:55 +0200 Subject: [PATCH] const_eval: Take just one set of substitutions in lookup_const_by_id. --- src/librustc/middle/check_match.rs | 11 ++-- src/librustc/middle/const_eval.rs | 67 +++++++++--------------- src/librustc_mir/hair/cx/expr.rs | 3 +- src/librustc_mir/hair/cx/pattern.rs | 9 ++-- src/librustc_passes/consts.rs | 5 +- src/librustc_trans/trans/consts.rs | 16 +++--- src/librustc_trans/trans/mir/constant.rs | 6 +-- src/librustdoc/clean/inline.rs | 4 +- 8 files changed, 49 insertions(+), 72 deletions(-) diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index 89b57e0d90a..16e0a334440 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -475,9 +475,9 @@ impl<'a, 'tcx> Folder for StaticInliner<'a, 'tcx> { let def = self.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()); match def { Some(Def::AssociatedConst(did)) | - Some(Def::Const(did)) => match lookup_const_by_id(self.tcx, did, - Some(pat.id), None) { - Some((const_expr, _const_ty)) => { + Some(Def::Const(did)) => { + let substs = Some(self.tcx.node_id_item_substs(pat.id).substs); + if let Some((const_expr, _)) = lookup_const_by_id(self.tcx, did, substs) { const_expr_to_pat(self.tcx, const_expr, pat.span).map(|new_pat| { if let Some(ref mut renaming_map) = self.renaming_map { @@ -487,14 +487,13 @@ impl<'a, 'tcx> Folder for StaticInliner<'a, 'tcx> { new_pat }) - } - None => { + } else { self.failed = true; span_err!(self.tcx.sess, pat.span, E0158, "statics cannot be referenced in patterns"); pat } - }, + } _ => noop_fold_pat(pat, self) } } diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index 5d4226fe4ce..47b6c49fddb 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -19,7 +19,6 @@ use front::map::blocks::FnLikeNode; 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}; @@ -89,16 +88,13 @@ fn lookup_variant_by_id<'a>(tcx: &'a 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, - param_substs: Option<&'tcx subst::Substs<'tcx>>) + substs: Option>) -> Option<(&'tcx Expr, Option>)> { if let Some(node_id) = tcx.map.as_local_node_id(def_id) { match tcx.map.find(node_id) { @@ -111,28 +107,20 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: &'a TyCtxt<'tcx>, }, 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 @@ -153,7 +141,7 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: &'a TyCtxt<'tcx>, } 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) => { @@ -163,21 +151,15 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: &'a TyCtxt<'tcx>, }, 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 @@ -190,10 +172,10 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: &'a TyCtxt<'tcx>, }, _ => 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))); @@ -389,7 +371,8 @@ pub fn const_expr_to_pat(tcx: &TyCtxt, expr: &Expr, span: Span) -> P { 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!(), @@ -788,12 +771,12 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &TyCtxt<'tcx>, 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, @@ -1077,7 +1060,7 @@ fn resolve_trait_associated_const<'a, 'tcx: 'a>(tcx: &'a TyCtxt<'tcx>, 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))) diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 204b1c1d1e0..4d87d926e40 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -672,7 +672,8 @@ fn convert_path_expr<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, expr: &'tcx hir::Expr) }, Def::Const(def_id) | Def::AssociatedConst(def_id) => { - if let Some(e) = const_eval::lookup_const_by_id(cx.tcx, def_id, Some(expr.id), None) { + let substs = Some(cx.tcx.node_id_item_substs(expr.id).substs); + if let Some((e, _)) = const_eval::lookup_const_by_id(cx.tcx, def_id, substs) { // FIXME ConstVal can't be yet used with adjustments, as they would be lost. if !cx.tcx.tables.borrow().adjustments.contains_key(&e.id) { if let Some(v) = cx.try_const_eval_literal(e) { diff --git a/src/librustc_mir/hair/cx/pattern.rs b/src/librustc_mir/hair/cx/pattern.rs index 232404417e0..a9873778374 100644 --- a/src/librustc_mir/hair/cx/pattern.rs +++ b/src/librustc_mir/hair/cx/pattern.rs @@ -86,9 +86,9 @@ impl<'patcx, 'cx, 'tcx> PatCx<'patcx, 'cx, 'tcx> { { let def = self.cx.tcx.def_map.borrow().get(&pat.id).unwrap().full_def(); match def { - Def::Const(def_id) | Def::AssociatedConst(def_id) => - match const_eval::lookup_const_by_id(self.cx.tcx, def_id, - Some(pat.id), None) { + Def::Const(def_id) | Def::AssociatedConst(def_id) => { + let substs = Some(self.cx.tcx.node_id_item_substs(pat.id).substs); + match const_eval::lookup_const_by_id(self.cx.tcx, def_id, substs) { Some((const_expr, _const_ty)) => { let pat = const_eval::const_expr_to_pat(self.cx.tcx, const_expr, pat.span); @@ -99,7 +99,8 @@ impl<'patcx, 'cx, 'tcx> PatCx<'patcx, 'cx, 'tcx> { pat.span, &format!("cannot eval constant: {:?}", def_id)) } - }, + } + } _ => self.cx.tcx.sess.span_bug( pat.span, diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs index 74ede89be55..c964179d407 100644 --- a/src/librustc_passes/consts.rs +++ b/src/librustc_passes/consts.rs @@ -610,9 +610,8 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, } Some(Def::Const(did)) | Some(Def::AssociatedConst(did)) => { - if let Some((expr, _ty)) = const_eval::lookup_const_by_id(v.tcx, did, - Some(e.id), - None) { + let substs = Some(v.tcx.node_id_item_substs(e.id).substs); + if let Some((expr, _)) = const_eval::lookup_const_by_id(v.tcx, did, substs) { let inner = v.global_expr(Mode::Const, expr); v.add_qualif(inner); } diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs index 349afbba3ec..82cd6aace0a 100644 --- a/src/librustc_trans/trans/consts.rs +++ b/src/librustc_trans/trans/consts.rs @@ -13,12 +13,11 @@ use llvm; 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}; @@ -225,14 +224,11 @@ pub fn get_const_expr<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, 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") diff --git a/src/librustc_trans/trans/mir/constant.rs b/src/librustc_trans/trans/mir/constant.rs index 06eef5d3005..d4934718d75 100644 --- a/src/librustc_trans/trans/mir/constant.rs +++ b/src/librustc_trans/trans/mir/constant.rs @@ -19,7 +19,6 @@ use trans::common::{self, BlockAndBuilder, C_bool, C_bytes, C_floating_f64, C_in use trans::consts; use trans::datum; use trans::expr; -use trans::inline; use trans::type_of; use trans::type_::Type; @@ -114,9 +113,8 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { }; } - let substs = bcx.tcx().mk_substs(bcx.monomorphize(&substs)); - let def_id = inline::maybe_instantiate_inline(bcx.ccx(), def_id); - let expr = const_eval::lookup_const_by_id(bcx.tcx(), def_id, None, Some(substs)) + let substs = Some(bcx.monomorphize(substs)); + let expr = const_eval::lookup_const_by_id(bcx.tcx(), def_id, substs) .expect("def was const, but lookup_const_by_id failed").0; // FIXME: this is falling back to translating from HIR. This is not easy to fix, // because we would have somehow adapt const_eval to work on MIR rather than HIR. diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index ef54be72037..49091a6c2bc 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -336,7 +336,7 @@ pub fn build_impl(cx: &DocContext, let did = assoc_const.def_id; let type_scheme = tcx.lookup_item_type(did); let default = if assoc_const.has_value { - Some(const_eval::lookup_const_by_id(tcx, did, None, None) + Some(const_eval::lookup_const_by_id(tcx, did, None) .unwrap().0.span.to_src(cx)) } else { None @@ -479,7 +479,7 @@ fn build_const(cx: &DocContext, tcx: &TyCtxt, use rustc::middle::const_eval; use rustc_front::print::pprust; - let (expr, ty) = const_eval::lookup_const_by_id(tcx, did, None, None).unwrap_or_else(|| { + let (expr, ty) = const_eval::lookup_const_by_id(tcx, did, None).unwrap_or_else(|| { panic!("expected lookup_const_by_id to succeed for {:?}", did); }); debug!("converting constant expr {:?} to snippet", expr);