From 85a4a192c73f3b1f6c0d4c6fcb54532a8f820122 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 6 Jan 2017 21:54:24 +0200 Subject: [PATCH] rustc: keep track of tables everywhere as if they were per-body. --- src/Cargo.lock | 1 - src/librustc/cfg/construct.rs | 24 +- src/librustc/hir/map/blocks.rs | 19 - src/librustc/infer/mod.rs | 192 +++++++--- src/librustc/lint/context.rs | 46 ++- src/librustc/middle/const_val.rs | 15 +- src/librustc/middle/dead.rs | 47 ++- src/librustc/middle/effect.rs | 22 +- src/librustc/middle/expr_use_visitor.rs | 4 +- src/librustc/middle/intrinsicck.rs | 60 +-- src/librustc/middle/liveness.rs | 85 ++--- src/librustc/middle/mem_categorization.rs | 2 +- src/librustc/middle/reachable.rs | 41 +- src/librustc/mir/mod.rs | 11 +- src/librustc/traits/mod.rs | 4 +- src/librustc/traits/specialize/mod.rs | 4 +- .../traits/specialize/specialization_graph.rs | 2 +- src/librustc/ty/context.rs | 26 +- src/librustc/ty/maps.rs | 2 + src/librustc/ty/mod.rs | 19 +- src/librustc/ty/util.rs | 4 +- src/librustc_borrowck/borrowck/check_loans.rs | 4 +- .../borrowck/gather_loans/gather_moves.rs | 12 +- .../borrowck/gather_loans/mod.rs | 36 +- src/librustc_borrowck/borrowck/mod.rs | 33 +- src/librustc_const_eval/check_match.rs | 18 +- src/librustc_const_eval/eval.rs | 360 +++++++++--------- src/librustc_const_eval/pattern.rs | 53 +-- src/librustc_driver/pretty.rs | 20 +- src/librustc_driver/test.rs | 2 +- src/librustc_lint/builtin.rs | 51 ++- src/librustc_lint/types.rs | 25 +- src/librustc_lint/unused.rs | 4 +- src/librustc_metadata/astencode.rs | 14 +- src/librustc_metadata/encoder.rs | 2 +- src/librustc_mir/build/mod.rs | 9 +- src/librustc_mir/hair/cx/block.rs | 4 +- src/librustc_mir/hair/cx/expr.rs | 81 ++-- src/librustc_mir/hair/cx/mod.rs | 12 +- src/librustc_mir/mir_map.rs | 201 +++------- src/librustc_mir/transform/qualify_consts.rs | 2 +- src/librustc_mir/transform/type_check.rs | 2 +- src/librustc_passes/consts.rs | 65 ++-- src/librustc_passes/rvalues.rs | 27 +- src/librustc_privacy/lib.rs | 22 +- src/librustc_save_analysis/dump_visitor.rs | 50 ++- src/librustc_save_analysis/lib.rs | 36 +- src/librustc_trans/common.rs | 2 +- src/librustc_trans/context.rs | 2 +- src/librustc_trans/glue.rs | 2 +- src/librustc_trans/mir/constant.rs | 1 - src/librustc_typeck/astconv.rs | 3 +- src/librustc_typeck/check/closure.rs | 4 +- src/librustc_typeck/check/compare_method.rs | 4 +- src/librustc_typeck/check/dropck.rs | 2 +- src/librustc_typeck/check/method/probe.rs | 12 +- src/librustc_typeck/check/mod.rs | 24 +- src/librustc_typeck/check/upvar.rs | 6 +- src/librustc_typeck/check/writeback.rs | 21 +- src/librustc_typeck/coherence/builtin.rs | 2 +- src/librustc_typeck/coherence/overlap.rs | 2 +- src/librustc_typeck/collect.rs | 10 +- src/librustc_typeck/lib.rs | 2 +- src/librustdoc/Cargo.toml | 1 - src/librustdoc/clean/mod.rs | 20 +- src/librustdoc/lib.rs | 1 - src/test/compile-fail/const-eval-overflow.rs | 14 +- src/test/run-pass/issue-28189.rs | 15 - 68 files changed, 946 insertions(+), 979 deletions(-) delete mode 100644 src/test/run-pass/issue-28189.rs diff --git a/src/Cargo.lock b/src/Cargo.lock index 3da29933c812e..d153945dc091f 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -569,7 +569,6 @@ dependencies = [ "rustc 0.0.0", "rustc_back 0.0.0", "rustc_const_eval 0.0.0", - "rustc_const_math 0.0.0", "rustc_data_structures 0.0.0", "rustc_driver 0.0.0", "rustc_errors 0.0.0", diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs index 4d66bba9f07ee..35afdd75cb8c4 100644 --- a/src/librustc/cfg/construct.rs +++ b/src/librustc/cfg/construct.rs @@ -18,6 +18,7 @@ use hir::{self, PatKind}; struct CFGBuilder<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, + tables: &'a ty::Tables<'tcx>, graph: CFGGraph, fn_exit: CFGIndex, loop_scopes: Vec, @@ -42,10 +43,23 @@ pub fn construct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let fn_exit = graph.add_node(CFGNodeData::Exit); let body_exit; + // Find the function this expression is from. + let mut node_id = body.id; + loop { + let node = tcx.map.get(node_id); + if hir::map::blocks::FnLikeNode::from_node(node).is_some() { + break; + } + let parent = tcx.map.get_parent_node(node_id); + assert!(node_id != parent); + node_id = parent; + } + let mut cfg_builder = CFGBuilder { + tcx: tcx, + tables: tcx.item_tables(tcx.map.local_def_id(node_id)), graph: graph, fn_exit: fn_exit, - tcx: tcx, loop_scopes: Vec::new() }; body_exit = cfg_builder.expr(body, entry); @@ -310,11 +324,11 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { } hir::ExprIndex(ref l, ref r) | - hir::ExprBinary(_, ref l, ref r) if self.tcx.tables().is_method_call(expr.id) => { + hir::ExprBinary(_, ref l, ref r) if self.tables.is_method_call(expr.id) => { self.call(expr, pred, &l, Some(&**r).into_iter()) } - hir::ExprUnary(_, ref e) if self.tcx.tables().is_method_call(expr.id) => { + hir::ExprUnary(_, ref e) if self.tables.is_method_call(expr.id) => { self.call(expr, pred, &e, None::.iter()) } @@ -368,9 +382,9 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { func_or_rcvr: &hir::Expr, args: I) -> CFGIndex { let method_call = ty::MethodCall::expr(call_expr.id); - let fn_ty = match self.tcx.tables().method_map.get(&method_call) { + let fn_ty = match self.tables.method_map.get(&method_call) { Some(method) => method.ty, - None => self.tcx.tables().expr_ty_adjusted(func_or_rcvr) + None => self.tables.expr_ty_adjusted(func_or_rcvr) }; let func_or_rcvr_exit = self.expr(func_or_rcvr, pred); diff --git a/src/librustc/hir/map/blocks.rs b/src/librustc/hir/map/blocks.rs index 6e08b52f9a249..91e88e2c73ff8 100644 --- a/src/librustc/hir/map/blocks.rs +++ b/src/librustc/hir/map/blocks.rs @@ -45,15 +45,6 @@ pub struct FnLikeNode<'a> { node: map::Node<'a> } /// corresponds to some FnLikeNode. pub trait MaybeFnLike { fn is_fn_like(&self) -> bool; } -/// Components shared by fn-like things (fn items, methods, closures). -pub struct FnParts<'a> { - pub decl: &'a FnDecl, - pub body: ast::BodyId, - pub kind: FnKind<'a>, - pub span: Span, - pub id: NodeId, -} - impl MaybeFnLike for ast::Item { fn is_fn_like(&self) -> bool { match self.node { ast::ItemFn(..) => true, _ => false, } @@ -165,16 +156,6 @@ impl<'a> FnLikeNode<'a> { } } - pub fn to_fn_parts(self) -> FnParts<'a> { - FnParts { - decl: self.decl(), - body: self.body(), - kind: self.kind(), - span: self.span(), - id: self.id(), - } - } - pub fn body(self) -> ast::BodyId { self.handle(|i: ItemFnParts<'a>| i.body, |_, _, _: &'a ast::MethodSig, _, body: ast::BodyId, _, _| body, diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 7b6ed56b779fd..b44e1563ee7ed 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -27,7 +27,6 @@ use middle::region::CodeExtent; use middle::lang_items; use mir::tcx::LvalueTy; use ty::subst::{Kind, Subst, Substs}; -use ty::adjustment; use ty::{TyVid, IntVid, FloatVid}; use ty::{self, Ty, TyCtxt}; use ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric}; @@ -37,10 +36,11 @@ use traits::{self, ObligationCause, PredicateObligations, Reveal}; use rustc_data_structures::unify::{self, UnificationTable}; use std::cell::{Cell, RefCell, Ref, RefMut}; use std::fmt; +use std::ops::Deref; use syntax::ast; use errors::DiagnosticBuilder; use syntax_pos::{self, Span, DUMMY_SP}; -use util::nodemap::{FxHashMap, FxHashSet, NodeMap}; +use util::nodemap::{FxHashMap, FxHashSet}; use arena::DroplessArena; use self::combine::CombineFields; @@ -76,28 +76,63 @@ pub type Bound = Option; pub type UnitResult<'tcx> = RelateResult<'tcx, ()>; // "unify result" pub type FixupResult = Result; // "fixup result" -/// A version of &ty::Tables which can be global or local. -/// Only the local version supports borrow_mut. +/// A version of &ty::Tables which can be `Missing` (not needed), +/// `InProgress` (during typeck) or `Interned` (result of typeck). +/// Only the `InProgress` version supports `borrow_mut`. #[derive(Copy, Clone)] pub enum InferTables<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { - Global(&'a RefCell>), - Local(&'a RefCell>) + Interned(&'a ty::Tables<'gcx>), + InProgress(&'a RefCell>), + Missing +} + +pub enum InferTablesRef<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { + Interned(&'a ty::Tables<'gcx>), + InProgress(Ref<'a, ty::Tables<'tcx>>) +} + +impl<'a, 'gcx, 'tcx> Deref for InferTablesRef<'a, 'gcx, 'tcx> { + type Target = ty::Tables<'tcx>; + fn deref(&self) -> &Self::Target { + match *self { + InferTablesRef::Interned(tables) => tables, + InferTablesRef::InProgress(ref tables) => tables + } + } } impl<'a, 'gcx, 'tcx> InferTables<'a, 'gcx, 'tcx> { - pub fn borrow(self) -> Ref<'a, ty::Tables<'tcx>> { + pub fn borrow(self) -> InferTablesRef<'a, 'gcx, 'tcx> { match self { - InferTables::Global(tables) => tables.borrow(), - InferTables::Local(tables) => tables.borrow() + InferTables::Interned(tables) => InferTablesRef::Interned(tables), + InferTables::InProgress(tables) => InferTablesRef::InProgress(tables.borrow()), + InferTables::Missing => { + bug!("InferTables: infcx.tables.borrow() with no tables") + } + } + } + + pub fn expect_interned(self) -> &'a ty::Tables<'gcx> { + match self { + InferTables::Interned(tables) => tables, + InferTables::InProgress(_) => { + bug!("InferTables: infcx.tables.expect_interned() during type-checking"); + } + InferTables::Missing => { + bug!("InferTables: infcx.tables.expect_interned() with no tables") + } } } pub fn borrow_mut(self) -> RefMut<'a, ty::Tables<'tcx>> { match self { - InferTables::Global(_) => { + InferTables::Interned(_) => { bug!("InferTables: infcx.tables.borrow_mut() outside of type-checking"); } - InferTables::Local(tables) => tables.borrow_mut() + InferTables::InProgress(tables) => tables.borrow_mut(), + InferTables::Missing => { + bug!("InferTables: infcx.tables.borrow_mut() with no tables") + } } } } @@ -370,27 +405,84 @@ impl fmt::Display for FixupError { } } +pub trait InferEnv<'a, 'tcx> { + fn to_parts(self, tcx: TyCtxt<'a, 'tcx, 'tcx>) + -> (Option<&'a ty::Tables<'tcx>>, + Option>, + Option>); +} + +impl<'a, 'tcx> InferEnv<'a, 'tcx> for () { + fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>) + -> (Option<&'a ty::Tables<'tcx>>, + Option>, + Option>) { + (None, None, None) + } +} + +impl<'a, 'tcx> InferEnv<'a, 'tcx> for ty::ParameterEnvironment<'tcx> { + fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>) + -> (Option<&'a ty::Tables<'tcx>>, + Option>, + Option>) { + (None, None, Some(self)) + } +} + +impl<'a, 'tcx> InferEnv<'a, 'tcx> for (&'a ty::Tables<'tcx>, ty::ParameterEnvironment<'tcx>) { + fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>) + -> (Option<&'a ty::Tables<'tcx>>, + Option>, + Option>) { + (Some(self.0), None, Some(self.1)) + } +} + +impl<'a, 'tcx> InferEnv<'a, 'tcx> for (ty::Tables<'tcx>, ty::ParameterEnvironment<'tcx>) { + fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>) + -> (Option<&'a ty::Tables<'tcx>>, + Option>, + Option>) { + (None, Some(self.0), Some(self.1)) + } +} + +impl<'a, 'tcx> InferEnv<'a, 'tcx> for hir::BodyId { + fn to_parts(self, tcx: TyCtxt<'a, 'tcx, 'tcx>) + -> (Option<&'a ty::Tables<'tcx>>, + Option>, + Option>) { + let item_id = tcx.map.body_owner(self); + (Some(tcx.item_tables(tcx.map.local_def_id(item_id))), + None, + Some(ty::ParameterEnvironment::for_item(tcx, item_id))) + } +} + /// Helper type of a temporary returned by tcx.infer_ctxt(...). /// Necessary because we can't write the following bound: /// F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(InferCtxt<'b, 'gcx, 'tcx>). pub struct InferCtxtBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { global_tcx: TyCtxt<'a, 'gcx, 'gcx>, arena: DroplessArena, - tables: Option>>, + fresh_tables: Option>>, + tables: Option<&'a ty::Tables<'gcx>>, param_env: Option>, projection_mode: Reveal, } impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> { - pub fn infer_ctxt(self, - tables: Option>, - param_env: Option>, - projection_mode: Reveal) - -> InferCtxtBuilder<'a, 'gcx, 'tcx> { + pub fn infer_ctxt>(self, + env: E, + projection_mode: Reveal) + -> InferCtxtBuilder<'a, 'gcx, 'tcx> { + let (tables, fresh_tables, param_env) = env.to_parts(self); InferCtxtBuilder { global_tcx: self, arena: DroplessArena::new(), - tables: tables.map(RefCell::new), + fresh_tables: fresh_tables.map(RefCell::new), + tables: tables, param_env: param_env, projection_mode: projection_mode, } @@ -399,16 +491,17 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> { /// Fake InferCtxt with the global tcx. Used by pre-MIR borrowck /// for MemCategorizationContext/ExprUseVisitor. /// If any inference functionality is used, ICEs will occur. - pub fn borrowck_fake_infer_ctxt(self, param_env: ty::ParameterEnvironment<'gcx>) + pub fn borrowck_fake_infer_ctxt(self, body: hir::BodyId) -> InferCtxt<'a, 'gcx, 'gcx> { + let (tables, _, param_env) = body.to_parts(self); InferCtxt { tcx: self, - tables: InferTables::Global(&self.tables), + tables: InferTables::Interned(tables.unwrap()), type_variables: RefCell::new(type_variable::TypeVariableTable::new()), int_unification_table: RefCell::new(UnificationTable::new()), float_unification_table: RefCell::new(UnificationTable::new()), region_vars: RegionVarBindings::new(self), - parameter_environment: param_env, + parameter_environment: param_env.unwrap(), selection_cache: traits::SelectionCache::new(), evaluation_cache: traits::EvaluationCache::new(), projection_cache: RefCell::new(traits::ProjectionCache::new()), @@ -428,15 +521,14 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> { let InferCtxtBuilder { global_tcx, ref arena, - ref tables, + ref fresh_tables, + tables, ref mut param_env, projection_mode, } = *self; - let tables = if let Some(ref tables) = *tables { - InferTables::Local(tables) - } else { - InferTables::Global(&global_tcx.tables) - }; + let tables = tables.map(InferTables::Interned).unwrap_or_else(|| { + fresh_tables.as_ref().map_or(InferTables::Missing, InferTables::InProgress) + }); let param_env = param_env.take().unwrap_or_else(|| { global_tcx.empty_parameter_environment() }); @@ -555,7 +647,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { return value; } - self.infer_ctxt(None, None, Reveal::All).enter(|infcx| { + self.infer_ctxt((), Reveal::All).enter(|infcx| { value.trans_normalize(&infcx) }) } @@ -573,7 +665,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { return value; } - self.infer_ctxt(None, Some(env.clone()), Reveal::All).enter(|infcx| { + self.infer_ctxt(env.clone(), Reveal::All).enter(|infcx| { value.trans_normalize(&infcx) }) } @@ -1490,8 +1582,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // Even if the type may have no inference variables, during // type-checking closure types are in local tables only. let local_closures = match self.tables { - InferTables::Local(_) => ty.has_closure_types(), - InferTables::Global(_) => false + InferTables::InProgress(_) => ty.has_closure_types(), + _ => false }; if !local_closures { return ty.moves_by_default(self.tcx.global_tcx(), self.param_env(), span); @@ -1526,15 +1618,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { .map(|method| method.def_id) } - pub fn adjustments(&self) -> Ref>> { - fn project_adjustments<'a, 'tcx>(tables: &'a ty::Tables<'tcx>) - -> &'a NodeMap> { - &tables.adjustments - } - - Ref::map(self.tables.borrow(), project_adjustments) - } - pub fn is_method_call(&self, id: ast::NodeId) -> bool { self.tables.borrow().method_map.contains_key(&ty::MethodCall::expr(id)) } @@ -1555,15 +1638,17 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { def_id: DefId) -> Option { - if def_id.is_local() { - self.tables.borrow().closure_kinds.get(&def_id).cloned() - } else { - // During typeck, ALL closures are local. But afterwards, - // during trans, we see closure ids from other traits. - // That may require loading the closure data out of the - // cstore. - Some(self.tcx.closure_kind(def_id)) + if let InferTables::InProgress(tables) = self.tables { + if let Some(id) = self.tcx.map.as_local_node_id(def_id) { + return tables.borrow().closure_kinds.get(&id).cloned(); + } } + + // During typeck, ALL closures are local. But afterwards, + // during trans, we see closure ids from other traits. + // That may require loading the closure data out of the + // cstore. + Some(self.tcx.closure_kind(def_id)) } pub fn closure_type(&self, @@ -1571,14 +1656,15 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { substs: ty::ClosureSubsts<'tcx>) -> ty::ClosureTy<'tcx> { - if let InferTables::Local(tables) = self.tables { - if let Some(ty) = tables.borrow().closure_tys.get(&def_id) { - return ty.subst(self.tcx, substs.substs); + if let InferTables::InProgress(tables) = self.tables { + if let Some(id) = self.tcx.map.as_local_node_id(def_id) { + if let Some(ty) = tables.borrow().closure_tys.get(&id) { + return ty.subst(self.tcx, substs.substs); + } } } - let closure_ty = self.tcx.closure_type(def_id, substs); - closure_ty + self.tcx.closure_type(def_id, substs) } } diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index cce79820ca8da..f7f9a17ee51ee 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -27,7 +27,7 @@ use self::TargetLint::*; use dep_graph::DepNode; use middle::privacy::AccessLevels; -use ty::TyCtxt; +use ty::{self, TyCtxt}; use session::{config, early_error, Session}; use lint::{Level, LevelSource, Lint, LintId, LintPass, LintSource}; use lint::{EarlyLintPassObject, LateLintPassObject}; @@ -336,6 +336,9 @@ pub struct LateContext<'a, 'tcx: 'a> { /// Type context we're checking in. pub tcx: TyCtxt<'a, 'tcx, 'tcx>, + /// Side-tables for the body we are in. + pub tables: &'a ty::Tables<'tcx>, + /// The crate being checked. pub krate: &'a hir::Crate, @@ -703,22 +706,6 @@ impl<'a> EarlyContext<'a> { } impl<'a, 'tcx> LateContext<'a, 'tcx> { - fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, - krate: &'a hir::Crate, - access_levels: &'a AccessLevels) -> LateContext<'a, 'tcx> { - // We want to own the lint store, so move it out of the session. - let lint_store = mem::replace(&mut *tcx.sess.lint_store.borrow_mut(), - LintStore::new()); - - LateContext { - tcx: tcx, - krate: krate, - access_levels: access_levels, - lints: lint_store, - level_stack: vec![], - } - } - fn visit_ids<'b, F: 'b>(&'b mut self, f: F) where F: FnOnce(&mut IdVisitor<'b, 'a, 'tcx>) { @@ -795,6 +782,14 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> { hir_visit::NestedVisitorMap::All(&self.tcx.map) } + fn visit_nested_body(&mut self, body: hir::BodyId) { + let old_tables = self.tables; + self.tables = self.tcx.body_tables(body); + let body = self.tcx.map.body(body); + self.visit_body(body); + self.tables = old_tables; + } + fn visit_item(&mut self, it: &'tcx hir::Item) { self.with_lint_attrs(&it.attrs, |cx| { run_lints!(cx, check_item, late_passes, it); @@ -837,10 +832,15 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> { fn visit_fn(&mut self, fk: hir_visit::FnKind<'tcx>, decl: &'tcx hir::FnDecl, body_id: hir::BodyId, span: Span, id: ast::NodeId) { + // Wrap in tables here, not just in visit_nested_body, + // in order for `check_fn` to be able to use them. + let old_tables = self.tables; + self.tables = self.tcx.body_tables(body_id); let body = self.tcx.map.body(body_id); run_lints!(self, check_fn, late_passes, fk, decl, body, span, id); hir_visit::walk_fn(self, fk, decl, body_id, span, id); run_lints!(self, check_fn_post, late_passes, fk, decl, body, span, id); + self.tables = old_tables; } fn visit_variant_data(&mut self, @@ -1238,7 +1238,17 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let _task = tcx.dep_graph.in_task(DepNode::LateLintCheck); let krate = tcx.map.krate(); - let mut cx = LateContext::new(tcx, krate, access_levels); + + // We want to own the lint store, so move it out of the session. + let lint_store = mem::replace(&mut *tcx.sess.lint_store.borrow_mut(), LintStore::new()); + let mut cx = LateContext { + tcx: tcx, + tables: &ty::Tables::empty(), + krate: krate, + access_levels: access_levels, + lints: lint_store, + level_stack: vec![], + }; // Visit the whole crate. cx.with_lint_attrs(&krate.attrs, |cx| { diff --git a/src/librustc/middle/const_val.rs b/src/librustc/middle/const_val.rs index 9677082a43a3c..f583f601726ed 100644 --- a/src/librustc/middle/const_val.rs +++ b/src/librustc/middle/const_val.rs @@ -15,6 +15,8 @@ use hir::def_id::DefId; use rustc_const_math::*; use self::ConstVal::*; +use std::collections::BTreeMap; + #[derive(Clone, Debug, Hash, RustcEncodable, RustcDecodable, Eq, PartialEq)] pub enum ConstVal { Float(ConstFloat), @@ -22,16 +24,12 @@ pub enum ConstVal { Str(InternedString), ByteStr(Rc>), Bool(bool), - Struct(ast::NodeId), - Tuple(ast::NodeId), Function(DefId), - Array(ast::NodeId, u64), - Repeat(ast::NodeId, u64), + Struct(BTreeMap), + Tuple(Vec), + Array(Vec), + Repeat(Box, u64), Char(char), - /// A value that only occurs in case `eval_const_expr` reported an error. You should never - /// handle this case. Its sole purpose is to allow more errors to be reported instead of - /// causing a fatal error. - Dummy, } impl ConstVal { @@ -48,7 +46,6 @@ impl ConstVal { Array(..) => "array", Repeat(..) => "repeat", Char(..) => "char", - Dummy => "dummy value", } } } diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 00e21410c7077..5af62d0172f5c 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -49,6 +49,7 @@ fn should_explore<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, struct MarkSymbolVisitor<'a, 'tcx: 'a> { worklist: Vec, tcx: TyCtxt<'a, 'tcx, 'tcx>, + tables: &'a ty::Tables<'tcx>, live_symbols: Box>, struct_has_extern_repr: bool, ignore_non_const_paths: bool, @@ -57,19 +58,6 @@ struct MarkSymbolVisitor<'a, 'tcx: 'a> { } impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { - fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, - worklist: Vec) -> MarkSymbolVisitor<'a, 'tcx> { - MarkSymbolVisitor { - worklist: worklist, - tcx: tcx, - live_symbols: box FxHashSet(), - struct_has_extern_repr: false, - ignore_non_const_paths: false, - inherited_pub_visibility: false, - ignore_variant_stack: vec![], - } - } - fn check_def_id(&mut self, def_id: DefId) { if let Some(node_id) = self.tcx.map.as_local_node_id(def_id) { if should_explore(self.tcx, node_id) { @@ -109,12 +97,12 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { fn lookup_and_handle_method(&mut self, id: ast::NodeId) { let method_call = ty::MethodCall::expr(id); - let method = self.tcx.tables().method_map[&method_call]; + let method = self.tables.method_map[&method_call]; self.check_def_id(method.def_id); } fn handle_field_access(&mut self, lhs: &hir::Expr, name: ast::Name) { - match self.tcx.tables().expr_ty_adjusted(lhs).sty { + match self.tables.expr_ty_adjusted(lhs).sty { ty::TyAdt(def, _) => { self.insert_def_id(def.struct_variant().field_named(name).did); } @@ -123,7 +111,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { } fn handle_tup_field_access(&mut self, lhs: &hir::Expr, idx: usize) { - match self.tcx.tables().expr_ty_adjusted(lhs).sty { + match self.tables.expr_ty_adjusted(lhs).sty { ty::TyAdt(def, _) => { self.insert_def_id(def.struct_variant().fields[idx].did); } @@ -134,7 +122,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { fn handle_field_pattern_match(&mut self, lhs: &hir::Pat, def: Def, pats: &[codemap::Spanned]) { - let variant = match self.tcx.tables().node_id_to_type(lhs.id).sty { + let variant = match self.tables.node_id_to_type(lhs.id).sty { ty::TyAdt(adt, _) => adt.variant_of_def(def), _ => span_bug!(lhs.span, "non-ADT in struct pattern") }; @@ -209,7 +197,15 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::OnlyBodies(&self.tcx.map) + NestedVisitorMap::None + } + + fn visit_nested_body(&mut self, body: hir::BodyId) { + let old_tables = self.tables; + self.tables = self.tcx.body_tables(body); + let body = self.tcx.map.body(body); + self.visit_body(body); + self.tables = old_tables; } fn visit_variant_data(&mut self, def: &'tcx hir::VariantData, _: ast::Name, @@ -227,7 +223,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &'tcx hir::Expr) { match expr.node { hir::ExprPath(ref qpath @ hir::QPath::TypeRelative(..)) => { - let def = self.tcx.tables().qpath_def(qpath, expr.id); + let def = self.tables.qpath_def(qpath, expr.id); self.handle_definition(def); } hir::ExprMethodCall(..) => { @@ -267,7 +263,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> { self.handle_field_pattern_match(pat, path.def, fields); } PatKind::Path(ref qpath @ hir::QPath::TypeRelative(..)) => { - let def = self.tcx.tables().qpath_def(qpath, pat.id); + let def = self.tables.qpath_def(qpath, pat.id); self.handle_definition(def); } _ => () @@ -393,7 +389,16 @@ fn find_live<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, krate: &hir::Crate) -> Box> { let worklist = create_and_seed_worklist(tcx, access_levels, krate); - let mut symbol_visitor = MarkSymbolVisitor::new(tcx, worklist); + let mut symbol_visitor = MarkSymbolVisitor { + worklist: worklist, + tcx: tcx, + tables: &ty::Tables::empty(), + live_symbols: box FxHashSet(), + struct_has_extern_repr: false, + ignore_non_const_paths: false, + inherited_pub_visibility: false, + ignore_variant_stack: vec![], + }; symbol_visitor.mark_live_symbols(); symbol_visitor.live_symbols } diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs index 38b0b18b0129a..c42e8fcb08ced 100644 --- a/src/librustc/middle/effect.rs +++ b/src/librustc/middle/effect.rs @@ -52,6 +52,7 @@ fn type_is_unsafe_function(ty: Ty) -> bool { struct EffectCheckVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, + tables: &'a ty::Tables<'tcx>, /// Whether we're in an unsafe context. unsafe_context: UnsafeContext, @@ -94,7 +95,15 @@ impl<'a, 'tcx> EffectCheckVisitor<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for EffectCheckVisitor<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::OnlyBodies(&self.tcx.map) + NestedVisitorMap::None + } + + fn visit_nested_body(&mut self, body: hir::BodyId) { + let old_tables = self.tables; + self.tables = self.tcx.body_tables(body); + let body = self.tcx.map.body(body); + self.visit_body(body); + self.tables = old_tables; } fn visit_fn(&mut self, fn_kind: FnKind<'tcx>, fn_decl: &'tcx hir::FnDecl, @@ -163,7 +172,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EffectCheckVisitor<'a, 'tcx> { match expr.node { hir::ExprMethodCall(..) => { let method_call = MethodCall::expr(expr.id); - let base_type = self.tcx.tables().method_map[&method_call].ty; + let base_type = self.tables.method_map[&method_call].ty; debug!("effect: method call case, base type is {:?}", base_type); if type_is_unsafe_function(base_type) { @@ -172,7 +181,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EffectCheckVisitor<'a, 'tcx> { } } hir::ExprCall(ref base, _) => { - let base_type = self.tcx.tables().expr_ty_adjusted(base); + let base_type = self.tables.expr_ty_adjusted(base); debug!("effect: call case, base type is {:?}", base_type); if type_is_unsafe_function(base_type) { @@ -180,7 +189,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EffectCheckVisitor<'a, 'tcx> { } } hir::ExprUnary(hir::UnDeref, ref base) => { - let base_type = self.tcx.tables().expr_ty_adjusted(base); + let base_type = self.tables.expr_ty_adjusted(base); debug!("effect: unary case, base type is {:?}", base_type); if let ty::TyRawPtr(_) = base_type.sty { @@ -204,7 +213,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EffectCheckVisitor<'a, 'tcx> { } } hir::ExprField(ref base_expr, field) => { - if let ty::TyAdt(adt, ..) = self.tcx.tables().expr_ty_adjusted(base_expr).sty { + if let ty::TyAdt(adt, ..) = self.tables.expr_ty_adjusted(base_expr).sty { if adt.is_union() { self.require_unsafe(field.span, "access to union field"); } @@ -218,7 +227,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EffectCheckVisitor<'a, 'tcx> { fn visit_pat(&mut self, pat: &'tcx hir::Pat) { if let PatKind::Struct(_, ref fields, _) = pat.node { - if let ty::TyAdt(adt, ..) = self.tcx.tables().pat_ty(pat).sty { + if let ty::TyAdt(adt, ..) = self.tables.pat_ty(pat).sty { if adt.is_union() { for field in fields { self.require_unsafe(field.span, "matching on union field"); @@ -236,6 +245,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { let mut visitor = EffectCheckVisitor { tcx: tcx, + tables: &ty::Tables::empty(), unsafe_context: UnsafeContext::new(SafeContext), }; diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index a3a49c916338e..0eacbba3fdd44 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -708,7 +708,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { fn walk_adjustment(&mut self, expr: &hir::Expr) { let infcx = self.mc.infcx; //NOTE(@jroesch): mixed RefCell borrow causes crash - let adj = infcx.adjustments().get(&expr.id).map(|x| x.clone()); + let adj = infcx.tables.borrow().adjustments.get(&expr.id).map(|x| x.clone()); if let Some(adjustment) = adj { match adjustment.kind { adjustment::Adjust::NeverToAny | @@ -989,7 +989,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { PatKind::Struct(ref qpath, ..) => qpath, _ => return }; - let def = tcx.tables().qpath_def(qpath, pat.id); + let def = infcx.tables.borrow().qpath_def(qpath, pat.id); match def { Def::Variant(variant_did) | Def::VariantCtor(variant_did, ..) => { diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs index d932061d42d3d..d42b866d47209 100644 --- a/src/librustc/middle/intrinsicck.rs +++ b/src/librustc/middle/intrinsicck.rs @@ -19,7 +19,7 @@ use ty::layout::{LayoutError, Pointer, SizeSkeleton}; use syntax::abi::Abi::RustIntrinsic; use syntax::ast; use syntax_pos::Span; -use hir::intravisit::{self, Visitor, FnKind, NestedVisitorMap}; +use hir::intravisit::{self, Visitor, NestedVisitorMap}; use hir; pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { @@ -33,18 +33,6 @@ struct ItemVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx> } -impl<'a, 'tcx> ItemVisitor<'a, 'tcx> { - fn visit_const(&mut self, item_id: ast::NodeId, body: hir::BodyId) { - let param_env = ty::ParameterEnvironment::for_item(self.tcx, item_id); - self.tcx.infer_ctxt(None, Some(param_env), Reveal::All).enter(|infcx| { - let mut visitor = ExprVisitor { - infcx: &infcx - }; - visitor.visit_nested_body(body); - }); - } -} - struct ExprVisitor<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { infcx: &'a InferCtxt<'a, 'gcx, 'tcx> } @@ -118,64 +106,36 @@ impl<'a, 'gcx, 'tcx> ExprVisitor<'a, 'gcx, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for ItemVisitor<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::OnlyBodies(&self.tcx.map) + NestedVisitorMap::None } - // const, static and N in [T; N]. - fn visit_body(&mut self, body: &'tcx hir::Body) { - self.tcx.infer_ctxt(None, None, Reveal::All).enter(|infcx| { + fn visit_nested_body(&mut self, body_id: hir::BodyId) { + let body = self.tcx.map.body(body_id); + self.tcx.infer_ctxt(body_id, Reveal::All).enter(|infcx| { let mut visitor = ExprVisitor { infcx: &infcx }; visitor.visit_body(body); }); - } - - fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem) { - if let hir::TraitItemKind::Const(_, Some(body)) = item.node { - self.visit_const(item.id, body); - } else { - intravisit::walk_trait_item(self, item); - } - } - - fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem) { - if let hir::ImplItemKind::Const(_, body) = item.node { - self.visit_const(item.id, body); - } else { - intravisit::walk_impl_item(self, item); - } - } - - fn visit_fn(&mut self, fk: FnKind<'tcx>, fd: &'tcx hir::FnDecl, - b: hir::BodyId, s: Span, id: ast::NodeId) { - if let FnKind::Closure(..) = fk { - span_bug!(s, "intrinsicck: closure outside of function") - } - let param_env = ty::ParameterEnvironment::for_item(self.tcx, id); - self.tcx.infer_ctxt(None, Some(param_env), Reveal::All).enter(|infcx| { - let mut visitor = ExprVisitor { - infcx: &infcx - }; - visitor.visit_fn(fk, fd, b, s, id); - }); + self.visit_body(body); } } impl<'a, 'gcx, 'tcx> Visitor<'gcx> for ExprVisitor<'a, 'gcx, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> { - NestedVisitorMap::OnlyBodies(&self.infcx.tcx.map) + NestedVisitorMap::None } fn visit_expr(&mut self, expr: &'gcx hir::Expr) { let def = if let hir::ExprPath(ref qpath) = expr.node { - self.infcx.tcx.tables().qpath_def(qpath, expr.id) + self.infcx.tables.borrow().qpath_def(qpath, expr.id) } else { Def::Err }; match def { Def::Fn(did) if self.def_id_is_transmute(did) => { - let typ = self.infcx.tcx.tables().node_id_to_type(expr.id); + let typ = self.infcx.tables.borrow().node_id_to_type(expr.id); + let typ = self.infcx.tcx.lift_to_global(&typ).unwrap(); match typ.sty { ty::TyFnDef(.., ref bare_fn_ty) if bare_fn_ty.abi == RustIntrinsic => { let from = bare_fn_ty.sig.skip_binder().inputs()[0]; diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 745a94a5ddba3..5307b4ec77452 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -351,22 +351,6 @@ impl<'a, 'tcx> IrMaps<'a, 'tcx> { } } -impl<'a, 'tcx> Visitor<'tcx> for Liveness<'a, 'tcx> { - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::None - } - - fn visit_local(&mut self, l: &'tcx hir::Local) { - check_local(self, l); - } - fn visit_expr(&mut self, ex: &'tcx Expr) { - check_expr(self, ex); - } - fn visit_arm(&mut self, a: &'tcx hir::Arm) { - check_arm(self, a); - } -} - fn visit_fn<'a, 'tcx: 'a>(ir: &mut IrMaps<'a, 'tcx>, fk: FnKind<'tcx>, decl: &'tcx hir::FnDecl, @@ -394,24 +378,13 @@ fn visit_fn<'a, 'tcx: 'a>(ir: &mut IrMaps<'a, 'tcx>, // and so forth: intravisit::walk_fn(&mut fn_maps, fk, decl, body_id, sp, id); - // Special nodes and variables: - // - exit_ln represents the end of the fn, either by return or panic - // - implicit_ret_var is a pseudo-variable that represents - // an implicit return - let specials = Specials { - exit_ln: fn_maps.add_live_node(ExitNode), - fallthrough_ln: fn_maps.add_live_node(ExitNode), - no_ret_var: fn_maps.add_variable(ImplicitRet), - clean_exit_var: fn_maps.add_variable(CleanExit) - }; - // compute liveness - let mut lsets = Liveness::new(&mut fn_maps, specials); + let mut lsets = Liveness::new(&mut fn_maps, body_id); let entry_ln = lsets.compute(&body.value); // check for various error conditions lsets.visit_body(body); - lsets.check_ret(id, sp, fk, entry_ln, body); + lsets.check_ret(id, sp, entry_ln, body); lsets.warn_about_unused_args(body, entry_ln); } @@ -539,6 +512,7 @@ const ACC_USE: u32 = 4; struct Liveness<'a, 'tcx: 'a> { ir: &'a mut IrMaps<'a, 'tcx>, + tables: &'a ty::Tables<'tcx>, s: Specials, successors: Vec, users: Vec, @@ -553,11 +527,26 @@ struct Liveness<'a, 'tcx: 'a> { } impl<'a, 'tcx> Liveness<'a, 'tcx> { - fn new(ir: &'a mut IrMaps<'a, 'tcx>, specials: Specials) -> Liveness<'a, 'tcx> { + fn new(ir: &'a mut IrMaps<'a, 'tcx>, body: hir::BodyId) -> Liveness<'a, 'tcx> { + // Special nodes and variables: + // - exit_ln represents the end of the fn, either by return or panic + // - implicit_ret_var is a pseudo-variable that represents + // an implicit return + let specials = Specials { + exit_ln: ir.add_live_node(ExitNode), + fallthrough_ln: ir.add_live_node(ExitNode), + no_ret_var: ir.add_variable(ImplicitRet), + clean_exit_var: ir.add_variable(CleanExit) + }; + + let tables = ir.tcx.body_tables(body); + let num_live_nodes = ir.num_live_nodes; let num_vars = ir.num_vars; + Liveness { ir: ir, + tables: tables, s: specials, successors: vec![invalid_node(); num_live_nodes], users: vec![invalid_users(); num_live_nodes * num_vars], @@ -1065,7 +1054,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { hir::ExprAssignOp(_, ref l, ref r) => { // an overloaded assign op is like a method call - if self.ir.tcx.tables().is_method_call(expr.id) { + if self.tables.is_method_call(expr.id) { let succ = self.propagate_through_expr(&l, succ); self.propagate_through_expr(&r, succ) } else { @@ -1092,8 +1081,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { hir::ExprCall(ref f, ref args) => { // FIXME(canndrew): This is_never should really be an is_uninhabited - let diverges = !self.ir.tcx.tables().is_method_call(expr.id) && - self.ir.tcx.tables().expr_ty_adjusted(&f).fn_ret().0.is_never(); + let diverges = !self.tables.is_method_call(expr.id) && + self.tables.expr_ty_adjusted(&f).fn_ret().0.is_never(); let succ = if diverges { self.s.exit_ln } else { @@ -1105,7 +1094,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { hir::ExprMethodCall(.., ref args) => { let method_call = ty::MethodCall::expr(expr.id); - let method_ty = self.ir.tcx.tables().method_map[&method_call].ty; + let method_ty = self.tables.method_map[&method_call].ty; // FIXME(canndrew): This is_never should really be an is_uninhabited let succ = if method_ty.fn_ret().0.is_never() { self.s.exit_ln @@ -1355,6 +1344,22 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { // _______________________________________________________________________ // Checking for error conditions +impl<'a, 'tcx> Visitor<'tcx> for Liveness<'a, 'tcx> { + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { + NestedVisitorMap::None + } + + fn visit_local(&mut self, l: &'tcx hir::Local) { + check_local(self, l); + } + fn visit_expr(&mut self, ex: &'tcx Expr) { + check_expr(self, ex); + } + fn visit_arm(&mut self, a: &'tcx hir::Arm) { + check_arm(self, a); + } +} + fn check_local<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, local: &'tcx hir::Local) { match local.init { Some(_) => { @@ -1389,7 +1394,7 @@ fn check_expr<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, expr: &'tcx Expr) { } hir::ExprAssignOp(_, ref l, _) => { - if !this.ir.tcx.tables().is_method_call(expr.id) { + if !this.tables.is_method_call(expr.id) { this.check_lvalue(&l); } @@ -1432,15 +1437,10 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { fn check_ret(&self, id: NodeId, sp: Span, - fk: FnKind, entry_ln: LiveNode, body: &hir::Body) { - let fn_ty = if let FnKind::Closure(_) = fk { - self.ir.tcx.tables().node_id_to_type(id) - } else { - self.ir.tcx.item_type(self.ir.tcx.map.local_def_id(id)) - }; + let fn_ty = self.ir.tcx.item_type(self.ir.tcx.map.local_def_id(id)); let fn_ret = match fn_ty.sty { ty::TyClosure(closure_def_id, substs) => self.ir.tcx.closure_type(closure_def_id, substs).sig.output(), @@ -1457,8 +1457,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { if !fn_ret.is_never() && self.live_on_entry(entry_ln, self.s.no_ret_var).is_some() { let param_env = ParameterEnvironment::for_item(self.ir.tcx, id); let t_ret_subst = fn_ret.subst(self.ir.tcx, ¶m_env.free_substs); - let is_nil = self.ir.tcx.infer_ctxt(None, Some(param_env), - Reveal::All).enter(|infcx| { + let is_nil = self.ir.tcx.infer_ctxt(param_env, Reveal::All).enter(|infcx| { let cause = traits::ObligationCause::dummy(); traits::fully_normalize(&infcx, cause, &t_ret_subst).unwrap().is_nil() }); diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 2d88567b8b873..92e69d7d72957 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -384,7 +384,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { } pub fn cat_expr(&self, expr: &hir::Expr) -> McResult> { - match self.infcx.adjustments().get(&expr.id) { + match self.infcx.tables.borrow().adjustments.get(&expr.id) { None => { // No adjustments. self.cat_expr_unadjusted(expr) diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index 765d93742d8fb..6eaf3448d0284 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -79,6 +79,7 @@ fn method_might_be_inlined<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, struct ReachableContext<'a, 'tcx: 'a> { // The type context. tcx: TyCtxt<'a, 'tcx, 'tcx>, + tables: &'a ty::Tables<'tcx>, // The set of items which must be exported in the linkage sense. reachable_symbols: NodeSet, // A worklist of item IDs. Each item ID in this worklist will be inlined @@ -90,17 +91,25 @@ struct ReachableContext<'a, 'tcx: 'a> { impl<'a, 'tcx> Visitor<'tcx> for ReachableContext<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::OnlyBodies(&self.tcx.map) + NestedVisitorMap::None + } + + fn visit_nested_body(&mut self, body: hir::BodyId) { + let old_tables = self.tables; + self.tables = self.tcx.body_tables(body); + let body = self.tcx.map.body(body); + self.visit_body(body); + self.tables = old_tables; } fn visit_expr(&mut self, expr: &'tcx hir::Expr) { let def = match expr.node { hir::ExprPath(ref qpath) => { - Some(self.tcx.tables().qpath_def(qpath, expr.id)) + Some(self.tables.qpath_def(qpath, expr.id)) } hir::ExprMethodCall(..) => { let method_call = ty::MethodCall::expr(expr.id); - let def_id = self.tcx.tables.borrow().method_map[&method_call].def_id; + let def_id = self.tables.method_map[&method_call].def_id; Some(Def::Method(def_id)) } _ => None @@ -135,20 +144,6 @@ impl<'a, 'tcx> Visitor<'tcx> for ReachableContext<'a, 'tcx> { } impl<'a, 'tcx> ReachableContext<'a, 'tcx> { - // Creates a new reachability computation context. - fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ReachableContext<'a, 'tcx> { - let any_library = tcx.sess.crate_types.borrow().iter().any(|ty| { - *ty == config::CrateTypeRlib || *ty == config::CrateTypeDylib || - *ty == config::CrateTypeProcMacro - }); - ReachableContext { - tcx: tcx, - reachable_symbols: NodeSet(), - worklist: Vec::new(), - any_library: any_library, - } - } - // Returns true if the given def ID represents a local item that is // eligible for inlining and false otherwise. fn def_id_represents_local_inlined_item(&self, def_id: DefId) -> bool { @@ -369,7 +364,17 @@ pub fn find_reachable<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, -> NodeSet { let _task = tcx.dep_graph.in_task(DepNode::Reachability); - let mut reachable_context = ReachableContext::new(tcx); + let any_library = tcx.sess.crate_types.borrow().iter().any(|ty| { + *ty == config::CrateTypeRlib || *ty == config::CrateTypeDylib || + *ty == config::CrateTypeProcMacro + }); + let mut reachable_context = ReachableContext { + tcx: tcx, + tables: &ty::Tables::empty(), + reachable_symbols: NodeSet(), + worklist: Vec::new(), + any_library: any_library, + }; // Step 1: Seed the worklist with all nodes which were found to be public as // a result of the privacy pass along with all local lang items and impl items. diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 1d0e95245ea2d..5bae0e347f7c4 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -29,7 +29,7 @@ use std::fmt::{self, Debug, Formatter, Write}; use std::{iter, u32}; use std::ops::{Index, IndexMut}; use std::vec::IntoIter; -use syntax::ast::{self, Name}; +use syntax::ast::Name; use syntax_pos::Span; mod cache; @@ -1271,17 +1271,12 @@ fn fmt_const_val(fmt: &mut W, const_val: &ConstVal) -> fmt::Result { } Bool(b) => write!(fmt, "{:?}", b), Function(def_id) => write!(fmt, "{}", item_path_str(def_id)), - Struct(node_id) | Tuple(node_id) | Array(node_id, _) | Repeat(node_id, _) => - write!(fmt, "{}", node_to_string(node_id)), + Struct(_) | Tuple(_) | Array(_) | Repeat(..) => + bug!("ConstVal `{:?}` should not be in MIR", const_val), Char(c) => write!(fmt, "{:?}", c), - Dummy => bug!(), } } -fn node_to_string(node_id: ast::NodeId) -> String { - ty::tls::with(|tcx| tcx.map.node_to_user_string(node_id)) -} - fn item_path_str(def_id: DefId) -> String { ty::tls::with(|tcx| tcx.item_path_str(def_id)) } diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 5c5bf130c3ba4..4893e24091127 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -474,7 +474,7 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let elaborated_env = unnormalized_env.with_caller_bounds(predicates); - tcx.infer_ctxt(None, Some(elaborated_env), Reveal::NotSpecializable).enter(|infcx| { + tcx.infer_ctxt(elaborated_env, Reveal::NotSpecializable).enter(|infcx| { let predicates = match fully_normalize(&infcx, cause, &infcx.parameter_environment.caller_bounds) { Ok(predicates) => predicates, @@ -576,7 +576,7 @@ pub fn normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, debug!("normalize_and_test_predicates(predicates={:?})", predicates); - tcx.infer_ctxt(None, None, Reveal::All).enter(|infcx| { + tcx.infer_ctxt((), Reveal::All).enter(|infcx| { let mut selcx = SelectionContext::new(&infcx); let mut fulfill_cx = FulfillmentContext::new(); let cause = ObligationCause::dummy(); diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index 59e3d398b2fd3..0fe054b30ba31 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -123,7 +123,7 @@ pub fn find_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let ancestors = trait_def.ancestors(impl_data.impl_def_id); match ancestors.defs(tcx, name, ty::AssociatedKind::Method).next() { Some(node_item) => { - let substs = tcx.infer_ctxt(None, None, Reveal::All).enter(|infcx| { + let substs = tcx.infer_ctxt((), Reveal::All).enter(|infcx| { let substs = substs.rebase_onto(tcx, trait_def_id, impl_data.substs); let substs = translate_substs(&infcx, impl_data.impl_def_id, substs, node_item.node); @@ -189,7 +189,7 @@ pub fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, .subst(tcx, &penv.free_substs); // Create a infcx, taking the predicates of impl1 as assumptions: - let result = tcx.infer_ctxt(None, Some(penv), Reveal::ExactMatch).enter(|infcx| { + let result = tcx.infer_ctxt(penv, Reveal::ExactMatch).enter(|infcx| { // Normalize the trait reference. The WF rules ought to ensure // that this always succeeds. let impl1_trait_ref = diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs index a41523f2def76..368b1fb4bcbd3 100644 --- a/src/librustc/traits/specialize/specialization_graph.rs +++ b/src/librustc/traits/specialize/specialization_graph.rs @@ -108,7 +108,7 @@ impl<'a, 'gcx, 'tcx> Children { let possible_sibling = *slot; let tcx = tcx.global_tcx(); - let (le, ge) = tcx.infer_ctxt(None, None, Reveal::ExactMatch).enter(|infcx| { + let (le, ge) = tcx.infer_ctxt((), Reveal::ExactMatch).enter(|infcx| { let overlap = traits::overlapping_impls(&infcx, possible_sibling, impl_def_id); diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 644df8741e853..0860881bf6bd5 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -211,13 +211,11 @@ pub struct Tables<'tcx> { /// Borrows pub upvar_capture_map: ty::UpvarCaptureMap<'tcx>, - /// Records the type of each closure. The def ID is the ID of the - /// expression defining the closure. - pub closure_tys: DefIdMap>, + /// Records the type of each closure. + pub closure_tys: NodeMap>, - /// Records the type of each closure. The def ID is the ID of the - /// expression defining the closure. - pub closure_kinds: DefIdMap, + /// Records the type of each closure. + pub closure_kinds: NodeMap, /// For each fn, records the "liberated" types of its arguments /// and return type. Liberated means that all bound regions @@ -233,7 +231,7 @@ pub struct Tables<'tcx> { pub fru_field_types: NodeMap>> } -impl<'a, 'gcx, 'tcx> Tables<'tcx> { +impl<'tcx> Tables<'tcx> { pub fn empty() -> Tables<'tcx> { Tables { type_relative_path_defs: NodeMap(), @@ -242,8 +240,8 @@ impl<'a, 'gcx, 'tcx> Tables<'tcx> { adjustments: NodeMap(), method_map: FxHashMap(), upvar_capture_map: FxHashMap(), - closure_tys: DefIdMap(), - closure_kinds: DefIdMap(), + closure_tys: NodeMap(), + closure_kinds: NodeMap(), liberated_fn_sigs: NodeMap(), fru_field_types: NodeMap() } @@ -524,6 +522,14 @@ pub struct GlobalCtxt<'tcx> { /// Caches CoerceUnsized kinds for impls on custom types. pub custom_coerce_unsized_kinds: RefCell>, + /// Records the type of each closure. The def ID is the ID of the + /// expression defining the closure. + pub closure_tys: RefCell>>, + + /// Records the type of each closure. The def ID is the ID of the + /// expression defining the closure. + pub closure_kinds: RefCell>>, + /// Maps a cast expression to its kind. This is keyed on the /// *from* expression of the cast, not the cast itself. pub cast_kinds: RefCell>, @@ -777,6 +783,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { repr_hint_cache: RefCell::new(DepTrackingMap::new(dep_graph.clone())), rvalue_promotable_to_static: RefCell::new(NodeMap()), custom_coerce_unsized_kinds: RefCell::new(DefIdMap()), + closure_tys: RefCell::new(DepTrackingMap::new(dep_graph.clone())), + closure_kinds: RefCell::new(DepTrackingMap::new(dep_graph.clone())), cast_kinds: RefCell::new(NodeMap()), fragment_infos: RefCell::new(DefIdMap()), crate_name: Symbol::intern(crate_name), diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index 42b3544421f8b..b2337372805a9 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -46,3 +46,5 @@ dep_map_ty! { ItemVariances: ItemSignature(DefId) -> Rc> } dep_map_ty! { InherentImpls: InherentImpls(DefId) -> Vec } dep_map_ty! { ReprHints: ReprHints(DefId) -> Rc> } dep_map_ty! { Mir: Mir(DefId) -> &'tcx RefCell> } +dep_map_ty! { ClosureKinds: ItemSignature(DefId) -> ty::ClosureKind } +dep_map_ty! { ClosureTypes: ItemSignature(DefId) -> ty::ClosureTy<'tcx> } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index fa62e893a2875..86a9372989dc5 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1921,6 +1921,17 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.tables.borrow() } + pub fn body_tables(self, body: hir::BodyId) -> &'a Tables<'gcx> { + self.item_tables(self.map.body_owner_def_id(body)) + } + + pub fn item_tables(self, _def_id: DefId) -> &'a Tables<'gcx> { + // HACK(eddyb) temporarily work around RefCell until proper per-body tables + unsafe { + mem::transmute::<&Tables, &Tables>(&self.tables()) + } + } + pub fn expr_span(self, id: NodeId) -> Span { match self.map.find(id) { Some(ast_map::NodeExpr(e)) => { @@ -2454,12 +2465,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // If this is a local def-id, it should be inserted into the // tables by typeck; else, it will be retreived from // the external crate metadata. - if let Some(&kind) = self.tables.borrow().closure_kinds.get(&def_id) { + if let Some(&kind) = self.closure_kinds.borrow().get(&def_id) { return kind; } let kind = self.sess.cstore.closure_kind(def_id); - self.tables.borrow_mut().closure_kinds.insert(def_id, kind); + self.closure_kinds.borrow_mut().insert(def_id, kind); kind } @@ -2471,12 +2482,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // If this is a local def-id, it should be inserted into the // tables by typeck; else, it will be retreived from // the external crate metadata. - if let Some(ty) = self.tables.borrow().closure_tys.get(&def_id) { + if let Some(ty) = self.closure_tys.borrow().get(&def_id) { return ty.subst(self, substs.substs); } let ty = self.sess.cstore.closure_ty(self.global_tcx(), def_id); - self.tables.borrow_mut().closure_tys.insert(def_id, ty.clone()); + self.closure_tys.borrow_mut().insert(def_id, ty.clone()); ty.subst(self, substs.substs) } diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 0b1030f74b0fd..65bec9ecdaf95 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -146,7 +146,7 @@ impl<'tcx> ParameterEnvironment<'tcx> { self_type: Ty<'tcx>, span: Span) -> Result<(), CopyImplementationError> { // FIXME: (@jroesch) float this code up - tcx.infer_ctxt(None, Some(self.clone()), Reveal::NotSpecializable).enter(|infcx| { + tcx.infer_ctxt(self.clone(), Reveal::NotSpecializable).enter(|infcx| { let (adt, substs) = match self_type.sty { ty::TyAdt(adt, substs) => (adt, substs), _ => return Err(CopyImplementationError::NotAnAdt) @@ -536,7 +536,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> { } } let result = - tcx.infer_ctxt(None, Some(param_env.clone()), Reveal::ExactMatch) + tcx.infer_ctxt(param_env.clone(), Reveal::ExactMatch) .enter(|infcx| { traits::type_known_to_meet_bound(&infcx, self, def_id, span) }); diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index dc2214dd34e72..0605644d497db 100644 --- a/src/librustc_borrowck/borrowck/check_loans.rs +++ b/src/librustc_borrowck/borrowck/check_loans.rs @@ -188,12 +188,10 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, dfcx_loans: &LoanDataFlow<'b, 'tcx>, move_data: &move_data::FlowedMoveData<'c, 'tcx>, all_loans: &[Loan<'tcx>], - fn_id: ast::NodeId, body: &hir::Body) { debug!("check_loans(body id={})", body.value.id); - let param_env = ty::ParameterEnvironment::for_item(bccx.tcx, fn_id); - let infcx = bccx.tcx.borrowck_fake_infer_ctxt(param_env); + let infcx = bccx.tcx.borrowck_fake_infer_ctxt(body.id()); let mut clcx = CheckLoanCtxt { bccx: bccx, dfcx_loans: dfcx_loans, diff --git a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs index 2c277c04a52e3..c33ced52e2bd6 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs @@ -18,7 +18,7 @@ use rustc::middle::expr_use_visitor as euv; use rustc::middle::mem_categorization as mc; use rustc::middle::mem_categorization::Categorization; use rustc::middle::mem_categorization::InteriorOffsetKind as Kind; -use rustc::ty; +use rustc::ty::{self, Ty}; use std::rc::Rc; use syntax::ast; @@ -34,12 +34,10 @@ struct GatherMoveInfo<'tcx> { pub fn gather_decl<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, move_data: &MoveData<'tcx>, - decl_id: ast::NodeId, - _decl_span: Span, - var_id: ast::NodeId) { - let ty = bccx.tcx.tables().node_id_to_type(var_id); - let loan_path = Rc::new(LoanPath::new(LpVar(var_id), ty)); - move_data.add_move(bccx.tcx, loan_path, decl_id, Declared); + var_id: ast::NodeId, + var_ty: Ty<'tcx>) { + let loan_path = Rc::new(LoanPath::new(LpVar(var_id), var_ty)); + move_data.add_move(bccx.tcx, loan_path, var_id, Declared); } pub fn gather_move_from_expr<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs index 34f1ad57c6211..7101d843b4ce3 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs @@ -18,6 +18,7 @@ use borrowck::*; use borrowck::move_data::MoveData; +use rustc::infer::InferCtxt; use rustc::middle::expr_use_visitor as euv; use rustc::middle::mem_categorization as mc; use rustc::middle::mem_categorization::Categorization; @@ -25,7 +26,6 @@ use rustc::middle::region; use rustc::ty::{self, TyCtxt}; use syntax::ast; -use syntax::ast::NodeId; use syntax_pos::Span; use rustc::hir; use rustc::hir::Expr; @@ -40,20 +40,20 @@ mod gather_moves; mod move_error; pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, - fn_id: NodeId, - body: &hir::Body) + body: hir::BodyId) -> (Vec>, move_data::MoveData<'tcx>) { + let infcx = bccx.tcx.borrowck_fake_infer_ctxt(body); let mut glcx = GatherLoanCtxt { bccx: bccx, + infcx: &infcx, all_loans: Vec::new(), - item_ub: bccx.tcx.region_maps.node_extent(body.value.id), + item_ub: bccx.tcx.region_maps.node_extent(body.node_id), move_data: MoveData::new(), move_error_collector: move_error::MoveErrorCollector::new(), }; - let param_env = ty::ParameterEnvironment::for_item(bccx.tcx, fn_id); - let infcx = bccx.tcx.borrowck_fake_infer_ctxt(param_env); + let body = glcx.bccx.tcx.map.body(body); euv::ExprUseVisitor::new(&mut glcx, &infcx).consume_body(body); glcx.report_potential_errors(); @@ -63,6 +63,7 @@ pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, struct GatherLoanCtxt<'a, 'tcx: 'a> { bccx: &'a BorrowckCtxt<'a, 'tcx>, + infcx: &'a InferCtxt<'a, 'tcx, 'tcx>, move_data: move_data::MoveData<'tcx>, move_error_collector: move_error::MoveErrorCollector<'tcx>, all_loans: Vec>, @@ -158,8 +159,9 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> { mode); } - fn decl_without_init(&mut self, id: ast::NodeId, span: Span) { - gather_moves::gather_decl(self.bccx, &self.move_data, id, span, id); + fn decl_without_init(&mut self, id: ast::NodeId, _span: Span) { + let ty = self.infcx.tables.borrow().node_id_to_type(id); + gather_moves::gather_decl(self.bccx, &self.move_data, id, ty); } } @@ -516,19 +518,17 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> { /// sure the loans being taken are sound. struct StaticInitializerCtxt<'a, 'tcx: 'a> { bccx: &'a BorrowckCtxt<'a, 'tcx>, - item_id: ast::NodeId + body_id: hir::BodyId, } impl<'a, 'tcx> Visitor<'tcx> for StaticInitializerCtxt<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::OnlyBodies(&self.bccx.tcx.map) + NestedVisitorMap::None } fn visit_expr(&mut self, ex: &'tcx Expr) { if let hir::ExprAddrOf(mutbl, ref base) = ex.node { - let param_env = ty::ParameterEnvironment::for_item(self.bccx.tcx, - self.item_id); - let infcx = self.bccx.tcx.borrowck_fake_infer_ctxt(param_env); + let infcx = self.bccx.tcx.borrowck_fake_infer_ctxt(self.body_id); let mc = mc::MemCategorizationContext::new(&infcx); let base_cmt = mc.cat_expr(&base).unwrap(); let borrow_kind = ty::BorrowKind::from_mutbl(mutbl); @@ -545,16 +545,14 @@ impl<'a, 'tcx> Visitor<'tcx> for StaticInitializerCtxt<'a, 'tcx> { } } -pub fn gather_loans_in_static_initializer<'a, 'tcx>(bccx: &mut BorrowckCtxt<'a, 'tcx>, - item_id: ast::NodeId, - body: hir::BodyId) { - +pub fn gather_loans_in_static_initializer(bccx: &mut BorrowckCtxt, body: hir::BodyId) { debug!("gather_loans_in_static_initializer(expr={:?})", body); let mut sicx = StaticInitializerCtxt { bccx: bccx, - item_id: item_id + body_id: body }; - sicx.visit_nested_body(body); + let body = sicx.bccx.tcx.map.body(body); + sicx.visit_body(body); } diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 1ba313015d596..c0e038d183dad 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -24,7 +24,7 @@ use self::InteriorKind::*; use rustc::dep_graph::DepNode; use rustc::hir::map as hir_map; -use rustc::hir::map::blocks::{FnParts, FnLikeNode}; +use rustc::hir::map::blocks::FnLikeNode; use rustc::cfg; use rustc::middle::dataflow::DataFlowContext; use rustc::middle::dataflow::BitwiseOperator; @@ -89,14 +89,14 @@ impl<'a, 'tcx> Visitor<'tcx> for BorrowckCtxt<'a, 'tcx> { fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem) { if let hir::TraitItemKind::Const(_, Some(expr)) = ti.node { - gather_loans::gather_loans_in_static_initializer(self, ti.id, expr); + gather_loans::gather_loans_in_static_initializer(self, expr); } intravisit::walk_trait_item(self, ti); } fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) { if let hir::ImplItemKind::Const(_, expr) = ii.node { - gather_loans::gather_loans_in_static_initializer(self, ii.id, expr); + gather_loans::gather_loans_in_static_initializer(self, expr); } intravisit::walk_impl_item(self, ii); } @@ -143,7 +143,7 @@ fn borrowck_item<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>, item: &'tcx hir::I match item.node { hir::ItemStatic(.., ex) | hir::ItemConst(_, ex) => { - gather_loans::gather_loans_in_static_initializer(this, item.id, ex); + gather_loans::gather_loans_in_static_initializer(this, ex); } _ => { } } @@ -179,7 +179,7 @@ fn borrowck_fn<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>, let AnalysisData { all_loans, loans: loan_dfcx, move_data: flowed_moves } = - build_borrowck_dataflow_data(this, &cfg, body, id); + build_borrowck_dataflow_data(this, &cfg, body_id); move_data::fragments::instrument_move_fragments(&flowed_moves.move_data, this.tcx, @@ -189,31 +189,26 @@ fn borrowck_fn<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>, &flowed_moves.move_data, id); - check_loans::check_loans(this, - &loan_dfcx, - &flowed_moves, - &all_loans[..], - id, - body); + check_loans::check_loans(this, &loan_dfcx, &flowed_moves, &all_loans[..], body); intravisit::walk_fn(this, fk, decl, body_id, sp, id); } fn build_borrowck_dataflow_data<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>, cfg: &cfg::CFG, - body: &'tcx hir::Body, - id: ast::NodeId) + body_id: hir::BodyId) -> AnalysisData<'a, 'tcx> { // Check the body of fn items. let tcx = this.tcx; + let body = tcx.map.body(body_id); let id_range = { let mut visitor = intravisit::IdRangeComputingVisitor::new(&tcx.map); visitor.visit_body(body); visitor.result() }; let (all_loans, move_data) = - gather_loans::gather_loans_in_fn(this, id, body); + gather_loans::gather_loans_in_fn(this, body_id); let mut loan_dfcx = DataFlowContext::new(this.tcx, @@ -246,7 +241,7 @@ fn build_borrowck_dataflow_data<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>, /// the `BorrowckCtxt` itself , e.g. the flowgraph visualizer. pub fn build_borrowck_dataflow_data_for_fn<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, - fn_parts: FnParts<'tcx>, + body: hir::BodyId, cfg: &cfg::CFG) -> (BorrowckCtxt<'a, 'tcx>, AnalysisData<'a, 'tcx>) { @@ -262,13 +257,7 @@ pub fn build_borrowck_dataflow_data_for_fn<'a, 'tcx>( } }; - let body = tcx.map.body(fn_parts.body); - - let dataflow_data = build_borrowck_dataflow_data(&mut bccx, - cfg, - body, - fn_parts.id); - + let dataflow_data = build_borrowck_dataflow_data(&mut bccx, cfg, body); (bccx, dataflow_data) } diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index 2949cf0d535bf..400af3c702346 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -51,6 +51,7 @@ impl<'a, 'tcx> Visitor<'tcx> for OuterVisitor<'a, 'tcx> { MatchVisitor { tcx: self.tcx, + tables: self.tcx.body_tables(b), param_env: &ty::ParameterEnvironment::for_item(self.tcx, id) }.visit_body(self.tcx.map.body(b)); } @@ -68,6 +69,7 @@ fn create_e0004<'a>(sess: &'a Session, sp: Span, error_message: String) -> Diagn struct MatchVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, + tables: &'a ty::Tables<'tcx>, param_env: &'a ty::ParameterEnvironment<'tcx> } @@ -156,7 +158,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { let inlined_arms : Vec<(Vec<_>, _)> = arms.iter().map(|arm| ( arm.pats.iter().map(|pat| { - let mut patcx = PatternContext::new(self.tcx); + let mut patcx = PatternContext::new(self.tcx, self.tables); let pattern = expand_pattern(cx, patcx.lower_pattern(&pat)); if !patcx.errors.is_empty() { self.report_inlining_errors(patcx, pat.span); @@ -181,7 +183,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { .flat_map(|arm| &arm.0) .map(|pat| vec![pat.0]) .collect(); - let scrut_ty = cx.tcx.tables().node_id_to_type(scrut.id); + let scrut_ty = self.tables.node_id_to_type(scrut.id); check_exhaustive(cx, scrut_ty, scrut.span, &matrix, source); }) } @@ -195,7 +197,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { let module = self.tcx.map.local_def_id(self.tcx.map.get_module_parent(pat.id)); MatchCheckCtxt::create_and_enter(self.tcx, module, |ref mut cx| { - let mut patcx = PatternContext::new(self.tcx); + let mut patcx = PatternContext::new(self.tcx, self.tables); let pattern = patcx.lower_pattern(pat); let pattern_ty = pattern.ty; let pats : Matrix = vec![vec![ @@ -228,7 +230,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { fn check_for_bindings_named_the_same_as_variants(cx: &MatchVisitor, pat: &Pat) { pat.walk(|p| { if let PatKind::Binding(hir::BindByValue(hir::MutImmutable), _, name, None) = p.node { - let pat_ty = cx.tcx.tables().pat_ty(p); + let pat_ty = cx.tables.pat_ty(p); if let ty::TyAdt(edef, _) = pat_ty.sty { if edef.is_enum() && edef.variants.iter().any(|variant| { variant.name == name.node && variant.ctor_kind == CtorKind::Const @@ -455,7 +457,7 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor, for pat in pats { pat.walk(|p| { if let PatKind::Binding(hir::BindByValue(..), _, _, ref sub) = p.node { - let pat_ty = cx.tcx.tables().node_id_to_type(p.id); + let pat_ty = cx.tables.node_id_to_type(p.id); if pat_ty.moves_by_default(cx.tcx, cx.param_env, pat.span) { check_move(p, sub.as_ref().map(|p| &**p)); } @@ -470,13 +472,11 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor, /// /// FIXME: this should be done by borrowck. fn check_for_mutation_in_guard(cx: &MatchVisitor, guard: &hir::Expr) { - cx.tcx.infer_ctxt(None, Some(cx.param_env.clone()), - Reveal::NotSpecializable).enter(|infcx| { + cx.tcx.infer_ctxt((cx.tables, cx.param_env.clone()), Reveal::NotSpecializable).enter(|infcx| { let mut checker = MutationChecker { cx: cx, }; - let mut visitor = ExprUseVisitor::new(&mut checker, &infcx); - visitor.walk_expr(guard); + ExprUseVisitor::new(&mut checker, &infcx).walk_expr(guard); }); } diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index 6b8e0e34c1df6..442d583907b1f 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -52,34 +52,25 @@ macro_rules! math { fn lookup_variant_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, variant_def: DefId) - -> Option<&'tcx Expr> { - let variant_expr = |variants: &'tcx [hir::Variant], id: ast::NodeId | - -> Option<&'tcx Expr> { - for variant in variants { - if variant.node.data.id() == id { - return variant.node.disr_expr.map(|e| { - &tcx.map.body(e).value - }); - } - } - None - }; - + -> Option<(&'tcx Expr, &'a ty::Tables<'tcx>)> { if let Some(variant_node_id) = tcx.map.as_local_node_id(variant_def) { let enum_node_id = tcx.map.get_parent(variant_node_id); - match tcx.map.find(enum_node_id) { - None => None, - Some(ast_map::NodeItem(it)) => match it.node { + if let Some(ast_map::NodeItem(it)) = tcx.map.find(enum_node_id) { + match it.node { hir::ItemEnum(hir::EnumDef { ref variants }, _) => { - variant_expr(variants, variant_node_id) + for variant in variants { + if variant.node.data.id() == variant_node_id { + return variant.node.disr_expr.map(|e| { + (&tcx.map.body(e).value, tcx.body_tables(e)) + }); + } + } } - _ => None - }, - Some(_) => None + _ => {} + } } - } else { - None } + None } /// * `def_id` is the id of the constant. @@ -90,17 +81,20 @@ fn lookup_variant_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, substs: Option<&'tcx Substs<'tcx>>) - -> Option<(&'tcx Expr, Option>)> { + -> Option<(&'tcx Expr, &'a ty::Tables<'tcx>, + Option>)> { 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 ty, body) => { - Some((&tcx.map.body(body).value, - tcx.ast_ty_to_prim_ty(ty))) - } - _ => None - }, + Some(ast_map::NodeItem(&hir::Item { + node: hir::ItemConst(ref ty, body), .. + })) | + Some(ast_map::NodeImplItem(&hir::ImplItem { + node: hir::ImplItemKind::Const(ref ty, body), .. + })) => { + Some((&tcx.map.body(body).value, tcx.item_tables(def_id), + tcx.ast_ty_to_prim_ty(ty))) + } Some(ast_map::NodeTraitItem(ti)) => match ti.node { hir::TraitItemKind::Const(ref ty, default) => { if let Some(substs) = substs { @@ -110,7 +104,7 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let trait_id = tcx.map.get_parent(node_id); let trait_id = tcx.map.local_def_id(trait_id); let default_value = default.map(|body| { - (&tcx.map.body(body).value, + (&tcx.map.body(body).value, tcx.item_tables(def_id), tcx.ast_ty_to_prim_ty(ty)) }); resolve_trait_associated_const(tcx, def_id, default_value, trait_id, substs) @@ -126,18 +120,12 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } _ => None }, - Some(ast_map::NodeImplItem(ii)) => match ii.node { - hir::ImplItemKind::Const(ref ty, body) => { - Some((&tcx.map.body(body).value, - tcx.ast_ty_to_prim_ty(ty))) - } - _ => None - }, Some(_) => None } } else { - let expr_ty = tcx.sess.cstore.maybe_get_item_body(tcx, def_id).map(|body| { - (&body.value, Some(tcx.sess.cstore.item_type(tcx, def_id))) + let expr_tables_ty = tcx.sess.cstore.maybe_get_item_body(tcx, def_id).map(|body| { + (&body.value, tcx.item_tables(def_id), + Some(tcx.sess.cstore.item_type(tcx, def_id))) }); match tcx.sess.cstore.describe_def(def_id) { Some(Def::AssociatedConst(_)) => { @@ -148,34 +136,37 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // substitutions for the reference to it. if let Some(trait_id) = trait_id { if let Some(substs) = substs { - resolve_trait_associated_const(tcx, def_id, expr_ty, trait_id, substs) + resolve_trait_associated_const(tcx, def_id, expr_tables_ty, + trait_id, substs) } else { None } } else { - expr_ty + expr_tables_ty } }, - Some(Def::Const(..)) => expr_ty, + Some(Def::Const(..)) => expr_tables_ty, _ => None } } } fn lookup_const_fn_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) - -> Option<&'tcx hir::Body> + -> Option<(&'tcx hir::Body, &'a ty::Tables<'tcx>)> { if let Some(node_id) = tcx.map.as_local_node_id(def_id) { FnLikeNode::from_node(tcx.map.get(node_id)).and_then(|fn_like| { if fn_like.constness() == hir::Constness::Const { - Some(tcx.map.body(fn_like.body())) + Some((tcx.map.body(fn_like.body()), tcx.body_tables(fn_like.body()))) } else { None } }) } else { if tcx.sess.cstore.is_const_fn(def_id) { - tcx.sess.cstore.maybe_get_item_body(tcx, def_id) + tcx.sess.cstore.maybe_get_item_body(tcx, def_id).map(|body| { + (body, tcx.item_tables(def_id)) + }) } else { None } @@ -230,30 +221,33 @@ pub fn note_const_eval_err<'a, 'tcx>( } } -pub fn eval_const_expr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - e: &Expr) -> ConstVal { - match eval_const_expr_checked(tcx, e) { - Ok(r) => r, - // non-const path still needs to be a fatal error, because enums are funky - Err(s) => { - report_const_eval_err(tcx, &s, e.span, "expression").emit(); - match s.kind { - NonConstPath | - UnimplementedConstVal(_) => tcx.sess.abort_if_errors(), - _ => {} - } - Dummy - }, - } +pub struct ConstContext<'a, 'tcx: 'a> { + tcx: TyCtxt<'a, 'tcx, 'tcx>, + tables: &'a ty::Tables<'tcx>, + fn_args: Option> } -pub fn eval_const_expr_checked<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - e: &Expr) -> EvalResult -{ - eval_const_expr_partial(tcx, e, ExprTypeChecked, None) -} +impl<'a, 'tcx> ConstContext<'a, 'tcx> { + pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, body: hir::BodyId) -> Self { + ConstContext::with_tables(tcx, tcx.body_tables(body)) + } + + pub fn with_tables(tcx: TyCtxt<'a, 'tcx, 'tcx>, tables: &'a ty::Tables<'tcx>) -> Self { + ConstContext { + tcx: tcx, + tables: tables, + fn_args: None + } + } -pub type FnArgMap<'a> = Option<&'a DefIdMap>; + /// Evaluate a constant expression in a context where the expression isn't + /// guaranteed to be evaluatable. `ty_hint` is usually ExprTypeChecked, + /// but a few places need to evaluate constants during type-checking, like + /// computing the length of an array. (See also the FIXME above EvalHint.) + pub fn eval(&self, e: &Expr, ty_hint: EvalHint<'tcx>) -> EvalResult { + eval_const_expr_partial(self, e, ty_hint) + } +} #[derive(Clone, Debug)] pub struct ConstEvalErr { @@ -433,20 +427,16 @@ macro_rules! signal { } } -/// Evaluate a constant expression in a context where the expression isn't -/// guaranteed to be evaluatable. `ty_hint` is usually ExprTypeChecked, -/// but a few places need to evaluate constants during type-checking, like -/// computing the length of an array. (See also the FIXME above EvalHint.) -pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - e: &Expr, - ty_hint: EvalHint<'tcx>, - fn_args: FnArgMap) -> EvalResult { +fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>, + e: &Expr, + ty_hint: EvalHint<'tcx>) -> EvalResult { + let tcx = cx.tcx; // Try to compute the type of the expression based on the EvalHint. // (See also the definition of EvalHint, and the FIXME above EvalHint.) let ety = match ty_hint { ExprTypeChecked => { // After type-checking, expr_ty is guaranteed to succeed. - Some(tcx.tables().expr_ty(e)) + Some(cx.tables.expr_ty(e)) } UncheckedExprHint(ty) => { // Use the type hint; it's not guaranteed to be right, but it's @@ -457,7 +447,7 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // This expression might not be type-checked, and we have no hint. // Try to query the context for a type anyway; we might get lucky // (for example, if the expression was imported from another crate). - tcx.tables().expr_ty_opt(e) + cx.tables.expr_ty_opt(e) } }; let result = match e.node { @@ -510,14 +500,14 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, _ => {}, } } - match eval_const_expr_partial(tcx, &inner, ty_hint, fn_args)? { + match cx.eval(inner, ty_hint)? { Float(f) => Float(-f), Integral(i) => Integral(math!(e, -i)), const_val => signal!(e, NegateOn(const_val)), } } hir::ExprUnary(hir::UnNot, ref inner) => { - match eval_const_expr_partial(tcx, &inner, ty_hint, fn_args)? { + match cx.eval(inner, ty_hint)? { Integral(i) => Integral(math!(e, !i)), Bool(b) => Bool(!b), const_val => signal!(e, NotOn(const_val)), @@ -533,8 +523,8 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // gives us a type through a type-suffix, cast or const def type // we need to re-eval the other value of the BinOp if it was // not inferred - match (eval_const_expr_partial(tcx, &a, ty_hint, fn_args)?, - eval_const_expr_partial(tcx, &b, b_ty, fn_args)?) { + match (cx.eval(a, ty_hint)?, + cx.eval(b, b_ty)?) { (Float(a), Float(b)) => { use std::cmp::Ordering::*; match op.node { @@ -604,13 +594,13 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let base_hint = if let ExprTypeChecked = ty_hint { ExprTypeChecked } else { - match tcx.tables().expr_ty_opt(&base) { + match cx.tables.expr_ty_opt(&base) { Some(t) => UncheckedExprHint(t), None => ty_hint } }; - let val = match eval_const_expr_partial(tcx, &base, base_hint, fn_args) { + let val = match cx.eval(base, base_hint) { Ok(val) => val, Err(ConstEvalErr { kind: ErroneousReferencedConstant( box ConstEvalErr { kind: TypeMismatch(_, val), .. }), .. }) | @@ -623,7 +613,7 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // we had a type hint, so we can't have an unknown type None => bug!(), }; - eval_const_expr_partial(tcx, &base, hint, fn_args)? + cx.eval(base, hint)? }, Err(e) => return Err(e), }; @@ -633,22 +623,23 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } hir::ExprPath(ref qpath) => { - let def = tcx.tables().qpath_def(qpath, e.id); + let def = cx.tables.qpath_def(qpath, e.id); match def { Def::Const(def_id) | Def::AssociatedConst(def_id) => { let substs = if let ExprTypeChecked = ty_hint { - Some(tcx.tables().node_id_item_substs(e.id) + Some(cx.tables.node_id_item_substs(e.id) .unwrap_or_else(|| tcx.intern_substs(&[]))) } else { None }; - if let Some((expr, ty)) = lookup_const_by_id(tcx, def_id, substs) { + if let Some((expr, tables, ty)) = lookup_const_by_id(tcx, def_id, substs) { let item_hint = match ty { Some(ty) => ty_hint.checked_or(ty), None => ty_hint, }; - match eval_const_expr_partial(tcx, expr, item_hint, None) { + let cx = ConstContext::with_tables(tcx, tables); + match cx.eval(expr, item_hint) { Ok(val) => val, Err(err) => { debug!("bad reference: {:?}, {:?}", err.description(), err.span); @@ -660,8 +651,9 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } }, Def::VariantCtor(variant_def, ..) => { - if let Some(const_expr) = lookup_variant_by_id(tcx, variant_def) { - match eval_const_expr_partial(tcx, const_expr, ty_hint, None) { + if let Some((expr, tables)) = lookup_variant_by_id(tcx, variant_def) { + let cx = ConstContext::with_tables(tcx, tables); + match cx.eval(expr, ty_hint) { Ok(val) => val, Err(err) => { debug!("bad reference: {:?}, {:?}", err.description(), err.span); @@ -673,11 +665,11 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } Def::StructCtor(..) => { - ConstVal::Struct(e.id) + ConstVal::Struct(Default::default()) } Def::Local(def_id) => { - debug!("Def::Local({:?}): {:?}", def_id, fn_args); - if let Some(val) = fn_args.and_then(|args| args.get(&def_id)) { + debug!("Def::Local({:?}): {:?}", def_id, cx.fn_args); + if let Some(val) = cx.fn_args.as_ref().and_then(|args| args.get(&def_id)) { val.clone() } else { signal!(e, NonConstPath); @@ -690,14 +682,14 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } hir::ExprCall(ref callee, ref args) => { let sub_ty_hint = ty_hint.erase_hint(); - let callee_val = eval_const_expr_partial(tcx, callee, sub_ty_hint, fn_args)?; + let callee_val = cx.eval(callee, sub_ty_hint)?; let did = match callee_val { Function(did) => did, Struct(_) => signal!(e, UnimplementedConstVal("tuple struct constructors")), callee => signal!(e, CallOn(callee)), }; - let body = match lookup_const_fn_by_id(tcx, did) { - Some(body) => body, + let (body, tables) = match lookup_const_fn_by_id(tcx, did) { + Some(x) => x, None => signal!(e, NonConstPath), }; @@ -710,19 +702,19 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let mut call_args = DefIdMap(); for (arg, arg_expr) in arg_defs.into_iter().zip(args.iter()) { let arg_hint = ty_hint.erase_hint(); - let arg_val = eval_const_expr_partial( - tcx, - arg_expr, - arg_hint, - fn_args - )?; + let arg_val = cx.eval(arg_expr, arg_hint)?; debug!("const call arg: {:?}", arg); if let Some(def_id) = arg { assert!(call_args.insert(def_id, arg_val).is_none()); } } debug!("const call({:?})", call_args); - eval_const_expr_partial(tcx, &body.value, ty_hint, Some(&call_args))? + let callee_cx = ConstContext { + tcx: tcx, + tables: tables, + fn_args: Some(call_args) + }; + callee_cx.eval(&body.value, ty_hint)? }, hir::ExprLit(ref lit) => match lit_to_const(&lit.node, tcx, ety) { Ok(val) => val, @@ -730,46 +722,49 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }, hir::ExprBlock(ref block) => { match block.expr { - Some(ref expr) => eval_const_expr_partial(tcx, &expr, ty_hint, fn_args)?, + Some(ref expr) => cx.eval(expr, ty_hint)?, None => signal!(e, UnimplementedConstVal("empty block")), } } - hir::ExprType(ref e, _) => eval_const_expr_partial(tcx, &e, ty_hint, fn_args)?, - hir::ExprTup(_) => Tuple(e.id), - hir::ExprStruct(..) => Struct(e.id), + hir::ExprType(ref e, _) => cx.eval(e, ty_hint)?, + hir::ExprTup(ref fields) => { + let field_hint = ty_hint.erase_hint(); + Tuple(fields.iter().map(|e| cx.eval(e, field_hint)).collect::>()?) + } + hir::ExprStruct(_, ref fields, _) => { + let field_hint = ty_hint.erase_hint(); + Struct(fields.iter().map(|f| { + cx.eval(&f.expr, field_hint).map(|v| (f.name.node, v)) + }).collect::>()?) + } hir::ExprIndex(ref arr, ref idx) => { if !tcx.sess.features.borrow().const_indexing { signal!(e, IndexOpFeatureGated); } let arr_hint = ty_hint.erase_hint(); - let arr = eval_const_expr_partial(tcx, arr, arr_hint, fn_args)?; + let arr = cx.eval(arr, arr_hint)?; let idx_hint = ty_hint.checked_or(tcx.types.usize); - let idx = match eval_const_expr_partial(tcx, idx, idx_hint, fn_args)? { + let idx = match cx.eval(idx, idx_hint)? { Integral(Usize(i)) => i.as_u64(tcx.sess.target.uint_type), Integral(_) => bug!(), _ => signal!(idx, IndexNotInt), }; assert_eq!(idx as usize as u64, idx); match arr { - Array(_, n) if idx >= n => { - signal!(e, IndexOutOfBounds { len: n, index: idx }) + Array(ref v) => { + if let Some(elem) = v.get(idx as usize) { + elem.clone() + } else { + let n = v.len() as u64; + assert_eq!(n as usize as u64, n); + signal!(e, IndexOutOfBounds { len: n, index: idx }) + } } - Array(v, n) => if let hir::ExprArray(ref v) = tcx.map.expect_expr(v).node { - assert_eq!(n as usize as u64, n); - eval_const_expr_partial(tcx, &v[idx as usize], ty_hint, fn_args)? - } else { - bug!() - }, - Repeat(_, n) if idx >= n => { + Repeat(.., n) if idx >= n => { signal!(e, IndexOutOfBounds { len: n, index: idx }) } - Repeat(elem, _) => eval_const_expr_partial( - tcx, - &tcx.map.expect_expr(elem), - ty_hint, - fn_args, - )?, + Repeat(ref elem, _) => (**elem).clone(), ByteStr(ref data) if idx >= data.len() as u64 => { signal!(e, IndexOutOfBounds { len: data.len() as u64, index: idx }) @@ -781,31 +776,38 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, _ => signal!(e, IndexedNonVec), } } - hir::ExprArray(ref v) => Array(e.id, v.len() as u64), - hir::ExprRepeat(_, n) => { + hir::ExprArray(ref v) => { + let elem_hint = ty_hint.erase_hint(); + Array(v.iter().map(|e| cx.eval(e, elem_hint)).collect::>()?) + } + hir::ExprRepeat(ref elem, count) => { + let elem_hint = ty_hint.erase_hint(); let len_hint = ty_hint.checked_or(tcx.types.usize); - let n = &tcx.map.body(n).value; - Repeat( - e.id, - match eval_const_expr_partial(tcx, n, len_hint, fn_args)? { - Integral(Usize(i)) => i.as_u64(tcx.sess.target.uint_type), - Integral(_) => signal!(e, RepeatCountNotNatural), - _ => signal!(e, RepeatCountNotInt), - }, - ) + let n = if let Some(ty) = ety { + // For cross-crate constants, we have the type already, + // but not the body for `count`, so use the type. + match ty.sty { + ty::TyArray(_, n) => n as u64, + _ => bug!() + } + } else { + let n = &tcx.map.body(count).value; + match ConstContext::new(tcx, count).eval(n, len_hint)? { + Integral(Usize(i)) => i.as_u64(tcx.sess.target.uint_type), + Integral(_) => signal!(e, RepeatCountNotNatural), + _ => signal!(e, RepeatCountNotInt), + } + }; + Repeat(Box::new(cx.eval(elem, elem_hint)?), n) }, hir::ExprTupField(ref base, index) => { let base_hint = ty_hint.erase_hint(); - let c = eval_const_expr_partial(tcx, base, base_hint, fn_args)?; - if let Tuple(tup_id) = c { - if let hir::ExprTup(ref fields) = tcx.map.expect_expr(tup_id).node { - if index.node < fields.len() { - eval_const_expr_partial(tcx, &fields[index.node], ty_hint, fn_args)? - } else { - signal!(e, TupleIndexOutOfBounds); - } + let c = cx.eval(base, base_hint)?; + if let Tuple(ref fields) = c { + if let Some(elem) = fields.get(index.node) { + elem.clone() } else { - bug!() + signal!(e, TupleIndexOutOfBounds); } } else { signal!(base, ExpectedConstTuple); @@ -813,20 +815,12 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } hir::ExprField(ref base, field_name) => { let base_hint = ty_hint.erase_hint(); - // Get the base expression if it is a struct and it is constant - let c = eval_const_expr_partial(tcx, base, base_hint, fn_args)?; - if let Struct(struct_id) = c { - if let hir::ExprStruct(_, ref fields, _) = tcx.map.expect_expr(struct_id).node { - // Check that the given field exists and evaluate it - // if the idents are compared run-pass/issue-19244 fails - if let Some(f) = fields.iter().find(|f| f.name.node - == field_name.node) { - eval_const_expr_partial(tcx, &f.expr, ty_hint, fn_args)? - } else { - signal!(e, MissingStructField); - } + let c = cx.eval(base, base_hint)?; + if let Struct(ref fields) = c { + if let Some(f) = fields.get(&field_name.node) { + f.clone() } else { - bug!() + signal!(e, MissingStructField); } } else { signal!(base, ExpectedConstStruct); @@ -909,17 +903,17 @@ fn infer<'a, 'tcx>(i: ConstInt, fn resolve_trait_associated_const<'a, 'tcx: 'a>( tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_item_id: DefId, - default_value: Option<(&'tcx Expr, Option>)>, + default_value: Option<(&'tcx Expr, &'a ty::Tables<'tcx>, Option>)>, trait_id: DefId, rcvr_substs: &'tcx Substs<'tcx> -) -> Option<(&'tcx Expr, Option>)> +) -> Option<(&'tcx Expr, &'a ty::Tables<'tcx>, Option>)> { let trait_ref = ty::Binder(ty::TraitRef::new(trait_id, rcvr_substs)); debug!("resolve_trait_associated_const: trait_ref={:?}", trait_ref); tcx.populate_implementations_for_trait_if_necessary(trait_id); - tcx.infer_ctxt(None, None, Reveal::NotSpecializable).enter(|infcx| { + tcx.infer_ctxt((), Reveal::NotSpecializable).enter(|infcx| { let mut selcx = traits::SelectionContext::new(&infcx); let obligation = traits::Obligation::new(traits::ObligationCause::dummy(), trait_ref.to_poly_trait_predicate()); @@ -1160,36 +1154,40 @@ pub fn compare_const_vals(tcx: TyCtxt, span: Span, a: &ConstVal, b: &ConstVal) } } -pub fn compare_lit_exprs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - span: Span, - a: &Expr, - b: &Expr) -> Result { - let a = match eval_const_expr_partial(tcx, a, ExprTypeChecked, None) { - Ok(a) => a, - Err(e) => { - report_const_eval_err(tcx, &e, a.span, "expression").emit(); - return Err(ErrorReported); - } - }; - let b = match eval_const_expr_partial(tcx, b, ExprTypeChecked, None) { - Ok(b) => b, - Err(e) => { - report_const_eval_err(tcx, &e, b.span, "expression").emit(); - return Err(ErrorReported); - } - }; - compare_const_vals(tcx, span, &a, &b) +impl<'a, 'tcx> ConstContext<'a, 'tcx> { + pub fn compare_lit_exprs(&self, + span: Span, + a: &Expr, + b: &Expr) -> Result { + let tcx = self.tcx; + let a = match self.eval(a, ExprTypeChecked) { + Ok(a) => a, + Err(e) => { + report_const_eval_err(tcx, &e, a.span, "expression").emit(); + return Err(ErrorReported); + } + }; + let b = match self.eval(b, ExprTypeChecked) { + Ok(b) => b, + Err(e) => { + report_const_eval_err(tcx, &e, b.span, "expression").emit(); + return Err(ErrorReported); + } + }; + compare_const_vals(tcx, span, &a, &b) + } } /// Returns the value of the length-valued expression pub fn eval_length<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - count_expr: &hir::Expr, + count: hir::BodyId, reason: &str) -> Result { let hint = UncheckedExprHint(tcx.types.usize); - match eval_const_expr_partial(tcx, count_expr, hint, None) { + let count_expr = &tcx.map.body(count).value; + match ConstContext::new(tcx, count).eval(count_expr, hint) { Ok(Integral(Usize(count))) => { let val = count.as_u64(tcx.sess.target.uint_type); assert_eq!(val as usize as u64, val); diff --git a/src/librustc_const_eval/pattern.rs b/src/librustc_const_eval/pattern.rs index 42394f4745f66..86c11dc32da12 100644 --- a/src/librustc_const_eval/pattern.rs +++ b/src/librustc_const_eval/pattern.rs @@ -119,8 +119,7 @@ fn print_const_val(value: &ConstVal, f: &mut fmt::Formatter) -> fmt::Result { ConstVal::Tuple(_) | ConstVal::Function(_) | ConstVal::Array(..) | - ConstVal::Repeat(..) | - ConstVal::Dummy => bug!("{:?} not printable in a pattern", value) + ConstVal::Repeat(..) => bug!("{:?} not printable in a pattern", value) } } @@ -261,12 +260,15 @@ impl<'tcx> fmt::Display for Pattern<'tcx> { pub struct PatternContext<'a, 'gcx: 'tcx, 'tcx: 'a> { pub tcx: TyCtxt<'a, 'gcx, 'tcx>, + pub tables: &'a ty::Tables<'gcx>, pub errors: Vec, } impl<'a, 'gcx, 'tcx> Pattern<'tcx> { - pub fn from_hir(tcx: TyCtxt<'a, 'gcx, 'tcx>, pat: &hir::Pat) -> Self { - let mut pcx = PatternContext::new(tcx); + pub fn from_hir(tcx: TyCtxt<'a, 'gcx, 'tcx>, + tables: &'a ty::Tables<'gcx>, + pat: &hir::Pat) -> Self { + let mut pcx = PatternContext::new(tcx, tables); let result = pcx.lower_pattern(pat); if !pcx.errors.is_empty() { span_bug!(pat.span, "encountered errors lowering pattern: {:?}", pcx.errors) @@ -277,12 +279,12 @@ impl<'a, 'gcx, 'tcx> Pattern<'tcx> { } impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { - pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Self { - PatternContext { tcx: tcx, errors: vec![] } + pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, tables: &'a ty::Tables<'gcx>) -> Self { + PatternContext { tcx: tcx, tables: tables, errors: vec![] } } pub fn lower_pattern(&mut self, pat: &hir::Pat) -> Pattern<'tcx> { - let mut ty = self.tcx.tables().node_id_to_type(pat.id); + let mut ty = self.tables.node_id_to_type(pat.id); let kind = match pat.node { PatKind::Wild => PatternKind::Wild, @@ -309,7 +311,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { } PatKind::Slice(ref prefix, ref slice, ref suffix) => { - let ty = self.tcx.tables().node_id_to_type(pat.id); + let ty = self.tables.node_id_to_type(pat.id); match ty.sty { ty::TyRef(_, mt) => PatternKind::Deref { @@ -334,7 +336,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { } PatKind::Tuple(ref subpatterns, ddpos) => { - let ty = self.tcx.tables().node_id_to_type(pat.id); + let ty = self.tables.node_id_to_type(pat.id); match ty.sty { ty::TyTuple(ref tys) => { let subpatterns = @@ -355,7 +357,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { PatKind::Binding(bm, def_id, ref ident, ref sub) => { let id = self.tcx.map.as_local_node_id(def_id).unwrap(); - let var_ty = self.tcx.tables().node_id_to_type(pat.id); + let var_ty = self.tables.node_id_to_type(pat.id); let region = match var_ty.sty { ty::TyRef(r, _) => Some(r), _ => None, @@ -392,7 +394,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { } PatKind::TupleStruct(ref qpath, ref subpatterns, ddpos) => { - let def = self.tcx.tables().qpath_def(qpath, pat.id); + let def = self.tables.qpath_def(qpath, pat.id); let adt_def = match ty.sty { ty::TyAdt(adt_def, _) => adt_def, _ => span_bug!(pat.span, "tuple struct pattern not applied to an ADT"), @@ -411,7 +413,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { } PatKind::Struct(ref qpath, ref fields, _) => { - let def = self.tcx.tables().qpath_def(qpath, pat.id); + let def = self.tables.qpath_def(qpath, pat.id); let adt_def = match ty.sty { ty::TyAdt(adt_def, _) => adt_def, _ => { @@ -569,16 +571,21 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { pat_id: ast::NodeId, span: Span) -> Pattern<'tcx> { - let ty = self.tcx.tables().node_id_to_type(id); - let def = self.tcx.tables().qpath_def(qpath, id); + let ty = self.tables.node_id_to_type(id); + let def = self.tables.qpath_def(qpath, id); let kind = match def { Def::Const(def_id) | Def::AssociatedConst(def_id) => { let tcx = self.tcx.global_tcx(); - let substs = tcx.tables().node_id_item_substs(id) + let substs = self.tables.node_id_item_substs(id) .unwrap_or_else(|| tcx.intern_substs(&[])); match eval::lookup_const_by_id(tcx, def_id, Some(substs)) { - Some((const_expr, _const_ty)) => { - return self.lower_const_expr(const_expr, pat_id, span); + Some((const_expr, const_tables, _const_ty)) => { + // 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 = old_tables; + return pat; } None => { self.errors.push(PatternError::StaticInPattern(span)); @@ -597,7 +604,8 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { } fn lower_lit(&mut self, expr: &hir::Expr) -> PatternKind<'tcx> { - match eval::eval_const_expr_checked(self.tcx.global_tcx(), expr) { + let const_cx = eval::ConstContext::with_tables(self.tcx.global_tcx(), self.tables); + match const_cx.eval(expr, eval::EvalHint::ExprTypeChecked) { Ok(value) => { PatternKind::Constant { value: value } } @@ -613,7 +621,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { pat_id: ast::NodeId, span: Span) -> Pattern<'tcx> { - let pat_ty = self.tcx.tables().expr_ty(expr); + let pat_ty = self.tables.expr_ty(expr); debug!("expr={:?} pat_ty={:?} pat_id={}", expr, pat_ty, pat_id); match pat_ty.sty { ty::TyFloat(_) => { @@ -659,8 +667,8 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { hir::ExprPath(ref qpath) => qpath, _ => bug!() }; - let ty = self.tcx.tables().node_id_to_type(callee.id); - let def = self.tcx.tables().qpath_def(qpath, callee.id); + let ty = self.tables.node_id_to_type(callee.id); + let def = self.tables.qpath_def(qpath, callee.id); match def { Def::Fn(..) | Def::Method(..) => self.lower_lit(expr), _ => { @@ -676,8 +684,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { } hir::ExprStruct(ref qpath, ref fields, None) => { - let def = self.tcx.tables().qpath_def(qpath, expr.id); - let pat_ty = self.tcx.tables().node_id_to_type(expr.id); + let def = self.tables.qpath_def(qpath, expr.id); let adt_def = match pat_ty.sty { ty::TyAdt(adt_def, _) => adt_def, _ => { diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index cc288619cdee0..afacfb6e3f9fd 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -39,6 +39,7 @@ use syntax_pos; use graphviz as dot; +use std::cell::Cell; use std::fs::File; use std::io::{self, Write}; use std::iter; @@ -236,7 +237,11 @@ impl PpSourceMode { arenas, id, |tcx, _, _, _| { - let annotation = TypedAnnotation { tcx: tcx }; + let empty_tables = ty::Tables::empty(); + let annotation = TypedAnnotation { + tcx: tcx, + tables: Cell::new(&empty_tables) + }; let _ignore = tcx.dep_graph.in_ignore(); f(&annotation, payload, ast_map.forest.krate()) }), @@ -488,6 +493,7 @@ impl<'ast> pprust::PpAnn for HygieneAnnotation<'ast> { struct TypedAnnotation<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, + tables: Cell<&'a ty::Tables<'tcx>>, } impl<'b, 'tcx> HirPrinterSupport<'tcx> for TypedAnnotation<'b, 'tcx> { @@ -511,7 +517,13 @@ impl<'b, 'tcx> HirPrinterSupport<'tcx> for TypedAnnotation<'b, 'tcx> { impl<'a, 'tcx> pprust_hir::PpAnn for TypedAnnotation<'a, 'tcx> { fn nested(&self, state: &mut pprust_hir::State, nested: pprust_hir::Nested) -> io::Result<()> { - pprust_hir::PpAnn::nested(&self.tcx.map, state, nested) + let old_tables = self.tables.get(); + if let pprust_hir::Nested::Body(id) = nested { + self.tables.set(self.tcx.body_tables(id)); + } + pprust_hir::PpAnn::nested(&self.tcx.map, state, nested)?; + self.tables.set(old_tables); + Ok(()) } fn pre(&self, s: &mut pprust_hir::State, node: pprust_hir::AnnNode) -> io::Result<()> { match node { @@ -525,7 +537,7 @@ impl<'a, 'tcx> pprust_hir::PpAnn for TypedAnnotation<'a, 'tcx> { pp::space(&mut s.s)?; pp::word(&mut s.s, "as")?; pp::space(&mut s.s)?; - pp::word(&mut s.s, &self.tcx.tables().expr_ty(expr).to_string())?; + pp::word(&mut s.s, &self.tables.get().expr_ty(expr).to_string())?; s.pclose() } _ => Ok(()), @@ -751,7 +763,7 @@ fn print_flowgraph<'a, 'tcx, W: Write>(variants: Vec, } blocks::Code::FnLike(fn_like) => { let (bccx, analysis_data) = - borrowck::build_borrowck_dataflow_data_for_fn(tcx, fn_like.to_fn_parts(), &cfg); + borrowck::build_borrowck_dataflow_data_for_fn(tcx, fn_like.body(), &cfg); let lcfg = borrowck_dot::DataflowLabeller { inner: lcfg, diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 887e586a3112e..ede35d052ad51 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -149,7 +149,7 @@ fn test_env(source_string: &str, index, "test_crate", |tcx| { - tcx.infer_ctxt(None, None, Reveal::NotSpecializable).enter(|infcx| { + tcx.infer_ctxt((), Reveal::NotSpecializable).enter(|infcx| { body(Env { infcx: &infcx }); let free_regions = FreeRegionMap::new(); diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index c021ffee81899..8d86e7e2e8b9e 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -138,7 +138,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoxPointers { } fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) { - let ty = cx.tcx.tables().node_id_to_type(e.id); + let ty = cx.tables.node_id_to_type(e.id); self.check_heap_type(cx, e.span, ty); } } @@ -738,8 +738,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion { // is this a recursive call? let self_recursive = if node_id != ast::DUMMY_NODE_ID { match method { - Some(ref method) => expr_refers_to_this_method(cx.tcx, method, node_id), - None => expr_refers_to_this_fn(cx.tcx, id, node_id), + Some(ref method) => expr_refers_to_this_method(cx, method, node_id), + None => expr_refers_to_this_fn(cx, id, node_id), } } else { false @@ -787,43 +787,42 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion { // Functions for identifying if the given Expr NodeId `id` // represents a call to the function `fn_id`/method `method`. - fn expr_refers_to_this_fn(tcx: TyCtxt, fn_id: ast::NodeId, id: ast::NodeId) -> bool { - match tcx.map.get(id) { + fn expr_refers_to_this_fn(cx: &LateContext, fn_id: ast::NodeId, id: ast::NodeId) -> bool { + match cx.tcx.map.get(id) { hir_map::NodeExpr(&hir::Expr { node: hir::ExprCall(ref callee, _), .. }) => { let def = if let hir::ExprPath(ref qpath) = callee.node { - tcx.tables().qpath_def(qpath, callee.id) + cx.tables.qpath_def(qpath, callee.id) } else { return false; }; - def.def_id() == tcx.map.local_def_id(fn_id) + def.def_id() == cx.tcx.map.local_def_id(fn_id) } _ => false, } } // Check if the expression `id` performs a call to `method`. - fn expr_refers_to_this_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - method: &ty::AssociatedItem, - id: ast::NodeId) - -> bool { + fn expr_refers_to_this_method(cx: &LateContext, + method: &ty::AssociatedItem, + id: ast::NodeId) + -> bool { use rustc::ty::adjustment::*; // Check for method calls and overloaded operators. - let opt_m = tcx.tables().method_map.get(&ty::MethodCall::expr(id)).cloned(); + let opt_m = cx.tables.method_map.get(&ty::MethodCall::expr(id)).cloned(); if let Some(m) = opt_m { - if method_call_refers_to_method(tcx, method, m.def_id, m.substs, id) { + if method_call_refers_to_method(cx.tcx, method, m.def_id, m.substs, id) { return true; } } // Check for overloaded autoderef method calls. - let opt_adj = tcx.tables().adjustments.get(&id).cloned(); + let opt_adj = cx.tables.adjustments.get(&id).cloned(); if let Some(Adjustment { kind: Adjust::DerefRef { autoderefs, .. }, .. }) = opt_adj { for i in 0..autoderefs { let method_call = ty::MethodCall::autoderef(id, i as u32); - if let Some(m) = tcx.tables().method_map.get(&method_call) - .cloned() { - if method_call_refers_to_method(tcx, method, m.def_id, m.substs, id) { + if let Some(m) = cx.tables.method_map.get(&method_call).cloned() { + if method_call_refers_to_method(cx.tcx, method, m.def_id, m.substs, id) { return true; } } @@ -831,19 +830,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion { } // Check for calls to methods via explicit paths (e.g. `T::method()`). - match tcx.map.get(id) { + match cx.tcx.map.get(id) { hir_map::NodeExpr(&hir::Expr { node: hir::ExprCall(ref callee, _), .. }) => { let def = if let hir::ExprPath(ref qpath) = callee.node { - tcx.tables().qpath_def(qpath, callee.id) + cx.tables.qpath_def(qpath, callee.id) } else { return false; }; match def { Def::Method(def_id) => { - let substs = tcx.tables().node_id_item_substs(callee.id) - .unwrap_or_else(|| tcx.intern_substs(&[])); + let substs = cx.tables.node_id_item_substs(callee.id) + .unwrap_or_else(|| cx.tcx.intern_substs(&[])); method_call_refers_to_method( - tcx, method, def_id, substs, id) + cx.tcx, method, def_id, substs, id) } _ => false, } @@ -882,8 +881,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion { // checking, so it's always local let node_id = tcx.map.as_local_node_id(method.def_id).unwrap(); - let param_env = Some(ty::ParameterEnvironment::for_item(tcx, node_id)); - tcx.infer_ctxt(None, param_env, Reveal::NotSpecializable).enter(|infcx| { + let param_env = ty::ParameterEnvironment::for_item(tcx, node_id); + tcx.infer_ctxt(param_env, Reveal::NotSpecializable).enter(|infcx| { let mut selcx = traits::SelectionContext::new(&infcx); match selcx.select(&obligation) { // The method comes from a `T: Trait` bound. @@ -1073,7 +1072,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes { expr: &hir::Expr) -> Option<(&'tcx ty::TypeVariants<'tcx>, &'tcx ty::TypeVariants<'tcx>)> { let def = if let hir::ExprPath(ref qpath) = expr.node { - cx.tcx.tables().qpath_def(qpath, expr.id) + cx.tables.qpath_def(qpath, expr.id) } else { return None; }; @@ -1081,7 +1080,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes { if !def_id_is_transmute(cx, did) { return None; } - let typ = cx.tcx.tables().node_id_to_type(expr.id); + let typ = cx.tables.node_id_to_type(expr.id); match typ.sty { ty::TyFnDef(.., ref bare_fn) if bare_fn.abi == RustIntrinsic => { let from = bare_fn.sig.skip_binder().inputs()[0]; diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 570365c407f48..2a77e9a4a7c8b 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -16,7 +16,7 @@ use rustc::ty::{self, AdtKind, Ty, TyCtxt}; use rustc::ty::layout::{Layout, Primitive}; use rustc::traits::Reveal; use middle::const_val::ConstVal; -use rustc_const_eval::eval_const_expr_partial; +use rustc_const_eval::ConstContext; use rustc_const_eval::EvalHint::ExprTypeChecked; use util::nodemap::FxHashSet; use lint::{LateContext, LintContext, LintArray}; @@ -89,14 +89,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { } } hir::ExprBinary(binop, ref l, ref r) => { - if is_comparison(binop) && !check_limits(cx.tcx, binop, &l, &r) { + if is_comparison(binop) && !check_limits(cx, binop, &l, &r) { cx.span_lint(UNUSED_COMPARISONS, e.span, "comparison is useless due to type limits"); } if binop.node.is_shift() { - let opt_ty_bits = match cx.tcx.tables().node_id_to_type(l.id).sty { + let opt_ty_bits = match cx.tables.node_id_to_type(l.id).sty { ty::TyInt(t) => Some(int_ty_bits(t, cx.sess().target.int_type)), ty::TyUint(t) => Some(uint_ty_bits(t, cx.sess().target.uint_type)), _ => None, @@ -110,7 +110,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { false } } else { - match eval_const_expr_partial(cx.tcx, &r, ExprTypeChecked, None) { + let const_cx = ConstContext::with_tables(cx.tcx, cx.tables); + match const_cx.eval(&r, ExprTypeChecked) { Ok(ConstVal::Integral(i)) => { i.is_negative() || i.to_u64() @@ -129,7 +130,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { } } hir::ExprLit(ref lit) => { - match cx.tcx.tables().node_id_to_type(e.id).sty { + match cx.tables.node_id_to_type(e.id).sty { ty::TyInt(t) => { match lit.node { ast::LitKind::Int(v, ast::LitIntType::Signed(_)) | @@ -274,11 +275,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { } } - fn check_limits<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - binop: hir::BinOp, - l: &hir::Expr, - r: &hir::Expr) - -> bool { + fn check_limits(cx: &LateContext, + binop: hir::BinOp, + l: &hir::Expr, + r: &hir::Expr) + -> bool { let (lit, expr, swap) = match (&l.node, &r.node) { (&hir::ExprLit(_), _) => (l, r, true), (_, &hir::ExprLit(_)) => (r, l, false), @@ -287,7 +288,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { // Normalize the binop so that the literal is always on the RHS in // the comparison let norm_binop = if swap { rev_binop(binop) } else { binop }; - match tcx.tables().node_id_to_type(expr.id).sty { + match cx.tables.node_id_to_type(expr.id).sty { ty::TyInt(int_ty) => { let (min, max) = int_ty_range(int_ty); let lit_val: i128 = match lit.node { @@ -696,7 +697,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences { if gens.ty_params.is_empty() { // sizes only make sense for non-generic types let t = cx.tcx.item_type(cx.tcx.map.local_def_id(it.id)); - let layout = cx.tcx.infer_ctxt(None, None, Reveal::All).enter(|infcx| { + let layout = cx.tcx.infer_ctxt((), Reveal::All).enter(|infcx| { let ty = cx.tcx.erase_regions(&t); ty.layout(&infcx).unwrap_or_else(|e| { bug!("failed to get layout for `{}`: {}", t, e) diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index b7ee688117d93..48d9f5e72c26d 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -139,7 +139,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { return; } - let t = cx.tcx.tables().expr_ty(&expr); + let t = cx.tables.expr_ty(&expr); let warned = match t.sty { ty::TyTuple(ref tys) if tys.is_empty() => return, ty::TyNever => return, @@ -440,7 +440,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAllocation { _ => return, } - if let Some(adjustment) = cx.tcx.tables().adjustments.get(&e.id) { + if let Some(adjustment) = cx.tables.adjustments.get(&e.id) { if let adjustment::Adjust::DerefRef { autoref, .. } = adjustment.kind { match autoref { Some(adjustment::AutoBorrow::Ref(_, hir::MutImmutable)) => { diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs index b27b164bd47aa..692e1e62c61a6 100644 --- a/src/librustc_metadata/astencode.rs +++ b/src/librustc_metadata/astencode.rs @@ -55,6 +55,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let tables_pos = self.position(); let tables_count = { let mut visitor = SideTableEncodingIdVisitor { + tables: self.tcx.body_tables(body.id()), ecx: self, count: 0, }; @@ -87,6 +88,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { struct SideTableEncodingIdVisitor<'a, 'b: 'a, 'tcx: 'b> { ecx: &'a mut EncodeContext<'b, 'tcx>, + tables: &'a ty::Tables<'tcx>, count: usize, } @@ -98,7 +100,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for SideTableEncodingIdVisitor<'a, 'b, 'tcx> { fn visit_id(&mut self, id: ast::NodeId) { debug!("Encoding side tables for id {}", id); - let tcx = self.ecx.tcx; + let tables = self.tables; let mut encode = |entry: Option| { if let Some(entry) = entry { (id, entry).encode(self.ecx).unwrap(); @@ -106,11 +108,11 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for SideTableEncodingIdVisitor<'a, 'b, 'tcx> { } }; - encode(tcx.tables().type_relative_path_defs.get(&id).cloned() - .map(TableEntry::TypeRelativeDef)); - encode(tcx.tables().node_types.get(&id).cloned().map(TableEntry::NodeType)); - encode(tcx.tables().item_substs.get(&id).cloned().map(TableEntry::ItemSubsts)); - encode(tcx.tables().adjustments.get(&id).cloned().map(TableEntry::Adjustment)); + encode(tables.type_relative_path_defs.get(&id).cloned() + .map(TableEntry::TypeRelativeDef)); + encode(tables.node_types.get(&id).cloned().map(TableEntry::NodeType)); + encode(tables.item_substs.get(&id).cloned().map(TableEntry::ItemSubsts)); + encode(tables.adjustments.get(&id).cloned().map(TableEntry::Adjustment)); } } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index c3bcdf42d4ede..7de768b7b9049 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -1037,7 +1037,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let data = ClosureData { kind: tcx.closure_kind(def_id), - ty: self.lazy(&tcx.tables().closure_tys[&def_id]), + ty: self.lazy(&tcx.closure_tys.borrow()[&def_id]), }; Entry { diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index cfdc1bf27df35..7347841a5f1ef 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -169,7 +169,7 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, let upvar_decls: Vec<_> = tcx.with_freevars(fn_id, |freevars| { freevars.iter().map(|fv| { let var_id = tcx.map.as_local_node_id(fv.def.def_id()).unwrap(); - let by_ref = tcx.tables().upvar_capture(ty::UpvarId { + let by_ref = hir.tables().upvar_capture(ty::UpvarId { var_id: var_id, closure_expr_id: fn_id }).map_or(false, |capture| match capture { @@ -195,13 +195,12 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, } pub fn construct_const<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>, - item_id: ast::NodeId, body_id: hir::BodyId) -> Mir<'tcx> { let tcx = hir.tcx(); let ast_expr = &tcx.map.body(body_id).value; - let ty = tcx.tables().expr_ty_adjusted(ast_expr); - let span = tcx.map.span(item_id); + let ty = hir.tables().expr_ty_adjusted(ast_expr); + let span = tcx.map.span(tcx.map.body_owner(body_id)); let mut builder = Builder::new(hir, span, 0, ty); let extent = tcx.region_maps.temporary_scope(ast_expr.id) @@ -306,7 +305,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let lvalue = Lvalue::Local(Local::new(index + 1)); if let Some(pattern) = pattern { - let pattern = Pattern::from_hir(self.hir.tcx(), pattern); + let pattern = Pattern::from_hir(self.hir.tcx(), self.hir.tables(), pattern); scope = self.declare_bindings(scope, ast_body.span, &pattern); unpack!(block = self.lvalue_into_pattern(block, pattern, &lvalue)); } diff --git a/src/librustc_mir/hair/cx/block.rs b/src/librustc_mir/hair/cx/block.rs index b355c8f2c4c6f..4b3d62fd6d6ef 100644 --- a/src/librustc_mir/hair/cx/block.rs +++ b/src/librustc_mir/hair/cx/block.rs @@ -61,7 +61,7 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, let remainder_extent = cx.tcx.region_maps.lookup_code_extent(remainder_extent); - let pattern = Pattern::from_hir(cx.tcx, &local.pat); + let pattern = Pattern::from_hir(cx.tcx, cx.tables(), &local.pat); result.push(StmtRef::Mirror(Box::new(Stmt { span: stmt.span, kind: StmtKind::Let { @@ -82,7 +82,7 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, pub fn to_expr_ref<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, block: &'tcx hir::Block) -> ExprRef<'tcx> { - let block_ty = cx.tcx.tables().node_id_to_type(block.id); + let block_ty = cx.tables().node_id_to_type(block.id); let temp_lifetime = cx.tcx.region_maps.temporary_scope(block.id); let expr = Expr { ty: block_ty, diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index cc65fdede092f..fe10fb57c35e8 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -17,7 +17,7 @@ use hair::cx::to_ref::ToRef; use rustc::hir::map; use rustc::hir::def::{Def, CtorKind}; use rustc::middle::const_val::ConstVal; -use rustc_const_eval as const_eval; +use rustc_const_eval::{ConstContext, EvalHint, fatal_const_eval_err}; use rustc::ty::{self, AdtKind, VariantDef, Ty}; use rustc::ty::cast::CastKind as TyCastKind; use rustc::hir; @@ -33,7 +33,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { debug!("Expr::make_mirror(): id={}, span={:?}", self.id, self.span); let mut expr = make_mirror_unadjusted(cx, self); - let adj = cx.tcx.tables().adjustments.get(&self.id).cloned(); + let adj = cx.tables().adjustments.get(&self.id).cloned(); debug!("make_mirror: unadjusted-expr={:?} applying adjustments={:?}", expr, @@ -80,13 +80,13 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { let i = i as u32; let adjusted_ty = expr.ty.adjust_for_autoderef(cx.tcx, self.id, self.span, i, |mc| { - cx.tcx.tables().method_map.get(&mc).map(|m| m.ty) + cx.tables().method_map.get(&mc).map(|m| m.ty) }); debug!("make_mirror: autoderef #{}, adjusted_ty={:?}", i, adjusted_ty); let method_key = ty::MethodCall::autoderef(self.id, i); - let meth_ty = cx.tcx.tables().method_map.get(&method_key).map(|m| m.ty); + let meth_ty = cx.tables().method_map.get(&method_key).map(|m| m.ty); let kind = if let Some(meth_ty) = meth_ty { debug!("make_mirror: overloaded autoderef (meth_ty={:?})", meth_ty); @@ -217,7 +217,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, expr: &'tcx hir::Expr) -> Expr<'tcx> { - let expr_ty = cx.tcx.tables().expr_ty(expr); + let expr_ty = cx.tables().expr_ty(expr); let temp_lifetime = cx.tcx.region_maps.temporary_scope(expr.id); let kind = match expr.node { @@ -236,7 +236,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } hir::ExprCall(ref fun, ref args) => { - if cx.tcx.tables().is_method_call(expr.id) { + if cx.tables().is_method_call(expr.id) { // The callee is something implementing Fn, FnMut, or FnOnce. // Find the actual method implementation being called and // build the appropriate UFCS call expression with the @@ -285,9 +285,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, None }; if let Some((adt_def, index)) = adt_data { - let substs = cx.tcx - .tables() - .node_id_item_substs(fun.id) + let substs = cx.tables().node_id_item_substs(fun.id) .unwrap_or_else(|| cx.tcx.intern_substs(&[])); let field_refs = args.iter() .enumerate() @@ -307,7 +305,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } } else { ExprKind::Call { - ty: cx.tcx.tables().node_id_to_type(fun.id), + ty: cx.tables().node_id_to_type(fun.id), fun: fun.to_ref(), args: args.to_ref(), } @@ -337,7 +335,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } hir::ExprAssignOp(op, ref lhs, ref rhs) => { - if cx.tcx.tables().is_method_call(expr.id) { + if cx.tables().is_method_call(expr.id) { let pass_args = if op.node.is_by_value() { PassArgs::ByValue } else { @@ -361,7 +359,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, hir::ExprLit(..) => ExprKind::Literal { literal: cx.const_eval_literal(expr) }, hir::ExprBinary(op, ref lhs, ref rhs) => { - if cx.tcx.tables().is_method_call(expr.id) { + if cx.tables().is_method_call(expr.id) { let pass_args = if op.node.is_by_value() { PassArgs::ByValue } else { @@ -421,7 +419,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } hir::ExprIndex(ref lhs, ref index) => { - if cx.tcx.tables().is_method_call(expr.id) { + if cx.tables().is_method_call(expr.id) { overloaded_lvalue(cx, expr, ty::MethodCall::expr(expr.id), @@ -437,7 +435,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } hir::ExprUnary(hir::UnOp::UnDeref, ref arg) => { - if cx.tcx.tables().is_method_call(expr.id) { + if cx.tables().is_method_call(expr.id) { overloaded_lvalue(cx, expr, ty::MethodCall::expr(expr.id), @@ -450,7 +448,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } hir::ExprUnary(hir::UnOp::UnNot, ref arg) => { - if cx.tcx.tables().is_method_call(expr.id) { + if cx.tables().is_method_call(expr.id) { overloaded_operator(cx, expr, ty::MethodCall::expr(expr.id), @@ -466,7 +464,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } hir::ExprUnary(hir::UnOp::UnNeg, ref arg) => { - if cx.tcx.tables().is_method_call(expr.id) { + if cx.tables().is_method_call(expr.id) { overloaded_operator(cx, expr, ty::MethodCall::expr(expr.id), @@ -500,8 +498,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, base: base.as_ref().map(|base| { FruInfo { base: base.to_ref(), - field_types: cx.tcx.tables().fru_field_types[&expr.id] - .clone(), + field_types: cx.tables().fru_field_types[&expr.id].clone(), } }), } @@ -541,7 +538,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } hir::ExprClosure(..) => { - let closure_ty = cx.tcx.tables().expr_ty(expr); + let closure_ty = cx.tables().expr_ty(expr); let (def_id, substs) = match closure_ty.sty { ty::TyClosure(def_id, substs) => (def_id, substs), _ => { @@ -562,7 +559,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } hir::ExprPath(ref qpath) => { - let def = cx.tcx.tables().qpath_def(qpath, expr.id); + let def = cx.tables().qpath_def(qpath, expr.id); convert_path_expr(cx, expr, def) } @@ -575,17 +572,21 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } // Now comes the rote stuff: - hir::ExprRepeat(ref v, c) => { - let c = &cx.tcx.map.body(c).value; + hir::ExprRepeat(ref v, count) => { + let tcx = cx.tcx.global_tcx(); + let c = &cx.tcx.map.body(count).value; + let count = match ConstContext::new(tcx, count).eval(c, EvalHint::ExprTypeChecked) { + Ok(ConstVal::Integral(ConstInt::Usize(u))) => u, + Ok(other) => bug!("constant evaluation of repeat count yielded {:?}", other), + Err(s) => fatal_const_eval_err(tcx, &s, c.span, "expression") + }; + ExprKind::Repeat { value: v.to_ref(), count: TypedConstVal { - ty: cx.tcx.tables().expr_ty(c), + ty: cx.tcx.types.usize, span: c.span, - value: match const_eval::eval_const_expr(cx.tcx.global_tcx(), c) { - ConstVal::Integral(ConstInt::Usize(u)) => u, - other => bug!("constant evaluation of repeat count yielded {:?}", other), - }, + value: count } } } @@ -627,7 +628,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } } hir::ExprField(ref source, name) => { - let index = match cx.tcx.tables().expr_ty_adjusted(source).sty { + let index = match cx.tables().expr_ty_adjusted(source).sty { ty::TyAdt(adt_def, _) => adt_def.variants[0].index_of_field_named(name.node), ref ty => span_bug!(expr.span, "field of non-ADT: {:?}", ty), }; @@ -679,7 +680,7 @@ fn method_callee<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, expr: &hir::Expr, method_call: ty::MethodCall) -> Expr<'tcx> { - let callee = cx.tcx.tables().method_map[&method_call]; + let callee = cx.tables().method_map[&method_call]; let temp_lifetime = cx.tcx.region_maps.temporary_scope(expr.id); Expr { temp_lifetime: temp_lifetime, @@ -703,7 +704,7 @@ fn to_borrow_kind(m: hir::Mutability) -> BorrowKind { fn convert_arm<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, arm: &'tcx hir::Arm) -> Arm<'tcx> { Arm { - patterns: arm.pats.iter().map(|p| Pattern::from_hir(cx.tcx, p)).collect(), + patterns: arm.pats.iter().map(|p| Pattern::from_hir(cx.tcx, cx.tables(), p)).collect(), guard: arm.guard.to_ref(), body: arm.body.to_ref(), } @@ -713,9 +714,7 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, expr: &'tcx hir::Expr, def: Def) -> ExprKind<'tcx> { - let substs = cx.tcx - .tables() - .node_id_item_substs(expr.id) + let substs = cx.tables().node_id_item_substs(expr.id) .unwrap_or_else(|| cx.tcx.intern_substs(&[])); let def_id = match def { // A regular function, constructor function or a constant. @@ -728,7 +727,7 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, Def::StructCtor(def_id, CtorKind::Const) | Def::VariantCtor(def_id, CtorKind::Const) => { - match cx.tcx.tables().node_id_to_type(expr.id).sty { + match cx.tables().node_id_to_type(expr.id).sty { // A unit struct/variant which is used as a value. // We return a completely different ExprKind here to account for this special case. ty::TyAdt(adt_def, substs) => { @@ -776,7 +775,7 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, id_var, index, closure_expr_id); - let var_ty = cx.tcx.tables().node_id_to_type(id_var); + let var_ty = cx.tables().node_id_to_type(id_var); let body_id = match cx.tcx.map.find(closure_expr_id) { Some(map::NodeExpr(expr)) => { @@ -793,7 +792,7 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, }; // FIXME free regions in closures are not right - let closure_ty = cx.tcx.tables().node_id_to_type(closure_expr_id); + let closure_ty = cx.tables().node_id_to_type(closure_expr_id); // FIXME we're just hard-coding the idea that the // signature will be &self or &mut self and hence will @@ -869,7 +868,7 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, var_id: id_var, closure_expr_id: closure_expr_id, }; - let upvar_capture = match cx.tcx.tables().upvar_capture(upvar_id) { + let upvar_capture = match cx.tables().upvar_capture(upvar_id) { Some(c) => c, None => { span_bug!(expr.span, "no upvar_capture for {:?}", upvar_id); @@ -948,7 +947,7 @@ fn overloaded_operator<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, let temp_lifetime = cx.tcx.region_maps.temporary_scope(expr.id); argrefs.extend(args.iter() .map(|arg| { - let arg_ty = cx.tcx.tables().expr_ty_adjusted(arg); + let arg_ty = cx.tables().expr_ty_adjusted(arg); let adjusted_ty = cx.tcx.mk_ref(region, ty::TypeAndMut { ty: arg_ty, @@ -990,7 +989,7 @@ fn overloaded_lvalue<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, // line up (this is because `*x` and `x[y]` represent lvalues): // to find the type &T of the content returned by the method; - let ref_ty = cx.tcx.tables().method_map[&method_call].ty.fn_ret(); + let ref_ty = cx.tables().method_map[&method_call].ty.fn_ret(); let ref_ty = cx.tcx.no_late_bound_regions(&ref_ty).unwrap(); // callees always have all late-bound regions fully instantiated, @@ -1019,9 +1018,9 @@ fn capture_freevar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, var_id: id_var, closure_expr_id: closure_expr.id, }; - let upvar_capture = cx.tcx.tables().upvar_capture(upvar_id).unwrap(); + let upvar_capture = cx.tables().upvar_capture(upvar_id).unwrap(); let temp_lifetime = cx.tcx.region_maps.temporary_scope(closure_expr.id); - let var_ty = cx.tcx.tables().node_id_to_type(id_var); + let var_ty = cx.tables().node_id_to_type(id_var); let captured_var = Expr { temp_lifetime: temp_lifetime, ty: var_ty, diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index 7d111fccd0056..aa5ebdf77a2ab 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -18,7 +18,7 @@ use hair::*; use rustc::mir::transform::MirSource; use rustc::middle::const_val::ConstVal; -use rustc_const_eval as const_eval; +use rustc_const_eval::{ConstContext, EvalHint, fatal_const_eval_err}; use rustc_data_structures::indexed_vec::Idx; use rustc::dep_graph::DepNode; use rustc::hir::def_id::DefId; @@ -128,7 +128,11 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { } pub fn const_eval_literal(&mut self, e: &hir::Expr) -> Literal<'tcx> { - Literal::Value { value: const_eval::eval_const_expr(self.tcx.global_tcx(), e) } + let tcx = self.tcx.global_tcx(); + match ConstContext::with_tables(tcx, self.tables()).eval(e, EvalHint::ExprTypeChecked) { + Ok(value) => Literal::Value { value: value }, + Err(s) => fatal_const_eval_err(tcx, &s, e.span, "expression") + } } pub fn trait_method(&mut self, @@ -177,6 +181,10 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { self.tcx } + pub fn tables(&self) -> &'a ty::Tables<'gcx> { + self.infcx.tables.expect_interned() + } + pub fn check_overflow(&self) -> bool { self.check_overflow } diff --git a/src/librustc_mir/mir_map.rs b/src/librustc_mir/mir_map.rs index cbc53ea3c51c7..453c3e43b6b86 100644 --- a/src/librustc_mir/mir_map.rs +++ b/src/librustc_mir/mir_map.rs @@ -18,19 +18,18 @@ use build; use rustc::dep_graph::DepNode; -use rustc::hir::def_id::DefId; use rustc::mir::Mir; use rustc::mir::transform::MirSource; use rustc::mir::visit::MutVisitor; use pretty; use hair::cx::Cx; -use rustc::infer::InferCtxtBuilder; +use rustc::infer::InferCtxt; use rustc::traits::Reveal; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::subst::Substs; use rustc::hir; -use rustc::hir::intravisit::{self, FnKind, Visitor, NestedVisitorMap}; +use rustc::hir::intravisit::{Visitor, NestedVisitorMap}; use syntax::abi::Abi; use syntax::ast; use syntax_pos::Span; @@ -80,34 +79,50 @@ struct BuildMir<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx> } -/// Helper type of a temporary returned by BuildMir::cx(...). -/// Necessary because we can't write the following bound: -/// F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(Cx<'b, 'gcx, 'tcx>). -struct CxBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { - src: MirSource, - def_id: DefId, - infcx: InferCtxtBuilder<'a, 'gcx, 'tcx> -} +fn build<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, + body_id: hir::BodyId) + -> (Mir<'tcx>, MirSource) { + let tcx = infcx.tcx.global_tcx(); -impl<'a, 'gcx, 'tcx> BuildMir<'a, 'gcx> { - fn cx<'b>(&'b mut self, src: MirSource) -> CxBuilder<'b, 'gcx, 'tcx> { - let param_env = ty::ParameterEnvironment::for_item(self.tcx, src.item_id()); - let def_id = self.tcx.map.local_def_id(src.item_id()); - CxBuilder { - src: src, - infcx: self.tcx.infer_ctxt(None, Some(param_env), Reveal::NotSpecializable), - def_id: def_id - } + let item_id = tcx.map.body_owner(body_id); + let src = MirSource::from_node(tcx, item_id); + let cx = Cx::new(infcx, src); + if let MirSource::Fn(id) = src { + // fetch the fully liberated fn signature (that is, all bound + // types/lifetimes replaced) + let fn_sig = cx.tables().liberated_fn_sigs[&id].clone(); + + let ty = tcx.item_type(tcx.map.local_def_id(id)); + let (abi, implicit_argument) = if let ty::TyClosure(..) = ty.sty { + (Abi::Rust, Some((closure_self_ty(tcx, id, body_id), None))) + } else { + (ty.fn_abi(), None) + }; + + let body = tcx.map.body(body_id); + let explicit_arguments = + body.arguments + .iter() + .enumerate() + .map(|(index, arg)| { + (fn_sig.inputs()[index], Some(&*arg.pat)) + }); + + let arguments = implicit_argument.into_iter().chain(explicit_arguments); + (build::construct_fn(cx, id, arguments, abi, fn_sig.output(), body), src) + } else { + (build::construct_const(cx, body_id), src) } } -impl<'a, 'gcx, 'tcx> CxBuilder<'a, 'gcx, 'tcx> { - fn build(&'tcx mut self, f: F) - where F: for<'b> FnOnce(Cx<'b, 'gcx, 'tcx>) -> Mir<'tcx> - { - let (src, def_id) = (self.src, self.def_id); - self.infcx.enter(|infcx| { - let mut mir = f(Cx::new(&infcx, src)); +impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> { + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { + NestedVisitorMap::None + } + + fn visit_nested_body(&mut self, body_id: hir::BodyId) { + self.tcx.infer_ctxt(body_id, Reveal::NotSpecializable).enter(|infcx| { + let (mut mir, src) = build(&infcx, body_id); // Convert the Mir to global types. let tcx = infcx.tcx.global_tcx(); @@ -117,152 +132,32 @@ impl<'a, 'gcx, 'tcx> CxBuilder<'a, 'gcx, 'tcx> { }; globalizer.visit_mir(&mut mir); let mir = unsafe { - mem::transmute::>(mir) + mem::transmute::>(mir) }; pretty::dump_mir(tcx, "mir_map", &0, src, &mir); let mir = tcx.alloc_mir(mir); + let def_id = tcx.map.local_def_id(src.item_id()); assert!(tcx.mir_map.borrow_mut().insert(def_id, mir).is_none()); }); - } -} - -impl<'a, 'gcx> BuildMir<'a, 'gcx> { - fn build_const_integer(&mut self, body: hir::BodyId) { - let body = self.tcx.map.body(body); - // FIXME(eddyb) Closures should have separate - // function definition IDs and expression IDs. - // Type-checking should not let closures get - // this far in an integer constant position. - if let hir::ExprClosure(..) = body.value.node { - return; - } - self.cx(MirSource::Const(body.value.id)).build(|cx| { - build::construct_const(cx, body.value.id, body.id()) - }); - } -} - -impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> { - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::OnlyBodies(&self.tcx.map) - } - - // Const and static items. - fn visit_item(&mut self, item: &'tcx hir::Item) { - match item.node { - hir::ItemConst(_, expr) => { - self.cx(MirSource::Const(item.id)).build(|cx| { - build::construct_const(cx, item.id, expr) - }); - } - hir::ItemStatic(_, m, expr) => { - self.cx(MirSource::Static(item.id, m)).build(|cx| { - build::construct_const(cx, item.id, expr) - }); - } - _ => {} - } - intravisit::walk_item(self, item); - } - - // Trait associated const defaults. - fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem) { - if let hir::TraitItemKind::Const(_, Some(expr)) = item.node { - self.cx(MirSource::Const(item.id)).build(|cx| { - build::construct_const(cx, item.id, expr) - }); - } - intravisit::walk_trait_item(self, item); - } - - // Impl associated const. - fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem) { - if let hir::ImplItemKind::Const(_, expr) = item.node { - self.cx(MirSource::Const(item.id)).build(|cx| { - build::construct_const(cx, item.id, expr) - }); - } - intravisit::walk_impl_item(self, item); - } - - // Repeat counts, i.e. [expr; constant]. - fn visit_expr(&mut self, expr: &'tcx hir::Expr) { - if let hir::ExprRepeat(_, count) = expr.node { - self.build_const_integer(count); - } - intravisit::walk_expr(self, expr); - } - - // Array lengths, i.e. [T; constant]. - fn visit_ty(&mut self, ty: &'tcx hir::Ty) { - if let hir::TyArray(_, length) = ty.node { - self.build_const_integer(length); - } - intravisit::walk_ty(self, ty); - } - - // Enum variant discriminant values. - fn visit_variant(&mut self, v: &'tcx hir::Variant, - g: &'tcx hir::Generics, item_id: ast::NodeId) { - if let Some(expr) = v.node.disr_expr { - self.build_const_integer(expr); - } - intravisit::walk_variant(self, v, g, item_id); - } - - fn visit_fn(&mut self, - fk: FnKind<'tcx>, - decl: &'tcx hir::FnDecl, - body_id: hir::BodyId, - span: Span, - id: ast::NodeId) { - // fetch the fully liberated fn signature (that is, all bound - // types/lifetimes replaced) - let fn_sig = match self.tcx.tables().liberated_fn_sigs.get(&id) { - Some(f) => f.clone(), - None => { - span_bug!(span, "no liberated fn sig for {:?}", id); - } - }; - - let (abi, implicit_argument) = if let FnKind::Closure(..) = fk { - (Abi::Rust, Some((closure_self_ty(self.tcx, id, body_id.node_id), None))) - } else { - let def_id = self.tcx.map.local_def_id(id); - (self.tcx.item_type(def_id).fn_abi(), None) - }; let body = self.tcx.map.body(body_id); - let explicit_arguments = - body.arguments - .iter() - .enumerate() - .map(|(index, arg)| { - (fn_sig.inputs()[index], Some(&*arg.pat)) - }); - - let arguments = implicit_argument.into_iter().chain(explicit_arguments); - self.cx(MirSource::Fn(id)).build(|cx| { - build::construct_fn(cx, id, arguments, abi, fn_sig.output(), body) - }); - - intravisit::walk_fn(self, fk, decl, body_id, span, id); + self.visit_body(body); } } fn closure_self_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, closure_expr_id: ast::NodeId, - body_id: ast::NodeId) + body_id: hir::BodyId) -> Ty<'tcx> { - let closure_ty = tcx.tables().node_id_to_type(closure_expr_id); + let closure_ty = tcx.body_tables(body_id).node_id_to_type(closure_expr_id); // We're just hard-coding the idea that the signature will be // &self or &mut self and hence will have a bound region with // number 0, hokey. let region = ty::Region::ReFree(ty::FreeRegion { - scope: tcx.region_maps.item_extent(body_id), + scope: tcx.region_maps.item_extent(body_id.node_id), bound_region: ty::BoundRegion::BrAnon(0), }); let region = tcx.mk_region(region); diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index d144651fb7db6..fea27ee5c5483 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -1038,7 +1038,7 @@ impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants { // Statics must be Sync. if mode == Mode::Static { let ty = mir.return_ty; - tcx.infer_ctxt(None, None, Reveal::NotSpecializable).enter(|infcx| { + tcx.infer_ctxt((), Reveal::NotSpecializable).enter(|infcx| { let cause = traits::ObligationCause::new(mir.span, id, traits::SharedStatic); let mut fulfillment_cx = traits::FulfillmentContext::new(); fulfillment_cx.register_bound(&infcx, ty, diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs index 4c86331a52576..0fabbe6678ad8 100644 --- a/src/librustc_mir/transform/type_check.rs +++ b/src/librustc_mir/transform/type_check.rs @@ -725,7 +725,7 @@ impl<'tcx> MirPass<'tcx> for TypeckMir { return; } let param_env = ty::ParameterEnvironment::for_item(tcx, src.item_id()); - tcx.infer_ctxt(None, Some(param_env), Reveal::NotSpecializable).enter(|infcx| { + tcx.infer_ctxt(param_env, Reveal::NotSpecializable).enter(|infcx| { let mut checker = TypeChecker::new(&infcx, src.item_id()); { let mut verifier = TypeVerifier::new(&mut checker, mir); diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs index d1d9a201567bb..8f12817511ad3 100644 --- a/src/librustc_passes/consts.rs +++ b/src/librustc_passes/consts.rs @@ -26,10 +26,9 @@ use rustc::dep_graph::DepNode; use rustc::ty::cast::CastKind; -use rustc_const_eval::{ConstEvalErr, compare_lit_exprs}; -use rustc_const_eval::{eval_const_expr_partial}; +use rustc_const_eval::{ConstEvalErr, ConstContext}; use rustc_const_eval::ErrKind::{IndexOpFeatureGated, UnimplementedConstVal, MiscCatchAll, Math}; -use rustc_const_eval::ErrKind::{ErroneousReferencedConstant, MiscBinaryOp, NonConstPath}; +use rustc_const_eval::ErrKind::{ErroneousReferencedConstant, MiscBinaryOp, NonConstPath, BadType}; use rustc_const_eval::ErrKind::UnresolvedPath; use rustc_const_eval::EvalHint::ExprTypeChecked; use rustc_const_math::{ConstMathErr, Op}; @@ -61,15 +60,18 @@ struct CheckCrateVisitor<'a, 'tcx: 'a> { promotable: bool, mut_rvalue_borrows: NodeSet, param_env: ty::ParameterEnvironment<'tcx>, + tables: &'a ty::Tables<'tcx>, } impl<'a, 'gcx> CheckCrateVisitor<'a, 'gcx> { fn check_const_eval(&self, expr: &'gcx hir::Expr) { - if let Err(err) = eval_const_expr_partial(self.tcx, expr, ExprTypeChecked, None) { + let const_cx = ConstContext::with_tables(self.tcx, self.tables); + if let Err(err) = const_cx.eval(expr, ExprTypeChecked) { match err.kind { UnimplementedConstVal(_) => {} IndexOpFeatureGated => {} ErroneousReferencedConstant(_) => {} + BadType(_) => {} _ => { self.tcx.sess.add_lint(CONST_ERR, expr.id, @@ -111,8 +113,8 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> { NestedVisitorMap::None } - fn visit_nested_body(&mut self, body: hir::BodyId) { - match self.tcx.rvalue_promotable_to_static.borrow_mut().entry(body.node_id) { + fn visit_nested_body(&mut self, body_id: hir::BodyId) { + match self.tcx.rvalue_promotable_to_static.borrow_mut().entry(body_id.node_id) { Entry::Occupied(_) => return, Entry::Vacant(entry) => { // Prevent infinite recursion on re-entry. @@ -120,7 +122,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> { } } - let item_id = self.tcx.map.body_owner(body); + let item_id = self.tcx.map.body_owner(body_id); let outer_in_fn = self.in_fn; self.in_fn = match MirSource::from_node(self.tcx, item_id) { @@ -128,19 +130,25 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> { _ => false }; - let body = self.tcx.map.body(body); + let outer_tables = self.tables; + self.tables = self.tcx.item_tables(self.tcx.map.local_def_id(item_id)); + + let body = self.tcx.map.body(body_id); if !self.in_fn { self.check_const_eval(&body.value); } - let param_env = ty::ParameterEnvironment::for_item(self.tcx, item_id); - let outer_param_env = mem::replace(&mut self.param_env, param_env); - self.tcx.infer_ctxt(None, Some(self.param_env.clone()), Reveal::NotSpecializable) - .enter(|infcx| euv::ExprUseVisitor::new(self, &infcx).consume_body(body)); + let outer_penv = self.tcx.infer_ctxt(body_id, Reveal::NotSpecializable).enter(|infcx| { + let param_env = infcx.parameter_environment.clone(); + let outer_penv = mem::replace(&mut self.param_env, param_env); + euv::ExprUseVisitor::new(self, &infcx).consume_body(body); + outer_penv + }); self.visit_body(body); - self.param_env = outer_param_env; + self.param_env = outer_penv; + self.tables = outer_tables; self.in_fn = outer_in_fn; } @@ -150,10 +158,8 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> { self.check_const_eval(lit); } PatKind::Range(ref start, ref end) => { - self.check_const_eval(start); - self.check_const_eval(end); - - match compare_lit_exprs(self.tcx, p.span, start, end) { + let const_cx = ConstContext::with_tables(self.tcx, self.tables); + match const_cx.compare_lit_exprs(p.span, start, end) { Ok(Ordering::Less) | Ok(Ordering::Equal) => {} Ok(Ordering::Greater) => { @@ -193,7 +199,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> { let outer = self.promotable; self.promotable = true; - let node_ty = self.tcx.tables().node_id_to_type(ex.id); + let node_ty = self.tables.node_id_to_type(ex.id); check_expr(self, ex, node_ty); check_adjustments(self, ex); @@ -219,7 +225,8 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> { } if self.in_fn && self.promotable { - match eval_const_expr_partial(self.tcx, ex, ExprTypeChecked, None) { + let const_cx = ConstContext::with_tables(self.tcx, self.tables); + match const_cx.eval(ex, ExprTypeChecked) { Ok(_) => {} Err(ConstEvalErr { kind: UnimplementedConstVal(_), .. }) | Err(ConstEvalErr { kind: MiscCatchAll, .. }) | @@ -230,6 +237,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> { Err(ConstEvalErr { kind: Math(ConstMathErr::Overflow(Op::Shr)), .. }) | Err(ConstEvalErr { kind: Math(ConstMathErr::Overflow(Op::Shl)), .. }) | Err(ConstEvalErr { kind: IndexOpFeatureGated, .. }) => {} + Err(ConstEvalErr { kind: BadType(_), .. }) => {} Err(msg) => { self.tcx.sess.add_lint(CONST_ERR, ex.id, @@ -262,14 +270,14 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node match e.node { hir::ExprUnary(..) | hir::ExprBinary(..) | - hir::ExprIndex(..) if v.tcx.tables().method_map.contains_key(&method_call) => { + hir::ExprIndex(..) if v.tables.method_map.contains_key(&method_call) => { v.promotable = false; } hir::ExprBox(_) => { v.promotable = false; } hir::ExprUnary(op, ref inner) => { - match v.tcx.tables().node_id_to_type(inner.id).sty { + match v.tables.node_id_to_type(inner.id).sty { ty::TyRawPtr(_) => { assert!(op == hir::UnDeref); @@ -279,7 +287,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node } } hir::ExprBinary(op, ref lhs, _) => { - match v.tcx.tables().node_id_to_type(lhs.id).sty { + match v.tables.node_id_to_type(lhs.id).sty { ty::TyRawPtr(_) => { assert!(op.node == hir::BiEq || op.node == hir::BiNe || op.node == hir::BiLe || op.node == hir::BiLt || @@ -301,7 +309,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node } } hir::ExprPath(ref qpath) => { - let def = v.tcx.tables().qpath_def(qpath, e.id); + let def = v.tables.qpath_def(qpath, e.id); match def { Def::VariantCtor(..) | Def::StructCtor(..) | Def::Fn(..) | Def::Method(..) => {} @@ -337,7 +345,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node } // The callee is an arbitrary expression, it doesn't necessarily have a definition. let def = if let hir::ExprPath(ref qpath) = callee.node { - v.tcx.tables().qpath_def(qpath, callee.id) + v.tables.qpath_def(qpath, callee.id) } else { Def::Err }; @@ -359,14 +367,14 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node } } hir::ExprMethodCall(..) => { - let method = v.tcx.tables().method_map[&method_call]; + let method = v.tables.method_map[&method_call]; match v.tcx.associated_item(method.def_id).container { ty::ImplContainer(_) => v.handle_const_fn_call(method.def_id, node_ty), ty::TraitContainer(_) => v.promotable = false } } hir::ExprStruct(..) => { - if let ty::TyAdt(adt, ..) = v.tcx.tables().expr_ty(e).sty { + if let ty::TyAdt(adt, ..) = v.tables.expr_ty(e).sty { // unsafe_cell_type doesn't necessarily exist with no_core if Some(adt.did) == v.tcx.lang_items.unsafe_cell_type() { v.promotable = false; @@ -420,7 +428,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node fn check_adjustments<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr) { use rustc::ty::adjustment::*; - match v.tcx.tables().adjustments.get(&e.id).map(|adj| adj.kind) { + match v.tables.adjustments.get(&e.id).map(|adj| adj.kind) { None | Some(Adjust::NeverToAny) | Some(Adjust::ReifyFnPointer) | @@ -429,7 +437,7 @@ fn check_adjustments<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Exp Some(Adjust::DerefRef { autoderefs, .. }) => { if (0..autoderefs as u32) - .any(|autoderef| v.tcx.tables().is_overloaded_autoderef(e.id, autoderef)) { + .any(|autoderef| v.tables.is_overloaded_autoderef(e.id, autoderef)) { v.promotable = false; } } @@ -440,6 +448,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { tcx.visit_all_item_likes_in_krate(DepNode::CheckConst, &mut CheckCrateVisitor { tcx: tcx, + tables: &ty::Tables::empty(), in_fn: false, promotable: false, mut_rvalue_borrows: NodeSet(), diff --git a/src/librustc_passes/rvalues.rs b/src/librustc_passes/rvalues.rs index 3da4f24b6c2fe..78b591a48cca5 100644 --- a/src/librustc_passes/rvalues.rs +++ b/src/librustc_passes/rvalues.rs @@ -14,11 +14,11 @@ use rustc::dep_graph::DepNode; use rustc::middle::expr_use_visitor as euv; use rustc::middle::mem_categorization as mc; -use rustc::ty::{self, TyCtxt, ParameterEnvironment}; +use rustc::ty::{self, TyCtxt}; use rustc::traits::Reveal; use rustc::hir; -use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; +use rustc::hir::intravisit::{Visitor, NestedVisitorMap}; use syntax::ast; use syntax_pos::Span; @@ -33,28 +33,19 @@ struct RvalueContext<'a, 'tcx: 'a> { impl<'a, 'tcx> Visitor<'tcx> for RvalueContext<'a, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::OnlyBodies(&self.tcx.map) + NestedVisitorMap::None } - fn visit_fn(&mut self, - fk: intravisit::FnKind<'tcx>, - fd: &'tcx hir::FnDecl, - b: hir::BodyId, - s: Span, - fn_id: ast::NodeId) { - // FIXME (@jroesch) change this to be an inference context - let param_env = ParameterEnvironment::for_item(self.tcx, fn_id); - self.tcx.infer_ctxt(None, Some(param_env.clone()), - Reveal::NotSpecializable).enter(|infcx| { + fn visit_nested_body(&mut self, body_id: hir::BodyId) { + let body = self.tcx.map.body(body_id); + self.tcx.infer_ctxt(body_id, Reveal::NotSpecializable).enter(|infcx| { let mut delegate = RvalueContextDelegate { tcx: infcx.tcx, - param_env: ¶m_env + param_env: &infcx.parameter_environment }; - let body = infcx.tcx.map.body(b); - let mut euv = euv::ExprUseVisitor::new(&mut delegate, &infcx); - euv.consume_body(body); + euv::ExprUseVisitor::new(&mut delegate, &infcx).consume_body(body); }); - intravisit::walk_fn(self, fk, fd, b, s, fn_id) + self.visit_body(body); } } diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 81863a3fadfd3..f68dcf30e780f 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -392,6 +392,7 @@ struct PrivacyVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, curitem: DefId, in_foreign: bool, + tables: &'a ty::Tables<'tcx>, } impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { @@ -435,6 +436,14 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivacyVisitor<'a, 'tcx> { NestedVisitorMap::All(&self.tcx.map) } + fn visit_nested_body(&mut self, body: hir::BodyId) { + let old_tables = self.tables; + self.tables = self.tcx.body_tables(body); + let body = self.tcx.map.body(body); + self.visit_body(body); + self.tables = old_tables; + } + fn visit_item(&mut self, item: &'tcx hir::Item) { let orig_curitem = replace(&mut self.curitem, self.tcx.map.local_def_id(item.id)); intravisit::walk_item(self, item); @@ -445,12 +454,12 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivacyVisitor<'a, 'tcx> { match expr.node { hir::ExprMethodCall(..) => { let method_call = ty::MethodCall::expr(expr.id); - let method = self.tcx.tables().method_map[&method_call]; + let method = self.tables.method_map[&method_call]; self.check_method(expr.span, method.def_id); } hir::ExprStruct(ref qpath, ref expr_fields, _) => { - let def = self.tcx.tables().qpath_def(qpath, expr.id); - let adt = self.tcx.tables().expr_ty(expr).ty_adt_def().unwrap(); + let def = self.tables.qpath_def(qpath, expr.id); + let adt = self.tables.expr_ty(expr).ty_adt_def().unwrap(); let variant = adt.variant_of_def(def); // RFC 736: ensure all unmentioned fields are visible. // Rather than computing the set of unmentioned fields @@ -511,15 +520,15 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivacyVisitor<'a, 'tcx> { match pattern.node { PatKind::Struct(ref qpath, ref fields, _) => { - let def = self.tcx.tables().qpath_def(qpath, pattern.id); - let adt = self.tcx.tables().pat_ty(pattern).ty_adt_def().unwrap(); + let def = self.tables.qpath_def(qpath, pattern.id); + let adt = self.tables.pat_ty(pattern).ty_adt_def().unwrap(); let variant = adt.variant_of_def(def); for field in fields { self.check_field(field.span, adt, variant.field_named(field.node.name)); } } PatKind::TupleStruct(_, ref fields, ddpos) => { - match self.tcx.tables().pat_ty(pattern).sty { + match self.tables.pat_ty(pattern).sty { // enum fields have no privacy at this time ty::TyAdt(def, _) if !def.is_enum() => { let expected_len = def.struct_variant().fields.len(); @@ -1203,6 +1212,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, curitem: DefId::local(CRATE_DEF_INDEX), in_foreign: false, tcx: tcx, + tables: &ty::Tables::empty(), }; intravisit::walk_crate(&mut visitor, krate); diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 093a739c69ffa..424017ebd12bb 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -99,7 +99,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { } } - fn nest(&mut self, scope_id: NodeId, f: F) + fn nest_scope(&mut self, scope_id: NodeId, f: F) where F: FnOnce(&mut DumpVisitor<'l, 'tcx, 'll, D>) { let parent_scope = self.cur_scope; @@ -108,6 +108,16 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { self.cur_scope = parent_scope; } + fn nest_tables(&mut self, item_id: NodeId, f: F) + where F: FnOnce(&mut DumpVisitor<'l, 'tcx, 'll, D>) + { + let old_tables = self.save_ctxt.tables; + let item_def_id = self.tcx.map.local_def_id(item_id); + self.save_ctxt.tables = self.tcx.item_tables(item_def_id); + f(self); + self.save_ctxt.tables = old_tables; + } + pub fn dump_crate_info(&mut self, name: &str, krate: &ast::Crate) { let source_file = self.tcx.sess.local_crate_source_file.as_ref(); let crate_root = source_file.map(|source_file| { @@ -337,7 +347,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { collector.visit_pat(&arg.pat); let span_utils = self.span.clone(); for &(id, ref p, ..) in &collector.collected_paths { - let typ = match self.tcx.tables().node_types.get(&id) { + let typ = match self.save_ctxt.tables.node_types.get(&id) { Some(s) => s.to_string(), None => continue, }; @@ -378,7 +388,9 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { let sig_str = ::make_signature(&sig.decl, &sig.generics); if body.is_some() { - self.process_formals(&sig.decl.inputs, &method_data.qualname); + self.nest_tables(id, |v| { + v.process_formals(&sig.decl.inputs, &method_data.qualname) + }); } // If the method is defined in an impl, then try and find the corresponding @@ -448,7 +460,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { // walk the fn body if let Some(body) = body { - self.nest(id, |v| v.visit_block(body)); + self.nest_tables(id, |v| v.nest_scope(id, |v| v.visit_block(body))); } } @@ -520,7 +532,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { self.dumper.function(fn_data.clone().lower(self.tcx)); } - self.process_formals(&decl.inputs, &fn_data.qualname); + self.nest_tables(item.id, |v| v.process_formals(&decl.inputs, &fn_data.qualname)); self.process_generic_params(ty_params, item.span, &fn_data.qualname, item.id); } @@ -532,7 +544,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { self.visit_ty(&ret_ty); } - self.nest(item.id, |v| v.visit_block(&body)); + self.nest_tables(item.id, |v| v.nest_scope(item.id, |v| v.visit_block(&body))); } fn process_static_or_const_item(&mut self, @@ -991,7 +1003,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { match p.node { PatKind::Struct(ref path, ref fields, _) => { visit::walk_path(self, path); - let adt = match self.tcx.tables().node_id_to_type_opt(p.id) { + let adt = match self.save_ctxt.tables.node_id_to_type_opt(p.id) { Some(ty) => ty.ty_adt_def().unwrap(), None => { visit::walk_pat(self, p); @@ -1032,7 +1044,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { ast::Mutability::Immutable => value.to_string(), _ => String::new(), }; - let typ = match self.tcx.tables().node_types.get(&id) { + let typ = match self.save_ctxt.tables.node_types.get(&id) { Some(typ) => { let typ = typ.to_string(); if !value.is_empty() { @@ -1286,7 +1298,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, self.process_trait(item, generics, trait_refs, methods), Mod(ref m) => { self.process_mod(item); - self.nest(item.id, |v| visit::walk_mod(v, m)); + self.nest_scope(item.id, |v| visit::walk_mod(v, m)); } Ty(ref ty, ref ty_params) => { let qualname = format!("::{}", self.tcx.node_path_str(item.id)); @@ -1349,6 +1361,10 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, visit::walk_path(self, path); } + ast::TyKind::Array(ref element, ref length) => { + self.visit_ty(element); + self.nest_tables(length.id, |v| v.visit_expr(length)); + } _ => visit::walk_ty(self, t), } } @@ -1367,7 +1383,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, } ast::ExprKind::Struct(ref path, ref fields, ref base) => { let hir_expr = self.save_ctxt.tcx.map.expect_expr(ex.id); - let adt = match self.tcx.tables().expr_ty_opt(&hir_expr) { + let adt = match self.save_ctxt.tables.expr_ty_opt(&hir_expr) { Some(ty) => ty.ty_adt_def().unwrap(), None => { visit::walk_expr(self, ex); @@ -1399,7 +1415,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, return; } }; - let ty = match self.tcx.tables().expr_ty_adjusted_opt(&hir_node) { + let ty = match self.save_ctxt.tables.expr_ty_adjusted_opt(&hir_node) { Some(ty) => &ty.sty, None => { visit::walk_expr(self, ex); @@ -1427,7 +1443,6 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, ast::ExprKind::Closure(_, ref decl, ref body, _fn_decl_span) => { let mut id = String::from("$"); id.push_str(&ex.id.to_string()); - self.process_formals(&decl.inputs, &id); // walk arg and return types for arg in &decl.inputs { @@ -1439,7 +1454,10 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, } // walk the body - self.nest(ex.id, |v| v.visit_expr(body)); + self.nest_tables(ex.id, |v| { + v.process_formals(&decl.inputs, &id); + v.nest_scope(ex.id, |v| v.visit_expr(body)) + }); } ast::ExprKind::ForLoop(ref pattern, ref subexpression, ref block, _) | ast::ExprKind::WhileLet(ref pattern, ref subexpression, ref block, _) => { @@ -1455,6 +1473,10 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, visit::walk_block(self, block); opt_else.as_ref().map(|el| visit::walk_expr(self, el)); } + ast::ExprKind::Repeat(ref element, ref count) => { + self.visit_expr(element); + self.nest_tables(count.id, |v| v.visit_expr(count)); + } _ => { visit::walk_expr(self, ex) } @@ -1492,7 +1514,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll, } else { "".to_string() }; - let typ = self.tcx.tables().node_types + let typ = self.save_ctxt.tables.node_types .get(&id).map(|t| t.to_string()).unwrap_or(String::new()); value.push_str(": "); value.push_str(&typ); diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 43e3b1dd2b50a..9e512ec194c3b 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -84,6 +84,7 @@ pub mod recorder { pub struct SaveContext<'l, 'tcx: 'l> { tcx: TyCtxt<'l, 'tcx, 'tcx>, + tables: &'l ty::Tables<'tcx>, analysis: &'l ty::CrateAnalysis<'tcx>, span_utils: SpanUtils<'tcx>, } @@ -93,24 +94,6 @@ macro_rules! option_try( ); impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { - pub fn new(tcx: TyCtxt<'l, 'tcx, 'tcx>, - analysis: &'l ty::CrateAnalysis<'tcx>) - -> SaveContext<'l, 'tcx> { - let span_utils = SpanUtils::new(&tcx.sess); - SaveContext::from_span_utils(tcx, analysis, span_utils) - } - - pub fn from_span_utils(tcx: TyCtxt<'l, 'tcx, 'tcx>, - analysis: &'l ty::CrateAnalysis<'tcx>, - span_utils: SpanUtils<'tcx>) - -> SaveContext<'l, 'tcx> { - SaveContext { - tcx: tcx, - analysis: analysis, - span_utils: span_utils, - } - } - // List external crates used by the current crate. pub fn get_external_crates(&self) -> Vec { let mut result = Vec::new(); @@ -460,7 +443,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { pub fn get_expr_data(&self, expr: &ast::Expr) -> Option { let hir_node = self.tcx.map.expect_expr(expr.id); - let ty = self.tcx.tables().expr_ty_adjusted_opt(&hir_node); + let ty = self.tables.expr_ty_adjusted_opt(&hir_node); if ty.is_none() || ty.unwrap().sty == ty::TyError { return None; } @@ -474,7 +457,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { return None; } }; - match self.tcx.tables().expr_ty_adjusted(&hir_node).sty { + match self.tables.expr_ty_adjusted(&hir_node).sty { ty::TyAdt(def, _) if !def.is_enum() => { let f = def.struct_variant().field_named(ident.node.name); let sub_span = self.span_utils.span_for_last_ident(expr.span); @@ -493,7 +476,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } } ast::ExprKind::Struct(ref path, ..) => { - match self.tcx.tables().expr_ty_adjusted(&hir_node).sty { + match self.tables.expr_ty_adjusted(&hir_node).sty { ty::TyAdt(def, _) if !def.is_enum() => { let sub_span = self.span_utils.span_for_last_ident(path.span); filter!(self.span_utils, sub_span, path.span, None); @@ -514,7 +497,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } ast::ExprKind::MethodCall(..) => { let method_call = ty::MethodCall::expr(expr.id); - let method_id = self.tcx.tables().method_map[&method_call].def_id; + let method_id = self.tables.method_map[&method_call].def_id; let (def_id, decl_id) = match self.tcx.associated_item(method_id).container { ty::ImplContainer(_) => (Some(method_id), None), ty::TraitContainer(_) => (None, Some(method_id)), @@ -551,7 +534,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { Node::NodePat(&hir::Pat { node: hir::PatKind::Path(ref qpath), .. }) | Node::NodePat(&hir::Pat { node: hir::PatKind::Struct(ref qpath, ..), .. }) | Node::NodePat(&hir::Pat { node: hir::PatKind::TupleStruct(ref qpath, ..), .. }) => { - self.tcx.tables().qpath_def(qpath, id) + self.tables.qpath_def(qpath, id) } Node::NodeLocal(&hir::Pat { node: hir::PatKind::Binding(_, def_id, ..), .. }) => { @@ -914,7 +897,12 @@ pub fn process_crate<'l, 'tcx>(tcx: TyCtxt<'l, 'tcx, 'tcx>, root_path.pop(); let output = &mut output_file; - let save_ctxt = SaveContext::new(tcx, analysis); + let save_ctxt = SaveContext { + tcx: tcx, + tables: &ty::Tables::empty(), + analysis: analysis, + span_utils: SpanUtils::new(&tcx.sess), + }; macro_rules! dump { ($new_dumper: expr) => {{ diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs index 13163518f941e..eb6ea8fa94b0a 100644 --- a/src/librustc_trans/common.rs +++ b/src/librustc_trans/common.rs @@ -465,7 +465,7 @@ pub fn fulfill_obligation<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, // Do the initial selection for the obligation. This yields the // shallow result we are looking for -- that is, what specific impl. - tcx.infer_ctxt(None, None, Reveal::All).enter(|infcx| { + tcx.infer_ctxt((), Reveal::All).enter(|infcx| { let mut selcx = SelectionContext::new(&infcx); let obligation_cause = traits::ObligationCause::misc(span, diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index 413b643740861..5efdd129a32b8 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -851,7 +851,7 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { } pub fn layout_of(&self, ty: Ty<'tcx>) -> &'tcx ty::layout::Layout { - self.tcx().infer_ctxt(None, None, traits::Reveal::All).enter(|infcx| { + self.tcx().infer_ctxt((), traits::Reveal::All).enter(|infcx| { ty.layout(&infcx).unwrap_or_else(|e| { match e { ty::layout::LayoutError::SizeOverflow(_) => diff --git a/src/librustc_trans/glue.rs b/src/librustc_trans/glue.rs index 4fe07c9b86abf..b24f00ee6976d 100644 --- a/src/librustc_trans/glue.rs +++ b/src/librustc_trans/glue.rs @@ -80,7 +80,7 @@ pub fn get_drop_glue_type<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, t: Ty<'t } match t.sty { ty::TyBox(typ) if !scx.type_needs_drop(typ) && scx.type_is_sized(typ) => { - scx.tcx().infer_ctxt(None, None, traits::Reveal::All).enter(|infcx| { + scx.tcx().infer_ctxt((), traits::Reveal::All).enter(|infcx| { let layout = t.layout(&infcx).unwrap(); if layout.size(&scx.tcx().data_layout).bytes() == 0 { // `Box` does not allocate. diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index 13e659a5ae0e8..9ac2bea3b82fb 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -101,7 +101,6 @@ impl<'tcx> Const<'tcx> { bug!("MIR must not use `{:?}` (which refers to a local ID)", cv) } ConstVal::Char(c) => C_integral(Type::char(ccx), c as u64, false), - ConstVal::Dummy => bug!(), }; assert!(!ty.has_erasable_regions()); diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 75c25a605af25..bc984949fc69d 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1660,8 +1660,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { self.associated_path_def_to_ty(ast_ty.id, ast_ty.span, ty, def, segment).0 } hir::TyArray(ref ty, length) => { - let e = &tcx.map.body(length).value; - if let Ok(length) = eval_length(tcx.global_tcx(), e, "array length") { + if let Ok(length) = eval_length(tcx.global_tcx(), length, "array length") { tcx.mk_array(self.ast_ty_to_ty(rscope, &ty), length) } else { self.tcx().types.err diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 9412c9105c7aa..0551887e2e8a0 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -99,10 +99,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn_ty.sig, opt_kind); - self.tables.borrow_mut().closure_tys.insert(expr_def_id, fn_ty); + self.tables.borrow_mut().closure_tys.insert(expr.id, fn_ty); match opt_kind { Some(kind) => { - self.tables.borrow_mut().closure_kinds.insert(expr_def_id, kind); + self.tables.borrow_mut().closure_kinds.insert(expr.id, kind); } None => {} } diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index be10b77bd8b90..3960dc9edbd27 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -227,7 +227,7 @@ fn compare_predicate_entailment<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, trait_param_env, normalize_cause.clone()); - tcx.infer_ctxt(None, Some(trait_param_env), Reveal::NotSpecializable).enter(|infcx| { + tcx.infer_ctxt(trait_param_env, Reveal::NotSpecializable).enter(|infcx| { let inh = Inherited::new(ccx, infcx); let infcx = &inh.infcx; let fulfillment_cx = &inh.fulfillment_cx; @@ -747,7 +747,7 @@ pub fn compare_const_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, debug!("compare_const_impl(impl_trait_ref={:?})", impl_trait_ref); let tcx = ccx.tcx; - tcx.infer_ctxt(None, None, Reveal::NotSpecializable).enter(|infcx| { + tcx.infer_ctxt((), Reveal::NotSpecializable).enter(|infcx| { let mut fulfillment_cx = traits::FulfillmentContext::new(); // The below is for the most part highly similar to the procedure diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index e13c4ea314f06..9cd54bd94c817 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -81,7 +81,7 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>( // check that the impl type can be made to match the trait type. let impl_param_env = ty::ParameterEnvironment::for_item(tcx, self_type_node_id); - tcx.infer_ctxt(None, Some(impl_param_env), Reveal::NotSpecializable).enter(|infcx| { + tcx.infer_ctxt(impl_param_env, Reveal::NotSpecializable).enter(|infcx| { let tcx = infcx.tcx; let mut fulfillment_cx = traits::FulfillmentContext::new(); diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 5c3da4237bef2..f331c561f0c40 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -801,13 +801,19 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { // If so, add "synthetic impls". let steps = self.steps.clone(); for step in steps.iter() { - let closure_def_id = match step.self_ty.sty { - ty::TyClosure(a, _) => a, + let closure_id = match step.self_ty.sty { + ty::TyClosure(def_id, _) => { + if let Some(id) = self.tcx.map.as_local_node_id(def_id) { + id + } else { + continue; + } + } _ => continue, }; let closure_kinds = &self.tables.borrow().closure_kinds; - let closure_kind = match closure_kinds.get(&closure_def_id) { + let closure_kind = match closure_kinds.get(&closure_id) { Some(&k) => k, None => { return Err(MethodError::ClosureAmbiguity(trait_def_id)); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index ec1ca99c7687f..e7657fb16463c 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -105,7 +105,7 @@ use lint; use util::common::{ErrorReported, indenter}; use util::nodemap::{DefIdMap, FxHashMap, FxHashSet, NodeMap}; -use std::cell::{Cell, Ref, RefCell}; +use std::cell::{Cell, RefCell}; use std::cmp; use std::mem::replace; use std::ops::{self, Deref}; @@ -483,12 +483,11 @@ pub struct InheritedBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { impl<'a, 'gcx, 'tcx> CrateCtxt<'a, 'gcx> { pub fn inherited(&'a self, id: ast::NodeId) -> InheritedBuilder<'a, 'gcx, 'tcx> { + let tables = ty::Tables::empty(); let param_env = ParameterEnvironment::for_item(self.tcx, id); InheritedBuilder { ccx: self, - infcx: self.tcx.infer_ctxt(Some(ty::Tables::empty()), - Some(param_env), - Reveal::NotSpecializable) + infcx: self.tcx.infer_ctxt((tables, param_env), Reveal::NotSpecializable) } } } @@ -612,8 +611,7 @@ pub fn check_item_bodies(ccx: &CrateCtxt) -> CompileResult { let _task = ccx.tcx.dep_graph.in_task(DepNode::TypeckItemBody(def_id)); let param_env = ParameterEnvironment::for_item(ccx.tcx, item_id); - ccx.tcx.infer_ctxt(None, Some(param_env), - Reveal::NotSpecializable).enter(|infcx| { + ccx.tcx.infer_ctxt(param_env, Reveal::NotSpecializable).enter(|infcx| { let mut fulfillment_cx = traits::FulfillmentContext::new(); for obligation in obligations.iter().map(|o| o.to_obligation()) { fulfillment_cx.register_predicate_obligation(&infcx, obligation); @@ -1871,17 +1869,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } - pub fn item_substs(&self) -> Ref>> { - // NOTE: @jroesch this is hack that appears to be fixed on nightly, will monitor if - // it changes when we upgrade the snapshot compiler - fn project_item_susbts<'a, 'tcx>(tables: &'a ty::Tables<'tcx>) - -> &'a NodeMap> { - &tables.item_substs - } - - Ref::map(self.tables.borrow(), project_item_susbts) - } - pub fn opt_node_ty_substs(&self, id: ast::NodeId, f: F) where @@ -3872,8 +3859,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { tcx.mk_array(unified, args.len()) } hir::ExprRepeat(ref element, count) => { - let count_expr = &tcx.map.body(count).value; - let count = eval_length(self.tcx.global_tcx(), count_expr, "repeat count") + let count = eval_length(self.tcx.global_tcx(), count, "repeat count") .unwrap_or(0); let uty = match expected { diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index 5d927a503a116..95da5a97f6750 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -106,8 +106,7 @@ impl<'a, 'gcx, 'tcx> SeedBorrowKind<'a, 'gcx, 'tcx> { expr: &hir::Expr, capture_clause: hir::CaptureClause) { - let closure_def_id = self.fcx.tcx.map.local_def_id(expr.id); - if !self.fcx.tables.borrow().closure_kinds.contains_key(&closure_def_id) { + if !self.fcx.tables.borrow().closure_kinds.contains_key(&expr.id) { self.temp_closure_kinds.insert(expr.id, ty::ClosureKind::Fn); debug!("check_closure: adding closure {:?} as Fn", expr.id); } @@ -211,8 +210,7 @@ impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> { // main table and process any deferred resolutions. let closure_def_id = self.fcx.tcx.map.local_def_id(id); if let Some(&kind) = self.temp_closure_kinds.get(&id) { - self.fcx.tables.borrow_mut().closure_kinds - .insert(closure_def_id, kind); + self.fcx.tables.borrow_mut().closure_kinds.insert(id, kind); debug!("closure_kind({:?}) = {:?}", closure_def_id, kind); let mut deferred_call_resolutions = diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 6d32b7364f8ea..0f5f8d889e810 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -228,11 +228,6 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> { self.visit_node_id(ResolvingPattern(p.span), p.id); - debug!("Type for pattern binding {} (id {}) resolved to {:?}", - self.tcx().map.node_to_pretty_string(p.id), - p.id, - self.tcx().tables().node_id_to_type(p.id)); - intravisit::walk_pat(self, p); } @@ -280,13 +275,15 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { return } - for (def_id, closure_ty) in self.fcx.tables.borrow().closure_tys.iter() { - let closure_ty = self.resolve(closure_ty, ResolvingClosure(*def_id)); - self.tcx().tables.borrow_mut().closure_tys.insert(*def_id, closure_ty); + for (&id, closure_ty) in self.fcx.tables.borrow().closure_tys.iter() { + let closure_ty = self.resolve(closure_ty, ResolvingClosure(id)); + let def_id = self.tcx().map.local_def_id(id); + self.tcx().closure_tys.borrow_mut().insert(def_id, closure_ty); } - for (def_id, &closure_kind) in self.fcx.tables.borrow().closure_kinds.iter() { - self.tcx().tables.borrow_mut().closure_kinds.insert(*def_id, closure_kind); + for (&id, &closure_kind) in self.fcx.tables.borrow().closure_kinds.iter() { + let def_id = self.tcx().map.local_def_id(id); + self.tcx().closure_kinds.borrow_mut().insert(def_id, closure_kind); } } @@ -496,7 +493,7 @@ enum ResolveReason { ResolvingLocal(Span), ResolvingPattern(Span), ResolvingUpvar(ty::UpvarId), - ResolvingClosure(DefId), + ResolvingClosure(ast::NodeId), ResolvingFnSig(ast::NodeId), ResolvingFieldTypes(ast::NodeId), ResolvingAnonTy(DefId), @@ -513,12 +510,12 @@ impl<'a, 'gcx, 'tcx> ResolveReason { ResolvingUpvar(upvar_id) => { tcx.expr_span(upvar_id.closure_expr_id) } + ResolvingClosure(id) | ResolvingFnSig(id) | ResolvingFieldTypes(id) | ResolvingTyNode(id) => { tcx.map.span(id) } - ResolvingClosure(did) | ResolvingAnonTy(did) => { tcx.def_span(did) } diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index ba95a17989165..57df0fb2cee93 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -205,7 +205,7 @@ fn visit_implementation_of_coerce_unsized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, source, target); - tcx.infer_ctxt(None, Some(param_env), Reveal::ExactMatch).enter(|infcx| { + tcx.infer_ctxt(param_env, Reveal::ExactMatch).enter(|infcx| { let cause = ObligationCause::misc(span, impl_node_id); let check_mutbl = |mt_a: ty::TypeAndMut<'tcx>, mt_b: ty::TypeAndMut<'tcx>, diff --git a/src/librustc_typeck/coherence/overlap.rs b/src/librustc_typeck/coherence/overlap.rs index a09bdf0533a15..08293c1d874a8 100644 --- a/src/librustc_typeck/coherence/overlap.rs +++ b/src/librustc_typeck/coherence/overlap.rs @@ -87,7 +87,7 @@ impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> { for (i, &impl1_def_id) in impls.iter().enumerate() { for &impl2_def_id in &impls[(i + 1)..] { - self.tcx.infer_ctxt(None, None, Reveal::ExactMatch).enter(|infcx| { + self.tcx.infer_ctxt((), Reveal::ExactMatch).enter(|infcx| { if traits::overlapping_impls(&infcx, impl1_def_id, impl2_def_id).is_some() { self.check_for_common_items_in_impls(impl1_def_id, impl2_def_id) } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 7ddf10375bf23..f832bf8d86e93 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -63,7 +63,7 @@ use constrained_type_params as ctp; use middle::lang_items::SizedTraitLangItem; use middle::const_val::ConstVal; use rustc_const_eval::EvalHint::UncheckedExprHint; -use rustc_const_eval::{eval_const_expr_partial, report_const_eval_err}; +use rustc_const_eval::{ConstContext, report_const_eval_err}; use rustc::ty::subst::Substs; use rustc::ty::{ToPredicate, ImplContainer, AssociatedItemContainer, TraitContainer}; use rustc::ty::{self, AdtKind, ToPolyTraitRef, Ty, TyCtxt}; @@ -1039,8 +1039,9 @@ fn convert_union_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, adt } - fn evaluate_disr_expr(ccx: &CrateCtxt, repr_ty: attr::IntType, e: &hir::Expr) + fn evaluate_disr_expr(ccx: &CrateCtxt, repr_ty: attr::IntType, body: hir::BodyId) -> Option { + let e = &ccx.tcx.map.body(body).value; debug!("disr expr, checking {}", ccx.tcx.map.node_to_pretty_string(e.id)); let ty_hint = repr_ty.to_ty(ccx.tcx); @@ -1052,9 +1053,9 @@ fn convert_union_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, }; let hint = UncheckedExprHint(ty_hint); - match eval_const_expr_partial(ccx.tcx, e, hint, None) { + match ConstContext::new(ccx.tcx, body).eval(e, hint) { Ok(ConstVal::Integral(i)) => { - // FIXME: eval_const_expr_partial should return an error if the hint is wrong + // FIXME: eval should return an error if the hint is wrong match (repr_ty, i) { (attr::SignedInt(ast::IntTy::I8), ConstInt::I8(_)) | (attr::SignedInt(ast::IntTy::I16), ConstInt::I16(_)) | @@ -1103,7 +1104,6 @@ fn convert_enum_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let variants = def.variants.iter().map(|v| { let wrapped_disr = prev_disr.map_or(initial, |d| d.wrap_incr()); let disr = if let Some(e) = v.node.disr_expr { - let e = &tcx.map.body(e).value; evaluate_disr_expr(ccx, repr_type, e) } else if let Some(disr) = repr_type.disr_incr(tcx, prev_disr) { Some(disr) diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index ec17813ed2a52..58d228ee6cd74 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -177,7 +177,7 @@ fn require_same_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, expected: Ty<'tcx>, actual: Ty<'tcx>) -> bool { - ccx.tcx.infer_ctxt(None, None, Reveal::NotSpecializable).enter(|infcx| { + ccx.tcx.infer_ctxt((), Reveal::NotSpecializable).enter(|infcx| { match infcx.eq_types(false, &cause, expected, actual) { Ok(InferOk { obligations, .. }) => { // FIXME(#32730) propagate obligations diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index d66d2001f2304..93c0bd6d6d836 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -14,7 +14,6 @@ arena = { path = "../libarena" } rustc = { path = "../librustc" } rustc_back = { path = "../librustc_back" } rustc_const_eval = { path = "../librustc_const_eval" } -rustc_const_math = { path = "../librustc_const_math" } rustc_driver = { path = "../librustc_driver" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_errors = { path = "../librustc_errors" } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index faf39db572380..6a640e7b5ed80 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1692,22 +1692,10 @@ impl Clean for hir::Ty { BorrowedRef {lifetime: l.clean(cx), mutability: m.mutbl.clean(cx), type_: box m.ty.clean(cx)}, TySlice(ref ty) => Vector(box ty.clean(cx)), - TyArray(ref ty, e) => { - use rustc_const_math::{ConstInt, ConstUsize}; - use rustc_const_eval::eval_const_expr; - use rustc::middle::const_val::ConstVal; - - let e = &cx.tcx.map.body(e).value; - let n = match eval_const_expr(cx.tcx, e) { - ConstVal::Integral(ConstInt::Usize(u)) => match u { - ConstUsize::Us16(u) => u.to_string(), - ConstUsize::Us32(u) => u.to_string(), - ConstUsize::Us64(u) => u.to_string(), - }, - // after type checking this can't fail - _ => unreachable!(), - }; - FixedVector(box ty.clean(cx), n) + TyArray(ref ty, length) => { + use rustc_const_eval::eval_length; + let n = eval_length(cx.tcx, length, "array length").unwrap(); + FixedVector(box ty.clean(cx), n.to_string()) }, TyTup(ref tys) => Tuple(tys.clean(cx)), TyPath(hir::QPath::Resolved(None, ref path)) => { diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 47616044879cd..81d47d3eee88e 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -33,7 +33,6 @@ extern crate getopts; extern crate libc; extern crate rustc; extern crate rustc_const_eval; -extern crate rustc_const_math; extern crate rustc_data_structures; extern crate rustc_trans; extern crate rustc_driver; diff --git a/src/test/compile-fail/const-eval-overflow.rs b/src/test/compile-fail/const-eval-overflow.rs index b8f3f714a84ec..3c688d58fd195 100644 --- a/src/test/compile-fail/const-eval-overflow.rs +++ b/src/test/compile-fail/const-eval-overflow.rs @@ -15,6 +15,8 @@ // change this warn to a deny, then the compiler will exit before // those errors are detected. +#![warn(const_err)] + use std::fmt; use std::{i8, i16, i32, i64, isize}; use std::{u8, u16, u32, u64, usize}; @@ -80,7 +82,8 @@ const VALS_I64: (i64, i64, i64, i64) = ); const VALS_U8: (u8, u8, u8, u8) = - (-(u8::MIN as i8) as u8, + ( //~ WARN constant evaluation error: attempt to subtract with overflow. + -(u8::MIN as i8) as u8, u8::MIN - 1, //~^ ERROR constant evaluation error //~| attempt to subtract with overflow @@ -93,7 +96,8 @@ const VALS_U8: (u8, u8, u8, u8) = ); const VALS_U16: (u16, u16, u16, u16) = - (-(u16::MIN as i16) as u16, + ( //~ WARN constant evaluation error: attempt to subtract with overflow. + -(u16::MIN as i16) as u16, u16::MIN - 1, //~^ ERROR constant evaluation error //~| attempt to subtract with overflow @@ -106,7 +110,8 @@ const VALS_U16: (u16, u16, u16, u16) = ); const VALS_U32: (u32, u32, u32, u32) = - (-(u32::MIN as i32) as u32, + ( //~ WARN constant evaluation error: attempt to subtract with overflow. + -(u32::MIN as i32) as u32, u32::MIN - 1, //~^ ERROR constant evaluation error //~| attempt to subtract with overflow @@ -119,7 +124,8 @@ const VALS_U32: (u32, u32, u32, u32) = ); const VALS_U64: (u64, u64, u64, u64) = - (-(u64::MIN as i64) as u64, + ( //~ WARN constant evaluation error: attempt to subtract with overflow. + -(u64::MIN as i64) as u64, u64::MIN - 1, //~^ ERROR constant evaluation error //~| attempt to subtract with overflow diff --git a/src/test/run-pass/issue-28189.rs b/src/test/run-pass/issue-28189.rs deleted file mode 100644 index 0e624a778583d..0000000000000 --- a/src/test/run-pass/issue-28189.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct S(T) where [T; (||{}, 1).1]: Copy; - -fn main() { - -}