about summary refs log tree commit diff
path: root/src/rustc
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2012-03-14 14:05:57 -0700
committerPatrick Walton <pcwalton@mimiga.net>2012-03-14 14:05:57 -0700
commit715d1995d7fdb28caeaa5401e1dbdbb3751bee60 (patch)
treea482976575fd953756699405f6760b05b79a9713 /src/rustc
parent3a45f87620eb04242a63544b872ed1807cd38c72 (diff)
rustc: Make the self region work properly in enums
Diffstat (limited to 'src/rustc')
-rw-r--r--src/rustc/middle/typeck.rs132
1 files changed, 91 insertions, 41 deletions
diff --git a/src/rustc/middle/typeck.rs b/src/rustc/middle/typeck.rs
index 74f8fcca4ad..cee041c6f8b 100644
--- a/src/rustc/middle/typeck.rs
+++ b/src/rustc/middle/typeck.rs
@@ -1442,25 +1442,49 @@ fn valid_range_bounds(tcx: ty::ctxt, from: @ast::expr, to: @ast::expr)
     ast_util::compare_lit_exprs(tcx, from, to) <= 0
 }
 
-fn check_pat_variant(fcx: @fn_ctxt, map: pat_util::pat_id_map,
-                     pat: @ast::pat, path: @ast::path, subpats: [@ast::pat],
-                     expected: ty::t) {
+type pat_ctxt = {
+    fcx: @fn_ctxt,
+    map: pat_util::pat_id_map,
+    alt_region: ty::region,
+    block_region: ty::region,
+    /* Equal to either alt_region or block_region. */
+    pat_region: ty::region
+};
+
+fn instantiate_self_regions(pcx: pat_ctxt, args: [ty::t]) -> [ty::t] {
+    vec::map(args, {|arg_ty|
+        if ty::type_has_rptrs(arg_ty) {
+            ty::fold_ty(pcx.fcx.ccx.tcx, ty::fm_rptr({|r|
+                alt r {
+                    ty::re_inferred | ty::re_caller(_) { pcx.pat_region }
+                    _ { r }
+                }
+            }), arg_ty)
+        } else {
+            arg_ty
+        }
+    })
+}
+
+fn check_pat_variant(pcx: pat_ctxt, pat: @ast::pat, path: @ast::path,
+                     subpats: [@ast::pat], expected: ty::t) {
     // Typecheck the path.
-    let tcx = fcx.ccx.tcx;
-    let v_def = lookup_def(fcx, path.span, pat.id);
+    let tcx = pcx.fcx.ccx.tcx;
+    let v_def = lookup_def(pcx.fcx, path.span, pat.id);
     let v_def_ids = ast_util::variant_def_ids(v_def);
     let ctor_tpt = ty::lookup_item_type(tcx, v_def_ids.enm);
-    instantiate_path(fcx, path, ctor_tpt, pat.span, pat.id);
+    instantiate_path(pcx.fcx, path, ctor_tpt, pat.span, pat.id);
 
     // Take the enum type params out of `expected`.
-    alt structure_of(fcx, pat.span, expected) {
+    alt structure_of(pcx.fcx, pat.span, expected) {
       ty::ty_enum(_, expected_tps) {
         let ctor_ty = ty::node_id_to_type(tcx, pat.id);
-        demand::with_substs(fcx, pat.span, expected, ctor_ty,
+        demand::with_substs(pcx.fcx, pat.span, expected, ctor_ty,
                             expected_tps);
         // Get the number of arguments in this enum variant.
-        let arg_types = variant_arg_types(fcx.ccx, pat.span,
+        let arg_types = variant_arg_types(pcx.fcx.ccx, pat.span,
                                           v_def_ids.var, expected_tps);
+        arg_types = instantiate_self_regions(pcx, arg_types);
         let subpats_len = subpats.len(), arg_len = arg_types.len();
         if arg_len > 0u {
             // N-ary variant.
@@ -1475,7 +1499,7 @@ fn check_pat_variant(fcx: @fn_ctxt, map: pat_util::pat_id_map,
             }
 
             vec::iter2(subpats, arg_types) {|subpat, arg_ty|
-                check_pat(fcx, map, subpat, arg_ty);
+                check_pat(pcx, subpat, arg_ty);
             }
         } else if subpats_len > 0u {
             tcx.sess.span_err
@@ -1497,23 +1521,23 @@ fn check_pat_variant(fcx: @fn_ctxt, map: pat_util::pat_id_map,
 
 // Pattern checking is top-down rather than bottom-up so that bindings get
 // their types immediately.
-fn check_pat(fcx: @fn_ctxt, map: pat_util::pat_id_map, pat: @ast::pat,
-             expected: ty::t) {
-    let tcx = fcx.ccx.tcx;
+fn check_pat(pcx: pat_ctxt, pat: @ast::pat, expected: ty::t) {
+    let tcx = pcx.fcx.ccx.tcx;
     alt pat.node {
       ast::pat_wild {
         write_ty(tcx, pat.id, expected);
       }
       ast::pat_lit(lt) {
-        check_expr_with(fcx, lt, expected);
+        check_expr_with(pcx.fcx, lt, expected);
         write_ty(tcx, pat.id, expr_ty(tcx, lt));
       }
       ast::pat_range(begin, end) {
-        check_expr_with(fcx, begin, expected);
-        check_expr_with(fcx, end, expected);
-        let b_ty = resolve_type_vars_if_possible(fcx, expr_ty(tcx, begin));
+        check_expr_with(pcx.fcx, begin, expected);
+        check_expr_with(pcx.fcx, end, expected);
+        let b_ty = resolve_type_vars_if_possible(pcx.fcx,
+                                                 expr_ty(tcx, begin));
         if !ty::same_type(tcx, b_ty, resolve_type_vars_if_possible(
-            fcx, expr_ty(tcx, end))) {
+            pcx.fcx, expr_ty(tcx, end))) {
             tcx.sess.span_err(pat.span, "mismatched types in range");
         } else if !ty::type_is_numeric(b_ty) {
             tcx.sess.span_err(pat.span, "non-numeric type used in range");
@@ -1525,29 +1549,30 @@ fn check_pat(fcx: @fn_ctxt, map: pat_util::pat_id_map, pat: @ast::pat,
       }
       ast::pat_ident(name, sub)
       if !pat_util::pat_is_variant(tcx.def_map, pat) {
-        let vid = lookup_local(fcx, pat.span, pat.id);
+        let vid = lookup_local(pcx.fcx, pat.span, pat.id);
         let typ = ty::mk_var(tcx, vid);
-        typ = demand::simple(fcx, pat.span, expected, typ);
-        let canon_id = map.get(path_to_ident(name));
+        typ = demand::simple(pcx.fcx, pat.span, expected, typ);
+        let canon_id = pcx.map.get(path_to_ident(name));
         if canon_id != pat.id {
-            let ct = ty::mk_var(tcx, lookup_local(fcx, pat.span, canon_id));
-            typ = demand::simple(fcx, pat.span, ct, typ);
+            let tv_id = lookup_local(pcx.fcx, pat.span, canon_id);
+            let ct = ty::mk_var(tcx, tv_id);
+            typ = demand::simple(pcx.fcx, pat.span, ct, typ);
         }
         write_ty(tcx, pat.id, typ);
         alt sub {
-          some(p) { check_pat(fcx, map, p, expected); }
+          some(p) { check_pat(pcx, p, expected); }
           _ {}
         }
       }
       ast::pat_ident(path, _) {
-        check_pat_variant(fcx, map, pat, path, [], expected);
+        check_pat_variant(pcx, pat, path, [], expected);
       }
       ast::pat_enum(path, subpats) {
-        check_pat_variant(fcx, map, pat, path, subpats, expected);
+        check_pat_variant(pcx, pat, path, subpats, expected);
       }
       ast::pat_rec(fields, etc) {
         let ex_fields;
-        alt structure_of(fcx, pat.span, expected) {
+        alt structure_of(pcx.fcx, pat.span, expected) {
           ty::ty_rec(fields) { ex_fields = fields; }
           _ {
             tcx.sess.span_fatal
@@ -1570,7 +1595,9 @@ fn check_pat(fcx: @fn_ctxt, map: pat_util::pat_id_map, pat: @ast::pat,
         }
         for f: ast::field_pat in fields {
             alt vec::find(ex_fields, bind matches(f.ident, _)) {
-              some(field) { check_pat(fcx, map, f.pat, field.mt.ty); }
+              some(field) {
+                check_pat(pcx, f.pat, field.mt.ty);
+              }
               none {
                 tcx.sess.span_fatal(pat.span,
                                     #fmt["mismatched types: did not \
@@ -1583,7 +1610,7 @@ fn check_pat(fcx: @fn_ctxt, map: pat_util::pat_id_map, pat: @ast::pat,
       }
       ast::pat_tup(elts) {
         let ex_elts;
-        alt structure_of(fcx, pat.span, expected) {
+        alt structure_of(pcx.fcx, pat.span, expected) {
           ty::ty_tup(elts) { ex_elts = elts; }
           _ {
             tcx.sess.span_fatal
@@ -1600,13 +1627,17 @@ fn check_pat(fcx: @fn_ctxt, map: pat_util::pat_id_map, pat: @ast::pat,
                       fields", vec::len(ex_elts), e_count]);
         }
         let i = 0u;
-        for elt in elts { check_pat(fcx, map, elt, ex_elts[i]); i += 1u; }
+        for elt in elts {
+            check_pat(pcx, elt, ex_elts[i]);
+            i += 1u;
+        }
+
         write_ty(tcx, pat.id, expected);
       }
       ast::pat_box(inner) {
-        alt structure_of(fcx, pat.span, expected) {
+        alt structure_of(pcx.fcx, pat.span, expected) {
           ty::ty_box(e_inner) {
-            check_pat(fcx, map, inner, e_inner.ty);
+            check_pat(pcx, inner, e_inner.ty);
             write_ty(tcx, pat.id, expected);
           }
           _ {
@@ -1618,9 +1649,9 @@ fn check_pat(fcx: @fn_ctxt, map: pat_util::pat_id_map, pat: @ast::pat,
         }
       }
       ast::pat_uniq(inner) {
-        alt structure_of(fcx, pat.span, expected) {
+        alt structure_of(pcx.fcx, pat.span, expected) {
           ty::ty_uniq(e_inner) {
-            check_pat(fcx, map, inner, e_inner.ty);
+            check_pat(pcx, inner, e_inner.ty);
             write_ty(tcx, pat.id, expected);
           }
           _ {
@@ -2454,16 +2485,25 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
           write_ty(tcx, id, ty::mk_nil(tcx));
           bot = !may_break(body);
       }
-      ast::expr_alt(expr, arms, _) {
-        bot = check_expr(fcx, expr);
+      ast::expr_alt(discrim, arms, _) {
+        bot = check_expr(fcx, discrim);
+
+        let parent_block = tcx.region_map.rvalue_to_block.get(expr.id);
 
         // Typecheck the patterns first, so that we get types for all the
         // bindings.
-        let pattern_ty = ty::expr_ty(tcx, expr);
+        let pattern_ty = ty::expr_ty(tcx, discrim);
         for arm: ast::arm in arms {
-            let id_map = pat_util::pat_id_map(tcx.def_map, arm.pats[0]);
+            let pcx = {
+                fcx: fcx,
+                map: pat_util::pat_id_map(tcx.def_map, arm.pats[0]),
+                alt_region: ty::re_block(parent_block),
+                block_region: ty::re_block(arm.body.node.id),
+                pat_region: ty::re_block(parent_block)
+            };
+
             for p: @ast::pat in arm.pats {
-                check_pat(fcx, id_map, p, pattern_ty);
+                check_pat(pcx, p, pattern_ty);
             }
         }
         // Now typecheck the blocks.
@@ -2797,8 +2837,18 @@ fn check_decl_local(fcx: @fn_ctxt, local: @ast::local) -> bool {
       }
       _ {/* fall through */ }
     }
-    let id_map = pat_util::pat_id_map(fcx.ccx.tcx.def_map, local.node.pat);
-    check_pat(fcx, id_map, local.node.pat, t);
+
+    let block_id = fcx.ccx.tcx.region_map.rvalue_to_block.get(local.node.id);
+    let region = ty::re_block(block_id);
+    let pcx = {
+        fcx: fcx,
+        map: pat_util::pat_id_map(fcx.ccx.tcx.def_map, local.node.pat),
+        alt_region: region,
+        block_region: region,
+        pat_region: region
+    };
+
+    check_pat(pcx, local.node.pat, t);
     ret bot;
 }