mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-10 22:13:27 +00:00
rustc: keep track of tables everywhere as if they were per-body.
This commit is contained in:
parent
a28701a928
commit
85a4a192c7
1
src/Cargo.lock
generated
1
src/Cargo.lock
generated
@ -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",
|
||||
|
@ -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<LoopScope>,
|
||||
@ -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::<hir::Expr>.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);
|
||||
|
@ -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,
|
||||
|
@ -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<T> = Option<T>;
|
||||
pub type UnitResult<'tcx> = RelateResult<'tcx, ()>; // "unify result"
|
||||
pub type FixupResult<T> = Result<T, FixupError>; // "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<ty::Tables<'gcx>>),
|
||||
Local(&'a RefCell<ty::Tables<'tcx>>)
|
||||
Interned(&'a ty::Tables<'gcx>),
|
||||
InProgress(&'a RefCell<ty::Tables<'tcx>>),
|
||||
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<ty::Tables<'tcx>>,
|
||||
Option<ty::ParameterEnvironment<'tcx>>);
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> InferEnv<'a, 'tcx> for () {
|
||||
fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>)
|
||||
-> (Option<&'a ty::Tables<'tcx>>,
|
||||
Option<ty::Tables<'tcx>>,
|
||||
Option<ty::ParameterEnvironment<'tcx>>) {
|
||||
(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<ty::Tables<'tcx>>,
|
||||
Option<ty::ParameterEnvironment<'tcx>>) {
|
||||
(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<ty::Tables<'tcx>>,
|
||||
Option<ty::ParameterEnvironment<'tcx>>) {
|
||||
(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<ty::Tables<'tcx>>,
|
||||
Option<ty::ParameterEnvironment<'tcx>>) {
|
||||
(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<ty::Tables<'tcx>>,
|
||||
Option<ty::ParameterEnvironment<'tcx>>) {
|
||||
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<RefCell<ty::Tables<'tcx>>>,
|
||||
fresh_tables: Option<RefCell<ty::Tables<'tcx>>>,
|
||||
tables: Option<&'a ty::Tables<'gcx>>,
|
||||
param_env: Option<ty::ParameterEnvironment<'gcx>>,
|
||||
projection_mode: Reveal,
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
|
||||
pub fn infer_ctxt(self,
|
||||
tables: Option<ty::Tables<'tcx>>,
|
||||
param_env: Option<ty::ParameterEnvironment<'gcx>>,
|
||||
projection_mode: Reveal)
|
||||
-> InferCtxtBuilder<'a, 'gcx, 'tcx> {
|
||||
pub fn infer_ctxt<E: InferEnv<'a, 'gcx>>(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<NodeMap<adjustment::Adjustment<'tcx>>> {
|
||||
fn project_adjustments<'a, 'tcx>(tables: &'a ty::Tables<'tcx>)
|
||||
-> &'a NodeMap<adjustment::Adjustment<'tcx>> {
|
||||
&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<ty::ClosureKind>
|
||||
{
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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| {
|
||||
|
@ -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<Vec<u8>>),
|
||||
Bool(bool),
|
||||
Struct(ast::NodeId),
|
||||
Tuple(ast::NodeId),
|
||||
Function(DefId),
|
||||
Array(ast::NodeId, u64),
|
||||
Repeat(ast::NodeId, u64),
|
||||
Struct(BTreeMap<ast::Name, ConstVal>),
|
||||
Tuple(Vec<ConstVal>),
|
||||
Array(Vec<ConstVal>),
|
||||
Repeat(Box<ConstVal>, 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",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -49,6 +49,7 @@ fn should_explore<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
struct MarkSymbolVisitor<'a, 'tcx: 'a> {
|
||||
worklist: Vec<ast::NodeId>,
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
tables: &'a ty::Tables<'tcx>,
|
||||
live_symbols: Box<FxHashSet<ast::NodeId>>,
|
||||
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<ast::NodeId>) -> 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<hir::FieldPat>]) {
|
||||
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<FxHashSet<ast::NodeId>> {
|
||||
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
|
||||
}
|
||||
|
@ -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),
|
||||
};
|
||||
|
||||
|
@ -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, ..) => {
|
||||
|
@ -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];
|
||||
|
@ -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<LiveNode>,
|
||||
users: Vec<Users>,
|
||||
@ -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()
|
||||
});
|
||||
|
@ -384,7 +384,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
pub fn cat_expr(&self, expr: &hir::Expr) -> McResult<cmt<'tcx>> {
|
||||
match self.infcx.adjustments().get(&expr.id) {
|
||||
match self.infcx.tables.borrow().adjustments.get(&expr.id) {
|
||||
None => {
|
||||
// No adjustments.
|
||||
self.cat_expr_unadjusted(expr)
|
||||
|
@ -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.
|
||||
|
@ -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<W: Write>(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))
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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 =
|
||||
|
@ -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);
|
||||
|
@ -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<ty::ClosureTy<'tcx>>,
|
||||
/// Records the type of each closure.
|
||||
pub closure_tys: NodeMap<ty::ClosureTy<'tcx>>,
|
||||
|
||||
/// Records the type of each closure. The def ID is the ID of the
|
||||
/// expression defining the closure.
|
||||
pub closure_kinds: DefIdMap<ty::ClosureKind>,
|
||||
/// Records the type of each closure.
|
||||
pub closure_kinds: NodeMap<ty::ClosureKind>,
|
||||
|
||||
/// 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<Vec<Ty<'tcx>>>
|
||||
}
|
||||
|
||||
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<DefIdMap<ty::adjustment::CustomCoerceUnsized>>,
|
||||
|
||||
/// Records the type of each closure. The def ID is the ID of the
|
||||
/// expression defining the closure.
|
||||
pub closure_tys: RefCell<DepTrackingMap<maps::ClosureTypes<'tcx>>>,
|
||||
|
||||
/// Records the type of each closure. The def ID is the ID of the
|
||||
/// expression defining the closure.
|
||||
pub closure_kinds: RefCell<DepTrackingMap<maps::ClosureKinds<'tcx>>>,
|
||||
|
||||
/// 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<NodeMap<ty::cast::CastKind>>,
|
||||
@ -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),
|
||||
|
@ -46,3 +46,5 @@ dep_map_ty! { ItemVariances: ItemSignature(DefId) -> Rc<Vec<ty::Variance>> }
|
||||
dep_map_ty! { InherentImpls: InherentImpls(DefId) -> Vec<DefId> }
|
||||
dep_map_ty! { ReprHints: ReprHints(DefId) -> Rc<Vec<attr::ReprAttr>> }
|
||||
dep_map_ty! { Mir: Mir(DefId) -> &'tcx RefCell<mir::Mir<'tcx>> }
|
||||
dep_map_ty! { ClosureKinds: ItemSignature(DefId) -> ty::ClosureKind }
|
||||
dep_map_ty! { ClosureTypes: ItemSignature(DefId) -> ty::ClosureTy<'tcx> }
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
});
|
||||
|
@ -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,
|
||||
|
@ -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>,
|
||||
|
@ -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<Loan<'tcx>>,
|
||||
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<Loan<'tcx>>,
|
||||
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -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<ty::Ty<'tcx>>)> {
|
||||
-> Option<(&'tcx Expr, &'a ty::Tables<'tcx>,
|
||||
Option<ty::Ty<'tcx>>)> {
|
||||
if let Some(node_id) = tcx.map.as_local_node_id(def_id) {
|
||||
match tcx.map.find(node_id) {
|
||||
None => None,
|
||||
Some(ast_map::NodeItem(it)) => match it.node {
|
||||
hir::ItemConst(ref 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,31 +221,34 @@ 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<DefIdMap<ConstVal>>
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
/// 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)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn eval_const_expr_checked<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
e: &Expr) -> EvalResult
|
||||
{
|
||||
eval_const_expr_partial(tcx, e, ExprTypeChecked, None)
|
||||
}
|
||||
|
||||
pub type FnArgMap<'a> = Option<&'a DefIdMap<ConstVal>>;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ConstEvalErr {
|
||||
pub span: Span,
|
||||
@ -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::<Result<_, _>>()?)
|
||||
}
|
||||
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::<Result<_, _>>()?)
|
||||
}
|
||||
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::<Result<_, _>>()?)
|
||||
}
|
||||
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<ty::Ty<'tcx>>)>,
|
||||
default_value: Option<(&'tcx Expr, &'a ty::Tables<'tcx>, Option<ty::Ty<'tcx>>)>,
|
||||
trait_id: DefId,
|
||||
rcvr_substs: &'tcx Substs<'tcx>
|
||||
) -> Option<(&'tcx Expr, Option<ty::Ty<'tcx>>)>
|
||||
) -> Option<(&'tcx Expr, &'a ty::Tables<'tcx>, Option<ty::Ty<'tcx>>)>
|
||||
{
|
||||
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<Ordering, ErrorReported> {
|
||||
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<Ordering, ErrorReported> {
|
||||
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<usize, ErrorReported>
|
||||
{
|
||||
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);
|
||||
|
@ -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<PatternError>,
|
||||
}
|
||||
|
||||
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,
|
||||
_ => {
|
||||
|
@ -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<borrowck_dot::Variant>,
|
||||
}
|
||||
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,
|
||||
|
@ -149,7 +149,7 @@ fn test_env<F>(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();
|
||||
|
@ -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];
|
||||
|
@ -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)
|
||||
|
@ -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)) => {
|
||||
|
@ -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<TableEntry>| {
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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,161 +79,27 @@ 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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> CxBuilder<'a, 'gcx, 'tcx> {
|
||||
fn build<F>(&'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));
|
||||
|
||||
// Convert the Mir to global types.
|
||||
let tcx = infcx.tcx.global_tcx();
|
||||
let mut globalizer = GlobalizeMir {
|
||||
tcx: tcx,
|
||||
span: mir.span
|
||||
};
|
||||
globalizer.visit_mir(&mut mir);
|
||||
let mir = unsafe {
|
||||
mem::transmute::<Mir, Mir<'gcx>>(mir)
|
||||
};
|
||||
|
||||
pretty::dump_mir(tcx, "mir_map", &0, src, &mir);
|
||||
|
||||
let mir = tcx.alloc_mir(mir);
|
||||
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) {
|
||||
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 = match self.tcx.tables().liberated_fn_sigs.get(&id) {
|
||||
Some(f) => f.clone(),
|
||||
None => {
|
||||
span_bug!(span, "no liberated fn sig for {:?}", id);
|
||||
}
|
||||
};
|
||||
let fn_sig = cx.tables().liberated_fn_sigs[&id].clone();
|
||||
|
||||
let (abi, implicit_argument) = if let FnKind::Closure(..) = fk {
|
||||
(Abi::Rust, Some((closure_self_ty(self.tcx, id, body_id.node_id), None)))
|
||||
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 {
|
||||
let def_id = self.tcx.map.local_def_id(id);
|
||||
(self.tcx.item_type(def_id).fn_abi(), None)
|
||||
(ty.fn_abi(), None)
|
||||
};
|
||||
|
||||
let body = self.tcx.map.body(body_id);
|
||||
let body = tcx.map.body(body_id);
|
||||
let explicit_arguments =
|
||||
body.arguments
|
||||
.iter()
|
||||
@ -244,25 +109,55 @@ impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> {
|
||||
});
|
||||
|
||||
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)
|
||||
(build::construct_fn(cx, id, arguments, abi, fn_sig.output(), body), src)
|
||||
} else {
|
||||
(build::construct_const(cx, body_id), 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();
|
||||
let mut globalizer = GlobalizeMir {
|
||||
tcx: tcx,
|
||||
span: mir.span
|
||||
};
|
||||
globalizer.visit_mir(&mut mir);
|
||||
let mir = unsafe {
|
||||
mem::transmute::<Mir, Mir<'tcx>>(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());
|
||||
});
|
||||
|
||||
intravisit::walk_fn(self, fk, decl, body_id, span, id);
|
||||
let body = self.tcx.map.body(body_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);
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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(),
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -99,7 +99,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
|
||||
}
|
||||
}
|
||||
|
||||
fn nest<F>(&mut self, scope_id: NodeId, f: F)
|
||||
fn nest_scope<F>(&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<F>(&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 {
|
||||
"<mutable>".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);
|
||||
|
@ -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<CrateData> {
|
||||
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<Data> {
|
||||
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) => {{
|
||||
|
@ -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,
|
||||
|
@ -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(_) =>
|
||||
|
@ -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<ZeroSizeType>` does not allocate.
|
||||
|
@ -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());
|
||||
|
@ -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
|
||||
|
@ -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 => {}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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<NodeMap<ty::ItemSubsts<'tcx>>> {
|
||||
// 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<ty::ItemSubsts<'tcx>> {
|
||||
&tables.item_substs
|
||||
}
|
||||
|
||||
Ref::map(self.tables.borrow(), project_item_susbts)
|
||||
}
|
||||
|
||||
pub fn opt_node_ty_substs<F>(&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 {
|
||||
|
@ -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 =
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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>,
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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<ty::Disr> {
|
||||
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)
|
||||
|
@ -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
|
||||
|
@ -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" }
|
||||
|
@ -1692,22 +1692,10 @@ impl Clean<Type> 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)) => {
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
struct S<T>(T) where [T; (||{}, 1).1]: Copy;
|
||||
|
||||
fn main() {
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user