about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEduard-Mihai Burtescu <edy.burt@gmail.com>2017-05-20 23:52:52 +0300
committerEduard-Mihai Burtescu <edy.burt@gmail.com>2017-06-01 08:59:47 +0300
commit91d603a2a7ad6caed2275da0c7ae21d845ed72d1 (patch)
tree5813dcfc2005240f19eb62696800e735a711d7e2
parent4a754f224d2ec61268649bc2421b7843b686375b (diff)
downloadrust-91d603a2a7ad6caed2275da0c7ae21d845ed72d1.tar.gz
rust-91d603a2a7ad6caed2275da0c7ae21d845ed72d1.zip
rustc: move autoref and unsize from Adjust::DerefRef to Adjustment.
-rw-r--r--src/librustc/ich/impls_ty.rs6
-rw-r--r--src/librustc/middle/expr_use_visitor.rs29
-rw-r--r--src/librustc/middle/mem_categorization.rs9
-rw-r--r--src/librustc/ty/adjustment.rs169
-rw-r--r--src/librustc/ty/structural_impls.rs35
-rw-r--r--src/librustc_lint/builtin.rs2
-rw-r--r--src/librustc_lint/unused.rs24
-rw-r--r--src/librustc_mir/hair/cx/expr.rs113
-rw-r--r--src/librustc_passes/consts.rs2
-rw-r--r--src/librustc_typeck/check/callee.rs16
-rw-r--r--src/librustc_typeck/check/coercion.rs116
-rw-r--r--src/librustc_typeck/check/method/confirm.rs17
-rw-r--r--src/librustc_typeck/check/mod.rs40
-rw-r--r--src/librustc_typeck/check/op.rs8
-rw-r--r--src/librustc_typeck/check/regionck.rs8
15 files changed, 290 insertions, 304 deletions
diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs
index 22ef88e0e5a..f0fdb94b81b 100644
--- a/src/librustc/ich/impls_ty.rs
+++ b/src/librustc/ich/impls_ty.rs
@@ -100,16 +100,14 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::adjustment::Ad
             ty::adjustment::Adjust::UnsafeFnPointer |
             ty::adjustment::Adjust::ClosureFnPointer |
             ty::adjustment::Adjust::MutToConstPointer => {}
-            ty::adjustment::Adjust::DerefRef { ref autoderefs, ref autoref, unsize } => {
+            ty::adjustment::Adjust::Deref(ref autoderefs) => {
                 autoderefs.hash_stable(hcx, hasher);
-                autoref.hash_stable(hcx, hasher);
-                unsize.hash_stable(hcx, hasher);
             }
         }
     }
 }
 
-impl_stable_hash_for!(struct ty::adjustment::Adjustment<'tcx> { kind, target });
+impl_stable_hash_for!(struct ty::adjustment::Adjustment<'tcx> { kind, autoref, unsize, target });
 impl_stable_hash_for!(struct ty::adjustment::OverloadedDeref<'tcx> { region, mutbl, target });
 impl_stable_hash_for!(struct ty::UpvarId { var_id, closure_expr_id });
 impl_stable_hash_for!(struct ty::UpvarBorrow<'tcx> { kind, region });
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index f75f3a145f5..9120990777d 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -707,9 +707,9 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
         let infcx = self.mc.infcx;
         //NOTE(@jroesch): mixed RefCell borrow causes crash
         let adj = infcx.tables.borrow().adjustments.get(&expr.id).cloned();
-        let cmt_unadjusted =
-            return_if_err!(self.mc.cat_expr_unadjusted(expr));
+        let mut cmt = return_if_err!(self.mc.cat_expr_unadjusted(expr));
         if let Some(adjustment) = adj {
+            debug!("walk_adjustment expr={:?} adj={:?}", expr, adjustment);
             match adjustment.kind {
                 adjustment::Adjust::NeverToAny |
                 adjustment::Adjust::ReifyFnPointer |
@@ -718,23 +718,20 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
                 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");
-                    self.delegate_consume(expr.id, expr.span, cmt_unadjusted);
+                    self.delegate_consume(expr.id, expr.span, cmt);
+                    assert!(adjustment.autoref.is_none() && !adjustment.unsize);
+                    return;
                 }
-                adjustment::Adjust::DerefRef { ref autoderefs, autoref, unsize } => {
-                    debug!("walk_adjustment expr={:?} adj={:?}", expr, adjustment);
-
-                    let cmt_derefd =
-                        return_if_err!(self.walk_autoderefs(expr, cmt_unadjusted, autoderefs));
+                adjustment::Adjust::Deref(ref autoderefs) => {
+                    cmt = return_if_err!(self.walk_autoderefs(expr, cmt, autoderefs));
+                }
+            }
 
-                    let cmt_refd =
-                        self.walk_autoref(expr, cmt_derefd, autoref);
+            cmt = self.walk_autoref(expr, cmt, adjustment.autoref);
 
-                    if unsize {
-                        // Unsizing consumes the thin pointer and produces a fat one.
-                        self.delegate_consume(expr.id, expr.span, cmt_refd);
-                    }
-                }
+            if adjustment.unsize {
+                // Unsizing consumes the thin pointer and produces a fat one.
+                self.delegate_consume(expr.id, expr.span, cmt);
             }
         }
     }
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 68c56177490..707b52a1a22 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -475,11 +475,8 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
             Some(adjustment) => {
                 debug!("cat_expr({:?}): {:?}", adjustment, expr);
                 match adjustment.kind {
-                    adjustment::Adjust::DerefRef {
-                        ref autoderefs,
-                        autoref: None,
-                        unsize: false
-                    } => {
+                    adjustment::Adjust::Deref(ref autoderefs)
+                    if adjustment.autoref.is_none() && !adjustment.unsize => {
                         // Equivalent to *expr or something similar.
                         let mut cmt = self.cat_expr_unadjusted(expr)?;
                         debug!("cat_expr: autoderefs={:?}, cmt={:?}",
@@ -499,7 +496,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
                     adjustment::Adjust::UnsafeFnPointer |
                     adjustment::Adjust::ClosureFnPointer |
                     adjustment::Adjust::MutToConstPointer |
-                    adjustment::Adjust::DerefRef {..} => {
+                    adjustment::Adjust::Deref(_) => {
                         // Result is an rvalue.
                         let expr_ty = self.expr_ty_adjusted(expr)?;
                         Ok(self.cat_rvalue_node(expr.id(), expr.span(), expr_ty))
diff --git a/src/librustc/ty/adjustment.rs b/src/librustc/ty/adjustment.rs
index 55f85ef003b..e2e017e9f51 100644
--- a/src/librustc/ty/adjustment.rs
+++ b/src/librustc/ty/adjustment.rs
@@ -13,10 +13,83 @@ use hir::def_id::DefId;
 use ty::{self, Ty, TyCtxt, TypeAndMut};
 use ty::subst::Substs;
 
+
+/// Represents coercing a value to a different type of value.
+///
+/// We transform values by following the following steps in order:
+/// 1. Apply a step of `Adjust` (see its variants for details).
+/// 2. If `autoref` is `Some(_)`, then take the address and produce either a
+///    `&` or `*` pointer.
+/// 3. If `unsize` is `true`, 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 types 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
+/// `false`.
+///
+/// 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 dynamically sized one. E.g., &[i32; 4] -> &[i32] is
+/// represented by:
+///
+/// ```
+/// Adjustment {
+///     kind: Adjust::Deref(vec![None]),// &[i32; 4] -> [i32; 4]
+///     autoref: Some(AutoBorrow::Ref), // [i32; 4] -> &[i32; 4]
+///     unsize: true,                   // &[i32; 4] -> &[i32]
+///     target: `[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:
+///
+/// ```
+/// Adjustment {
+///     kind: Adjust::Deref(vec![]),
+///     autoref: None,
+///     unsize: true,
+///     target: `Box<[i32]>`,
+/// }
+/// ```
 #[derive(Clone, RustcEncodable, RustcDecodable)]
 pub struct Adjustment<'tcx> {
+    /// Step 1.
     pub kind: Adjust<'tcx>,
-    pub target: Ty<'tcx>
+
+    /// Step 2. Optionally produce a pointer/reference from the value.
+    pub 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.
+    pub unsize: bool,
+
+    pub target: Ty<'tcx>,
 }
 
 #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
@@ -36,103 +109,25 @@ pub enum Adjust<'tcx> {
     /// 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 through `self.autoderefs` steps (may be no steps).
-    /// 2. If `autoref` is `Some(_)`, then take the address and produce either a
-    ///    `&` or `*` pointer.
-    /// 3. If `unsize` is `true`, 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 types 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
-    /// `false`.
-    ///
-    /// 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 dynamically sized one. E.g., &[i32; 4] -> &[i32] is
-    /// represented by:
-    ///
-    /// ```
-    /// Adjustment {
-    ///     kind: Adjust::DerefRef {
-    ///         autoderefs: vec![None],         // &[i32; 4] -> [i32; 4]
-    ///         autoref: Some(AutoBorrow::Ref), // [i32; 4] -> &[i32; 4]
-    ///         unsize: true,                   // &[i32; 4] -> &[i32]
-    ///     },
-    ///     target: `[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:
-    ///
-    /// ```
-    /// Adjustment {
-    ///     Adjust::DerefRef {
-    ///         autoderefs: vec![],
-    ///         autoref: None,
-    ///         unsize: true,
-    ///     },
-    ///     target: `Box<[i32]>`,
-    /// }
-    /// ```
-    DerefRef {
-        /// Step 1. Apply a number of dereferences, producing an lvalue.
-        autoderefs: Vec<Option<OverloadedDeref<'tcx>>>,
-
-        /// 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,
-    }
+    /// Apply a number of dereferences, producing an lvalue,
+    /// if there are more than 0 dereferences.
+    Deref(Vec<Option<OverloadedDeref<'tcx>>>),
 }
 
 impl<'tcx> Adjustment<'tcx> {
     pub fn is_identity(&self) -> bool {
+        if self.autoref.is_some() || self.unsize {
+            return false;
+        }
         match self.kind {
             Adjust::NeverToAny => self.target.is_never(),
 
-            Adjust::DerefRef {
-                ref autoderefs,
-                autoref: None,
-                unsize: false
-            } if autoderefs.is_empty() => true,
+            Adjust::Deref(ref autoderefs) => autoderefs.is_empty(),
 
             Adjust::ReifyFnPointer |
             Adjust::UnsafeFnPointer |
             Adjust::ClosureFnPointer |
-            Adjust::MutToConstPointer |
-            Adjust::DerefRef {..} => false,
+            Adjust::MutToConstPointer => false,
         }
     }
 }
diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs
index 811b383324d..cd34ebc7650 100644
--- a/src/librustc/ty/structural_impls.rs
+++ b/src/librustc/ty/structural_impls.rs
@@ -224,8 +224,13 @@ impl<'a, 'tcx> Lift<'tcx> for ty::adjustment::Adjustment<'a> {
     type Lifted = ty::adjustment::Adjustment<'tcx>;
     fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
         tcx.lift(&self.kind).and_then(|kind| {
-            tcx.lift(&self.target).map(|target| {
-                ty::adjustment::Adjustment { kind, target }
+            tcx.lift(&(self.autoref, self.target)).map(|(autoref, target)| {
+                ty::adjustment::Adjustment {
+                    kind,
+                    autoref,
+                    unsize: self.unsize,
+                    target,
+                }
             })
         })
     }
@@ -245,12 +250,8 @@ impl<'a, 'tcx> Lift<'tcx> for ty::adjustment::Adjust<'a> {
                 Some(ty::adjustment::Adjust::ClosureFnPointer),
             ty::adjustment::Adjust::MutToConstPointer =>
                 Some(ty::adjustment::Adjust::MutToConstPointer),
-            ty::adjustment::Adjust::DerefRef { ref autoderefs, ref autoref, unsize } => {
-                tcx.lift(autoderefs).and_then(|autoderefs| {
-                    tcx.lift(autoref).map(|autoref| {
-                        ty::adjustment::Adjust::DerefRef { autoderefs, autoref, unsize }
-                    })
-                })
+            ty::adjustment::Adjust::Deref(ref autoderefs) => {
+                tcx.lift(autoderefs).map(ty::adjustment::Adjust::Deref)
             }
         }
     }
@@ -684,12 +685,16 @@ impl<'tcx> TypeFoldable<'tcx> for ty::adjustment::Adjustment<'tcx> {
     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
         ty::adjustment::Adjustment {
             kind: self.kind.fold_with(folder),
+            autoref: self.autoref.fold_with(folder),
+            unsize: self.unsize,
             target: self.target.fold_with(folder),
         }
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
-        self.kind.visit_with(visitor) || self.target.visit_with(visitor)
+        self.kind.visit_with(visitor) ||
+        self.autoref.visit_with(visitor) ||
+        self.target.visit_with(visitor)
     }
 }
 
@@ -701,12 +706,8 @@ impl<'tcx> TypeFoldable<'tcx> for ty::adjustment::Adjust<'tcx> {
             ty::adjustment::Adjust::UnsafeFnPointer |
             ty::adjustment::Adjust::ClosureFnPointer |
             ty::adjustment::Adjust::MutToConstPointer => self.clone(),
-            ty::adjustment::Adjust::DerefRef { ref autoderefs, ref autoref, unsize } => {
-                ty::adjustment::Adjust::DerefRef {
-                    autoderefs: autoderefs.fold_with(folder),
-                    autoref: autoref.fold_with(folder),
-                    unsize,
-                }
+            ty::adjustment::Adjust::Deref(ref autoderefs) => {
+                ty::adjustment::Adjust::Deref(autoderefs.fold_with(folder))
             }
         }
     }
@@ -718,8 +719,8 @@ impl<'tcx> TypeFoldable<'tcx> for ty::adjustment::Adjust<'tcx> {
             ty::adjustment::Adjust::UnsafeFnPointer |
             ty::adjustment::Adjust::ClosureFnPointer |
             ty::adjustment::Adjust::MutToConstPointer => false,
-            ty::adjustment::Adjust::DerefRef { ref autoderefs, ref autoref, unsize: _ } => {
-                autoderefs.visit_with(visitor) || autoref.visit_with(visitor)
+            ty::adjustment::Adjust::Deref(ref autoderefs) => {
+                autoderefs.visit_with(visitor)
             }
         }
     }
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index b0bfda4a658..e4a8a1267f0 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -890,7 +890,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion {
 
             // Check for overloaded autoderef method calls.
             if let Some(&Adjustment {
-                kind: Adjust::DerefRef { ref autoderefs, .. }, ..
+                kind: Adjust::Deref(ref autoderefs), ..
             }) = cx.tables.adjustments.get(&id) {
                 let mut source = cx.tables.expr_ty(expr);
                 for &overloaded in autoderefs {
diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs
index 93ff609a280..4db27647d42 100644
--- a/src/librustc_lint/unused.rs
+++ b/src/librustc_lint/unused.rs
@@ -469,20 +469,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAllocation {
         }
 
         if let Some(adjustment) = cx.tables.adjustments.get(&e.id) {
-            if let adjustment::Adjust::DerefRef { autoref, .. } = adjustment.kind {
-                match autoref {
-                    Some(adjustment::AutoBorrow::Ref(_, hir::MutImmutable)) => {
-                        cx.span_lint(UNUSED_ALLOCATION,
-                                     e.span,
-                                     "unnecessary allocation, use & instead");
-                    }
-                    Some(adjustment::AutoBorrow::Ref(_, hir::MutMutable)) => {
-                        cx.span_lint(UNUSED_ALLOCATION,
-                                     e.span,
-                                     "unnecessary allocation, use &mut instead");
-                    }
-                    _ => (),
+            match adjustment.autoref {
+                Some(adjustment::AutoBorrow::Ref(_, hir::MutImmutable)) => {
+                    cx.span_lint(UNUSED_ALLOCATION,
+                                 e.span,
+                                 "unnecessary allocation, use & instead");
                 }
+                Some(adjustment::AutoBorrow::Ref(_, hir::MutMutable)) => {
+                    cx.span_lint(UNUSED_ALLOCATION,
+                                 e.span,
+                                 "unnecessary allocation, use &mut instead");
+                }
+                _ => (),
             }
         }
     }
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index 05f6381d934..dbf35971fa3 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -86,8 +86,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
                     kind: ExprKind::Cast { source: expr.to_ref() },
                 };
             }
-            Some((&ty::adjustment::Adjust::DerefRef { ref autoderefs, autoref, unsize },
-                  adjusted_ty)) => {
+            Some((&ty::adjustment::Adjust::Deref(ref autoderefs), _)) => {
                 for &overloaded in autoderefs {
                     let source = expr.ty;
                     let target;
@@ -143,64 +142,66 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
                         kind: kind,
                     };
                 }
+            }
+        }
 
-                if let Some(autoref) = autoref {
-                    let adjusted_ty = expr.ty.adjust_for_autoref(cx.tcx, Some(autoref));
-                    match autoref {
-                        ty::adjustment::AutoBorrow::Ref(r, m) => {
-                            expr = Expr {
-                                temp_lifetime: temp_lifetime,
-                                temp_lifetime_was_shrunk: was_shrunk,
-                                ty: adjusted_ty,
-                                span: self.span,
-                                kind: ExprKind::Borrow {
-                                    region: r,
-                                    borrow_kind: to_borrow_kind(m),
-                                    arg: expr.to_ref(),
-                                },
-                            };
-                        }
-                        ty::adjustment::AutoBorrow::RawPtr(m) => {
-                            // Convert this to a suitable `&foo` and
-                            // then an unsafe coercion. Limit the region to be just this
-                            // expression.
-                            let region = ty::ReScope(expr_extent);
-                            let region = cx.tcx.mk_region(region);
-                            expr = Expr {
-                                temp_lifetime: temp_lifetime,
-                                temp_lifetime_was_shrunk: was_shrunk,
-                                ty: cx.tcx.mk_ref(region,
-                                                  ty::TypeAndMut {
-                                                      ty: expr.ty,
-                                                      mutbl: m,
-                                                  }),
-                                span: self.span,
-                                kind: ExprKind::Borrow {
-                                    region: region,
-                                    borrow_kind: to_borrow_kind(m),
-                                    arg: expr.to_ref(),
-                                },
-                            };
-                            expr = Expr {
-                                temp_lifetime: temp_lifetime,
-                                temp_lifetime_was_shrunk: was_shrunk,
-                                ty: adjusted_ty,
-                                span: self.span,
-                                kind: ExprKind::Cast { source: expr.to_ref() },
-                            };
-                        }
+        if let Some(adj) = adj {
+            if let Some(autoref) = adj.autoref {
+                let adjusted_ty = expr.ty.adjust_for_autoref(cx.tcx, Some(autoref));
+                match autoref {
+                    ty::adjustment::AutoBorrow::Ref(r, m) => {
+                        expr = Expr {
+                            temp_lifetime: temp_lifetime,
+                            temp_lifetime_was_shrunk: was_shrunk,
+                            ty: adjusted_ty,
+                            span: self.span,
+                            kind: ExprKind::Borrow {
+                                region: r,
+                                borrow_kind: to_borrow_kind(m),
+                                arg: expr.to_ref(),
+                            },
+                        };
+                    }
+                    ty::adjustment::AutoBorrow::RawPtr(m) => {
+                        // Convert this to a suitable `&foo` and
+                        // then an unsafe coercion. Limit the region to be just this
+                        // expression.
+                        let region = ty::ReScope(expr_extent);
+                        let region = cx.tcx.mk_region(region);
+                        expr = Expr {
+                            temp_lifetime: temp_lifetime,
+                            temp_lifetime_was_shrunk: was_shrunk,
+                            ty: cx.tcx.mk_ref(region,
+                                              ty::TypeAndMut {
+                                                    ty: expr.ty,
+                                                    mutbl: m,
+                                              }),
+                            span: self.span,
+                            kind: ExprKind::Borrow {
+                                region: region,
+                                borrow_kind: to_borrow_kind(m),
+                                arg: expr.to_ref(),
+                            },
+                        };
+                        expr = Expr {
+                            temp_lifetime: temp_lifetime,
+                            temp_lifetime_was_shrunk: was_shrunk,
+                            ty: adjusted_ty,
+                            span: self.span,
+                            kind: ExprKind::Cast { source: expr.to_ref() },
+                        };
                     }
                 }
+            }
 
-                if unsize {
-                    expr = Expr {
-                        temp_lifetime: temp_lifetime,
-                        temp_lifetime_was_shrunk: was_shrunk,
-                        ty: adjusted_ty,
-                        span: self.span,
-                        kind: ExprKind::Unsize { source: expr.to_ref() },
-                    };
-                }
+            if adj.unsize {
+                expr = Expr {
+                    temp_lifetime: temp_lifetime,
+                    temp_lifetime_was_shrunk: was_shrunk,
+                    ty: adj.target,
+                    span: self.span,
+                    kind: ExprKind::Unsize { source: expr.to_ref() },
+                };
             }
         }
 
diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs
index f73ae9d42f6..e7aa74494f9 100644
--- a/src/librustc_passes/consts.rs
+++ b/src/librustc_passes/consts.rs
@@ -449,7 +449,7 @@ fn check_adjustments<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Exp
         Some(&Adjust::ClosureFnPointer) |
         Some(&Adjust::MutToConstPointer) => {}
 
-        Some(&Adjust::DerefRef { ref autoderefs, .. }) => {
+        Some(&Adjust::Deref(ref autoderefs)) => {
             if autoderefs.iter().any(|overloaded| overloaded.is_some()) {
                 v.promotable = false;
             }
diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs
index b498d0f8082..579bcda8dc6 100644
--- a/src/librustc_typeck/check/callee.rs
+++ b/src/librustc_typeck/check/callee.rs
@@ -144,11 +144,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         self.try_overloaded_call_traits(call_expr, adjusted_ty).map(|(autoref, method)| {
             let autoderefs = autoderef.adjust_steps(LvaluePreference::NoPreference);
             self.apply_adjustment(callee_expr.id, Adjustment {
-                kind: Adjust::DerefRef {
-                    autoderefs,
-                    autoref,
-                    unsize: false
-                },
+                kind: Adjust::Deref(autoderefs),
+                autoref,
+                unsize: false,
                 target: method.sig.inputs()[0]
             });
             CallStep::Overloaded(method)
@@ -356,11 +354,9 @@ impl<'a, 'gcx, 'tcx> DeferredCallResolution<'gcx, 'tcx> {
                 fcx.demand_eqtype(self.call_expr.span, method_sig.output(), self.fn_sig.output());
 
                 fcx.apply_adjustment(self.callee_expr.id, Adjustment {
-                    kind: Adjust::DerefRef {
-                        autoderefs: self.autoderefs,
-                        autoref,
-                        unsize: false
-                    },
+                    kind: Adjust::Deref(self.autoderefs),
+                    autoref,
+                    unsize: false,
                     target: method_sig.inputs()[0]
                 });
 
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index 78559e470ae..dc373610814 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -108,23 +108,24 @@ fn coerce_mutbls<'tcx>(from_mutbl: hir::Mutability,
     }
 }
 
-fn identity<'tcx>() -> Adjust<'tcx> {
-    Adjust::DerefRef {
-        autoderefs: vec![],
+fn identity<'tcx>(target: Ty<'tcx>) -> Adjustment<'tcx> {
+    simple(Adjust::Deref(vec![]))(target)
+}
+
+fn simple<'tcx>(kind: Adjust<'tcx>) -> impl FnOnce(Ty<'tcx>) -> Adjustment<'tcx> {
+    move |target| Adjustment {
+        kind,
         autoref: None,
         unsize: false,
+        target
     }
 }
 
-fn success<'tcx>(kind: Adjust<'tcx>,
-                 target: Ty<'tcx>,
+fn success<'tcx>(adj: Adjustment<'tcx>,
                  obligations: traits::PredicateObligations<'tcx>)
                  -> CoerceResult<'tcx> {
     Ok(InferOk {
-        value: Adjustment {
-            kind,
-            target
-        },
+        value: adj,
         obligations
     })
 }
@@ -150,10 +151,12 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
     }
 
     /// Unify two types (using sub or lub) and produce a specific coercion.
-    fn unify_and(&self, a: Ty<'tcx>, b: Ty<'tcx>, kind: Adjust<'tcx>)
-                 -> CoerceResult<'tcx> {
+    fn unify_and<F>(&self, a: Ty<'tcx>, b: Ty<'tcx>, f: F)
+                    -> CoerceResult<'tcx>
+        where F: FnOnce(Ty<'tcx>) -> Adjustment<'tcx>
+    {
         self.unify(&a, &b).and_then(|InferOk { value: ty, obligations }| {
-            success(kind, ty, obligations)
+            success(f(ty), obligations)
         })
     }
 
@@ -163,7 +166,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
 
         // Just ignore error types.
         if a.references_error() || b.references_error() {
-            return success(identity(), b, vec![]);
+            return success(identity(b), vec![]);
         }
 
         if a.is_never() {
@@ -180,9 +183,9 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
                 // already resolved in some way.
                 let diverging_ty = self.next_diverging_ty_var(
                     TypeVariableOrigin::AdjustmentType(self.cause.span));
-                self.unify_and(&b, &diverging_ty, Adjust::NeverToAny)
+                self.unify_and(&b, &diverging_ty, simple(Adjust::NeverToAny))
             } else {
-                success(Adjust::NeverToAny, b, vec![])
+                success(simple(Adjust::NeverToAny)(b), vec![])
             };
         }
 
@@ -231,7 +234,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
             }
             _ => {
                 // Otherwise, just use unification rules.
-                self.unify_and(a, b, identity())
+                self.unify_and(a, b, identity)
             }
         }
     }
@@ -259,7 +262,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
                 coerce_mutbls(mt_a.mutbl, mt_b.mutbl)?;
                 (r_a, mt_a)
             }
-            _ => return self.unify_and(a, b, identity()),
+            _ => return self.unify_and(a, b, identity),
         };
 
         let span = self.cause.span;
@@ -404,7 +407,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
             // `self.x`, but we auto-coerce it to `foo(&mut *self.x)`,
             // which is a borrow.
             assert_eq!(mt_b.mutbl, hir::MutImmutable); // can only coerce &T -> &U
-            return success(identity(), ty, obligations);
+            return success(identity(ty), obligations);
         }
 
         // Now apply the autoref. We have to extract the region out of
@@ -426,11 +429,12 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
                autoderefs,
                autoref);
 
-        success(Adjust::DerefRef {
-            autoderefs,
+        success(Adjustment {
+            kind: Adjust::Deref(autoderefs),
             autoref,
             unsize: false,
-        }, ty, obligations)
+            target: ty
+        }, obligations)
     }
 
 
@@ -471,19 +475,18 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
         };
         let coerce_source = source.adjust_for_autoref(self.tcx, reborrow);
 
-        let adjust = Adjust::DerefRef {
-            autoderefs: if reborrow.is_some() { vec![None] } else { vec![] },
-            autoref: reborrow,
-            unsize: true,
-        };
-
         // Setup either a subtyping or a LUB relationship between
         // the `CoerceUnsized` target type and the expected type.
         // We only have the latter, so we use an inference variable
         // for the former and let type inference do the rest.
         let origin = TypeVariableOrigin::MiscVariable(self.cause.span);
         let coerce_target = self.next_ty_var(origin);
-        let mut coercion = self.unify_and(coerce_target, target, adjust)?;
+        let mut coercion = self.unify_and(coerce_target, target, |target| Adjustment {
+            kind: Adjust::Deref(if reborrow.is_some() { vec![None] } else { vec![] }),
+            autoref: reborrow,
+            unsize: true,
+            target
+        })?;
 
         let mut selcx = traits::SelectionContext::new(self);
 
@@ -536,13 +539,16 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
         Ok(coercion)
     }
 
-    fn coerce_from_safe_fn(&self,
-                           a: Ty<'tcx>,
-                           fn_ty_a: ty::PolyFnSig<'tcx>,
-                           b: Ty<'tcx>,
-                           to_unsafe: Adjust<'tcx>,
-                           normal: Adjust<'tcx>)
-                           -> CoerceResult<'tcx> {
+    fn coerce_from_safe_fn<F, G>(&self,
+                                 a: Ty<'tcx>,
+                                 fn_ty_a: ty::PolyFnSig<'tcx>,
+                                 b: Ty<'tcx>,
+                                 to_unsafe: F,
+                                 normal: G)
+                                 -> CoerceResult<'tcx>
+        where F: FnOnce(Ty<'tcx>) -> Adjustment<'tcx>,
+              G: FnOnce(Ty<'tcx>) -> Adjustment<'tcx>
+    {
         if let ty::TyFnPtr(fn_ty_b) = b.sty {
             match (fn_ty_a.unsafety(), fn_ty_b.unsafety()) {
                 (hir::Unsafety::Normal, hir::Unsafety::Unsafe) => {
@@ -568,7 +574,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
         debug!("coerce_from_fn_pointer(a={:?}, b={:?})", a, b);
 
         self.coerce_from_safe_fn(a, fn_ty_a, b,
-            Adjust::UnsafeFnPointer, identity())
+            simple(Adjust::UnsafeFnPointer), identity)
     }
 
     fn coerce_from_fn_item(&self,
@@ -587,9 +593,9 @@ 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,
-                    Adjust::ReifyFnPointer, Adjust::ReifyFnPointer)
+                    simple(Adjust::ReifyFnPointer), simple(Adjust::ReifyFnPointer))
             }
-            _ => self.unify_and(a, b, identity()),
+            _ => self.unify_and(a, b, identity),
         }
     }
 
@@ -631,9 +637,9 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
                 let pointer_ty = self.tcx.mk_fn_ptr(converted_sig);
                 debug!("coerce_closure_to_fn(a={:?}, b={:?}, pty={:?})",
                        a, b, pointer_ty);
-                self.unify_and(pointer_ty, b, Adjust::ClosureFnPointer)
+                self.unify_and(pointer_ty, b, simple(Adjust::ClosureFnPointer))
             }
-            _ => self.unify_and(a, b, identity()),
+            _ => self.unify_and(a, b, identity),
         }
     }
 
@@ -648,7 +654,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
             ty::TyRef(_, mt) => (true, mt),
             ty::TyRawPtr(mt) => (false, mt),
             _ => {
-                return self.unify_and(a, b, identity());
+                return self.unify_and(a, b, identity);
             }
         };
 
@@ -661,17 +667,18 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
         // Although references and unsafe ptrs have the same
         // representation, we still register an Adjust::DerefRef so that
         // regionck knows that the region for `a` must be valid here.
-        self.unify_and(a_unsafe, b, if is_ref {
-            Adjust::DerefRef {
-                autoderefs: vec![None],
+        if is_ref {
+            self.unify_and(a_unsafe, b, |target| Adjustment {
+                kind: Adjust::Deref(vec![None]),
                 autoref: Some(AutoBorrow::RawPtr(mutbl_b)),
                 unsize: false,
-            }
+                target
+            })
         } else if mt_a.mutbl != mutbl_b {
-            Adjust::MutToConstPointer
+            self.unify_and(a_unsafe, b, simple(Adjust::MutToConstPointer))
         } else {
-            identity()
-        })
+            self.unify_and(a_unsafe, b, identity)
+        }
     }
 }
 
@@ -776,6 +783,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                     // `NeverToAny`, so this should always be valid.
                     self.apply_adjustment(expr.id, Adjustment {
                         kind: Adjust::ReifyFnPointer,
+                        autoref: None,
+                        unsize: false,
                         target: fn_ptr
                     });
                 }
@@ -808,11 +817,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         // previous expressions, other than noop reborrows (ignoring lifetimes).
         for expr in exprs {
             let expr = expr.as_coercion_site();
-            let noop = match self.tables.borrow().adjustments.get(&expr.id).map(|adj| &adj.kind) {
-                Some(&Adjust::DerefRef {
-                    ref autoderefs,
+            let noop = match self.tables.borrow().adjustments.get(&expr.id) {
+                Some(&Adjustment {
+                    kind: Adjust::Deref(ref autoderefs),
                     autoref: Some(AutoBorrow::Ref(_, mutbl_adj)),
-                    unsize: false
+                    unsize: false,
+                    target: _
                 }) if autoderefs.len() == 1 => {
                     match self.node_ty(expr.id).sty {
                         ty::TyRef(_, mt_orig) => {
@@ -824,7 +834,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                         _ => false,
                     }
                 }
-                Some(&Adjust::NeverToAny) => true,
+                Some(&Adjustment { kind: Adjust::NeverToAny, .. }) => true,
                 Some(_) => false,
                 None => true,
             };
diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs
index ad05a839189..bdbc7f677e4 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -147,12 +147,10 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
 
         // Write out the final adjustment.
         self.apply_adjustment(self.self_expr.id, Adjustment {
-            kind: Adjust::DerefRef {
-                autoderefs,
-                autoref,
-                unsize: pick.unsize.is_some(),
-            },
-            target: target
+            kind: Adjust::Deref(autoderefs),
+            autoref,
+            unsize: pick.unsize.is_some(),
+            target,
         });
 
         target
@@ -440,7 +438,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
             // the correct region.
             let expr_ty = self.node_ty(expr.id);
             if let Some(adj) = self.tables.borrow_mut().adjustments.get_mut(&expr.id) {
-                if let Adjust::DerefRef { ref mut autoderefs, .. } = adj.kind {
+                if let Adjust::Deref(ref mut autoderefs) = adj.kind {
                     let mut autoderef = self.autoderef(expr.span, expr_ty);
                     autoderef.nth(autoderefs.len()).unwrap_or_else(|| {
                         span_bug!(expr.span,
@@ -502,9 +500,8 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
         // Convert the autoref in the base expr to mutable with the correct
         // region and mutability.
         if let Some(&mut Adjustment {
-            ref mut target, kind: Adjust::DerefRef {
-                autoref: Some(AutoBorrow::Ref(ref mut r, ref mut mutbl)), ..
-            }
+            ref mut target,
+            autoref: Some(AutoBorrow::Ref(ref mut r, ref mut mutbl)), ..
         }) = self.tables.borrow_mut().adjustments.get_mut(&base_expr.id) {
             debug!("convert_lvalue_op_to_mutable: converting autoref of {:?}", target);
 
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index bc76c56599d..e6d43f00403 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -1779,11 +1779,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                       autoderefs: Vec<Option<OverloadedDeref<'tcx>>>,
                                       adjusted_ty: Ty<'tcx>) {
         self.apply_adjustment(node_id, Adjustment {
-            kind: Adjust::DerefRef {
-                autoderefs,
-                autoref: None,
-                unsize: false
-            },
+            kind: Adjust::Deref(autoderefs),
+            autoref: None,
+            unsize: false,
             target: adjusted_ty
         });
     }
@@ -1799,17 +1797,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             Entry::Vacant(entry) => { entry.insert(adj); },
             Entry::Occupied(mut entry) => {
                 debug!(" - composing on top of {:?}", entry.get());
-                match (&entry.get().kind, &adj.kind) {
+                match (entry.get(), &adj) {
                     // Applying any adjustment on top of a NeverToAny
                     // is a valid NeverToAny adjustment, because it can't
                     // be reached.
-                    (&Adjust::NeverToAny, _) => return,
-                    (&Adjust::DerefRef {
-                        autoderefs: ref old,
+                    (&Adjustment { kind: Adjust::NeverToAny, .. }, _) => return,
+                    (&Adjustment {
+                        kind: Adjust::Deref(ref old),
                         autoref: Some(AutoBorrow::Ref(..)),
-                        unsize: false
-                    }, &Adjust::DerefRef {
-                        autoderefs: ref new, ..
+                        unsize: false, ..
+                    }, &Adjustment {
+                        kind: Adjust::Deref(ref new), ..
                     }) if old.len() == 1 && new.len() >= 1 => {
                         // A reborrow has no effect before a dereference.
                     }
@@ -2235,11 +2233,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 
                 let autoderefs = autoderef.adjust_steps(lvalue_pref);
                 self.apply_adjustment(base_expr.id, Adjustment {
-                    kind: Adjust::DerefRef {
-                        autoderefs,
-                        autoref,
-                        unsize
-                    },
+                    kind: Adjust::Deref(autoderefs),
+                    autoref,
+                    unsize,
                     target: method.sig.inputs()[0]
                 });
 
@@ -2651,6 +2647,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 TypeVariableOrigin::AdjustmentType(expr.span));
             self.apply_adjustment(expr.id, Adjustment {
                 kind: Adjust::NeverToAny,
+                autoref: None,
+                unsize: false,
                 target: adj_ty
             });
             ty = adj_ty;
@@ -3450,11 +3448,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                 expr.span, oprnd_t, lvalue_pref) {
                             let (autoref, method) = self.register_infer_ok_obligations(ok);
                             self.apply_adjustment(oprnd.id, Adjustment {
-                                kind: Adjust::DerefRef {
-                                    autoderefs: vec![],
-                                    autoref,
-                                    unsize: false
-                                },
+                                kind: Adjust::Deref(vec![]),
+                                autoref,
+                                unsize: false,
                                 target: method.sig.inputs()[0]
                             });
                             oprnd_t = self.make_overloaded_lvalue_return_type(method).ty;
diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs
index 0c820d2404a..8d442aae70e 100644
--- a/src/librustc_typeck/check/op.rs
+++ b/src/librustc_typeck/check/op.rs
@@ -414,11 +414,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 self.select_obligations_where_possible();
 
                 self.apply_adjustment(lhs_expr.id, Adjustment {
-                    kind: Adjust::DerefRef {
-                        autoderefs: vec![],
-                        autoref,
-                        unsize: false
-                    },
+                    kind: Adjust::Deref(vec![]),
+                    autoref,
+                    unsize: false,
                     target: method.sig.inputs()[0]
                 });
                 self.write_method_call(expr.id, method);
diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs
index 7fff0ceb778..119ae748f85 100644
--- a/src/librustc_typeck/check/regionck.rs
+++ b/src/librustc_typeck/check/regionck.rs
@@ -546,9 +546,9 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> {
         if let Some(adjustment) = adjustment {
             debug!("adjustment={:?}", adjustment);
             match adjustment.kind {
-                adjustment::Adjust::DerefRef { ref autoderefs, ref autoref, .. } => {
+                adjustment::Adjust::Deref(ref autoderefs) => {
                     let cmt = ignore_err!(self.constrain_autoderefs(expr, autoderefs));
-                    if let Some(ref autoref) = *autoref {
+                    if let Some(ref autoref) = adjustment.autoref {
                         self.link_autoref(expr, cmt, autoref);
 
                         // Require that the resulting region encompasses
@@ -569,7 +569,9 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> {
                                            source_ty, bounds.region_bound);
                 }
                 */
-                _ => {}
+                _ => {
+                    assert!(adjustment.autoref.is_none());
+                }
             }
 
             // If necessary, constrain destructors in the unadjusted form of this