Rollup merge of #37408 - eddyb:lazy-5, r=nikomatsakis

[5/n] rustc: record the target type of every adjustment.

_This is part of a series ([prev](https://github.com/rust-lang/rust/pull/37404) | [next](https://github.com/rust-lang/rust/pull/37412)) of patches designed to rework rustc into an out-of-order on-demand pipeline model for both better feature support (e.g. [MIR-based](https://github.com/solson/miri) early constant evaluation) and incremental execution of compiler passes (e.g. type-checking), with beneficial consequences to IDE support as well.
If any motivation is unclear, please ask for additional PR description clarifications or code comments._

<hr>

The first commit rearranges `tcx.tables` so that all users go through `tcx.tables()`. This in preparation for per-body `Tables` where they will be requested for a specific `DefId`. Included to minimize churn.

The rest of the changes focus on adjustments, there are some renamings, but the main addition is the target type, always available in all cases (as opposed to just for unsizing where it was previously needed).

Possibly the most significant effect of this change is that figuring out the final type of an expression is now _always_ just one successful `HashMap` lookup (either the adjustment or, if that doesn't exist, the node type).
This commit is contained in:
Alex Crichton 2016-11-04 16:49:28 -07:00 committed by GitHub
commit 1a0963292a
47 changed files with 630 additions and 801 deletions

View File

@ -311,11 +311,11 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
}
hir::ExprIndex(ref l, ref r) |
hir::ExprBinary(_, ref l, ref r) if self.tcx.is_method_call(expr.id) => {
hir::ExprBinary(_, ref l, ref r) if self.tcx.tables().is_method_call(expr.id) => {
self.call(expr, pred, &l, Some(&**r).into_iter())
}
hir::ExprUnary(_, ref e) if self.tcx.is_method_call(expr.id) => {
hir::ExprUnary(_, ref e) if self.tcx.tables().is_method_call(expr.id) => {
self.call(expr, pred, &e, None::<hir::Expr>.iter())
}
@ -372,9 +372,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.borrow().method_map.get(&method_call) {
let fn_ty = match self.tcx.tables().method_map.get(&method_call) {
Some(method) => method.ty,
None => self.tcx.expr_ty_adjusted(func_or_rcvr)
None => self.tcx.tables().expr_ty_adjusted(func_or_rcvr)
};
let func_or_rcvr_exit = self.expr(func_or_rcvr, pred);

View File

@ -1266,26 +1266,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
self.region_vars.new_bound(debruijn)
}
/// Apply `adjustment` to the type of `expr`
pub fn adjust_expr_ty(&self,
expr: &hir::Expr,
adjustment: Option<&adjustment::AutoAdjustment<'tcx>>)
-> Ty<'tcx>
{
let raw_ty = self.expr_ty(expr);
let raw_ty = self.shallow_resolve(raw_ty);
let resolve_ty = |ty: Ty<'tcx>| self.resolve_type_vars_if_possible(&ty);
raw_ty.adjust(self.tcx,
expr.span,
expr.id,
adjustment,
|method_call| self.tables
.borrow()
.method_map
.get(&method_call)
.map(|method| resolve_ty(method.ty)))
}
/// True if errors have been reported since this infcx was
/// created. This is sometimes used as a heuristic to skip
/// reporting errors that often occur as a result of earlier
@ -1622,7 +1602,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
}
pub fn expr_ty_adjusted(&self, expr: &hir::Expr) -> McResult<Ty<'tcx>> {
let ty = self.adjust_expr_ty(expr, self.tables.borrow().adjustments.get(&expr.id));
let ty = self.tables.borrow().expr_ty_adjusted(expr);
self.resolve_type_vars_or_error(&ty)
}
@ -1666,9 +1646,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
.map(|method| method.def_id)
}
pub fn adjustments(&self) -> Ref<NodeMap<adjustment::AutoAdjustment<'tcx>>> {
pub fn adjustments(&self) -> Ref<NodeMap<adjustment::Adjustment<'tcx>>> {
fn project_adjustments<'a, 'tcx>(tables: &'a ty::Tables<'tcx>)
-> &'a NodeMap<adjustment::AutoAdjustment<'tcx>> {
-> &'a NodeMap<adjustment::Adjustment<'tcx>> {
&tables.adjustments
}

View File

@ -92,7 +92,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
match def {
Def::AssociatedTy(..) | Def::Method(_) | Def::AssociatedConst(_)
if self.tcx.trait_of_item(def.def_id()).is_some() => {
if let Some(substs) = self.tcx.tables.borrow().item_substs.get(&id) {
if let Some(substs) = self.tcx.tables().item_substs.get(&id) {
if let ty::TyAdt(tyid, _) = substs.substs.type_at(0).sty {
self.check_def_id(tyid.did);
}
@ -123,12 +123,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.borrow().method_map[&method_call];
let method = self.tcx.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.expr_ty_adjusted(lhs).sty {
match self.tcx.tables().expr_ty_adjusted(lhs).sty {
ty::TyAdt(def, _) => {
self.insert_def_id(def.struct_variant().field_named(name).did);
}
@ -137,7 +137,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
}
fn handle_tup_field_access(&mut self, lhs: &hir::Expr, idx: usize) {
match self.tcx.expr_ty_adjusted(lhs).sty {
match self.tcx.tables().expr_ty_adjusted(lhs).sty {
ty::TyAdt(def, _) => {
self.insert_def_id(def.struct_variant().fields[idx].did);
}
@ -148,7 +148,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
fn handle_field_pattern_match(&mut self, lhs: &hir::Pat,
pats: &[codemap::Spanned<hir::FieldPat>]) {
let variant = match self.tcx.node_id_to_type(lhs.id).sty {
let variant = match self.tcx.tables().node_id_to_type(lhs.id).sty {
ty::TyAdt(adt, _) => {
adt.variant_of_def(self.tcx.expect_def(lhs.id))
}
@ -433,7 +433,7 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> {
}
fn should_warn_about_field(&mut self, field: &hir::StructField) -> bool {
let field_type = self.tcx.node_id_to_type(field.id);
let field_type = self.tcx.tables().node_id_to_type(field.id);
let is_marker_field = match field_type.ty_to_def_id() {
Some(def_id) => self.tcx.lang_items.items().iter().any(|item| *item == Some(def_id)),
_ => false

View File

@ -159,7 +159,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
match expr.node {
hir::ExprMethodCall(..) => {
let method_call = MethodCall::expr(expr.id);
let base_type = self.tcx.tables.borrow().method_map[&method_call].ty;
let base_type = self.tcx.tables().method_map[&method_call].ty;
debug!("effect: method call case, base type is {:?}",
base_type);
if type_is_unsafe_function(base_type) {
@ -168,7 +168,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
}
}
hir::ExprCall(ref base, _) => {
let base_type = self.tcx.expr_ty_adjusted(base);
let base_type = self.tcx.tables().expr_ty_adjusted(base);
debug!("effect: call case, base type is {:?}",
base_type);
if type_is_unsafe_function(base_type) {
@ -176,7 +176,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
}
}
hir::ExprUnary(hir::UnDeref, ref base) => {
let base_type = self.tcx.expr_ty_adjusted(base);
let base_type = self.tcx.tables().expr_ty_adjusted(base);
debug!("effect: unary case, base type is {:?}",
base_type);
if let ty::TyRawPtr(_) = base_type.sty {
@ -200,7 +200,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
}
}
hir::ExprField(ref base_expr, field) => {
if let ty::TyAdt(adt, ..) = self.tcx.expr_ty_adjusted(base_expr).sty {
if let ty::TyAdt(adt, ..) = self.tcx.tables().expr_ty_adjusted(base_expr).sty {
if adt.is_union() {
self.require_unsafe(field.span, "access to union field");
}
@ -214,7 +214,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
fn visit_pat(&mut self, pat: &hir::Pat) {
if let PatKind::Struct(_, ref fields, _) = pat.node {
if let ty::TyAdt(adt, ..) = self.tcx.pat_ty(pat).sty {
if let ty::TyAdt(adt, ..) = self.tcx.tables().pat_ty(pat).sty {
if adt.is_union() {
for field in fields {
self.require_unsafe(field.span, "matching on union field");

View File

@ -720,11 +720,11 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
//NOTE(@jroesch): mixed RefCell borrow causes crash
let adj = infcx.adjustments().get(&expr.id).map(|x| x.clone());
if let Some(adjustment) = adj {
match adjustment {
adjustment::AdjustNeverToAny(..) |
adjustment::AdjustReifyFnPointer |
adjustment::AdjustUnsafeFnPointer |
adjustment::AdjustMutToConstPointer => {
match adjustment.kind {
adjustment::Adjust::NeverToAny |
adjustment::Adjust::ReifyFnPointer |
adjustment::Adjust::UnsafeFnPointer |
adjustment::Adjust::MutToConstPointer => {
// Creating a closure/fn-pointer or unsizing consumes
// the input and stores it into the resulting rvalue.
debug!("walk_adjustment: trivial adjustment");
@ -732,8 +732,21 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
return_if_err!(self.mc.cat_expr_unadjusted(expr));
self.delegate_consume(expr.id, expr.span, cmt_unadjusted);
}
adjustment::AdjustDerefRef(ref adj) => {
self.walk_autoderefref(expr, adj);
adjustment::Adjust::DerefRef { autoderefs, autoref, unsize } => {
debug!("walk_adjustment expr={:?} adj={:?}", expr, adjustment);
self.walk_autoderefs(expr, autoderefs);
let cmt_derefd =
return_if_err!(self.mc.cat_expr_autoderefd(expr, autoderefs));
let cmt_refd =
self.walk_autoref(expr, cmt_derefd, autoref);
if unsize {
// Unsizing consumes the thin pointer and produces a fat one.
self.delegate_consume(expr.id, expr.span, cmt_refd);
}
}
}
}
@ -770,28 +783,6 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
}
}
fn walk_autoderefref(&mut self,
expr: &hir::Expr,
adj: &adjustment::AutoDerefRef<'tcx>) {
debug!("walk_autoderefref expr={:?} adj={:?}",
expr,
adj);
self.walk_autoderefs(expr, adj.autoderefs);
let cmt_derefd =
return_if_err!(self.mc.cat_expr_autoderefd(expr, adj.autoderefs));
let cmt_refd =
self.walk_autoref(expr, cmt_derefd, adj.autoref);
if adj.unsize.is_some() {
// Unsizing consumes the thin pointer and produces a fat one.
self.delegate_consume(expr.id, expr.span, cmt_refd);
}
}
/// Walks the autoref `opt_autoref` applied to the autoderef'd
/// `expr`. `cmt_derefd` is the mem-categorized form of `expr`
/// after all relevant autoderefs have occurred. Because AutoRefs
@ -803,7 +794,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
fn walk_autoref(&mut self,
expr: &hir::Expr,
cmt_base: mc::cmt<'tcx>,
opt_autoref: Option<adjustment::AutoRef<'tcx>>)
opt_autoref: Option<adjustment::AutoBorrow<'tcx>>)
-> mc::cmt<'tcx>
{
debug!("walk_autoref(expr.id={} cmt_derefd={:?} opt_autoref={:?})",
@ -822,7 +813,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
};
match *autoref {
adjustment::AutoPtr(r, m) => {
adjustment::AutoBorrow::Ref(r, m) => {
self.delegate.borrow(expr.id,
expr.span,
cmt_base,
@ -831,7 +822,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
AutoRef);
}
adjustment::AutoUnsafe(m) => {
adjustment::AutoBorrow::RawPtr(m) => {
debug!("walk_autoref: expr.id={} cmt_base={:?}",
expr.id,
cmt_base);

View File

@ -163,7 +163,7 @@ impl<'a, 'gcx, 'tcx, 'v> Visitor<'v> for ExprVisitor<'a, 'gcx, 'tcx> {
if let hir::ExprPath(..) = expr.node {
match self.infcx.tcx.expect_def(expr.id) {
Def::Fn(did) if self.def_id_is_transmute(did) => {
let typ = self.infcx.tcx.node_id_to_type(expr.id);
let typ = self.infcx.tcx.tables().node_id_to_type(expr.id);
match typ.sty {
ty::TyFnDef(.., ref bare_fn_ty) if bare_fn_ty.abi == RustIntrinsic => {
let from = bare_fn_ty.sig.0.inputs[0];

View File

@ -1081,7 +1081,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.is_method_call(expr.id) {
if self.ir.tcx.tables().is_method_call(expr.id) {
let succ = self.propagate_through_expr(&l, succ);
self.propagate_through_expr(&r, succ)
} else {
@ -1113,8 +1113,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.is_method_call(expr.id) &&
self.ir.tcx.expr_ty_adjusted(&f).fn_ret().0.is_never();
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 succ = if diverges {
self.s.exit_ln
} else {
@ -1126,7 +1126,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.borrow().method_map[&method_call].ty;
let method_ty = self.ir.tcx.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
@ -1409,7 +1409,7 @@ fn check_expr(this: &mut Liveness, expr: &Expr) {
}
hir::ExprAssignOp(_, ref l, _) => {
if !this.ir.tcx.is_method_call(expr.id) {
if !this.ir.tcx.tables().is_method_call(expr.id) {
this.check_lvalue(&l);
}
@ -1459,7 +1459,7 @@ fn check_fn(_v: &Liveness,
impl<'a, 'tcx> Liveness<'a, 'tcx> {
fn fn_ret(&self, id: NodeId) -> ty::Binder<Ty<'tcx>> {
let fn_ty = self.ir.tcx.node_id_to_type(id);
let fn_ty = self.ir.tcx.tables().node_id_to_type(id);
match fn_ty.sty {
ty::TyClosure(closure_def_id, substs) =>
self.ir.tcx.closure_type(closure_def_id, substs).sig.output(),
@ -1502,7 +1502,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
None if !body.stmts.is_empty() =>
match body.stmts.last().unwrap().node {
hir::StmtSemi(ref e, _) => {
self.ir.tcx.expr_ty(&e) == fn_ret
self.ir.tcx.tables().expr_ty(&e) == fn_ret
},
_ => false
},

View File

@ -354,11 +354,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
}
fn expr_ty_adjusted(&self, expr: &hir::Expr) -> McResult<Ty<'tcx>> {
let unadjusted_ty = self.expr_ty(expr)?;
Ok(unadjusted_ty.adjust(
self.tcx(), expr.span, expr.id,
self.infcx.adjustments().get(&expr.id),
|method_call| self.infcx.node_method_ty(method_call)))
self.infcx.expr_ty_adjusted(expr)
}
fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>> {
@ -396,19 +392,21 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
}
Some(adjustment) => {
match *adjustment {
adjustment::AdjustDerefRef(
adjustment::AutoDerefRef {
autoref: None, unsize: None, autoderefs, ..}) => {
match adjustment.kind {
adjustment::Adjust::DerefRef {
autoderefs,
autoref: None,
unsize: false
} => {
// Equivalent to *expr or something similar.
self.cat_expr_autoderefd(expr, autoderefs)
}
adjustment::AdjustNeverToAny(..) |
adjustment::AdjustReifyFnPointer |
adjustment::AdjustUnsafeFnPointer |
adjustment::AdjustMutToConstPointer |
adjustment::AdjustDerefRef(_) => {
adjustment::Adjust::NeverToAny |
adjustment::Adjust::ReifyFnPointer |
adjustment::Adjust::UnsafeFnPointer |
adjustment::Adjust::MutToConstPointer |
adjustment::Adjust::DerefRef {..} => {
debug!("cat_expr({:?}): {:?}",
adjustment,
expr);

View File

@ -116,7 +116,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ReachableContext<'a, 'tcx> {
}
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.tcx.tables().method_map[&method_call].def_id;
// Mark the trait item (and, possibly, its default impl) as reachable
// Or mark inherent impl item as reachable

View File

@ -555,11 +555,11 @@ pub fn check_expr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, e: &hir::Expr,
hir::ExprMethodCall(i, ..) => {
span = i.span;
let method_call = ty::MethodCall::expr(e.id);
tcx.tables.borrow().method_map[&method_call].def_id
tcx.tables().method_map[&method_call].def_id
}
hir::ExprField(ref base_e, ref field) => {
span = field.span;
match tcx.expr_ty_adjusted(base_e).sty {
match tcx.tables().expr_ty_adjusted(base_e).sty {
ty::TyAdt(def, _) => {
def.struct_variant().field_named(field.node).did
}
@ -569,7 +569,7 @@ pub fn check_expr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, e: &hir::Expr,
}
hir::ExprTupField(ref base_e, ref field) => {
span = field.span;
match tcx.expr_ty_adjusted(base_e).sty {
match tcx.tables().expr_ty_adjusted(base_e).sty {
ty::TyAdt(def, _) => {
def.struct_variant().fields[field.node].did
}
@ -580,7 +580,7 @@ pub fn check_expr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, e: &hir::Expr,
}
}
hir::ExprStruct(_, ref expr_fields, _) => {
match tcx.expr_ty(e).sty {
match tcx.tables().expr_ty(e).sty {
ty::TyAdt(adt, ..) => match adt.adt_kind() {
AdtKind::Struct | AdtKind::Union => {
// check the stability of each field that appears
@ -637,7 +637,7 @@ pub fn check_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pat: &hir::Pat,
debug!("check_pat(pat = {:?})", pat);
if is_internal(tcx, pat.span) { return; }
let v = match tcx.pat_ty_opt(pat).map(|ty| &ty.sty) {
let v = match tcx.tables().pat_ty_opt(pat).map(|ty| &ty.sty) {
Some(&ty::TyAdt(adt, _)) if !adt.is_enum() => adt.struct_variant(),
_ => return,
};

View File

@ -8,10 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
pub use self::AutoAdjustment::*;
pub use self::AutoRef::*;
use ty::{self, Ty, TyCtxt, TypeAndMut, TypeFoldable};
use ty::{self, Ty, TyCtxt, TypeAndMut};
use ty::LvaluePreference::{NoPreference};
use syntax::ast;
@ -20,116 +17,122 @@ use syntax_pos::Span;
use hir;
#[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
pub enum AutoAdjustment<'tcx> {
AdjustNeverToAny(Ty<'tcx>), // go from ! to any type
AdjustReifyFnPointer, // go from a fn-item type to a fn-pointer type
AdjustUnsafeFnPointer, // go from a safe fn pointer to an unsafe fn pointer
AdjustMutToConstPointer, // go from a mut raw pointer to a const raw pointer
AdjustDerefRef(AutoDerefRef<'tcx>),
pub struct Adjustment<'tcx> {
pub kind: Adjust<'tcx>,
pub target: Ty<'tcx>
}
/// Represents coercing a pointer to a different kind of pointer - where 'kind'
/// here means either or both of raw vs borrowed vs unique and fat vs thin.
///
/// We transform pointers by following the following steps in order:
/// 1. Deref the pointer `self.autoderefs` times (may be 0).
/// 2. If `autoref` is `Some(_)`, then take the address and produce either a
/// `&` or `*` pointer.
/// 3. If `unsize` is `Some(_)`, then apply the unsize transformation,
/// which will do things like convert thin pointers to fat
/// pointers, or convert structs containing thin pointers to
/// structs containing fat pointers, or convert between fat
/// pointers. We don't store the details of how the transform is
/// done (in fact, we don't know that, because it might depend on
/// the precise type parameters). We just store the target
/// type. Trans figures out what has to be done at monomorphization
/// time based on the precise source/target type at hand.
///
/// To make that more concrete, here are some common scenarios:
///
/// 1. The simplest cases are where the pointer is not adjusted fat vs thin.
/// Here the pointer will be dereferenced N times (where a dereference can
/// happen to raw or borrowed pointers or any smart pointer which implements
/// Deref, including Box<_>). The number of dereferences is given by
/// `autoderefs`. It can then be auto-referenced zero or one times, indicated
/// by `autoref`, to either a raw or borrowed pointer. In these cases unsize is
/// None.
///
/// 2. A thin-to-fat coercon involves unsizing the underlying data. We start
/// with a thin pointer, deref a number of times, unsize the underlying data,
/// then autoref. The 'unsize' phase may change a fixed length array to a
/// dynamically sized one, a concrete object to a trait object, or statically
/// sized struct to a dyncamically sized one. E.g., &[i32; 4] -> &[i32] is
/// represented by:
///
/// ```
/// AutoDerefRef {
/// autoderefs: 1, // &[i32; 4] -> [i32; 4]
/// autoref: Some(AutoPtr), // [i32] -> &[i32]
/// unsize: Some([i32]), // [i32; 4] -> [i32]
/// }
/// ```
///
/// Note that for a struct, the 'deep' unsizing of the struct is not recorded.
/// E.g., `struct Foo<T> { x: T }` we can coerce &Foo<[i32; 4]> to &Foo<[i32]>
/// The autoderef and -ref are the same as in the above example, but the type
/// stored in `unsize` is `Foo<[i32]>`, we don't store any further detail about
/// the underlying conversions from `[i32; 4]` to `[i32]`.
///
/// 3. Coercing a `Box<T>` to `Box<Trait>` is an interesting special case. In
/// that case, we have the pointer we need coming in, so there are no
/// autoderefs, and no autoref. Instead we just do the `Unsize` transformation.
/// At some point, of course, `Box` should move out of the compiler, in which
/// case this is analogous to transformating a struct. E.g., Box<[i32; 4]> ->
/// Box<[i32]> is represented by:
///
/// ```
/// AutoDerefRef {
/// autoderefs: 0,
/// autoref: None,
/// unsize: Some(Box<[i32]>),
/// }
/// ```
#[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
pub struct AutoDerefRef<'tcx> {
/// Step 1. Apply a number of dereferences, producing an lvalue.
pub autoderefs: usize,
#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
pub enum Adjust<'tcx> {
/// Go from ! to any type.
NeverToAny,
/// Step 2. Optionally produce a pointer/reference from the value.
pub autoref: Option<AutoRef<'tcx>>,
/// Go from a fn-item type to a fn-pointer type.
ReifyFnPointer,
/// Step 3. Unsize a pointer/reference value, e.g. `&[T; n]` to
/// `&[T]`. The stored type is the target pointer type. Note that
/// the source could be a thin or fat pointer.
pub unsize: Option<Ty<'tcx>>,
/// Go from a safe fn pointer to an unsafe fn pointer.
UnsafeFnPointer,
/// Go from a mut raw pointer to a const raw pointer.
MutToConstPointer,
/// Represents coercing a pointer to a different kind of pointer - where 'kind'
/// here means either or both of raw vs borrowed vs unique and fat vs thin.
///
/// We transform pointers by following the following steps in order:
/// 1. Deref the pointer `self.autoderefs` times (may be 0).
/// 2. If `autoref` is `Some(_)`, then take the address and produce either a
/// `&` or `*` pointer.
/// 3. If `unsize` is `Some(_)`, then apply the unsize transformation,
/// which will do things like convert thin pointers to fat
/// pointers, or convert structs containing thin pointers to
/// structs containing fat pointers, or convert between fat
/// pointers. We don't store the details of how the transform is
/// done (in fact, we don't know that, because it might depend on
/// the precise type parameters). We just store the target
/// type. Trans figures out what has to be done at monomorphization
/// time based on the precise source/target type at hand.
///
/// To make that more concrete, here are some common scenarios:
///
/// 1. The simplest cases are where the pointer is not adjusted fat vs thin.
/// Here the pointer will be dereferenced N times (where a dereference can
/// happen to raw or borrowed pointers or any smart pointer which implements
/// Deref, including Box<_>). The number of dereferences is given by
/// `autoderefs`. It can then be auto-referenced zero or one times, indicated
/// by `autoref`, to either a raw or borrowed pointer. In these cases unsize is
/// None.
///
/// 2. A thin-to-fat coercon involves unsizing the underlying data. We start
/// with a thin pointer, deref a number of times, unsize the underlying data,
/// then autoref. The 'unsize' phase may change a fixed length array to a
/// dynamically sized one, a concrete object to a trait object, or statically
/// sized struct to a dyncamically sized one. E.g., &[i32; 4] -> &[i32] is
/// represented by:
///
/// ```
/// Adjust::DerefRef {
/// autoderefs: 1, // &[i32; 4] -> [i32; 4]
/// autoref: Some(AutoBorrow::Ref), // [i32] -> &[i32]
/// unsize: Some([i32]), // [i32; 4] -> [i32]
/// }
/// ```
///
/// Note that for a struct, the 'deep' unsizing of the struct is not recorded.
/// E.g., `struct Foo<T> { x: T }` we can coerce &Foo<[i32; 4]> to &Foo<[i32]>
/// The autoderef and -ref are the same as in the above example, but the type
/// stored in `unsize` is `Foo<[i32]>`, we don't store any further detail about
/// the underlying conversions from `[i32; 4]` to `[i32]`.
///
/// 3. Coercing a `Box<T>` to `Box<Trait>` is an interesting special case. In
/// that case, we have the pointer we need coming in, so there are no
/// autoderefs, and no autoref. Instead we just do the `Unsize` transformation.
/// At some point, of course, `Box` should move out of the compiler, in which
/// case this is analogous to transformating a struct. E.g., Box<[i32; 4]> ->
/// Box<[i32]> is represented by:
///
/// ```
/// Adjust::DerefRef {
/// autoderefs: 0,
/// autoref: None,
/// unsize: Some(Box<[i32]>),
/// }
/// ```
DerefRef {
/// Step 1. Apply a number of dereferences, producing an lvalue.
autoderefs: usize,
/// Step 2. Optionally produce a pointer/reference from the value.
autoref: Option<AutoBorrow<'tcx>>,
/// Step 3. Unsize a pointer/reference value, e.g. `&[T; n]` to
/// `&[T]`. Note that the source could be a thin or fat pointer.
unsize: bool,
}
}
impl<'tcx> AutoAdjustment<'tcx> {
impl<'tcx> Adjustment<'tcx> {
pub fn is_identity(&self) -> bool {
match *self {
AdjustNeverToAny(ty) => ty.is_never(),
AdjustReifyFnPointer |
AdjustUnsafeFnPointer |
AdjustMutToConstPointer => false,
AdjustDerefRef(ref r) => r.is_identity(),
match self.kind {
Adjust::NeverToAny => self.target.is_never(),
Adjust::DerefRef { autoderefs: 0, autoref: None, unsize: false } => true,
Adjust::ReifyFnPointer |
Adjust::UnsafeFnPointer |
Adjust::MutToConstPointer |
Adjust::DerefRef {..} => false,
}
}
}
impl<'tcx> AutoDerefRef<'tcx> {
pub fn is_identity(&self) -> bool {
self.autoderefs == 0 && self.unsize.is_none() && self.autoref.is_none()
}
}
#[derive(Copy, Clone, PartialEq, Debug, RustcEncodable, RustcDecodable)]
pub enum AutoRef<'tcx> {
pub enum AutoBorrow<'tcx> {
/// Convert from T to &T.
AutoPtr(&'tcx ty::Region, hir::Mutability),
Ref(&'tcx ty::Region, hir::Mutability),
/// Convert from T to *T.
/// Value to thin pointer.
AutoUnsafe(hir::Mutability),
RawPtr(hir::Mutability),
}
#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
@ -139,84 +142,6 @@ pub enum CustomCoerceUnsized {
}
impl<'a, 'gcx, 'tcx> ty::TyS<'tcx> {
/// See `expr_ty_adjusted`
pub fn adjust<F>(&'tcx self,
tcx: TyCtxt<'a, 'gcx, 'tcx>,
span: Span,
expr_id: ast::NodeId,
adjustment: Option<&AutoAdjustment<'tcx>>,
mut method_type: F)
-> Ty<'tcx> where
F: FnMut(ty::MethodCall) -> Option<Ty<'tcx>>,
{
if let ty::TyError = self.sty {
return self;
}
return match adjustment {
Some(adjustment) => {
match *adjustment {
AdjustNeverToAny(ref ty) => ty,
AdjustReifyFnPointer => {
match self.sty {
ty::TyFnDef(.., f) => tcx.mk_fn_ptr(f),
_ => {
bug!("AdjustReifyFnPointer adjustment on non-fn-item: {:?}",
self);
}
}
}
AdjustUnsafeFnPointer => {
match self.sty {
ty::TyFnPtr(b) => tcx.safe_to_unsafe_fn_ty(b),
ref b => {
bug!("AdjustUnsafeFnPointer adjustment on non-fn-ptr: {:?}",
b);
}
}
}
AdjustMutToConstPointer => {
match self.sty {
ty::TyRawPtr(mt) => tcx.mk_ptr(ty::TypeAndMut {
ty: mt.ty,
mutbl: hir::MutImmutable
}),
ref b => {
bug!("AdjustMutToConstPointer on non-raw-ptr: {:?}",
b);
}
}
}
AdjustDerefRef(ref adj) => {
let mut adjusted_ty = self;
if !adjusted_ty.references_error() {
for i in 0..adj.autoderefs {
adjusted_ty =
adjusted_ty.adjust_for_autoderef(tcx,
expr_id,
span,
i as u32,
&mut method_type);
}
}
if let Some(target) = adj.unsize {
target
} else {
adjusted_ty.adjust_for_autoref(tcx, adj.autoref)
}
}
}
}
None => self
};
}
pub fn adjust_for_autoderef<F>(&'tcx self,
tcx: TyCtxt<'a, 'gcx, 'tcx>,
expr_id: ast::NodeId,
@ -247,14 +172,14 @@ impl<'a, 'gcx, 'tcx> ty::TyS<'tcx> {
}
pub fn adjust_for_autoref(&'tcx self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
autoref: Option<AutoRef<'tcx>>)
autoref: Option<AutoBorrow<'tcx>>)
-> Ty<'tcx> {
match autoref {
None => self,
Some(AutoPtr(r, m)) => {
Some(AutoBorrow::Ref(r, m)) => {
tcx.mk_ref(r, TypeAndMut { ty: self, mutbl: m })
}
Some(AutoUnsafe(m)) => {
Some(AutoBorrow::RawPtr(m)) => {
tcx.mk_ptr(TypeAndMut { ty: self, mutbl: m })
}
}

View File

@ -41,7 +41,7 @@ use rustc_data_structures::accumulate_vec::AccumulateVec;
use arena::TypedArena;
use std::borrow::Borrow;
use std::cell::{Cell, RefCell, Ref};
use std::cell::{Cell, RefCell};
use std::hash::{Hash, Hasher};
use std::mem;
use std::ops::Deref;
@ -212,7 +212,7 @@ pub struct Tables<'tcx> {
/// other items.
pub item_substs: NodeMap<ty::ItemSubsts<'tcx>>,
pub adjustments: NodeMap<ty::adjustment::AutoAdjustment<'tcx>>,
pub adjustments: NodeMap<ty::adjustment::Adjustment<'tcx>>,
pub method_map: ty::MethodMap<'tcx>,
@ -255,6 +255,76 @@ impl<'a, 'gcx, 'tcx> Tables<'tcx> {
fru_field_types: NodeMap()
}
}
pub fn node_id_to_type(&self, id: NodeId) -> Ty<'tcx> {
match self.node_id_to_type_opt(id) {
Some(ty) => ty,
None => {
bug!("node_id_to_type: no type for node `{}`",
tls::with(|tcx| tcx.map.node_to_string(id)))
}
}
}
pub fn node_id_to_type_opt(&self, id: NodeId) -> Option<Ty<'tcx>> {
self.node_types.get(&id).cloned()
}
pub fn node_id_item_substs(&self, id: NodeId) -> Option<&'tcx Substs<'tcx>> {
self.item_substs.get(&id).map(|ts| ts.substs)
}
// Returns the type of a pattern as a monotype. Like @expr_ty, this function
// doesn't provide type parameter substitutions.
pub fn pat_ty(&self, pat: &hir::Pat) -> Ty<'tcx> {
self.node_id_to_type(pat.id)
}
pub fn pat_ty_opt(&self, pat: &hir::Pat) -> Option<Ty<'tcx>> {
self.node_id_to_type_opt(pat.id)
}
// Returns the type of an expression as a monotype.
//
// NB (1): This is the PRE-ADJUSTMENT TYPE for the expression. That is, in
// some cases, we insert `Adjustment` annotations such as auto-deref or
// auto-ref. The type returned by this function does not consider such
// adjustments. See `expr_ty_adjusted()` instead.
//
// NB (2): This type doesn't provide type parameter substitutions; e.g. if you
// ask for the type of "id" in "id(3)", it will return "fn(&isize) -> isize"
// instead of "fn(ty) -> T with T = isize".
pub fn expr_ty(&self, expr: &hir::Expr) -> Ty<'tcx> {
self.node_id_to_type(expr.id)
}
pub fn expr_ty_opt(&self, expr: &hir::Expr) -> Option<Ty<'tcx>> {
self.node_id_to_type_opt(expr.id)
}
/// Returns the type of `expr`, considering any `Adjustment`
/// entry recorded for that expression.
pub fn expr_ty_adjusted(&self, expr: &hir::Expr) -> Ty<'tcx> {
self.adjustments.get(&expr.id)
.map_or_else(|| self.expr_ty(expr), |adj| adj.target)
}
pub fn expr_ty_adjusted_opt(&self, expr: &hir::Expr) -> Option<Ty<'tcx>> {
self.adjustments.get(&expr.id)
.map(|adj| adj.target).or_else(|| self.expr_ty_opt(expr))
}
pub fn is_method_call(&self, expr_id: NodeId) -> bool {
self.method_map.contains_key(&ty::MethodCall::expr(expr_id))
}
pub fn is_overloaded_autoderef(&self, expr_id: NodeId, autoderefs: u32) -> bool {
self.method_map.contains_key(&ty::MethodCall::autoderef(expr_id, autoderefs))
}
pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture<'tcx>> {
Some(self.upvar_capture_map.get(&upvar_id).unwrap().clone())
}
}
impl<'tcx> CommonTypes<'tcx> {
@ -599,14 +669,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
self.ty_param_defs.borrow().get(&node_id).unwrap().clone()
}
pub fn node_types(self) -> Ref<'a, NodeMap<Ty<'tcx>>> {
fn projection<'a, 'tcx>(tables: &'a Tables<'tcx>) -> &'a NodeMap<Ty<'tcx>> {
&tables.node_types
}
Ref::map(self.tables.borrow(), projection)
}
pub fn node_type_insert(self, id: NodeId, ty: Ty<'gcx>) {
self.tables.borrow_mut().node_types.insert(id, ty);
}

View File

@ -176,8 +176,8 @@ pub trait TypeFolder<'gcx: 'tcx, 'tcx> : Sized {
r.super_fold_with(self)
}
fn fold_autoref(&mut self, ar: &adjustment::AutoRef<'tcx>)
-> adjustment::AutoRef<'tcx> {
fn fold_autoref(&mut self, ar: &adjustment::AutoBorrow<'tcx>)
-> adjustment::AutoBorrow<'tcx> {
ar.super_fold_with(self)
}
}

View File

@ -2120,80 +2120,8 @@ impl BorrowKind {
}
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
pub fn node_id_to_type(self, id: NodeId) -> Ty<'gcx> {
match self.node_id_to_type_opt(id) {
Some(ty) => ty,
None => bug!("node_id_to_type: no type for node `{}`",
self.map.node_to_string(id))
}
}
pub fn node_id_to_type_opt(self, id: NodeId) -> Option<Ty<'gcx>> {
self.tables.borrow().node_types.get(&id).cloned()
}
pub fn node_id_item_substs(self, id: NodeId) -> ItemSubsts<'gcx> {
match self.tables.borrow().item_substs.get(&id) {
None => ItemSubsts {
substs: self.global_tcx().intern_substs(&[])
},
Some(ts) => ts.clone(),
}
}
// Returns the type of a pattern as a monotype. Like @expr_ty, this function
// doesn't provide type parameter substitutions.
pub fn pat_ty(self, pat: &hir::Pat) -> Ty<'gcx> {
self.node_id_to_type(pat.id)
}
pub fn pat_ty_opt(self, pat: &hir::Pat) -> Option<Ty<'gcx>> {
self.node_id_to_type_opt(pat.id)
}
// Returns the type of an expression as a monotype.
//
// NB (1): This is the PRE-ADJUSTMENT TYPE for the expression. That is, in
// some cases, we insert `AutoAdjustment` annotations such as auto-deref or
// auto-ref. The type returned by this function does not consider such
// adjustments. See `expr_ty_adjusted()` instead.
//
// NB (2): This type doesn't provide type parameter substitutions; e.g. if you
// ask for the type of "id" in "id(3)", it will return "fn(&isize) -> isize"
// instead of "fn(ty) -> T with T = isize".
pub fn expr_ty(self, expr: &hir::Expr) -> Ty<'gcx> {
self.node_id_to_type(expr.id)
}
pub fn expr_ty_opt(self, expr: &hir::Expr) -> Option<Ty<'gcx>> {
self.node_id_to_type_opt(expr.id)
}
/// Returns the type of `expr`, considering any `AutoAdjustment`
/// entry recorded for that expression.
///
/// It would almost certainly be better to store the adjusted ty in with
/// the `AutoAdjustment`, but I opted not to do this because it would
/// require serializing and deserializing the type and, although that's not
/// hard to do, I just hate that code so much I didn't want to touch it
/// unless it was to fix it properly, which seemed a distraction from the
/// thread at hand! -nmatsakis
pub fn expr_ty_adjusted(self, expr: &hir::Expr) -> Ty<'gcx> {
self.expr_ty(expr)
.adjust(self.global_tcx(), expr.span, expr.id,
self.tables.borrow().adjustments.get(&expr.id),
|method_call| {
self.tables.borrow().method_map.get(&method_call).map(|method| method.ty)
})
}
pub fn expr_ty_adjusted_opt(self, expr: &hir::Expr) -> Option<Ty<'gcx>> {
self.expr_ty_opt(expr).map(|t| t.adjust(self.global_tcx(),
expr.span,
expr.id,
self.tables.borrow().adjustments.get(&expr.id),
|method_call| {
self.tables.borrow().method_map.get(&method_call).map(|method| method.ty)
}))
pub fn tables(self) -> Ref<'a, Tables<'gcx>> {
self.tables.borrow()
}
pub fn expr_span(self, id: NodeId) -> Span {
@ -2908,19 +2836,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
self.mk_region(ty::ReScope(self.region_maps.node_extent(id)))
}
pub fn is_method_call(self, expr_id: NodeId) -> bool {
self.tables.borrow().method_map.contains_key(&MethodCall::expr(expr_id))
}
pub fn is_overloaded_autoderef(self, expr_id: NodeId, autoderefs: u32) -> bool {
self.tables.borrow().method_map.contains_key(&MethodCall::autoderef(expr_id,
autoderefs))
}
pub fn upvar_capture(self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture<'tcx>> {
Some(self.tables.borrow().upvar_capture_map.get(&upvar_id).unwrap().clone())
}
pub fn visit_all_items_in_krate<V,F>(self,
dep_node_fn: F,
visitor: &mut V)

View File

@ -218,15 +218,15 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ItemSubsts<'a> {
}
}
impl<'a, 'tcx> Lift<'tcx> for ty::adjustment::AutoRef<'a> {
type Lifted = ty::adjustment::AutoRef<'tcx>;
impl<'a, 'tcx> Lift<'tcx> for ty::adjustment::AutoBorrow<'a> {
type Lifted = ty::adjustment::AutoBorrow<'tcx>;
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
match *self {
ty::adjustment::AutoPtr(r, m) => {
tcx.lift(&r).map(|r| ty::adjustment::AutoPtr(r, m))
ty::adjustment::AutoBorrow::Ref(r, m) => {
tcx.lift(&r).map(|r| ty::adjustment::AutoBorrow::Ref(r, m))
}
ty::adjustment::AutoUnsafe(m) => {
Some(ty::adjustment::AutoUnsafe(m))
ty::adjustment::AutoBorrow::RawPtr(m) => {
Some(ty::adjustment::AutoBorrow::RawPtr(m))
}
}
}
@ -676,13 +676,13 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ItemSubsts<'tcx> {
}
}
impl<'tcx> TypeFoldable<'tcx> for ty::adjustment::AutoRef<'tcx> {
impl<'tcx> TypeFoldable<'tcx> for ty::adjustment::AutoBorrow<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
match *self {
ty::adjustment::AutoPtr(ref r, m) => {
ty::adjustment::AutoPtr(r.fold_with(folder), m)
ty::adjustment::AutoBorrow::Ref(ref r, m) => {
ty::adjustment::AutoBorrow::Ref(r.fold_with(folder), m)
}
ty::adjustment::AutoUnsafe(m) => ty::adjustment::AutoUnsafe(m)
ty::adjustment::AutoBorrow::RawPtr(m) => ty::adjustment::AutoBorrow::RawPtr(m)
}
}
@ -692,8 +692,8 @@ impl<'tcx> TypeFoldable<'tcx> for ty::adjustment::AutoRef<'tcx> {
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
match *self {
ty::adjustment::AutoPtr(r, _m) => r.visit_with(visitor),
ty::adjustment::AutoUnsafe(_m) => false,
ty::adjustment::AutoBorrow::Ref(r, _m) => r.visit_with(visitor),
ty::adjustment::AutoBorrow::RawPtr(_m) => false,
}
}
}

View File

@ -447,32 +447,9 @@ impl<'tcx, 'container> fmt::Debug for ty::AdtDefData<'tcx, 'container> {
}
}
impl<'tcx> fmt::Debug for ty::adjustment::AutoAdjustment<'tcx> {
impl<'tcx> fmt::Debug for ty::adjustment::Adjustment<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
ty::adjustment::AdjustNeverToAny(ref target) => {
write!(f, "AdjustNeverToAny({:?})", target)
}
ty::adjustment::AdjustReifyFnPointer => {
write!(f, "AdjustReifyFnPointer")
}
ty::adjustment::AdjustUnsafeFnPointer => {
write!(f, "AdjustUnsafeFnPointer")
}
ty::adjustment::AdjustMutToConstPointer => {
write!(f, "AdjustMutToConstPointer")
}
ty::adjustment::AdjustDerefRef(ref data) => {
write!(f, "{:?}", data)
}
}
}
}
impl<'tcx> fmt::Debug for ty::adjustment::AutoDerefRef<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "AutoDerefRef({}, unsize={:?}, {:?})",
self.autoderefs, self.unsize, self.autoref)
write!(f, "{:?} -> {}", self.kind, self.target)
}
}

View File

@ -37,7 +37,7 @@ pub fn gather_decl<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
decl_id: ast::NodeId,
_decl_span: Span,
var_id: ast::NodeId) {
let ty = bccx.tcx.node_id_to_type(var_id);
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);
}

View File

@ -201,7 +201,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
// Finally, check if the whole match expression is exhaustive.
// Check for empty enum, because is_useful only works on inhabited types.
let pat_ty = self.tcx.node_id_to_type(scrut.id);
let pat_ty = self.tcx.tables().node_id_to_type(scrut.id);
if inlined_arms.is_empty() {
if !pat_ty.is_uninhabited(self.tcx) {
// We know the type is inhabited, so this must be wrong
@ -262,7 +262,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.pat_ty(p);
let pat_ty = cx.tcx.tables().pat_ty(p);
if let ty::TyAdt(edef, _) = pat_ty.sty {
if edef.is_enum() {
if let Def::Local(..) = cx.tcx.expect_def(p.id) {
@ -486,7 +486,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.node_id_to_type(p.id);
let pat_ty = cx.tcx.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));
}

View File

@ -246,7 +246,7 @@ pub fn const_expr_to_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
pat_id: ast::NodeId,
span: Span)
-> Result<P<hir::Pat>, DefId> {
let pat_ty = tcx.expr_ty(expr);
let pat_ty = tcx.tables().expr_ty(expr);
debug!("expr={:?} pat_ty={:?} pat_id={}", expr, pat_ty, pat_id);
match pat_ty.sty {
ty::TyFloat(_) => {
@ -329,7 +329,8 @@ pub fn const_expr_to_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
Def::StructCtor(_, CtorKind::Const) |
Def::VariantCtor(_, CtorKind::Const) => PatKind::Path(None, path.clone()),
Def::Const(def_id) | Def::AssociatedConst(def_id) => {
let substs = Some(tcx.node_id_item_substs(expr.id).substs);
let substs = Some(tcx.tables().node_id_item_substs(expr.id)
.unwrap_or_else(|| tcx.intern_substs(&[])));
let (expr, _ty) = lookup_const_by_id(tcx, def_id, substs).unwrap();
return const_expr_to_pat(tcx, expr, pat_id, span);
},
@ -606,7 +607,7 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let ety = match ty_hint {
ExprTypeChecked => {
// After type-checking, expr_ty is guaranteed to succeed.
Some(tcx.expr_ty(e))
Some(tcx.tables().expr_ty(e))
}
UncheckedExprHint(ty) => {
// Use the type hint; it's not guaranteed to be right, but it's
@ -617,7 +618,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.expr_ty_opt(e)
tcx.tables().expr_ty_opt(e)
}
};
let result = match e.node {
@ -759,7 +760,7 @@ 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.expr_ty_opt(&base) {
match tcx.tables().expr_ty_opt(&base) {
Some(t) => UncheckedExprHint(t),
None => ty_hint
}
@ -798,7 +799,8 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
Def::Const(def_id) |
Def::AssociatedConst(def_id) => {
let substs = if let ExprTypeChecked = ty_hint {
Some(tcx.node_id_item_substs(e.id).substs)
Some(tcx.tables().node_id_item_substs(e.id)
.unwrap_or_else(|| tcx.intern_substs(&[])))
} else {
None
};

View File

@ -128,7 +128,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> {
}
pub fn lower_pattern(&mut self, pat: &hir::Pat) -> Pattern<'tcx> {
let mut ty = self.tcx.node_id_to_type(pat.id);
let mut ty = self.tcx.tables().node_id_to_type(pat.id);
let kind = match pat.node {
PatKind::Wild => PatternKind::Wild,
@ -167,8 +167,9 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> {
match self.tcx.expect_def(pat.id) {
Def::Const(def_id) | Def::AssociatedConst(def_id) => {
let tcx = self.tcx.global_tcx();
let substs = Some(self.tcx.node_id_item_substs(pat.id).substs);
match eval::lookup_const_by_id(tcx, def_id, substs) {
let substs = tcx.tables().node_id_item_substs(pat.id)
.unwrap_or_else(|| tcx.intern_substs(&[]));
match eval::lookup_const_by_id(tcx, def_id, Some(substs)) {
Some((const_expr, _const_ty)) => {
match eval::const_expr_to_pat(
tcx, const_expr, pat.id, pat.span)
@ -197,7 +198,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> {
}
PatKind::Slice(ref prefix, ref slice, ref suffix) => {
let ty = self.tcx.node_id_to_type(pat.id);
let ty = self.tcx.tables().node_id_to_type(pat.id);
match ty.sty {
ty::TyRef(_, mt) =>
PatternKind::Deref {
@ -222,7 +223,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> {
}
PatKind::Tuple(ref subpatterns, ddpos) => {
match self.tcx.node_id_to_type(pat.id).sty {
match self.tcx.tables().node_id_to_type(pat.id).sty {
ty::TyTuple(ref tys) => {
let subpatterns =
subpatterns.iter()
@ -243,7 +244,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> {
PatKind::Binding(bm, ref ident, ref sub) => {
let def_id = self.tcx.expect_def(pat.id).def_id();
let id = self.tcx.map.as_local_node_id(def_id).unwrap();
let var_ty = self.tcx.node_id_to_type(pat.id);
let var_ty = self.tcx.tables().node_id_to_type(pat.id);
let region = match var_ty.sty {
ty::TyRef(r, _) => Some(r),
_ => None,
@ -280,7 +281,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> {
}
PatKind::TupleStruct(_, ref subpatterns, ddpos) => {
let pat_ty = self.tcx.node_id_to_type(pat.id);
let pat_ty = self.tcx.tables().node_id_to_type(pat.id);
let adt_def = match pat_ty.sty {
ty::TyAdt(adt_def, _) => adt_def,
_ => span_bug!(pat.span, "tuple struct pattern not applied to an ADT"),
@ -299,7 +300,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> {
}
PatKind::Struct(_, ref fields, _) => {
let pat_ty = self.tcx.node_id_to_type(pat.id);
let pat_ty = self.tcx.tables().node_id_to_type(pat.id);
let adt_def = match pat_ty.sty {
ty::TyAdt(adt_def, _) => adt_def,
_ => {

View File

@ -501,7 +501,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.expr_ty(expr).to_string())?;
pp::word(&mut s.s, &self.tcx.tables().expr_ty(expr).to_string())?;
s.pclose()
}
_ => Ok(()),

View File

@ -34,7 +34,6 @@ use middle::stability;
use rustc::cfg;
use rustc::ty::subst::Substs;
use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::adjustment;
use rustc::traits::{self, Reveal};
use rustc::hir::map as hir_map;
use util::nodemap::NodeSet;
@ -118,7 +117,9 @@ impl LateLintPass for BoxPointers {
hir::ItemTy(..) |
hir::ItemEnum(..) |
hir::ItemStruct(..) |
hir::ItemUnion(..) => self.check_heap_type(cx, it.span, cx.tcx.node_id_to_type(it.id)),
hir::ItemUnion(..) => {
self.check_heap_type(cx, it.span, cx.tcx.tables().node_id_to_type(it.id))
}
_ => (),
}
@ -129,7 +130,7 @@ impl LateLintPass for BoxPointers {
for struct_field in struct_def.fields() {
self.check_heap_type(cx,
struct_field.span,
cx.tcx.node_id_to_type(struct_field.id));
cx.tcx.tables().node_id_to_type(struct_field.id));
}
}
_ => (),
@ -137,7 +138,7 @@ impl LateLintPass for BoxPointers {
}
fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
let ty = cx.tcx.node_id_to_type(e.id);
let ty = cx.tcx.tables().node_id_to_type(e.id);
self.check_heap_type(cx, e.span, ty);
}
}
@ -585,7 +586,7 @@ impl LateLintPass for MissingDebugImplementations {
let mut impls = NodeSet();
debug_def.for_each_impl(cx.tcx, |d| {
if let Some(n) = cx.tcx.map.as_local_node_id(d) {
if let Some(ty_def) = cx.tcx.node_id_to_type(n).ty_to_def_id() {
if let Some(ty_def) = cx.tcx.tables().node_id_to_type(n).ty_to_def_id() {
if let Some(node_id) = cx.tcx.map.as_local_node_id(ty_def) {
impls.insert(node_id);
}
@ -939,8 +940,10 @@ impl LateLintPass for UnconditionalRecursion {
method: &ty::Method,
id: ast::NodeId)
-> bool {
use rustc::ty::adjustment::*;
// Check for method calls and overloaded operators.
let opt_m = tcx.tables.borrow().method_map.get(&ty::MethodCall::expr(id)).cloned();
let opt_m = tcx.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) {
return true;
@ -948,15 +951,12 @@ impl LateLintPass for UnconditionalRecursion {
}
// Check for overloaded autoderef method calls.
let opt_adj = tcx.tables.borrow().adjustments.get(&id).cloned();
if let Some(adjustment::AdjustDerefRef(adj)) = opt_adj {
for i in 0..adj.autoderefs {
let opt_adj = tcx.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
.borrow()
.method_map
.get(&method_call)
.cloned() {
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) {
return true;
}
@ -971,12 +971,10 @@ impl LateLintPass for UnconditionalRecursion {
// it doesn't necessarily have a definition.
match tcx.expect_def_or_none(callee.id) {
Some(Def::Method(def_id)) => {
let item_substs = tcx.node_id_item_substs(callee.id);
method_call_refers_to_method(tcx,
method,
def_id,
&item_substs.substs,
id)
let substs = tcx.tables().node_id_item_substs(callee.id)
.unwrap_or_else(|| tcx.intern_substs(&[]));
method_call_refers_to_method(
tcx, method, def_id, substs, id)
}
_ => false,
}
@ -1213,7 +1211,7 @@ impl LateLintPass for MutableTransmutes {
if !def_id_is_transmute(cx, did) {
return None;
}
let typ = cx.tcx.node_id_to_type(expr.id);
let typ = cx.tcx.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.0.inputs[0];
@ -1284,7 +1282,7 @@ impl LateLintPass for UnionsWithDropFields {
if let hir::ItemUnion(ref vdata, _) = item.node {
let param_env = &ty::ParameterEnvironment::for_item(ctx.tcx, item.id);
for field in vdata.fields() {
let field_ty = ctx.tcx.node_id_to_type(field.id);
let field_ty = ctx.tcx.tables().node_id_to_type(field.id);
if ctx.tcx.type_needs_drop_given_env(field_ty, param_env) {
ctx.span_lint(UNIONS_WITH_DROP_FIELDS,
field.span,

View File

@ -113,14 +113,14 @@ impl LateLintPass for TypeLimits {
forbid_unsigned_negation(cx, e.span);
}
ast::LitKind::Int(_, ast::LitIntType::Unsuffixed) => {
if let ty::TyUint(_) = cx.tcx.node_id_to_type(e.id).sty {
if let ty::TyUint(_) = cx.tcx.tables().node_id_to_type(e.id).sty {
forbid_unsigned_negation(cx, e.span);
}
}
_ => (),
}
} else {
let t = cx.tcx.node_id_to_type(expr.id);
let t = cx.tcx.tables().node_id_to_type(expr.id);
if let ty::TyUint(_) = t.sty {
forbid_unsigned_negation(cx, e.span);
}
@ -138,7 +138,7 @@ impl LateLintPass for TypeLimits {
}
if binop.node.is_shift() {
let opt_ty_bits = match cx.tcx.node_id_to_type(l.id).sty {
let opt_ty_bits = match cx.tcx.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,
@ -171,7 +171,7 @@ impl LateLintPass for TypeLimits {
}
}
hir::ExprLit(ref lit) => {
match cx.tcx.node_id_to_type(e.id).sty {
match cx.tcx.tables().node_id_to_type(e.id).sty {
ty::TyInt(t) => {
match lit.node {
ast::LitKind::Int(v, ast::LitIntType::Signed(_)) |
@ -324,7 +324,7 @@ impl LateLintPass 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.node_id_to_type(expr.id).sty {
match tcx.tables().node_id_to_type(expr.id).sty {
ty::TyInt(int_ty) => {
let (min, max) = int_ty_range(int_ty);
let lit_val: i64 = match lit.node {
@ -740,7 +740,7 @@ impl LateLintPass for VariantSizeDifferences {
if let hir::ItemEnum(ref enum_definition, ref gens) = it.node {
if gens.ty_params.is_empty() {
// sizes only make sense for non-generic types
let t = cx.tcx.node_id_to_type(it.id);
let t = cx.tcx.tables().node_id_to_type(it.id);
let layout = cx.tcx.infer_ctxt(None, None, Reveal::All).enter(|infcx| {
let ty = cx.tcx.erase_regions(&t);
ty.layout(&infcx)

View File

@ -140,7 +140,7 @@ impl LateLintPass for UnusedResults {
return;
}
let t = cx.tcx.expr_ty(&expr);
let t = cx.tcx.tables().expr_ty(&expr);
let warned = match t.sty {
ty::TyTuple(ref tys) if tys.is_empty() => return,
ty::TyNever => return,
@ -441,16 +441,15 @@ impl LateLintPass for UnusedAllocation {
_ => return,
}
if let Some(adjustment) = cx.tcx.tables.borrow().adjustments.get(&e.id) {
if let adjustment::AdjustDerefRef(adjustment::AutoDerefRef { ref autoref, .. }) =
*adjustment {
if let Some(adjustment) = cx.tcx.tables().adjustments.get(&e.id) {
if let adjustment::Adjust::DerefRef { autoref, .. } = adjustment.kind {
match autoref {
&Some(adjustment::AutoPtr(_, hir::MutImmutable)) => {
Some(adjustment::AutoBorrow::Ref(_, hir::MutImmutable)) => {
cx.span_lint(UNUSED_ALLOCATION,
e.span,
"unnecessary allocation, use & instead");
}
&Some(adjustment::AutoPtr(_, hir::MutMutable)) => {
Some(adjustment::AutoBorrow::Ref(_, hir::MutMutable)) => {
cx.span_lint(UNUSED_ALLOCATION,
e.span,
"unnecessary allocation, use &mut instead");

View File

@ -38,7 +38,7 @@ enum TableEntry<'tcx> {
Def(Def),
NodeType(Ty<'tcx>),
ItemSubsts(ty::ItemSubsts<'tcx>),
Adjustment(ty::adjustment::AutoAdjustment<'tcx>),
Adjustment(ty::adjustment::Adjustment<'tcx>),
ConstQualif(ConstQualif),
}
@ -94,9 +94,9 @@ impl<'a, 'b, 'tcx, 'v> Visitor<'v> for SideTableEncodingIdVisitor<'a, 'b, 'tcx>
};
encode(tcx.expect_def_or_none(id).map(TableEntry::Def));
encode(tcx.node_types().get(&id).cloned().map(TableEntry::NodeType));
encode(tcx.tables.borrow().item_substs.get(&id).cloned().map(TableEntry::ItemSubsts));
encode(tcx.tables.borrow().adjustments.get(&id).cloned().map(TableEntry::Adjustment));
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(tcx.const_qualif_map.borrow().get(&id).cloned().map(TableEntry::ConstQualif));
}
}

View File

@ -1016,7 +1016,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
let data = ClosureData {
kind: tcx.closure_kind(def_id),
ty: self.lazy(&tcx.tables.borrow().closure_tys[&def_id]),
ty: self.lazy(&tcx.tables().closure_tys[&def_id]),
};
Entry {

View File

@ -191,7 +191,7 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
assert_eq!(block, builder.return_block());
let mut spread_arg = None;
match tcx.node_id_to_type(fn_id).sty {
match tcx.tables().node_id_to_type(fn_id).sty {
ty::TyFnDef(_, _, f) if f.abi == Abi::RustCall => {
// RustCall pseudo-ABI untuples the last argument.
spread_arg = Some(Local::new(arguments.len()));
@ -203,7 +203,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.upvar_capture(ty::UpvarId {
let by_ref = tcx.tables().upvar_capture(ty::UpvarId {
var_id: var_id,
closure_expr_id: fn_id
}).map_or(false, |capture| match capture {
@ -233,7 +233,7 @@ pub fn construct_const<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
ast_expr: &'tcx hir::Expr)
-> (Mir<'tcx>, ScopeAuxiliaryVec) {
let tcx = hir.tcx();
let ty = tcx.expr_ty_adjusted(ast_expr);
let ty = tcx.tables().expr_ty_adjusted(ast_expr);
let span = tcx.map.span(item_id);
let mut builder = Builder::new(hir, span, 0, ty);

View File

@ -77,7 +77,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.node_id_to_type(block.id);
let block_ty = cx.tcx.tables().node_id_to_type(block.id);
let temp_lifetime = cx.tcx.region_maps.temporary_scope(block.id);
let expr = Expr {
ty: block_ty,

View File

@ -35,15 +35,15 @@ 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();
debug!("make_mirror: unadjusted-expr={:?} applying adjustments={:?}",
expr, cx.tcx.tables.borrow().adjustments.get(&self.id));
expr, adj);
// Now apply adjustments, if any.
match cx.tcx.tables.borrow().adjustments.get(&self.id) {
match adj.map(|adj| (adj.kind, adj.target)) {
None => {}
Some(&ty::adjustment::AdjustReifyFnPointer) => {
let adjusted_ty = cx.tcx.expr_ty_adjusted(self);
Some((ty::adjustment::Adjust::ReifyFnPointer, adjusted_ty)) => {
expr = Expr {
temp_lifetime: temp_lifetime,
ty: adjusted_ty,
@ -51,8 +51,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
kind: ExprKind::ReifyFnPointer { source: expr.to_ref() },
};
}
Some(&ty::adjustment::AdjustUnsafeFnPointer) => {
let adjusted_ty = cx.tcx.expr_ty_adjusted(self);
Some((ty::adjustment::Adjust::UnsafeFnPointer, adjusted_ty)) => {
expr = Expr {
temp_lifetime: temp_lifetime,
ty: adjusted_ty,
@ -60,7 +59,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
kind: ExprKind::UnsafeFnPointer { source: expr.to_ref() },
};
}
Some(&ty::adjustment::AdjustNeverToAny(adjusted_ty)) => {
Some((ty::adjustment::Adjust::NeverToAny, adjusted_ty)) => {
expr = Expr {
temp_lifetime: temp_lifetime,
ty: adjusted_ty,
@ -68,8 +67,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
kind: ExprKind::NeverToAny { source: expr.to_ref() },
};
}
Some(&ty::adjustment::AdjustMutToConstPointer) => {
let adjusted_ty = cx.tcx.expr_ty_adjusted(self);
Some((ty::adjustment::Adjust::MutToConstPointer, adjusted_ty)) => {
expr = Expr {
temp_lifetime: temp_lifetime,
ty: adjusted_ty,
@ -77,8 +75,9 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
kind: ExprKind::Cast { source: expr.to_ref() },
};
}
Some(&ty::adjustment::AdjustDerefRef(ref adj)) => {
for i in 0..adj.autoderefs {
Some((ty::adjustment::Adjust::DerefRef { autoderefs, autoref, unsize },
adjusted_ty)) => {
for i in 0..autoderefs {
let i = i as u32;
let adjusted_ty =
expr.ty.adjust_for_autoderef(
@ -86,11 +85,11 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
self.id,
self.span,
i,
|mc| cx.tcx.tables.borrow().method_map.get(&mc).map(|m| m.ty));
|mc| cx.tcx.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.borrow().method_map.get(&method_key).map(|m| m.ty);
cx.tcx.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);
@ -128,10 +127,10 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
};
}
if let Some(autoref) = adj.autoref {
if let Some(autoref) = autoref {
let adjusted_ty = expr.ty.adjust_for_autoref(cx.tcx, Some(autoref));
match autoref {
ty::adjustment::AutoPtr(r, m) => {
ty::adjustment::AutoBorrow::Ref(r, m) => {
expr = Expr {
temp_lifetime: temp_lifetime,
ty: adjusted_ty,
@ -143,7 +142,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
},
};
}
ty::adjustment::AutoUnsafe(m) => {
ty::adjustment::AutoBorrow::RawPtr(m) => {
// Convert this to a suitable `&foo` and
// then an unsafe coercion. Limit the region to be just this
// expression.
@ -169,10 +168,10 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
}
}
if let Some(target) = adj.unsize {
if unsize {
expr = Expr {
temp_lifetime: temp_lifetime,
ty: target,
ty: adjusted_ty,
span: self.span,
kind: ExprKind::Unsize { source: expr.to_ref() },
};
@ -212,7 +211,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.expr_ty(expr);
let expr_ty = cx.tcx.tables().expr_ty(expr);
let temp_lifetime = cx.tcx.region_maps.temporary_scope(expr.id);
let kind = match expr.node {
@ -231,7 +230,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
}
hir::ExprCall(ref fun, ref args) => {
if cx.tcx.is_method_call(expr.id) {
if cx.tcx.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
@ -282,7 +281,8 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
})
} else { None };
if let Some((adt_def, index)) = adt_data {
let substs = cx.tcx.node_id_item_substs(fun.id).substs;
let substs = cx.tcx.tables().node_id_item_substs(fun.id)
.unwrap_or_else(|| cx.tcx.intern_substs(&[]));
let field_refs = args.iter().enumerate().map(|(idx, e)| FieldExprRef {
name: Field::new(idx),
expr: e.to_ref()
@ -296,7 +296,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
}
} else {
ExprKind::Call {
ty: cx.tcx.node_id_to_type(fun.id),
ty: cx.tcx.tables().node_id_to_type(fun.id),
fun: fun.to_ref(),
args: args.to_ref(),
}
@ -328,7 +328,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
}
hir::ExprAssignOp(op, ref lhs, ref rhs) => {
if cx.tcx.is_method_call(expr.id) {
if cx.tcx.tables().is_method_call(expr.id) {
let pass_args = if op.node.is_by_value() {
PassArgs::ByValue
} else {
@ -350,7 +350,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
},
hir::ExprBinary(op, ref lhs, ref rhs) => {
if cx.tcx.is_method_call(expr.id) {
if cx.tcx.tables().is_method_call(expr.id) {
let pass_args = if op.node.is_by_value() {
PassArgs::ByValue
} else {
@ -406,7 +406,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
}
hir::ExprIndex(ref lhs, ref index) => {
if cx.tcx.is_method_call(expr.id) {
if cx.tcx.tables().is_method_call(expr.id) {
overloaded_lvalue(cx, expr, ty::MethodCall::expr(expr.id),
PassArgs::ByValue, lhs.to_ref(), vec![index])
} else {
@ -418,7 +418,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
}
hir::ExprUnary(hir::UnOp::UnDeref, ref arg) => {
if cx.tcx.is_method_call(expr.id) {
if cx.tcx.tables().is_method_call(expr.id) {
overloaded_lvalue(cx, expr, ty::MethodCall::expr(expr.id),
PassArgs::ByValue, arg.to_ref(), vec![])
} else {
@ -427,7 +427,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
}
hir::ExprUnary(hir::UnOp::UnNot, ref arg) => {
if cx.tcx.is_method_call(expr.id) {
if cx.tcx.tables().is_method_call(expr.id) {
overloaded_operator(cx, expr, ty::MethodCall::expr(expr.id),
PassArgs::ByValue, arg.to_ref(), vec![])
} else {
@ -439,7 +439,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
}
hir::ExprUnary(hir::UnOp::UnNeg, ref arg) => {
if cx.tcx.is_method_call(expr.id) {
if cx.tcx.tables().is_method_call(expr.id) {
overloaded_operator(cx, expr, ty::MethodCall::expr(expr.id),
PassArgs::ByValue, arg.to_ref(), vec![])
} else {
@ -470,10 +470,8 @@ 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
.borrow()
.fru_field_types[&expr.id]
.clone()
field_types:
cx.tcx.tables().fru_field_types[&expr.id].clone()
}
})
}
@ -512,7 +510,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
}
hir::ExprClosure(..) => {
let closure_ty = cx.tcx.expr_ty(expr);
let closure_ty = cx.tcx.tables().expr_ty(expr);
let (def_id, substs) = match closure_ty.sty {
ty::TyClosure(def_id, substs) => (def_id, substs),
_ => {
@ -551,7 +549,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
hir::ExprRepeat(ref v, ref c) => ExprKind::Repeat {
value: v.to_ref(),
count: TypedConstVal {
ty: cx.tcx.expr_ty(c),
ty: cx.tcx.tables().expr_ty(c),
span: c.span,
value: match const_eval::eval_const_expr(cx.tcx.global_tcx(), c) {
ConstVal::Integral(ConstInt::Usize(u)) => u,
@ -579,7 +577,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
ExprKind::Loop { condition: None,
body: block::to_expr_ref(cx, body) },
hir::ExprField(ref source, name) => {
let index = match cx.tcx.expr_ty_adjusted(source).sty {
let index = match cx.tcx.tables().expr_ty_adjusted(source).sty {
ty::TyAdt(adt_def, _) =>
adt_def.variants[0].index_of_field_named(name.node),
ref ty =>
@ -631,8 +629,7 @@ fn method_callee<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
expr: &hir::Expr,
method_call: ty::MethodCall)
-> Expr<'tcx> {
let tables = cx.tcx.tables.borrow();
let callee = &tables.method_map[&method_call];
let callee = cx.tcx.tables().method_map[&method_call];
let temp_lifetime = cx.tcx.region_maps.temporary_scope(expr.id);
Expr {
temp_lifetime: temp_lifetime,
@ -666,8 +663,8 @@ fn convert_arm<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
expr: &'tcx hir::Expr)
-> ExprKind<'tcx> {
let substs = cx.tcx.node_id_item_substs(expr.id).substs;
// Otherwise there may be def_map borrow conflicts
let substs = cx.tcx.tables().node_id_item_substs(expr.id)
.unwrap_or_else(|| cx.tcx.intern_substs(&[]));
let def = cx.tcx.expect_def(expr.id);
let def_id = match def {
// A regular function, constructor function or a constant.
@ -677,18 +674,20 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
Def::Const(def_id) | Def::AssociatedConst(def_id) => def_id,
Def::StructCtor(def_id, CtorKind::Const) |
Def::VariantCtor(def_id, CtorKind::Const) => match cx.tcx.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) => return ExprKind::Adt {
adt_def: adt_def,
variant_index: adt_def.variant_index_with_id(def_id),
substs: substs,
fields: vec![],
base: None,
},
ref sty => bug!("unexpected sty: {:?}", sty)
},
Def::VariantCtor(def_id, CtorKind::Const) => {
match cx.tcx.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) => return ExprKind::Adt {
adt_def: adt_def,
variant_index: adt_def.variant_index_with_id(def_id),
substs: substs,
fields: vec![],
base: None,
},
ref sty => bug!("unexpected sty: {:?}", sty)
}
}
Def::Static(node_id, _) => return ExprKind::StaticRef {
id: node_id,
@ -720,7 +719,7 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
Def::Upvar(def_id, index, closure_expr_id) => {
let id_var = cx.tcx.map.as_local_node_id(def_id).unwrap();
debug!("convert_var(upvar({:?}, {:?}, {:?}))", id_var, index, closure_expr_id);
let var_ty = cx.tcx.node_id_to_type(id_var);
let var_ty = cx.tcx.tables().node_id_to_type(id_var);
let body_id = match cx.tcx.map.find(closure_expr_id) {
Some(map::NodeExpr(expr)) => {
@ -737,7 +736,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.node_id_to_type(closure_expr_id);
let closure_ty = cx.tcx.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
@ -809,7 +808,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.upvar_capture(upvar_id) {
let upvar_capture = match cx.tcx.tables().upvar_capture(upvar_id) {
Some(c) => c,
None => {
span_bug!(
@ -893,7 +892,7 @@ fn overloaded_operator<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
argrefs.extend(
args.iter()
.map(|arg| {
let arg_ty = cx.tcx.expr_ty_adjusted(arg);
let arg_ty = cx.tcx.tables().expr_ty_adjusted(arg);
let adjusted_ty =
cx.tcx.mk_ref(region,
ty::TypeAndMut { ty: arg_ty,
@ -931,9 +930,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 tables = cx.tcx.tables.borrow();
let callee = &tables.method_map[&method_call];
let ref_ty = callee.ty.fn_ret();
let ref_ty = cx.tcx.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,
@ -962,9 +959,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.upvar_capture(upvar_id).unwrap();
let upvar_capture = cx.tcx.tables().upvar_capture(upvar_id).unwrap();
let temp_lifetime = cx.tcx.region_maps.temporary_scope(closure_expr.id);
let var_ty = cx.tcx.node_id_to_type(id_var);
let var_ty = cx.tcx.tables().node_id_to_type(id_var);
let captured_var = Expr {
temp_lifetime: temp_lifetime,
ty: var_ty,

View File

@ -214,7 +214,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> {
id: ast::NodeId) {
// fetch the fully liberated fn signature (that is, all bound
// types/lifetimes replaced)
let fn_sig = match self.tcx.tables.borrow().liberated_fn_sigs.get(&id) {
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);
@ -248,7 +248,7 @@ fn closure_self_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
closure_expr_id: ast::NodeId,
body_id: ast::NodeId)
-> Ty<'tcx> {
let closure_ty = tcx.node_id_to_type(closure_expr_id);
let closure_ty = tcx.tables().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

View File

@ -319,7 +319,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
let mut outer = self.qualif;
self.qualif = ConstQualif::empty();
let node_ty = self.tcx.node_id_to_type(ex.id);
let node_ty = self.tcx.tables().node_id_to_type(ex.id);
check_expr(self, ex, node_ty);
check_adjustments(self, ex);
@ -449,14 +449,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.borrow().method_map.contains_key(&method_call) => {
hir::ExprIndex(..) if v.tcx.tables().method_map.contains_key(&method_call) => {
v.add_qualif(ConstQualif::NOT_CONST);
}
hir::ExprBox(_) => {
v.add_qualif(ConstQualif::NOT_CONST);
}
hir::ExprUnary(op, ref inner) => {
match v.tcx.node_id_to_type(inner.id).sty {
match v.tcx.tables().node_id_to_type(inner.id).sty {
ty::TyRawPtr(_) => {
assert!(op == hir::UnDeref);
@ -466,7 +466,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
}
}
hir::ExprBinary(op, ref lhs, _) => {
match v.tcx.node_id_to_type(lhs.id).sty {
match v.tcx.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 ||
@ -503,7 +503,8 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
}
}
Def::Const(did) | Def::AssociatedConst(did) => {
let substs = Some(v.tcx.node_id_item_substs(e.id).substs);
let substs = Some(v.tcx.tables().node_id_item_substs(e.id)
.unwrap_or_else(|| v.tcx.intern_substs(&[])));
if let Some((expr, _)) = lookup_const_by_id(v.tcx, did, substs) {
let inner = v.global_expr(Mode::Const, expr);
v.add_qualif(inner);
@ -555,7 +556,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
}
}
hir::ExprMethodCall(..) => {
let method = v.tcx.tables.borrow().method_map[&method_call];
let method = v.tcx.tables().method_map[&method_call];
let is_const = match v.tcx.impl_or_trait_item(method.def_id).container() {
ty::ImplContainer(_) => v.handle_const_fn_call(e, method.def_id, node_ty),
ty::TraitContainer(_) => false
@ -565,7 +566,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
}
}
hir::ExprStruct(..) => {
if let ty::TyAdt(adt, ..) = v.tcx.expr_ty(e).sty {
if let ty::TyAdt(adt, ..) = v.tcx.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.add_qualif(ConstQualif::MUTABLE_MEM);
@ -624,16 +625,18 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
/// Check the adjustments of an expression
fn check_adjustments<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr) {
match v.tcx.tables.borrow().adjustments.get(&e.id) {
None |
Some(&ty::adjustment::AdjustNeverToAny(..)) |
Some(&ty::adjustment::AdjustReifyFnPointer) |
Some(&ty::adjustment::AdjustUnsafeFnPointer) |
Some(&ty::adjustment::AdjustMutToConstPointer) => {}
use rustc::ty::adjustment::*;
Some(&ty::adjustment::AdjustDerefRef(ty::adjustment::AutoDerefRef { autoderefs, .. })) => {
match v.tcx.tables().adjustments.get(&e.id).map(|adj| adj.kind) {
None |
Some(Adjust::NeverToAny) |
Some(Adjust::ReifyFnPointer) |
Some(Adjust::UnsafeFnPointer) |
Some(Adjust::MutToConstPointer) => {}
Some(Adjust::DerefRef { autoderefs, .. }) => {
if (0..autoderefs as u32)
.any(|autoderef| v.tcx.is_overloaded_autoderef(e.id, autoderef)) {
.any(|autoderef| v.tcx.tables().is_overloaded_autoderef(e.id, autoderef)) {
v.add_qualif(ConstQualif::NOT_CONST);
}
}

View File

@ -430,11 +430,11 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
match expr.node {
hir::ExprMethodCall(..) => {
let method_call = ty::MethodCall::expr(expr.id);
let method = self.tcx.tables.borrow().method_map[&method_call];
let method = self.tcx.tables().method_map[&method_call];
self.check_method(expr.span, method.def_id);
}
hir::ExprStruct(_, ref expr_fields, _) => {
let adt = self.tcx.expr_ty(expr).ty_adt_def().unwrap();
let adt = self.tcx.tables().expr_ty(expr).ty_adt_def().unwrap();
let variant = adt.variant_of_def(self.tcx.expect_def(expr.id));
// RFC 736: ensure all unmentioned fields are visible.
// Rather than computing the set of unmentioned fields
@ -495,14 +495,14 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
match pattern.node {
PatKind::Struct(_, ref fields, _) => {
let adt = self.tcx.pat_ty(pattern).ty_adt_def().unwrap();
let adt = self.tcx.tables().pat_ty(pattern).ty_adt_def().unwrap();
let variant = adt.variant_of_def(self.tcx.expect_def(pattern.id));
for field in fields {
self.check_field(field.span, adt, variant.field_named(field.node.name));
}
}
PatKind::TupleStruct(_, ref fields, ddpos) => {
match self.tcx.pat_ty(pattern).sty {
match self.tcx.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();

View File

@ -356,7 +356,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 = self.tcx.node_types().get(&id).unwrap().to_string();
let typ = self.tcx.tables().node_types.get(&id).unwrap().to_string();
// get the span only for the name of the variable (I hope the path is only ever a
// variable name, but who knows?)
let sub_span = span_utils.span_for_last_ident(p.span);
@ -988,7 +988,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 = self.tcx.node_id_to_type(p.id).ty_adt_def().unwrap();
let adt = self.tcx.tables().node_id_to_type(p.id).ty_adt_def().unwrap();
let variant = adt.variant_of_def(self.tcx.expect_def(p.id));
for &Spanned { node: ref field, span } in fields {
@ -1023,8 +1023,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
ast::Mutability::Immutable => value.to_string(),
_ => String::new(),
};
let types = self.tcx.node_types();
let typ = match types.get(&id) {
let typ = match self.tcx.tables().node_types.get(&id) {
Some(typ) => {
let typ = typ.to_string();
if !value.is_empty() {
@ -1355,7 +1354,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D>
}
ast::ExprKind::Struct(ref path, ref fields, ref base) => {
let hir_expr = self.save_ctxt.tcx.map.expect_expr(ex.id);
let adt = self.tcx.expr_ty(&hir_expr).ty_adt_def().unwrap();
let adt = self.tcx.tables().expr_ty(&hir_expr).ty_adt_def().unwrap();
let def = self.tcx.expect_def(hir_expr.id);
self.process_struct_lit(ex, path, fields, adt.variant_of_def(def), base)
}
@ -1381,7 +1380,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D>
return;
}
};
let ty = &self.tcx.expr_ty_adjusted(&hir_node).sty;
let ty = &self.tcx.tables().expr_ty_adjusted(&hir_node).sty;
match *ty {
ty::TyAdt(def, _) => {
let sub_span = self.span.sub_span_after_token(ex.span, token::Dot);
@ -1468,7 +1467,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D>
} else {
"<mutable>".to_string()
};
let typ = self.tcx.node_types()
let typ = self.tcx.tables().node_types
.get(&id).map(|t| t.to_string()).unwrap_or(String::new());
value.push_str(": ");
value.push_str(&typ);

View File

@ -286,7 +286,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
scope: NodeId) -> Option<VariableData> {
if let Some(ident) = field.ident {
let qualname = format!("::{}::{}", self.tcx.node_path_str(scope), ident);
let typ = self.tcx.node_types().get(&field.id).unwrap().to_string();
let typ = self.tcx.tables().node_types.get(&field.id).unwrap().to_string();
let sub_span = self.span_utils.sub_span_before_token(field.span, token::Colon);
filter!(self.span_utils, sub_span, field.span, None);
Some(VariableData {
@ -418,7 +418,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.expr_ty_adjusted_opt(&hir_node);
let ty = self.tcx.tables().expr_ty_adjusted_opt(&hir_node);
if ty.is_none() || ty.unwrap().sty == ty::TyError {
return None;
}
@ -432,7 +432,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
return None;
}
};
match self.tcx.expr_ty_adjusted(&hir_node).sty {
match self.tcx.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);
@ -451,7 +451,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
}
}
ast::ExprKind::Struct(ref path, ..) => {
match self.tcx.expr_ty_adjusted(&hir_node).sty {
match self.tcx.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);
@ -472,7 +472,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.borrow().method_map[&method_call].def_id;
let method_id = self.tcx.tables().method_map[&method_call].def_id;
let (def_id, decl_id) = match self.tcx.impl_or_trait_item(method_id).container() {
ty::ImplContainer(_) => (Some(method_id), None),
ty::TraitContainer(_) => (None, Some(method_id)),

View File

@ -74,7 +74,7 @@ impl<'tcx> Callee<'tcx> {
pub fn method_call<'blk>(bcx: Block<'blk, 'tcx>,
method_call: ty::MethodCall)
-> Callee<'tcx> {
let method = bcx.tcx().tables.borrow().method_map[&method_call];
let method = bcx.tcx().tables().method_map[&method_call];
Callee::method(bcx, method)
}

View File

@ -1082,10 +1082,7 @@ impl<'b, 'a, 'v> hir_visit::Visitor<'v> for RootCollector<'b, 'a, 'v> {
hir::ItemStruct(_, ref generics) |
hir::ItemUnion(_, ref generics) => {
if !generics.is_parameterized() {
let ty = {
let tables = self.scx.tcx().tables.borrow();
tables.node_types[&item.id]
};
let ty = self.scx.tcx().tables().node_types[&item.id];
if self.mode == TransItemCollectionMode::Eager {
debug!("RootCollector: ADT drop-glue for {}",

View File

@ -1765,7 +1765,7 @@ pub fn create_global_var_metadata(cx: &CrateContext,
};
let is_local_to_unit = is_node_local_to_unit(cx, node_id);
let variable_type = tcx.erase_regions(&tcx.node_id_to_type(node_id));
let variable_type = tcx.erase_regions(&tcx.tables().node_id_to_type(node_id));
let type_metadata = type_metadata(cx, variable_type, span);
let var_name = tcx.item_name(node_def_id).to_string();
let linkage_name = mangled_name_of_item(cx, node_def_id, "");

View File

@ -1549,7 +1549,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
tcx.prohibit_type_params(base_segments);
let impl_id = tcx.map.as_local_node_id(def_id).unwrap();
let ty = tcx.node_id_to_type(impl_id);
let ty = tcx.tables().node_id_to_type(impl_id);
if let Some(free_substs) = self.get_free_substs() {
ty.subst(tcx, free_substs)
} else {

View File

@ -103,7 +103,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// If the callee is a bare function or a closure, then we're all set.
match self.structurally_resolved_type(callee_expr.span, adjusted_ty).sty {
ty::TyFnDef(..) | ty::TyFnPtr(_) => {
self.write_autoderef_adjustment(callee_expr.id, autoderefs);
self.write_autoderef_adjustment(callee_expr.id, autoderefs, adjusted_ty);
return Some(CallStep::Builtin);
}

View File

@ -65,10 +65,7 @@ use check::FnCtxt;
use rustc::hir;
use rustc::infer::{Coercion, InferOk, TypeOrigin, TypeTrace};
use rustc::traits::{self, ObligationCause};
use rustc::ty::adjustment::{AutoAdjustment, AutoDerefRef, AdjustDerefRef};
use rustc::ty::adjustment::{AutoPtr, AutoUnsafe, AdjustReifyFnPointer};
use rustc::ty::adjustment::{AdjustUnsafeFnPointer, AdjustMutToConstPointer};
use rustc::ty::adjustment::AdjustNeverToAny;
use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow};
use rustc::ty::{self, LvaluePreference, TypeAndMut, Ty};
use rustc::ty::fold::TypeFoldable;
use rustc::ty::error::TypeError;
@ -93,7 +90,7 @@ impl<'a, 'gcx, 'tcx> Deref for Coerce<'a, 'gcx, 'tcx> {
}
}
type CoerceResult<'tcx> = RelateResult<'tcx, (Ty<'tcx>, AutoAdjustment<'tcx>)>;
type CoerceResult<'tcx> = RelateResult<'tcx, (Ty<'tcx>, Adjust<'tcx>)>;
fn coerce_mutbls<'tcx>(from_mutbl: hir::Mutability,
to_mutbl: hir::Mutability)
@ -144,12 +141,11 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
/// Synthesize an identity adjustment.
fn identity(&self, ty: Ty<'tcx>) -> CoerceResult<'tcx> {
Ok((ty,
AdjustDerefRef(AutoDerefRef {
autoderefs: 0,
autoref: None,
unsize: None,
})))
Ok((ty, Adjust::DerefRef {
autoderefs: 0,
autoref: None,
unsize: false,
}))
}
fn coerce<'a, E, I>(&self, exprs: &E, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx>
@ -166,7 +162,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
}
if a.is_never() {
return Ok((b, AdjustNeverToAny(b)));
return Ok((b, Adjust::NeverToAny));
}
// Consider coercing the subtype to a DST
@ -396,17 +392,16 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
ty::TyRef(r_borrow, _) => r_borrow,
_ => span_bug!(span, "expected a ref type, got {:?}", ty),
};
let autoref = Some(AutoPtr(r_borrow, mt_b.mutbl));
let autoref = Some(AutoBorrow::Ref(r_borrow, mt_b.mutbl));
debug!("coerce_borrowed_pointer: succeeded ty={:?} autoderefs={:?} autoref={:?}",
ty,
autoderefs,
autoref);
Ok((ty,
AdjustDerefRef(AutoDerefRef {
autoderefs: autoderefs,
autoref: autoref,
unsize: None,
})))
Ok((ty, Adjust::DerefRef {
autoderefs: autoderefs,
autoref: autoref,
unsize: false,
}))
}
@ -437,11 +432,11 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
let coercion = Coercion(self.origin.span());
let r_borrow = self.next_region_var(coercion);
(mt_a.ty, Some(AutoPtr(r_borrow, mt_b.mutbl)))
(mt_a.ty, Some(AutoBorrow::Ref(r_borrow, mt_b.mutbl)))
}
(&ty::TyRef(_, mt_a), &ty::TyRawPtr(mt_b)) => {
coerce_mutbls(mt_a.mutbl, mt_b.mutbl)?;
(mt_a.ty, Some(AutoUnsafe(mt_b.mutbl)))
(mt_a.ty, Some(AutoBorrow::RawPtr(mt_b.mutbl)))
}
_ => (source, None),
};
@ -497,13 +492,13 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
*self.unsizing_obligations.borrow_mut() = leftover_predicates;
let adjustment = AutoDerefRef {
let adjustment = Adjust::DerefRef {
autoderefs: if reborrow.is_some() { 1 } else { 0 },
autoref: reborrow,
unsize: Some(target),
unsize: true,
};
debug!("Success, coerced with {:?}", adjustment);
Ok((target, AdjustDerefRef(adjustment)))
Ok((target, adjustment))
}
fn coerce_from_safe_fn(&self,
@ -516,7 +511,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
(hir::Unsafety::Normal, hir::Unsafety::Unsafe) => {
let unsafe_a = self.tcx.safe_to_unsafe_fn_ty(fn_ty_a);
return self.unify_and_identity(unsafe_a, b)
.map(|(ty, _)| (ty, AdjustUnsafeFnPointer));
.map(|(ty, _)| (ty, Adjust::UnsafeFnPointer));
}
_ => {}
}
@ -555,7 +550,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
ty::TyFnPtr(_) => {
let a_fn_pointer = self.tcx.mk_fn_ptr(fn_ty_a);
self.coerce_from_safe_fn(a_fn_pointer, fn_ty_a, b)
.map(|(ty, _)| (ty, AdjustReifyFnPointer))
.map(|(ty, _)| (ty, Adjust::ReifyFnPointer))
}
_ => self.unify_and_identity(a, b),
}
@ -585,17 +580,17 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
coerce_mutbls(mt_a.mutbl, mutbl_b)?;
// Although references and unsafe ptrs have the same
// representation, we still register an AutoDerefRef so that
// representation, we still register an Adjust::DerefRef so that
// regionck knows that the region for `a` must be valid here.
Ok((ty,
if is_ref {
AdjustDerefRef(AutoDerefRef {
Adjust::DerefRef {
autoderefs: 1,
autoref: Some(AutoUnsafe(mutbl_b)),
unsize: None,
})
autoref: Some(AutoBorrow::RawPtr(mutbl_b)),
unsize: false,
}
} else if mt_a.mutbl != mutbl_b {
AdjustMutToConstPointer
Adjust::MutToConstPointer
} else {
noop
}))
@ -606,24 +601,25 @@ fn apply<'a, 'b, 'gcx, 'tcx, E, I>(coerce: &mut Coerce<'a, 'gcx, 'tcx>,
exprs: &E,
a: Ty<'tcx>,
b: Ty<'tcx>)
-> CoerceResult<'tcx>
-> RelateResult<'tcx, Adjustment<'tcx>>
where E: Fn() -> I,
I: IntoIterator<Item = &'b hir::Expr>
{
let (ty, adjustment) = indent(|| coerce.coerce(exprs, a, b))?;
let (ty, adjust) = indent(|| coerce.coerce(exprs, a, b))?;
let fcx = coerce.fcx;
if let AdjustDerefRef(auto) = adjustment {
if auto.unsize.is_some() {
let mut obligations = coerce.unsizing_obligations.borrow_mut();
for obligation in obligations.drain(..) {
fcx.register_predicate(obligation);
}
if let Adjust::DerefRef { unsize: true, .. } = adjust {
let mut obligations = coerce.unsizing_obligations.borrow_mut();
for obligation in obligations.drain(..) {
fcx.register_predicate(obligation);
}
}
Ok((ty, adjustment))
Ok(Adjustment {
kind: adjust,
target: ty
})
}
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
@ -641,17 +637,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let mut coerce = Coerce::new(self, TypeOrigin::ExprAssignable(expr.span));
self.commit_if_ok(|_| {
let (ty, adjustment) = apply(&mut coerce, &|| Some(expr), source, target)?;
let adjustment = apply(&mut coerce, &|| Some(expr), source, target)?;
if !adjustment.is_identity() {
debug!("Success, coerced with {:?}", adjustment);
match self.tables.borrow().adjustments.get(&expr.id) {
None |
Some(&AdjustNeverToAny(..)) => (),
Some(&Adjustment { kind: Adjust::NeverToAny, .. }) => (),
_ => bug!("expr already has an adjustment on it!"),
};
self.write_adjustment(expr.id, adjustment);
}
Ok(ty)
Ok(adjustment.target)
})
}
@ -705,12 +701,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
}
// Reify both sides and return the reified fn pointer type.
let fn_ptr = self.tcx.mk_fn_ptr(fty);
for expr in exprs().into_iter().chain(Some(new)) {
// No adjustments can produce a fn item, so this should never trip.
assert!(!self.tables.borrow().adjustments.contains_key(&expr.id));
self.write_adjustment(expr.id, AdjustReifyFnPointer);
self.write_adjustment(expr.id, Adjustment {
kind: Adjust::ReifyFnPointer,
target: fn_ptr
});
}
return Ok(self.tcx.mk_fn_ptr(fty));
return Ok(fn_ptr);
}
_ => {}
}
@ -724,11 +724,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
if !self.tables.borrow().adjustments.contains_key(&new.id) {
let result = self.commit_if_ok(|_| apply(&mut coerce, &|| Some(new), new_ty, prev_ty));
match result {
Ok((ty, adjustment)) => {
Ok(adjustment) => {
if !adjustment.is_identity() {
self.write_adjustment(new.id, adjustment);
}
return Ok(ty);
return Ok(adjustment.target);
}
Err(e) => first_error = Some(e),
}
@ -738,10 +738,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// This requires ensuring there are no coercions applied to *any* of the
// previous expressions, other than noop reborrows (ignoring lifetimes).
for expr in exprs() {
let noop = match self.tables.borrow().adjustments.get(&expr.id) {
Some(&AdjustDerefRef(AutoDerefRef { autoderefs: 1,
autoref: Some(AutoPtr(_, mutbl_adj)),
unsize: None })) => {
let noop = match self.tables.borrow().adjustments.get(&expr.id).map(|adj| adj.kind) {
Some(Adjust::DerefRef {
autoderefs: 1,
autoref: Some(AutoBorrow::Ref(_, mutbl_adj)),
unsize: false
}) => {
match self.node_ty(expr.id).sty {
ty::TyRef(_, mt_orig) => {
// Reborrow that we can safely ignore.
@ -750,7 +752,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
_ => false,
}
}
Some(&AdjustNeverToAny(_)) => true,
Some(Adjust::NeverToAny) => true,
Some(_) => false,
None => true,
};
@ -783,18 +785,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
})
}
}
Ok((ty, adjustment)) => {
Ok(adjustment) => {
if !adjustment.is_identity() {
let mut tables = self.tables.borrow_mut();
for expr in exprs() {
let previous = self.tables.borrow().adjustments.get(&expr.id).cloned();
if let Some(AdjustNeverToAny(_)) = previous {
self.write_adjustment(expr.id, AdjustNeverToAny(ty));
} else {
self.write_adjustment(expr.id, adjustment);
if let Some(&mut Adjustment {
kind: Adjust::NeverToAny,
ref mut target
}) = tables.adjustments.get_mut(&expr.id) {
*target = adjustment.target;
continue;
}
tables.adjustments.insert(expr.id, adjustment);
}
}
Ok(ty)
Ok(adjustment.target)
}
}
}

View File

@ -15,7 +15,7 @@ use hir::def_id::DefId;
use rustc::ty::subst::Substs;
use rustc::traits;
use rustc::ty::{self, LvaluePreference, NoPreference, PreferMutLvalue, Ty};
use rustc::ty::adjustment::{AdjustDerefRef, AutoDerefRef, AutoPtr};
use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow};
use rustc::ty::fold::TypeFoldable;
use rustc::infer::{self, InferOk, TypeOrigin};
use syntax_pos::Span;
@ -140,20 +140,19 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
unadjusted_self_ty: Ty<'tcx>,
pick: &probe::Pick<'tcx>)
-> Ty<'tcx> {
let (autoref, unsize) = if let Some(mutbl) = pick.autoref {
let autoref = if let Some(mutbl) = pick.autoref {
let region = self.next_region_var(infer::Autoref(self.span));
let autoref = AutoPtr(region, mutbl);
(Some(autoref),
pick.unsize.map(|target| target.adjust_for_autoref(self.tcx, Some(autoref))))
Some(AutoBorrow::Ref(region, mutbl))
} else {
// No unsizing should be performed without autoref (at
// least during method dispach). This is because we
// currently only unsize `[T;N]` to `[T]`, and naturally
// that must occur being a reference.
assert!(pick.unsize.is_none());
(None, None)
None
};
// Commit the autoderefs by calling `autoderef` again, but this
// time writing the results into the various tables.
let mut autoderef = self.autoderef(self.span, unadjusted_self_ty);
@ -163,19 +162,20 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
autoderef.unambiguous_final_ty();
autoderef.finalize(LvaluePreference::NoPreference, Some(self.self_expr));
// Write out the final adjustment.
self.write_adjustment(self.self_expr.id,
AdjustDerefRef(AutoDerefRef {
autoderefs: pick.autoderefs,
autoref: autoref,
unsize: unsize,
}));
let target = pick.unsize.unwrap_or(autoderefd_ty);
let target = target.adjust_for_autoref(self.tcx, autoref);
if let Some(target) = unsize {
target
} else {
autoderefd_ty.adjust_for_autoref(self.tcx, autoref)
}
// Write out the final adjustment.
self.write_adjustment(self.self_expr.id, Adjustment {
kind: Adjust::DerefRef {
autoderefs: pick.autoderefs,
autoref: autoref,
unsize: pick.unsize.is_some(),
},
target: target
});
target
}
///////////////////////////////////////////////////////////////////////////
@ -463,29 +463,23 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
// Fix up autoderefs and derefs.
for (i, &expr) in exprs.iter().rev().enumerate() {
debug!("convert_lvalue_derefs_to_mutable: i={} expr={:?}", i, expr);
// Count autoderefs.
let autoderef_count = match self.tables
.borrow()
.adjustments
.get(&expr.id) {
Some(&AdjustDerefRef(ref adj)) => adj.autoderefs,
Some(_) | None => 0,
};
debug!("convert_lvalue_derefs_to_mutable: i={} expr={:?} \
autoderef_count={}",
i,
expr,
autoderef_count);
if autoderef_count > 0 {
let mut autoderef = self.autoderef(expr.span, self.node_ty(expr.id));
autoderef.nth(autoderef_count).unwrap_or_else(|| {
span_bug!(expr.span,
"expr was deref-able {} times but now isn't?",
autoderef_count);
});
autoderef.finalize(PreferMutLvalue, Some(expr));
let adjustment = self.tables.borrow().adjustments.get(&expr.id).cloned();
match adjustment {
Some(Adjustment { kind: Adjust::DerefRef { autoderefs, .. }, .. }) => {
if autoderefs > 0 {
let mut autoderef = self.autoderef(expr.span, self.node_ty(expr.id));
autoderef.nth(autoderefs).unwrap_or_else(|| {
span_bug!(expr.span,
"expr was deref-able {} times but now isn't?",
autoderefs);
});
autoderef.finalize(PreferMutLvalue, Some(expr));
}
}
Some(_) | None => {}
}
// Don't retry the first one or we might infinite loop!
@ -503,45 +497,55 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
// ought to recode this routine so it doesn't
// (ab)use the normal type checking paths.
let adj = self.tables.borrow().adjustments.get(&base_expr.id).cloned();
let (autoderefs, unsize) = match adj {
Some(AdjustDerefRef(adr)) => {
match adr.autoref {
let (autoderefs, unsize, adjusted_base_ty) = match adj {
Some(Adjustment {
kind: Adjust::DerefRef { autoderefs, autoref, unsize },
target
}) => {
match autoref {
None => {
assert!(adr.unsize.is_none());
(adr.autoderefs, None)
}
Some(AutoPtr(..)) => {
(adr.autoderefs,
adr.unsize.map(|target| {
target.builtin_deref(false, NoPreference)
.expect("fixup: AutoPtr is not &T")
.ty
}))
assert!(!unsize);
}
Some(AutoBorrow::Ref(..)) => {}
Some(_) => {
span_bug!(base_expr.span,
"unexpected adjustment autoref {:?}",
adr);
adj);
}
}
(autoderefs, unsize, if unsize {
target.builtin_deref(false, NoPreference)
.expect("fixup: AutoBorrow::Ref is not &T")
.ty
} else {
let ty = self.node_ty(base_expr.id);
let mut ty = self.shallow_resolve(ty);
let mut method_type = |method_call: ty::MethodCall| {
self.tables.borrow().method_map.get(&method_call).map(|m| {
self.resolve_type_vars_if_possible(&m.ty)
})
};
if !ty.references_error() {
for i in 0..autoderefs {
ty = ty.adjust_for_autoderef(self.tcx,
base_expr.id,
base_expr.span,
i as u32,
&mut method_type);
}
}
ty
})
}
None => (0, None),
None => (0, false, self.node_ty(base_expr.id)),
Some(_) => {
span_bug!(base_expr.span, "unexpected adjustment type");
}
};
let (adjusted_base_ty, unsize) = if let Some(target) = unsize {
(target, true)
} else {
(self.adjust_expr_ty(base_expr,
Some(&AdjustDerefRef(AutoDerefRef {
autoderefs: autoderefs,
autoref: None,
unsize: None,
}))),
false)
};
let index_expr_ty = self.node_ty(index_expr.id);
let result = self.try_index_step(ty::MethodCall::expr(expr.id),

View File

@ -16,7 +16,7 @@ use hir::def_id::DefId;
use rustc::ty::subst::Substs;
use rustc::traits;
use rustc::ty::{self, ToPredicate, ToPolyTraitRef, TraitRef, TypeFoldable};
use rustc::ty::adjustment::{AdjustDerefRef, AutoDerefRef, AutoPtr};
use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow};
use rustc::infer;
use syntax::ast;
@ -294,11 +294,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
unsize,
method_ty.explicit_self);
match method_ty.explicit_self {
let autoref = match method_ty.explicit_self {
ty::ExplicitSelfCategory::ByValue => {
// Trait method is fn(self), no transformation needed.
assert!(!unsize);
self.write_autoderef_adjustment(self_expr.id, autoderefs);
None
}
ty::ExplicitSelfCategory::ByReference(..) => {
@ -306,16 +306,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// autoref. Pull the region etc out of the type of first argument.
match transformed_self_ty.sty {
ty::TyRef(region, ty::TypeAndMut { mutbl, ty: _ }) => {
self.write_adjustment(self_expr.id,
AdjustDerefRef(AutoDerefRef {
autoderefs: autoderefs,
autoref: Some(AutoPtr(region, mutbl)),
unsize: if unsize {
Some(transformed_self_ty)
} else {
None
},
}));
Some(AutoBorrow::Ref(region, mutbl))
}
_ => {
@ -331,7 +322,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
"unexpected explicit self type in operator method: {:?}",
method_ty.explicit_self);
}
}
};
self.write_adjustment(self_expr.id, Adjustment {
kind: Adjust::DerefRef {
autoderefs: autoderefs,
autoref: autoref,
unsize: unsize
},
target: transformed_self_ty
});
}
}

View File

@ -777,7 +777,7 @@ pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
check_union(ccx, it.id, it.span);
}
hir::ItemTy(_, ref generics) => {
let pty_ty = ccx.tcx.node_id_to_type(it.id);
let pty_ty = ccx.tcx.tables().node_id_to_type(it.id);
check_bounds_are_used(ccx, generics, pty_ty);
}
hir::ItemForeignMod(ref m) => {
@ -1205,7 +1205,7 @@ fn check_representable<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
sp: Span,
item_id: ast::NodeId)
-> bool {
let rty = tcx.node_id_to_type(item_id);
let rty = tcx.tables().node_id_to_type(item_id);
// Check that it is possible to represent this type. This call identifies
// (1) types that contain themselves and (2) types that contain a different
@ -1224,7 +1224,7 @@ fn check_representable<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
}
pub fn check_simd<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sp: Span, id: ast::NodeId) {
let t = tcx.node_id_to_type(id);
let t = tcx.tables().node_id_to_type(id);
match t.sty {
ty::TyAdt(def, substs) if def.is_struct() => {
let fields = &def.struct_variant().fields;
@ -1581,20 +1581,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
pub fn write_autoderef_adjustment(&self,
node_id: ast::NodeId,
derefs: usize) {
self.write_adjustment(
node_id,
adjustment::AdjustDerefRef(adjustment::AutoDerefRef {
derefs: usize,
adjusted_ty: Ty<'tcx>) {
self.write_adjustment(node_id, adjustment::Adjustment {
kind: adjustment::Adjust::DerefRef {
autoderefs: derefs,
autoref: None,
unsize: None
})
);
unsize: false
},
target: adjusted_ty
});
}
pub fn write_adjustment(&self,
node_id: ast::NodeId,
adj: adjustment::AutoAdjustment<'tcx>) {
adj: adjustment::Adjustment<'tcx>) {
debug!("write_adjustment(node_id={}, adj={:?})", node_id, adj);
if adj.is_identity() {
@ -1760,21 +1761,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
t
}
/// Apply `adjustment` to the type of `expr`
pub fn adjust_expr_ty(&self,
expr: &hir::Expr,
adjustment: Option<&adjustment::AutoAdjustment<'tcx>>)
-> Ty<'tcx>
{
let raw_ty = self.node_ty(expr.id);
let raw_ty = self.shallow_resolve(raw_ty);
let resolve_ty = |ty: Ty<'tcx>| self.resolve_type_vars_if_possible(&ty);
raw_ty.adjust(self.tcx, expr.span, expr.id, adjustment, |method_call| {
self.tables.borrow().method_map.get(&method_call)
.map(|method| resolve_ty(method.ty))
})
}
pub fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx> {
match self.tables.borrow().node_types.get(&id) {
Some(&t) => t,
@ -2311,7 +2297,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
debug!("try_index_step: success, using built-in indexing");
// If we had `[T; N]`, we should've caught it before unsizing to `[T]`.
assert!(!unsize);
self.write_autoderef_adjustment(base_expr.id, autoderefs);
self.write_autoderef_adjustment(base_expr.id, autoderefs, adjusted_ty);
return Some((tcx.types.usize, ty));
}
_ => {}
@ -2867,9 +2853,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// In case we did perform an adjustment, we have to update
// the type of the block, because old trans still uses it.
let adj = self.tables.borrow().adjustments.get(&then.id).cloned();
if res.is_ok() && adj.is_some() {
self.write_ty(then_blk.id, self.adjust_expr_ty(then, adj.as_ref()));
if res.is_ok() {
let adj = self.tables.borrow().adjustments.get(&then.id).cloned();
if let Some(adj) = adj {
self.write_ty(then_blk.id, adj.target);
}
}
res
@ -2930,7 +2918,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let field_ty = self.field_ty(expr.span, field, substs);
if field.vis.is_accessible_from(self.body_id, &self.tcx().map) {
autoderef.finalize(lvalue_pref, Some(base));
self.write_autoderef_adjustment(base.id, autoderefs);
self.write_autoderef_adjustment(base.id, autoderefs, base_t);
return field_ty;
}
private_candidate = Some((base_def.did, field_ty));
@ -3048,7 +3036,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
if let Some(field_ty) = field {
autoderef.finalize(lvalue_pref, Some(base));
self.write_autoderef_adjustment(base.id, autoderefs);
self.write_autoderef_adjustment(base.id, autoderefs, base_t);
return field_ty;
}
}
@ -3358,8 +3346,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
if ty.is_never() {
if let Some(hir::map::NodeExpr(_)) = self.tcx.map.find(expr.id) {
let adj_ty = self.next_diverging_ty_var();
let adj = adjustment::AdjustNeverToAny(adj_ty);
self.write_adjustment(expr.id, adj);
self.write_adjustment(expr.id, adjustment::Adjustment {
kind: adjustment::Adjust::NeverToAny,
target: adj_ty
});
return adj_ty;
}
}

View File

@ -259,23 +259,10 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
self.resolve_type(t)
}
fn resolve_method_type(&self, method_call: MethodCall) -> Option<Ty<'tcx>> {
let method_ty = self.tables.borrow().method_map
.get(&method_call).map(|method| method.ty);
method_ty.map(|method_ty| self.resolve_type(method_ty))
}
/// Try to resolve the type for the given node.
pub fn resolve_expr_type_adjusted(&mut self, expr: &hir::Expr) -> Ty<'tcx> {
let ty_unadjusted = self.resolve_node_type(expr.id);
if ty_unadjusted.references_error() {
ty_unadjusted
} else {
ty_unadjusted.adjust(
self.tcx, expr.span, expr.id,
self.tables.borrow().adjustments.get(&expr.id),
|method_call| self.resolve_method_type(method_call))
}
let ty = self.tables.borrow().expr_ty_adjusted(expr);
self.resolve_type(ty)
}
fn visit_fn_body(&mut self,
@ -553,10 +540,8 @@ impl<'a, 'gcx, 'tcx, 'v> Visitor<'v> for RegionCtxt<'a, 'gcx, 'tcx> {
let adjustment = self.tables.borrow().adjustments.get(&expr.id).map(|a| a.clone());
if let Some(adjustment) = adjustment {
debug!("adjustment={:?}", adjustment);
match adjustment {
adjustment::AdjustDerefRef(adjustment::AutoDerefRef {
autoderefs, ref autoref, ..
}) => {
match adjustment.kind {
adjustment::Adjust::DerefRef { autoderefs, ref autoref, .. } => {
let expr_ty = self.resolve_node_type(expr.id);
self.constrain_autoderefs(expr, autoderefs, expr_ty);
if let Some(ref autoref) = *autoref {
@ -946,7 +931,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
let origin = infer::ParameterOrigin::OverloadedDeref;
self.substs_wf_in_scope(origin, method.substs, deref_expr.span, r_deref_expr);
// Treat overloaded autoderefs as if an AutoRef adjustment
// Treat overloaded autoderefs as if an AutoBorrow adjustment
// was applied on the base type, as that is always the case.
let fn_sig = method.ty.fn_sig();
let fn_sig = // late-bound regions should have been instantiated
@ -1060,15 +1045,12 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
id: ast::NodeId,
minimum_lifetime: &'tcx ty::Region)
{
let tcx = self.tcx;
// Try to resolve the type. If we encounter an error, then typeck
// is going to fail anyway, so just stop here and let typeck
// report errors later on in the writeback phase.
let ty0 = self.resolve_node_type(id);
let ty = ty0.adjust(tcx, origin.span(), id,
self.tables.borrow().adjustments.get(&id),
|method_call| self.resolve_method_type(method_call));
let ty = self.tables.borrow().adjustments.get(&id).map_or(ty0, |adj| adj.target);
let ty = self.resolve_type(ty);
debug!("constrain_regions_in_type_of_node(\
ty={}, ty0={}, id={}, minimum_lifetime={:?})",
ty, ty0,
@ -1165,7 +1147,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
fn link_autoref(&self,
expr: &hir::Expr,
autoderefs: usize,
autoref: &adjustment::AutoRef<'tcx>)
autoref: &adjustment::AutoBorrow<'tcx>)
{
debug!("link_autoref(autoref={:?})", autoref);
let mc = mc::MemCategorizationContext::new(self);
@ -1173,12 +1155,12 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
debug!("expr_cmt={:?}", expr_cmt);
match *autoref {
adjustment::AutoPtr(r, m) => {
adjustment::AutoBorrow::Ref(r, m) => {
self.link_region(expr.span, r,
ty::BorrowKind::from_mutbl(m), expr_cmt);
}
adjustment::AutoUnsafe(m) => {
adjustment::AutoBorrow::RawPtr(m) => {
let r = self.tcx.node_scope_region(expr.id);
self.link_region(expr.span, r, ty::BorrowKind::from_mutbl(m), expr_cmt);
}

View File

@ -416,7 +416,7 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> {
}
}
None => {
let self_ty = fcx.tcx.node_id_to_type(item.id);
let self_ty = fcx.tcx.tables().node_id_to_type(item.id);
let self_ty = fcx.instantiate_type_scheme(item.span, free_substs, &self_ty);
fcx.register_wf_obligation(self_ty, ast_self_ty.span, this.code.clone());
}
@ -519,7 +519,7 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> {
item: &hir::Item,
ast_generics: &hir::Generics)
{
let ty = self.tcx().node_id_to_type(item.id);
let ty = self.tcx().tables().node_id_to_type(item.id);
if self.tcx().has_error_field(ty) {
return;
}
@ -649,7 +649,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let fields =
struct_def.fields().iter()
.map(|field| {
let field_ty = self.tcx.node_id_to_type(field.id);
let field_ty = self.tcx.tables().node_id_to_type(field.id);
let field_ty = self.instantiate_type_scheme(field.span,
&self.parameter_environment
.free_substs,

View File

@ -229,7 +229,7 @@ impl<'cx, 'gcx, 'tcx, 'v> Visitor<'v> for WritebackCx<'cx, 'gcx, 'tcx> {
debug!("Type for pattern binding {} (id {}) resolved to {:?}",
pat_to_string(p),
p.id,
self.tcx().node_id_to_type(p.id));
self.tcx().tables().node_id_to_type(p.id));
intravisit::walk_pat(self, p);
}
@ -381,36 +381,40 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
}
Some(adjustment) => {
let resolved_adjustment = match adjustment {
adjustment::AdjustNeverToAny(ty) => {
adjustment::AdjustNeverToAny(self.resolve(&ty, reason))
let resolved_adjustment = match adjustment.kind {
adjustment::Adjust::NeverToAny => {
adjustment::Adjust::NeverToAny
}
adjustment::AdjustReifyFnPointer => {
adjustment::AdjustReifyFnPointer
adjustment::Adjust::ReifyFnPointer => {
adjustment::Adjust::ReifyFnPointer
}
adjustment::AdjustMutToConstPointer => {
adjustment::AdjustMutToConstPointer
adjustment::Adjust::MutToConstPointer => {
adjustment::Adjust::MutToConstPointer
}
adjustment::AdjustUnsafeFnPointer => {
adjustment::AdjustUnsafeFnPointer
adjustment::Adjust::UnsafeFnPointer => {
adjustment::Adjust::UnsafeFnPointer
}
adjustment::AdjustDerefRef(adj) => {
for autoderef in 0..adj.autoderefs {
adjustment::Adjust::DerefRef { autoderefs, autoref, unsize } => {
for autoderef in 0..autoderefs {
let method_call = MethodCall::autoderef(id, autoderef as u32);
self.visit_method_map_entry(reason, method_call);
}
adjustment::AdjustDerefRef(adjustment::AutoDerefRef {
autoderefs: adj.autoderefs,
autoref: self.resolve(&adj.autoref, reason),
unsize: self.resolve(&adj.unsize, reason),
})
adjustment::Adjust::DerefRef {
autoderefs: autoderefs,
autoref: self.resolve(&autoref, reason),
unsize: unsize,
}
}
};
let resolved_adjustment = adjustment::Adjustment {
kind: resolved_adjustment,
target: self.resolve(&adjustment.target, reason)
};
debug!("Adjustments for node {}: {:?}", id, resolved_adjustment);
self.tcx().tables.borrow_mut().adjustments.insert(
id, resolved_adjustment);

View File

@ -211,7 +211,7 @@ fn check_main_fn_ty(ccx: &CrateCtxt,
main_id: ast::NodeId,
main_span: Span) {
let tcx = ccx.tcx;
let main_t = tcx.node_id_to_type(main_id);
let main_t = tcx.tables().node_id_to_type(main_id);
match main_t.sty {
ty::TyFnDef(..) => {
match tcx.map.find(main_id) {
@ -263,7 +263,7 @@ fn check_start_fn_ty(ccx: &CrateCtxt,
start_id: ast::NodeId,
start_span: Span) {
let tcx = ccx.tcx;
let start_t = tcx.node_id_to_type(start_id);
let start_t = tcx.tables().node_id_to_type(start_id);
match start_t.sty {
ty::TyFnDef(..) => {
match tcx.map.find(start_id) {