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; + Ok(pc_ok) => { + debug!("result of preserve: pc_ok"); - 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); - } + // 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); + } + } + } + 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 { + 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],