]> git.lizzy.rs Git - rust.git/commitdiff
simplify const path lookup for constants and associated constants
authorOliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>
Thu, 3 Mar 2016 13:48:08 +0000 (14:48 +0100)
committerOliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>
Thu, 10 Mar 2016 11:50:13 +0000 (12:50 +0100)
src/librustc/middle/check_match.rs
src/librustc/middle/const_eval.rs
src/librustc/middle/ty/context.rs
src/librustc_mir/hair/cx/pattern.rs
src/librustc_passes/consts.rs
src/librustc_trans/trans/consts.rs

index 1f79e76f3ac32c2e0200b2b04451886e04e2e06a..51985be96db53991242b92376d84703522cfe720 100644 (file)
@@ -476,7 +476,7 @@ fn fold_pat(&mut self, pat: P<Pat>) -> P<Pat> {
                     Some(Def::AssociatedConst(did)) |
                     Some(Def::Const(did)) => match lookup_const_by_id(self.tcx, did,
                                                                     Some(pat.id), None) {
-                        Some(const_expr) => {
+                        Some((const_expr, _const_ty)) => {
                             const_expr_to_pat(self.tcx, const_expr, pat.span).map(|new_pat| {
 
                                 if let Some(ref mut renaming_map) = self.renaming_map {
index c02782b859cbc2aa39b0e67681fc230db3d0492d..3690f0c1d664b95138bef58fc1388e35dced8b6f 100644 (file)
@@ -98,13 +98,13 @@ 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>>)
-                                        -> Option<&'tcx Expr> {
+                                        -> 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) {
             None => None,
             Some(ast_map::NodeItem(it)) => match it.node {
-                hir::ItemConst(_, ref const_expr) => {
-                    Some(&const_expr)
+                hir::ItemConst(ref ty, ref const_expr) => {
+                    Some((&const_expr, ast_ty_to_prim_ty(tcx, ty)))
                 }
                 _ => None
             },
@@ -123,8 +123,7 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: &'a TyCtxt<'tcx>,
                             if let Some(param_substs) = param_substs {
                                 substs = substs.subst(tcx, param_substs);
                             }
-                            resolve_trait_associated_const(tcx, ti, trait_id,
-                                                           substs)
+                            resolve_trait_associated_const(tcx, ti, trait_id, substs)
                         }
                         // Technically, without knowing anything about the
                         // expression that generates the obligation, we could
@@ -138,8 +137,8 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: &'a TyCtxt<'tcx>,
                 _ => None
             },
             Some(ast_map::NodeImplItem(ii)) => match ii.node {
-                hir::ImplItemKind::Const(_, ref expr) => {
-                    Some(&expr)
+                hir::ImplItemKind::Const(ref ty, ref expr) => {
+                    Some((&expr, ast_ty_to_prim_ty(tcx, ty)))
                 }
                 _ => None
             },
@@ -147,16 +146,18 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: &'a TyCtxt<'tcx>,
         }
     } else {
         match tcx.extern_const_statics.borrow().get(&def_id) {
-            Some(&ast::DUMMY_NODE_ID) => return None,
-            Some(&expr_id) => {
-                return Some(tcx.map.expect_expr(expr_id));
+            Some(&None) => return None,
+            Some(&Some((expr_id, ty))) => {
+                return Some((tcx.map.expect_expr(expr_id), ty));
             }
             None => {}
         }
         let mut used_ref_id = false;
-        let expr_id = match tcx.sess.cstore.maybe_get_item_ast(tcx, def_id) {
+        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 const_expr) => Some(const_expr.id),
+                hir::ItemConst(ref ty, ref const_expr) => {
+                    Some((&**const_expr, ast_ty_to_prim_ty(tcx, ty)))
+                },
                 _ => None
             },
             cstore::FoundAst::Found(&InlinedItem::TraitItem(trait_id, ref ti)) => match ti.node {
@@ -173,8 +174,7 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: &'a TyCtxt<'tcx>,
                             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)
+                            resolve_trait_associated_const(tcx, ti, trait_id, substs)
                         }
                         None => None
                     }
@@ -182,7 +182,9 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: &'a TyCtxt<'tcx>,
                 _ => None
             },
             cstore::FoundAst::Found(&InlinedItem::ImplItem(_, ref ii)) => match ii.node {
-                hir::ImplItemKind::Const(_, ref expr) => Some(expr.id),
+                hir::ImplItemKind::Const(ref ty, ref expr) => {
+                    Some((&**expr, ast_ty_to_prim_ty(tcx, ty)))
+                },
                 _ => None
             },
             _ => None
@@ -192,10 +194,10 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: &'a TyCtxt<'tcx>,
         // lookup with the same def_id may yield a different result.
         if !used_ref_id {
             tcx.extern_const_statics
-               .borrow_mut().insert(def_id,
-                                    expr_id.unwrap_or(ast::DUMMY_NODE_ID));
+               .borrow_mut()
+               .insert(def_id, expr_ty.map(|(e, t)| (e.id, t)));
         }
-        expr_id.map(|id| tcx.map.expect_expr(id))
+        expr_ty
     }
 }
 
@@ -386,7 +388,7 @@ pub fn const_expr_to_pat(tcx: &TyCtxt, expr: &Expr, span: Span) -> P<hir::Pat> {
                     PatKind::Path(path.clone()),
                 Some(Def::Const(def_id)) |
                 Some(Def::AssociatedConst(def_id)) => {
-                    let expr = lookup_const_by_id(tcx, def_id, Some(expr.id), None).unwrap();
+                    let (expr, _ty) = lookup_const_by_id(tcx, def_id, Some(expr.id), None).unwrap();
                     return const_expr_to_pat(tcx, expr, span);
                 },
                 _ => unreachable!(),
@@ -778,90 +780,49 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &TyCtxt<'tcx>,
               if def.depth != 0 {
                   signal!(e, UnresolvedPath);
               }
-              Some(def.full_def())
+              def.full_def()
           } else {
-              None
+              signal!(e, NonConstPath);
           };
-          let (const_expr, const_ty) = match opt_def {
-              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 {
-                              hir::ItemConst(ref ty, ref expr) => {
-                                  (Some(&**expr), Some(&**ty))
-                              }
-                              _ => (None, None)
-                          },
-                          _ => (None, None)
-                      }
+          match opt_def {
+              Def::Const(def_id) |
+              Def::AssociatedConst(def_id) => {
+                  let maybe_ref_id = if let ExprTypeChecked = ty_hint {
+                      Some(e.id)
+                  } else {
+                      None
+                  };
+                  if let Some((e, ty)) = lookup_const_by_id(tcx, def_id, maybe_ref_id, None) {
+                      let item_hint = match ty {
+                          Some(ty) => ty_hint.checked_or(ty),
+                          None => ty_hint,
+                      };
+                      try!(eval_const_expr_partial(tcx, e, item_hint, None))
                   } else {
-                      (lookup_const_by_id(tcx, def_id, Some(e.id), None), None)
+                      signal!(e, NonConstPath);
                   }
-              }
-              Some(Def::AssociatedConst(def_id)) => {
-                  if let Some(node_id) = tcx.map.as_local_node_id(def_id) {
-                      match impl_or_trait_container(tcx, def_id) {
-                          ty::TraitContainer(trait_id) => match tcx.map.find(node_id) {
-                              Some(ast_map::NodeTraitItem(ti)) => match ti.node {
-                                  hir::ConstTraitItem(ref ty, _) => {
-                                      if let ExprTypeChecked = ty_hint {
-                                          let substs = tcx.node_id_item_substs(e.id).substs;
-                                          (resolve_trait_associated_const(tcx,
-                                                                          ti,
-                                                                          trait_id,
-                                                                          substs),
-                                           Some(&**ty))
-                                       } else {
-                                           (None, None)
-                                       }
-                                  }
-                                  _ => (None, None)
-                              },
-                              _ => (None, None)
-                          },
-                          ty::ImplContainer(_) => match tcx.map.find(node_id) {
-                              Some(ast_map::NodeImplItem(ii)) => match ii.node {
-                                  hir::ImplItemKind::Const(ref ty, ref expr) => {
-                                      (Some(&**expr), Some(&**ty))
-                                  }
-                                  _ => (None, None)
-                              },
-                              _ => (None, None)
-                          },
-                      }
+              },
+              Def::Variant(enum_def, variant_def) => {
+                  if let Some(const_expr) = lookup_variant_by_id(tcx, enum_def, variant_def) {
+                      try!(eval_const_expr_partial(tcx, const_expr, ty_hint, None))
                   } else {
-                      (lookup_const_by_id(tcx, def_id, Some(e.id), None), None)
+                      signal!(e, NonConstPath);
                   }
               }
-              Some(Def::Variant(enum_def, variant_def)) => {
-                  (lookup_variant_by_id(tcx, enum_def, variant_def), None)
+              Def::Struct(..) => {
+                  ConstVal::Struct(e.id)
               }
-              Some(Def::Struct(..)) => {
-                  return Ok(ConstVal::Struct(e.id))
-              }
-              Some(Def::Local(_, id)) => {
+              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());
+                      val.clone()
                   } else {
-                      (None, None)
+                      signal!(e, NonConstPath);
                   }
               },
-              Some(Def::Method(id)) | Some(Def::Fn(id)) => return Ok(Function(id)),
-              _ => (None, None)
-          };
-          let const_expr = match const_expr {
-              Some(actual_e) => actual_e,
-              None => signal!(e, NonConstPath)
-          };
-          let item_hint = match const_ty {
-              Some(ty) => match ast_ty_to_prim_ty(tcx, ty) {
-                  Some(ty) => ty_hint.checked_or(ty),
-                  None => ty_hint.erase_hint(),
-              },
-              None => ty_hint.erase_hint(),
-          };
-          try!(eval_const_expr_partial(tcx, const_expr, item_hint, fn_args))
+              Def::Method(id) | Def::Fn(id) => Function(id),
+              _ => signal!(e, NonConstPath),
+          }
       }
       hir::ExprCall(ref callee, ref args) => {
           let sub_ty_hint = ty_hint.erase_hint();
@@ -1097,28 +1058,11 @@ fn infer<'tcx>(
     }
 }
 
-fn impl_or_trait_container(tcx: &TyCtxt, def_id: DefId) -> ty::ImplOrTraitItemContainer {
-    // This is intended to be equivalent to tcx.impl_or_trait_item(def_id).container()
-    // for local def_id, but it can be called before tcx.impl_or_trait_items is complete.
-    if let Some(node_id) = tcx.map.as_local_node_id(def_id) {
-        if let Some(ast_map::NodeItem(item)) = tcx.map.find(tcx.map.get_parent_node(node_id)) {
-            let container_id = tcx.map.local_def_id(item.id);
-            match item.node {
-                hir::ItemImpl(..) => return ty::ImplContainer(container_id),
-                hir::ItemTrait(..) => return ty::TraitContainer(container_id),
-                _ => ()
-            }
-        }
-        panic!("No impl or trait container for {:?}", def_id);
-    }
-    panic!("{:?} is not local", def_id);
-}
-
 fn resolve_trait_associated_const<'a, 'tcx: 'a>(tcx: &'a TyCtxt<'tcx>,
                                                 ti: &'tcx hir::TraitItem,
                                                 trait_id: DefId,
                                                 rcvr_substs: subst::Substs<'tcx>)
-                                                -> Option<&'tcx Expr>
+                                                -> Option<(&'tcx Expr, Option<ty::Ty<'tcx>>)>
 {
     let trait_ref = ty::Binder(
         rcvr_substs.erase_regions().to_trait_ref(tcx, trait_id)
@@ -1151,7 +1095,9 @@ fn resolve_trait_associated_const<'a, 'tcx: 'a>(tcx: &'a TyCtxt<'tcx>,
                      .iter().find(|ic| ic.name == ti.name) {
                 Some(ic) => lookup_const_by_id(tcx, ic.def_id, None, None),
                 None => match ti.node {
-                    hir::ConstTraitItem(_, Some(ref expr)) => Some(&*expr),
+                    hir::ConstTraitItem(ref ty, Some(ref expr)) => {
+                        Some((&*expr, ast_ty_to_prim_ty(tcx, ty)))
+                    },
                     _ => None,
                 },
             }
index 61a7f49f45d4e7fd267db5be9e68a57633dfac3e..03c13115aea626fc91fc16747cbe1326594619f0 100644 (file)
@@ -342,8 +342,12 @@ pub struct TyCtxt<'tcx> {
     /// FIXME(arielb1): why is this separate from populated_external_types?
     pub populated_external_primitive_impls: RefCell<DefIdSet>,
 
-    /// These caches are used by const_eval when decoding external constants.
-    pub extern_const_statics: RefCell<DefIdMap<NodeId>>,
+    /// Cache used by const_eval when decoding external constants.
+    /// Contains `None` when the constant has been fetched but doesn't exist.
+    /// Constains `Some(expr_id, type)` otherwise.
+    /// `type` is `None` in case it's not a primitive type
+    pub extern_const_statics: RefCell<DefIdMap<Option<(NodeId, Option<Ty<'tcx>>)>>>,
+    /// Cache used by const_eval when decoding extern const fns
     pub extern_const_fns: RefCell<DefIdMap<NodeId>>,
 
     pub node_lint_levels: RefCell<FnvHashMap<(NodeId, lint::LintId),
index 6f4375d53ec4bf95f24531532d08b93682fa575d..d1e3f08aff894d01ea538f23b4e943bfba94bace 100644 (file)
@@ -87,7 +87,7 @@ fn to_pattern(&mut self, pat: &hir::Pat) -> Pattern<'tcx> {
                     Def::Const(def_id) | Def::AssociatedConst(def_id) =>
                         match const_eval::lookup_const_by_id(self.cx.tcx, def_id,
                                                              Some(pat.id), None) {
-                            Some(const_expr) => {
+                            Some((const_expr, _const_ty)) => {
                                 let pat = const_eval::const_expr_to_pat(self.cx.tcx, const_expr,
                                                                         pat.span);
                                 return self.to_pattern(&pat);
index 3a39a3c6dd1947ecb18c1feb08144e98114f85c6..a9e03bba7db8e0351967c18771fb545067864696 100644 (file)
@@ -604,7 +604,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
                 }
                 Some(Def::Const(did)) |
                 Some(Def::AssociatedConst(did)) => {
-                    if let Some(expr) = const_eval::lookup_const_by_id(v.tcx, did,
+                    if let Some((expr, _ty)) = const_eval::lookup_const_by_id(v.tcx, did,
                                                                        Some(e.id),
                                                                        None) {
                         let inner = v.global_expr(Mode::Const, expr);
index ebe19aa972ce540b522ff2b4b143c57b57e469b0..7d37627ad0eea53a7145e286857c7c80f8d2a77a 100644 (file)
@@ -227,7 +227,7 @@ pub fn get_const_expr<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     }
 
     match const_eval::lookup_const_by_id(ccx.tcx(), def_id, Some(ref_expr.id), Some(param_substs)) {
-        Some(ref expr) => expr,
+        Some((ref expr, _ty)) => expr,
         None => {
             ccx.sess().span_bug(ref_expr.span, "constant item not found")
         }