Skip to content

Commit

Permalink
Rollup merge of rust-lang#37408 - eddyb:lazy-5, r=nikomatsakis
Browse files Browse the repository at this point in the history
[5/n] rustc: record the target type of every adjustment.

_This is part of a series ([prev](rust-lang#37404) | [next](rust-lang#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).
  • Loading branch information
alexcrichton authored Nov 4, 2016
2 parents 0f6a71e + 0d7201e commit 1a09632
Show file tree
Hide file tree
Showing 47 changed files with 631 additions and 802 deletions.
8 changes: 4 additions & 4 deletions src/librustc/cfg/construct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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())
}

Expand Down Expand Up @@ -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);
Expand Down
26 changes: 3 additions & 23 deletions src/librustc/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
}

Expand Down Expand Up @@ -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
}

Expand Down
12 changes: 6 additions & 6 deletions src/librustc/middle/dead.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
}
Expand All @@ -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);
}
Expand All @@ -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))
}
Expand Down Expand Up @@ -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
Expand Down
10 changes: 5 additions & 5 deletions src/librustc/middle/effect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -168,15 +168,15 @@ 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) {
self.require_unsafe(expr.span, "call to unsafe function")
}
}
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 {
Expand All @@ -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");
}
Expand All @@ -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");
Expand Down
55 changes: 23 additions & 32 deletions src/librustc/middle/expr_use_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -720,20 +720,33 @@ 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");
let cmt_unadjusted =
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);
}
}
}
}
Expand Down Expand Up @@ -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
Expand All @@ -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={:?})",
Expand All @@ -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,
Expand All @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/intrinsicck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down
14 changes: 7 additions & 7 deletions src/librustc/middle/liveness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand All @@ -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
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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(),
Expand Down Expand Up @@ -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
},
Expand Down
26 changes: 12 additions & 14 deletions src/librustc/middle/mem_categorization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>> {
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/reachable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading

0 comments on commit 1a09632

Please sign in to comment.