about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/rustc/middle/borrowck/gather_loans.rs76
-rw-r--r--src/rustc/middle/typeck/check/method.rs29
-rw-r--r--src/rustc/middle/typeck/check/regionck.rs38
-rw-r--r--src/rustc/middle/typeck/infer/region_var_bindings.rs2
4 files changed, 101 insertions, 44 deletions
diff --git a/src/rustc/middle/borrowck/gather_loans.rs b/src/rustc/middle/borrowck/gather_loans.rs
index f5552515142..109c1f63644 100644
--- a/src/rustc/middle/borrowck/gather_loans.rs
+++ b/src/rustc/middle/borrowck/gather_loans.rs
@@ -338,39 +338,49 @@ impl gather_loan_ctxt {
             };
 
             match result {
-              Ok(pc_ok) => {
-                // we were able guarantee the validity of the ptr,
-                // perhaps by rooting or because it is immutably
-                // rooted.  good.
-                self.bccx.stable_paths += 1;
-              }
-              Ok(pc_if_pure(e)) => {
-                // we are only able to guarantee the validity if
-                // the scope is pure
-                match scope_r {
-                  ty::re_scope(pure_id) => {
-                    // if the scope is some block/expr in the fn,
-                    // then just require that this scope be pure
-                    self.req_maps.pure_map.insert(pure_id, e);
-                    self.bccx.req_pure_paths += 1;
-
-                    if self.tcx().sess.borrowck_note_pure() {
-                        self.bccx.span_note(
-                            cmt.span,
-                            fmt!("purity required"));
+                Ok(pc_ok) => {
+                    debug!("result of preserve: pc_ok");
+
+                    // we were able guarantee the validity of the ptr,
+                    // perhaps by rooting or because it is immutably
+                    // rooted.  good.
+                    self.bccx.stable_paths += 1;
+                }
+                Ok(pc_if_pure(e)) => {
+                    debug!("result of preserve: %?", pc_if_pure(e));
+
+                    // we are only able to guarantee the validity if
+                    // the scope is pure
+                    match scope_r {
+                        ty::re_scope(pure_id) => {
+                            // if the scope is some block/expr in the
+                            // fn, then just require that this scope
+                            // be pure
+                            self.req_maps.pure_map.insert(pure_id, e);
+                            self.bccx.req_pure_paths += 1;
+
+                            debug!("requiring purity for scope %?",
+                                   scope_r);
+
+                            if self.tcx().sess.borrowck_note_pure() {
+                                self.bccx.span_note(
+                                    cmt.span,
+                                    fmt!("purity required"));
+                            }
+                        }
+                        _ => {
+                            // otherwise, we can't enforce purity for
+                            // that scope, so give up and report an
+                            // error
+                            self.bccx.report(e);
+                        }
                     }
-                  }
-                  _ => {
-                    // otherwise, we can't enforce purity for that
-                    // scope, so give up and report an error
+                }
+                Err(e) => {
+                    // we cannot guarantee the validity of this pointer
+                    debug!("result of preserve: error");
                     self.bccx.report(e);
-                  }
                 }
-              }
-              Err(e) => {
-                // we cannot guarantee the validity of this pointer
-                self.bccx.report(e);
-              }
             }
           }
         }
@@ -386,13 +396,19 @@ impl gather_loan_ctxt {
     // mutable memory.
     fn check_mutbl(req_mutbl: ast::mutability,
                    cmt: cmt) -> bckres<preserve_condition> {
+        debug!("check_mutbl(req_mutbl=%?, cmt.mutbl=%?)",
+               req_mutbl, cmt.mutbl);
+
         if req_mutbl == m_const || req_mutbl == cmt.mutbl {
+            debug!("required is const or they are the same");
             Ok(pc_ok)
         } else {
             let e = {cmt: cmt,
                      code: err_mutbl(req_mutbl)};
             if req_mutbl == m_imm {
                 // you can treat mutable things as imm if you are pure
+                debug!("imm required, must be pure");
+
                 Ok(pc_if_pure(e))
             } else {
                 Err(e)
diff --git a/src/rustc/middle/typeck/check/method.rs b/src/rustc/middle/typeck/check/method.rs
index 21e58b2dd21..0223fed3837 100644
--- a/src/rustc/middle/typeck/check/method.rs
+++ b/src/rustc/middle/typeck/check/method.rs
@@ -758,6 +758,9 @@ impl LookupContext {
     }
 
     fn is_relevant(&self, self_ty: ty::t, candidate: &Candidate) -> bool {
+        debug!("is_relevant(self_ty=%s, candidate=%s)",
+               self.ty_to_str(self_ty), self.cand_to_str(candidate));
+
         self.fcx.can_mk_subty(self_ty, candidate.rcvr_ty).is_ok()
     }
 
@@ -782,7 +785,7 @@ impl LookupContext {
         }
     }
 
-    fn report_candidate(idx: uint, origin: &method_origin) {
+    fn report_candidate(&self, idx: uint, origin: &method_origin) {
         match *origin {
             method_static(impl_did) => {
                 self.report_static_candidate(idx, impl_did)
@@ -796,7 +799,7 @@ impl LookupContext {
         }
     }
 
-    fn report_static_candidate(idx: uint, did: def_id) {
+    fn report_static_candidate(&self, idx: uint, did: def_id) {
         let span = if did.crate == ast::local_crate {
             match self.tcx().items.get(did.node) {
               ast_map::node_method(m, _, _) => m.span,
@@ -812,7 +815,7 @@ impl LookupContext {
                  ty::item_path_str(self.tcx(), did)));
     }
 
-    fn report_param_candidate(idx: uint, did: def_id) {
+    fn report_param_candidate(&self, idx: uint, did: def_id) {
         self.tcx().sess.span_note(
             self.expr.span,
             fmt!("candidate #%u derives from the bound `%s`",
@@ -820,7 +823,7 @@ impl LookupContext {
                  ty::item_path_str(self.tcx(), did)));
     }
 
-    fn report_trait_candidate(idx: uint, did: def_id) {
+    fn report_trait_candidate(&self, idx: uint, did: def_id) {
         self.tcx().sess.span_note(
             self.expr.span,
             fmt!("candidate #%u derives from the type of the receiver, \
@@ -829,23 +832,31 @@ impl LookupContext {
                  ty::item_path_str(self.tcx(), did)));
     }
 
-    fn infcx() -> infer::infer_ctxt {
+    fn infcx(&self) -> infer::infer_ctxt {
         self.fcx.inh.infcx
     }
 
-    fn tcx() -> ty::ctxt {
+    fn tcx(&self) -> ty::ctxt {
         self.fcx.tcx()
     }
 
-    fn ty_to_str(t: ty::t) -> ~str {
+    fn ty_to_str(&self, t: ty::t) -> ~str {
         self.fcx.infcx().ty_to_str(t)
     }
 
-    fn did_to_str(did: def_id) -> ~str {
+    fn cand_to_str(&self, cand: &Candidate) -> ~str {
+        fmt!("Candidate(rcvr_ty=%s, rcvr_substs=%s, self_mode=%?, origin=%?)",
+             self.ty_to_str(cand.rcvr_ty),
+             ty::substs_to_str(self.tcx(), &cand.rcvr_substs),
+             cand.self_mode,
+             cand.origin)
+    }
+
+    fn did_to_str(&self, did: def_id) -> ~str {
         ty::item_path_str(self.tcx(), did)
     }
 
-    fn bug(s: ~str) -> ! {
+    fn bug(&self, s: ~str) -> ! {
         self.tcx().sess.bug(s)
     }
 }
diff --git a/src/rustc/middle/typeck/check/regionck.rs b/src/rustc/middle/typeck/check/regionck.rs
index d5c6be4116a..1eedb572d2c 100644
--- a/src/rustc/middle/typeck/check/regionck.rs
+++ b/src/rustc/middle/typeck/check/regionck.rs
@@ -159,8 +159,6 @@ fn visit_expr(expr: @ast::expr, &&rcx: @rcx, v: rvt) {
     debug!("visit_expr(e=%s)",
            pprust::expr_to_str(expr, rcx.fcx.tcx().sess.intr()));
 
-    // constrain_auto_ref(rcx, expr);
-
     match expr.node {
         ast::expr_path(*) => {
             // Avoid checking the use of local variables, as we
@@ -176,6 +174,36 @@ fn visit_expr(expr: @ast::expr, &&rcx: @rcx, v: rvt) {
             }
         }
 
+        ast::expr_call(callee, args, _) => {
+            // Check for a.b() where b is a method.  Ensure that
+            // any types in the callee are valid for the entire
+            // method call.
+
+            // FIXME(#3387)--we should really invoke
+            // `constrain_auto_ref()` on all exprs.  But that causes a
+            // lot of spurious errors because of how the region
+            // hierarchy is setup.
+            let tcx = rcx.fcx.tcx();
+            if rcx.fcx.ccx.method_map.contains_key(callee.id) {
+                match callee.node {
+                    ast::expr_field(base, _, _) => {
+                        constrain_auto_ref(rcx, base);
+                    }
+                    _ => {
+                        tcx.sess.span_bug(
+                            callee.span,
+                            ~"call of method that is not a field");
+                    }
+                }
+            } else {
+                constrain_auto_ref(rcx, callee);
+            }
+
+            for args.each |arg| {
+                constrain_auto_ref(rcx, arg);
+            }
+        }
+
         ast::expr_cast(source, _) => {
             // Determine if we are casting `source` to an trait
             // instance.  If so, we have to be sure that the type of
@@ -275,6 +303,8 @@ fn constrain_auto_ref(
      * function ensures that the lifetime of the resulting borrowed
      * ptr includes at least the expression `expr`. */
 
+    debug!("constrain_auto_ref(expr=%s)", rcx.fcx.expr_to_str(expr));
+
     let adjustment = rcx.fcx.inh.adjustments.find(expr.id);
     let region = match adjustment {
         Some(@{autoref: Some(ref auto_ref), _}) => auto_ref.region,
@@ -282,8 +312,8 @@ fn constrain_auto_ref(
     };
 
     let tcx = rcx.fcx.tcx();
-    let expr_region = ty::re_scope(expr.id);
-    match rcx.fcx.mk_subr(true, expr.span, expr_region, region) {
+    let encl_region = ty::encl_region(tcx, expr.id);
+    match rcx.fcx.mk_subr(true, expr.span, encl_region, region) {
         result::Ok(()) => {}
         result::Err(_) => {
             // In practice, this cannot happen: `region` is always a
diff --git a/src/rustc/middle/typeck/infer/region_var_bindings.rs b/src/rustc/middle/typeck/infer/region_var_bindings.rs
index eba683750fc..4f2eb7c7c75 100644
--- a/src/rustc/middle/typeck/infer/region_var_bindings.rs
+++ b/src/rustc/middle/typeck/infer/region_var_bindings.rs
@@ -583,7 +583,7 @@ impl RegionVarBindings {
     }
 
     fn resolve_var(rid: RegionVid) -> ty::region {
-        debug!("RegionVarBindings: resolve_var(%?)", rid);
+        debug!("RegionVarBindings: resolve_var(%?=%u)", rid, *rid);
         if self.values.is_empty() {
             self.tcx.sess.span_bug(
                 self.var_spans[*rid],