Skip to content

Commit 0434a9e

Browse files
committed
Extend region guarantor logic to handle autoref, which will
be necessary for reborrowing.
1 parent 159542b commit 0434a9e

File tree

1 file changed

+125
-83
lines changed

1 file changed

+125
-83
lines changed

src/librustc/middle/typeck/check/regionck.rs

Lines changed: 125 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,10 @@ fn encl_region_of_def(fcx: @fn_ctxt, def: ast::def) -> ty::Region {
7373
}
7474

7575
impl @rcx {
76-
fn resolve_type(unresolved_ty: ty::t) -> Option<ty::t> {
76+
fn resolve_type(unresolved_ty: ty::t) -> ty::t {
7777
/*!
7878
* Try to resolve the type for the given node, returning
79-
* None if an error results. Note that we never care
79+
* t_err if an error results. Note that we never care
8080
* about the details of the error, the same error will be
8181
* detected and reported in the writeback phase.
8282
*
@@ -104,13 +104,13 @@ impl @rcx {
104104
*/
105105
match resolve_type(self.fcx.infcx(), unresolved_ty,
106106
resolve_and_force_all_but_regions) {
107-
Ok(t) => Some(t),
108-
Err(_) => None
107+
Ok(t) => t,
108+
Err(_) => ty::mk_err(self.fcx.tcx())
109109
}
110110
}
111111

112112
/// Try to resolve the type for the given node.
113-
fn resolve_node_type(id: ast::node_id) -> Option<ty::t> {
113+
fn resolve_node_type(id: ast::node_id) -> ty::t {
114114
self.resolve_type(self.fcx.node_ty(id))
115115
}
116116
}
@@ -181,6 +181,12 @@ fn visit_block(b: ast::blk, &&rcx: @rcx, v: rvt) {
181181
fn visit_expr(expr: @ast::expr, &&rcx: @rcx, v: rvt) {
182182
debug!("visit_expr(e=%s)", rcx.fcx.expr_to_str(expr));
183183

184+
for rcx.fcx.inh.adjustments.find(expr.id).each |adjustment| {
185+
for adjustment.autoref.each |autoref| {
186+
guarantor::for_autoref(rcx, expr, *adjustment, autoref);
187+
}
188+
}
189+
184190
match /*bad*/copy expr.node {
185191
ast::expr_path(*) => {
186192
// Avoid checking the use of local variables, as we
@@ -250,15 +256,14 @@ fn visit_expr(expr: @ast::expr, &&rcx: @rcx, v: rvt) {
250256
// particular case. There is an extensive comment on the
251257
// function check_cast_for_escaping_regions() in kind.rs
252258
// explaining how it goes about doing that.
253-
for rcx.resolve_node_type(expr.id).each |target_ty| {
254-
match ty::get(*target_ty).sty {
255-
ty::ty_trait(_, _, vstore_slice(trait_region)) => {
256-
let source_ty = rcx.fcx.expr_ty(source);
257-
constrain_regions_in_type(rcx, trait_region,
258-
expr.span, source_ty);
259-
}
260-
_ => ()
259+
let target_ty = rcx.resolve_node_type(expr.id);
260+
match ty::get(target_ty).sty {
261+
ty::ty_trait(_, _, vstore_slice(trait_region)) => {
262+
let source_ty = rcx.fcx.expr_ty(source);
263+
constrain_regions_in_type(rcx, trait_region,
264+
expr.span, source_ty);
261265
}
266+
_ => ()
262267
}
263268
}
264269

@@ -271,16 +276,15 @@ fn visit_expr(expr: @ast::expr, &&rcx: @rcx, v: rvt) {
271276
}
272277

273278
ast::expr_fn(*) | ast::expr_fn_block(*) => {
274-
for rcx.resolve_node_type(expr.id).each |function_type| {
275-
match ty::get(*function_type).sty {
276-
ty::ty_fn(ref fn_ty) => {
277-
if fn_ty.meta.proto == ast::ProtoBorrowed {
278-
constrain_free_variables(
279-
rcx, fn_ty.meta.region, expr);
280-
}
279+
let function_type = rcx.resolve_node_type(expr.id);
280+
match ty::get(function_type).sty {
281+
ty::ty_fn(ref fn_ty) => {
282+
if fn_ty.meta.proto == ast::ProtoBorrowed {
283+
constrain_free_variables(
284+
rcx, fn_ty.meta.region, expr);
281285
}
282-
_ => ()
283286
}
287+
_ => ()
284288
}
285289
}
286290

@@ -409,15 +413,10 @@ fn constrain_regions_in_type_of_node(
409413
// Try to resolve the type. If we encounter an error, then typeck
410414
// is going to fail anyway, so just stop here and let typeck
411415
// report errors later on in the writeback phase.
412-
let ty = match rcx.resolve_node_type(id) {
413-
None => { return true; }
414-
Some(ty) => { ty }
415-
};
416-
416+
let ty = rcx.resolve_node_type(id);
417417
debug!("constrain_regions_in_type_of_node(\
418418
ty=%s, id=%d, encl_region=%?)",
419419
ty_to_str(tcx, ty), id, encl_region);
420-
421420
constrain_regions_in_type(rcx, encl_region, span, ty)
422421
}
423422

@@ -567,6 +566,30 @@ mod guarantor {
567566
}
568567
}
569568

569+
pub fn for_autoref(rcx: @rcx,
570+
expr: @ast::expr,
571+
adjustment: &ty::AutoAdjustment,
572+
autoref: &ty::AutoRef)
573+
{
574+
/*!
575+
*
576+
* Computes the guarantor for an expression that has an
577+
* autoref adjustment and links it to the lifetime of the
578+
* autoref. This is only important when auto re-borrowing
579+
* region pointers.
580+
*/
581+
582+
debug!("guarantor::for_autoref(expr=%s)", rcx.fcx.expr_to_str(expr));
583+
let _i = ::util::common::indenter();
584+
585+
let mut expr_ct = categorize_unadjusted(rcx, expr);
586+
expr_ct = apply_autoderefs(
587+
rcx, expr, adjustment.autoderefs, expr_ct);
588+
for expr_ct.cat.guarantor.each |g| {
589+
infallibly_mk_subr(rcx, true, expr.span, autoref.region, *g);
590+
}
591+
}
592+
570593
fn link(
571594
rcx: @rcx,
572595
span: span,
@@ -589,9 +612,10 @@ mod guarantor {
589612
// this routine is used for the result of ref bindings and &
590613
// expressions, both of which always yield a region variable, so
591614
// mk_subr should never fail.
592-
for rcx.resolve_node_type(id).each |rptr_ty| {
593-
debug!("rptr_ty=%s", ty_to_str(rcx.fcx.ccx.tcx, *rptr_ty));
594-
let r = ty::ty_region(*rptr_ty);
615+
let rptr_ty = rcx.resolve_node_type(id);
616+
if !ty::type_contains_err(rptr_ty) {
617+
debug!("rptr_ty=%s", ty_to_str(rcx.fcx.ccx.tcx, rptr_ty));
618+
let r = ty::ty_region(rptr_ty);
595619
infallibly_mk_subr(rcx, true, span, r, bound);
596620
}
597621
}
@@ -608,6 +632,11 @@ mod guarantor {
608632
pointer: PointerCat
609633
}
610634

635+
struct ExprCategorizationType {
636+
cat: ExprCategorization,
637+
ty: ty::t
638+
}
639+
611640
fn guarantor(rcx: @rcx, expr: @ast::expr) -> Option<ty::Region> {
612641
debug!("guarantor(expr=%s)", rcx.fcx.expr_to_str(expr));
613642
match expr.node {
@@ -683,52 +712,76 @@ mod guarantor {
683712
debug!("categorize(expr=%s)", rcx.fcx.expr_to_str(expr));
684713
let _i = ::util::common::indenter();
685714

686-
let tcx = rcx.fcx.ccx.tcx;
687-
if rcx.fcx.ccx.method_map.contains_key(expr.id) {
688-
debug!("method call");
689-
return id_categorization(rcx, None, expr.id);
690-
}
691-
692-
let expr_ty = match rcx.resolve_node_type(expr.id) {
693-
None => { return id_categorization(rcx, None, expr.id); }
694-
Some(t) => { t }
695-
};
696-
let mut cat = ExprCategorization {
697-
guarantor: guarantor(rcx, expr),
698-
pointer: pointer_categorize(expr_ty)
699-
};
700-
701-
debug!("before adjustments, cat=%?", cat);
715+
let mut expr_ct = categorize_unadjusted(rcx, expr);
716+
debug!("before adjustments, cat=%?", expr_ct.cat);
702717

703718
for rcx.fcx.inh.adjustments.find(expr.id).each |adjustment| {
704719
debug!("adjustment=%?", adjustment);
705-
for uint::range(0, adjustment.autoderefs) |_| {
706-
cat.guarantor = guarantor_of_deref(&cat);
707720

708-
match ty::deref(tcx, expr_ty, true) {
709-
Some(t) => {
710-
cat.pointer = pointer_categorize(t.ty);
711-
}
712-
None => {
713-
tcx.sess.span_bug(
714-
expr.span,
715-
fmt!("Autoderef but type not derefable: %s",
716-
ty_to_str(tcx, expr_ty)));
717-
}
718-
}
721+
expr_ct = apply_autoderefs(
722+
rcx, expr, adjustment.autoderefs, expr_ct);
719723

720-
debug!("autoderef, cat=%?", cat);
724+
for adjustment.autoref.each |autoref| {
725+
expr_ct.cat.guarantor = None;
726+
expr_ct.cat.pointer = BorrowedPointer(autoref.region);
727+
debug!("autoref, cat=%?", expr_ct.cat);
721728
}
729+
}
722730

723-
for adjustment.autoref.each |autoref| {
724-
cat.guarantor = None;
725-
cat.pointer = BorrowedPointer(autoref.region);
726-
debug!("autoref, cat=%?", cat);
731+
debug!("result=%?", expr_ct.cat);
732+
return expr_ct.cat;
733+
}
734+
735+
fn categorize_unadjusted(rcx: @rcx,
736+
expr: @ast::expr) -> ExprCategorizationType {
737+
debug!("categorize_unadjusted(expr=%s)", rcx.fcx.expr_to_str(expr));
738+
let _i = ::util::common::indenter();
739+
740+
let guarantor = {
741+
if rcx.fcx.ccx.method_map.contains_key(expr.id) {
742+
None
743+
} else {
744+
guarantor(rcx, expr)
727745
}
746+
};
747+
748+
let expr_ty = rcx.resolve_node_type(expr.id);
749+
ExprCategorizationType {
750+
cat: ExprCategorization {
751+
guarantor: guarantor,
752+
pointer: pointer_categorize(expr_ty)
753+
},
754+
ty: expr_ty
728755
}
756+
}
729757

730-
debug!("result=%?", cat);
731-
return cat;
758+
fn apply_autoderefs(
759+
+rcx: @rcx,
760+
+expr: @ast::expr,
761+
+autoderefs: uint,
762+
+ct: ExprCategorizationType) -> ExprCategorizationType
763+
{
764+
let mut ct = ct;
765+
let tcx = rcx.fcx.ccx.tcx;
766+
for uint::range(0, autoderefs) |_| {
767+
ct.cat.guarantor = guarantor_of_deref(&ct.cat);
768+
769+
match ty::deref(tcx, ct.ty, true) {
770+
Some(mt) => {
771+
ct.ty = mt.ty;
772+
ct.cat.pointer = pointer_categorize(ct.ty);
773+
}
774+
None => {
775+
tcx.sess.span_bug(
776+
expr.span,
777+
fmt!("Autoderef but type not derefable: %s",
778+
ty_to_str(tcx, ct.ty)));
779+
}
780+
}
781+
782+
debug!("autoderef, cat=%?", ct.cat);
783+
}
784+
return ct;
732785
}
733786

734787
fn pointer_categorize(ty: ty::t) -> PointerCat {
@@ -752,19 +805,6 @@ mod guarantor {
752805
}
753806
}
754807

755-
fn id_categorization(rcx: @rcx,
756-
guarantor: Option<ty::Region>,
757-
id: ast::node_id) -> ExprCategorization
758-
{
759-
let pointer = match rcx.resolve_node_type(id) {
760-
None => NotPointer,
761-
Some(t) => pointer_categorize(t)
762-
};
763-
764-
ExprCategorization {guarantor: guarantor,
765-
pointer: pointer}
766-
}
767-
768808
fn guarantor_of_deref(cat: &ExprCategorization) -> Option<ty::Region> {
769809
match cat.pointer {
770810
NotPointer => cat.guarantor,
@@ -824,16 +864,18 @@ mod guarantor {
824864
link_ref_bindings_in_pat(rcx, p, guarantor)
825865
}
826866
ast::pat_region(p) => {
827-
for rcx.resolve_node_type(pat.id).each |rptr_ty| {
828-
let r = ty::ty_region(*rptr_ty);
867+
let rptr_ty = rcx.resolve_node_type(pat.id);
868+
if !ty::type_contains_err(rptr_ty) {
869+
let r = ty::ty_region(rptr_ty);
829870
link_ref_bindings_in_pat(rcx, p, Some(r));
830871
}
831872
}
832873
ast::pat_lit(*) => {}
833874
ast::pat_range(*) => {}
834875
ast::pat_vec(ref ps, ref opt_tail_pat) => {
835-
for rcx.resolve_node_type(pat.id).each |vec_ty| {
836-
let vstore = ty::ty_vstore(*vec_ty);
876+
let vec_ty = rcx.resolve_node_type(pat.id);
877+
if !ty::type_contains_err(vec_ty) {
878+
let vstore = ty::ty_vstore(vec_ty);
837879
let guarantor1 = match vstore {
838880
ty::vstore_fixed(_) | ty::vstore_uniq => guarantor,
839881
ty::vstore_slice(r) => Some(r),

0 commit comments

Comments
 (0)