Skip to content

Commit

Permalink
rustc: record the target type of every adjustment.
Browse files Browse the repository at this point in the history
  • Loading branch information
eddyb committed Oct 27, 2016
1 parent 0c6c354 commit 89a28f6
Show file tree
Hide file tree
Showing 29 changed files with 422 additions and 582 deletions.
2 changes: 1 addition & 1 deletion src/librustc/cfg/construct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
let method_call = ty::MethodCall::expr(call_expr.id);
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 @@ -1256,26 +1256,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 @@ -1612,7 +1592,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 @@ -1656,9 +1636,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
4 changes: 2 additions & 2 deletions src/librustc/middle/dead.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
}

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 Down
6 changes: 3 additions & 3 deletions src/librustc/middle/effect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 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/liveness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1114,7 +1114,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
hir::ExprCall(ref f, ref args) => {
// FIXME(canndrew): This is_never should really be an is_uninhabited
let diverges = !self.ir.tcx.tables().is_method_call(expr.id) &&
self.ir.tcx.expr_ty_adjusted(&f).fn_ret().0.is_never();
self.ir.tcx.tables().expr_ty_adjusted(&f).fn_ret().0.is_never();
let succ = if diverges {
self.s.exit_ln
} else {
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
4 changes: 2 additions & 2 deletions src/librustc/middle/stability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -559,7 +559,7 @@ pub fn check_expr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, e: &hir::Expr,
}
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
}
Expand All @@ -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
}
Expand Down
Loading

0 comments on commit 89a28f6

Please sign in to comment.