about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2015-01-07 10:53:09 -0500
committerNiko Matsakis <niko@alum.mit.edu>2015-01-08 09:19:07 -0500
commit0a32010e430006d3850b74976d7d7bf0dda699b4 (patch)
tree9a31823b2ff962dd601339a0ca091fee99228b37
parent5364c4853fa61aced8fdf773d9de41b929a0d318 (diff)
downloadrust-0a32010e430006d3850b74976d7d7bf0dda699b4.tar.gz
rust-0a32010e430006d3850b74976d7d7bf0dda699b4.zip
Add comments to autoderef() helper and refactor it to take
an `Option<&Expr>` like everything else.
-rw-r--r--src/librustc_typeck/check/method/confirm.rs12
-rw-r--r--src/librustc_typeck/check/method/mod.rs8
-rw-r--r--src/librustc_typeck/check/mod.rs49
-rw-r--r--src/librustc_typeck/check/regionck.rs10
4 files changed, 58 insertions, 21 deletions
diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs
index 7e72f300f41..79460774859 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -143,7 +143,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
         // time writing the results into the various tables.
         let (autoderefd_ty, n, result) =
             check::autoderef(
-                self.fcx, self.span, unadjusted_self_ty, Some(self.self_expr.id), NoPreference,
+                self.fcx, self.span, unadjusted_self_ty, Some(self.self_expr), NoPreference,
                 |_, n| if n == auto_deref_ref.autoderefs { Some(()) } else { None });
         assert_eq!(n, auto_deref_ref.autoderefs);
         assert_eq!(result, Some(()));
@@ -492,7 +492,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
                exprs.repr(self.tcx()));
 
         // Fix up autoderefs and derefs.
-        for (i, expr) in exprs.iter().rev().enumerate() {
+        for (i, &expr) in exprs.iter().rev().enumerate() {
             // Count autoderefs.
             let autoderef_count = match self.fcx
                                             .inh
@@ -512,8 +512,8 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
             if autoderef_count > 0 {
                 check::autoderef(self.fcx,
                                  expr.span,
-                                 self.fcx.expr_ty(*expr),
-                                 Some(expr.id),
+                                 self.fcx.expr_ty(expr),
+                                 Some(expr),
                                  PreferMutLvalue,
                                  |_, autoderefs| {
                                      if autoderefs == autoderef_count + 1 {
@@ -567,7 +567,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
                         let result = check::try_index_step(
                             self.fcx,
                             MethodCall::expr(expr.id),
-                            *expr,
+                            expr,
                             &**base_expr,
                             adjusted_base_ty,
                             base_adjustment,
@@ -577,7 +577,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
                         if let Some((input_ty, return_ty)) = result {
                             demand::suptype(self.fcx, index_expr.span, input_ty, index_expr_ty);
 
-                            let expr_ty = self.fcx.expr_ty(&**expr);
+                            let expr_ty = self.fcx.expr_ty(&*expr);
                             demand::suptype(self.fcx, expr.span, expr_ty, return_ty);
                         }
                     }
diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs
index bb000742def..0c53a16a811 100644
--- a/src/librustc_typeck/check/method/mod.rs
+++ b/src/librustc_typeck/check/method/mod.rs
@@ -102,9 +102,9 @@ pub fn lookup<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     Ok(confirm::confirm(fcx, span, self_expr, call_expr, self_ty, pick, supplied_method_types))
 }
 
-pub fn lookup_in_trait<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>,
+pub fn lookup_in_trait<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                  span: Span,
-                                 self_expr: Option<&'a ast::Expr>,
+                                 self_expr: Option<&ast::Expr>,
                                  m_name: ast::Name,
                                  trait_def_id: DefId,
                                  self_ty: Ty<'tcx>,
@@ -125,9 +125,9 @@ pub fn lookup_in_trait<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>,
 /// method-lookup code. In particular, autoderef on index is basically identical to autoderef with
 /// normal probes, except that the test also looks for built-in indexing. Also, the second half of
 /// this method is basically the same as confirmation.
-pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>,
+pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                           span: Span,
-                                          self_expr: Option<&'a ast::Expr>,
+                                          self_expr: Option<&ast::Expr>,
                                           m_name: ast::Name,
                                           trait_def_id: DefId,
                                           autoderefref: ty::AutoDerefRef<'tcx>,
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index b98b327100c..4ade11a9a83 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -2263,17 +2263,36 @@ pub enum LvaluePreference {
 /// Executes an autoderef loop for the type `t`. At each step, invokes `should_stop` to decide
 /// whether to terminate the loop. Returns the final type and number of derefs that it performed.
 ///
+<<<<<<< HEAD
 /// Note: this method does not modify the adjustments table. The caller is responsible for
 /// inserting an AutoAdjustment record into the `fcx` using one of the suitable methods.
 pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
                                  sp: Span,
+||||||| merged common ancestors
+/// Note: this method does not modify the adjustments table. The caller is responsible for
+/// inserting an AutoAdjustment record into the `fcx` using one of the suitable methods.
+pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
+=======
+/// Note: this method does not modify the adjustments table. The
+/// caller is responsible for inserting an AutoAdjustment record into
+/// the `fcx` using one of the suitable methods.  However, if
+/// `opt_expr` is not `None`, it *will* insert the appropriate method
+/// entries for the overloaded deref call.
+pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
+                                 sp: Span,
+>>>>>>> Add comments to autoderef() helper and refactor it to take
                                  base_ty: Ty<'tcx>,
-                                 expr_id: Option<ast::NodeId>,
+                                 opt_expr: Option<&ast::Expr>,
                                  mut lvalue_pref: LvaluePreference,
                                  mut should_stop: F)
-                                 -> (Ty<'tcx>, uint, Option<T>) where
-    F: FnMut(Ty<'tcx>, uint) -> Option<T>,
+                                 -> (Ty<'tcx>, uint, Option<T>)
+    where F: FnMut(Ty<'tcx>, uint) -> Option<T>,
 {
+    debug!("autoderef(base_ty={}, opt_expr={}, lvalue_pref={})",
+           base_ty.repr(fcx.tcx()),
+           opt_expr,
+           lvalue_pref);
+
     let mut t = base_ty;
     for autoderefs in range(0, fcx.tcx().sess.recursion_limit.get()) {
         let resolved_t = structurally_resolved_type(fcx, sp, t);
@@ -2291,7 +2310,19 @@ pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
         let mt = match ty::deref(resolved_t, false) {
             Some(mt) => Some(mt),
             None => {
-                let method_call = expr_id.map(|id| MethodCall::autoderef(id, autoderefs));
+                let method_call = opt_expr.map(|expr| MethodCall::autoderef(expr.id, autoderefs));
+
+                // Super subtle: it might seem as though we should
+                // pass `opt_expr` to `try_overloaded_deref`, so that
+                // the (implicit) autoref of using an overloaded deref
+                // would get added to the adjustment table. However we
+                // do not do that, because it's kind of a
+                // "meta-adjustment" -- instead, we just leave it
+                // unrecorded and know that there "will be" an
+                // autoref. regionck and other bits of the code base,
+                // when they encounter an overloaded autoderef, have
+                // to do some reconstructive surgery. This is a pretty
+                // complex mess that is begging for a proper MIR.
                 try_overloaded_deref(fcx, sp, method_call, None, resolved_t, lvalue_pref)
             }
         };
@@ -2324,7 +2355,7 @@ fn try_overloaded_deref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     // Try DerefMut first, if preferred.
     let method = match (lvalue_pref, fcx.tcx().lang_items.deref_mut_trait()) {
         (PreferMutLvalue, Some(trait_did)) => {
-            method::lookup_in_trait(fcx, span, base_expr.map(|x| &*x),
+            method::lookup_in_trait(fcx, span, base_expr,
                                     token::intern("deref_mut"), trait_did,
                                     base_ty, None)
         }
@@ -2334,7 +2365,7 @@ fn try_overloaded_deref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     // Otherwise, fall back to Deref.
     let method = match (method, fcx.tcx().lang_items.deref_trait()) {
         (None, Some(trait_did)) => {
-            method::lookup_in_trait(fcx, span, base_expr.map(|x| &*x),
+            method::lookup_in_trait(fcx, span, base_expr,
                                     token::intern("deref"), trait_did,
                                     base_ty, None)
         }
@@ -2390,7 +2421,7 @@ fn autoderef_for_index<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
     // consolidated.
 
     let (ty, autoderefs, final_mt) =
-        autoderef(fcx, base_expr.span, base_ty, Some(base_expr.id), lvalue_pref, |adj_ty, idx| {
+        autoderef(fcx, base_expr.span, base_ty, Some(base_expr), lvalue_pref, |adj_ty, idx| {
             let autoderefref = ty::AutoDerefRef { autoderefs: idx, autoref: None };
             step(adj_ty, autoderefref)
         });
@@ -3360,7 +3391,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                                                 fcx.expr_ty(base));
         // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
         let (_, autoderefs, field_ty) =
-            autoderef(fcx, expr.span, expr_t, Some(base.id), lvalue_pref, |base_t, _| {
+            autoderef(fcx, expr.span, expr_t, Some(base), lvalue_pref, |base_t, _| {
                 match base_t.sty {
                     ty::ty_struct(base_id, substs) => {
                         debug!("struct named {}", ppaux::ty_to_string(tcx, base_t));
@@ -3421,7 +3452,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
         let mut tuple_like = false;
         // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
         let (_, autoderefs, field_ty) =
-            autoderef(fcx, expr.span, expr_t, Some(base.id), lvalue_pref, |base_t, _| {
+            autoderef(fcx, expr.span, expr_t, Some(base), lvalue_pref, |base_t, _| {
                 match base_t.sty {
                     ty::ty_struct(base_id, substs) => {
                         tuple_like = ty::is_tuple_struct(tcx, base_id);
diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs
index 112e0053642..c74612d3aa8 100644
--- a/src/librustc_typeck/check/regionck.rs
+++ b/src/librustc_typeck/check/regionck.rs
@@ -1049,13 +1049,16 @@ fn type_of_node_must_outlive<'a, 'tcx>(
 /// Computes the guarantor for an expression `&base` and then ensures that the lifetime of the
 /// resulting pointer is linked to the lifetime of its guarantor (if any).
 fn link_addr_of(rcx: &mut Rcx, expr: &ast::Expr,
-               mutability: ast::Mutability, base: &ast::Expr) {
-    debug!("link_addr_of(base=?)");
+                mutability: ast::Mutability, base: &ast::Expr) {
+    debug!("link_addr_of(expr={}, base={})", expr.repr(rcx.tcx()), base.repr(rcx.tcx()));
 
     let cmt = {
         let mc = mc::MemCategorizationContext::new(rcx.fcx);
         ignore_err!(mc.cat_expr(base))
     };
+
+    debug!("link_addr_of: cmt={}", cmt.repr(rcx.tcx()));
+
     link_region_from_node_type(rcx, expr.span, expr.id, mutability, cmt);
 }
 
@@ -1182,6 +1185,9 @@ fn link_region_from_node_type<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
                                         id: ast::NodeId,
                                         mutbl: ast::Mutability,
                                         cmt_borrowed: mc::cmt<'tcx>) {
+    debug!("link_region_from_node_type(id={}, mutbl={}, cmt_borrowed={})",
+           id, mutbl, cmt_borrowed.repr(rcx.tcx()));
+
     let rptr_ty = rcx.resolve_node_type(id);
     if !ty::type_is_error(rptr_ty) {
         let tcx = rcx.fcx.ccx.tcx;