]> git.lizzy.rs Git - rust.git/commitdiff
Various regions fixes.
authorNiko Matsakis <niko@alum.mit.edu>
Sat, 21 Apr 2012 17:04:58 +0000 (10:04 -0700)
committerNiko Matsakis <niko@alum.mit.edu>
Mon, 23 Apr 2012 15:02:59 +0000 (08:02 -0700)
src/etc/indenter
src/rustc/middle/infer.rs
src/rustc/middle/ty.rs
src/rustc/middle/typeck.rs
src/test/compile-fail/regions-creating-enums3.rs [new file with mode: 0644]
src/test/compile-fail/regions-creating-enums4.rs [new file with mode: 0644]
src/test/run-pass/regions-creating-enums2.rs [new file with mode: 0644]
src/test/run-pass/regions-creating-enums5.rs [new file with mode: 0644]
src/test/run-pass/regions-nullary-variant.rs [new file with mode: 0644]

index 49fd73fcf725a00e8cc1f59960f998c12cf8c9a9..f2e41da9b4e44c674fab5194da5dee893205a9b0 100755 (executable)
@@ -6,10 +6,12 @@ my $indent = 0;
 while (<>) {
     if (/^rust: ">>/) {
         $indent += 1;
-    } elsif (/^rust: "<</) {
-        $indent -= 1;
     }
 
     printf "%03d  %s%s", $indent, ("  " x $indent), $_;
+
+    if (/^rust: "<</) {
+        $indent -= 1;
+    }
 }
 
index 9443cac0ea2a8f3ee94f379cfca8dda939eb7e3a..1e513d3da8c8ae3c1bc44b6cf3835da1ca2b2f48 100644 (file)
@@ -92,21 +92,19 @@ fn compare_tys(tcx: ty::ctxt, a: ty::t, b: ty::t) -> ures {
     mk_eqty(infcx, a, b)
 }
 
-// Resolves one level of type structure but not any type variables
-// that may be nested within.
-fn resolve_shallow(cx: infer_ctxt, a: ty::t) -> fres<ty::t> {
-    resolver(cx, false, false).resolve(a)
+// See comment on the type `resolve_state` below
+fn resolve_shallow(cx: infer_ctxt, a: ty::t,
+                   force_vars: bool) -> fres<ty::t> {
+    resolver(cx, false, force_vars).resolve(a)
 }
 
-// see resolve_deep()
+// See comment on the type `resolve_state` below
 fn resolve_deep_var(cx: infer_ctxt, vid: ty_vid,
                     force_vars: bool) -> fres<ty::t> {
     resolver(cx, true, force_vars).resolve(ty::mk_var(cx.tcx, vid))
 }
 
-// Resolves all levels of type structure.  If `force_vars` is true,
-// then we will resolve unconstrained type/region variables to
-// something arbitrary.  Otherwise, we preserve them as variables.
+// See comment on the type `resolve_state` below
 fn resolve_deep(cx: infer_ctxt, a: ty::t, force_vars: bool) -> fres<ty::t> {
     resolver(cx, true, force_vars).resolve(a)
 }
@@ -556,8 +554,12 @@ fn eq_tys(a: ty::t, b: ty::t) -> ures {
     }
 
     fn eq_regions(a: ty::region, b: ty::region) -> ures {
-        self.sub_regions(a, b).then {||
-            self.sub_regions(b, a)
+        #debug["eq_regions(%s, %s)",
+               a.to_str(self), b.to_str(self)];
+        indent {||
+            self.sub_regions(a, b).then {||
+                self.sub_regions(b, a)
+            }
         }
     }
 }
@@ -599,16 +601,20 @@ impl methods for resolve_state {
     fn resolve(typ: ty::t) -> fres<ty::t> {
         self.err = none;
 
+        #debug["Resolving %s (deep=%b, force_vars=%b)",
+               ty_to_str(self.infcx.tcx, typ),
+               self.deep,
+               self.force_vars];
+
         // n.b. This is a hokey mess because the current fold doesn't
         // allow us to pass back errors in any useful way.
 
         assert vec::is_empty(self.v_seen) && vec::is_empty(self.r_seen);
-        let rty = self.resolve1(typ);
+        let rty = indent {|| self.resolve1(typ) };
         assert vec::is_empty(self.v_seen) && vec::is_empty(self.r_seen);
         alt self.err {
           none {
-            #debug["Resolved %s to %s (deep=%b, force_vars=%b)",
-                   ty_to_str(self.infcx.tcx, typ),
+            #debug["Resolved to %s (deep=%b, force_vars=%b)",
                    ty_to_str(self.infcx.tcx, rty),
                    self.deep,
                    self.force_vars];
@@ -619,25 +625,32 @@ fn resolve(typ: ty::t) -> fres<ty::t> {
     }
 
     fn resolve1(typ: ty::t) -> ty::t {
-        let tb = ty::get(typ);
-        alt tb.struct {
-          ty::ty_var(vid) { self.resolve_ty_var(vid) }
-          _ if !tb.has_regions && !self.deep { typ }
-          _ {
-            ty::fold_regions_and_ty(
-                self.infcx.tcx, typ,
-                { |r| self.resolve_region(r) },
-                { |t| self.resolve_if_deep(t) },
-                { |t| self.resolve_if_deep(t) })
-          }
-        }
+        #debug("Resolve1(%s)", typ.to_str(self.infcx));
+        indent(fn&() -> ty::t {
+            if !ty::get(typ).has_vars { ret typ; }
+
+            let tb = ty::get(typ);
+            alt tb.struct {
+              ty::ty_var(vid) { self.resolve_ty_var(vid) }
+              _ if !tb.has_regions && !self.deep { typ }
+              _ {
+                ty::fold_regions_and_ty(
+                    self.infcx.tcx, typ,
+                    { |r| self.resolve_region(r) },
+                    { |t| self.resolve_if_deep(t) },
+                    { |t| self.resolve_if_deep(t) })
+              }
+            }
+        })
     }
 
     fn resolve_if_deep(typ: ty::t) -> ty::t {
+        #debug("Resolve_if_deep(%s)", typ.to_str(self.infcx));
         if !self.deep {typ} else {self.resolve1(typ)}
     }
 
     fn resolve_region(orig: ty::region) -> ty::region {
+        #debug("Resolve_region(%s)", orig.to_str(self.infcx));
         alt orig {
           ty::re_var(rid) { self.resolve_region_var(rid) }
           _ { orig }
@@ -650,16 +663,15 @@ fn resolve_region_var(rid: region_vid) -> ty::region {
             ret ty::re_var(rid);
         } else {
             vec::push(self.r_seen, rid);
-            let r = self.resolve_var(
-                self.infcx.rb,
-                {|_t| false },
-                rid,
-                {||
-                    if self.force_vars {ty::re_static}
-                    else {ty::re_var(rid)}
-                });
+            let {root:_, bounds} = self.infcx.get(self.infcx.rb, rid);
+            let r1 = alt bounds {
+              { ub:_, lb:some(t) } { self.resolve_region(t) }
+              { ub:some(t), lb:_ } { self.resolve_region(t) }
+              { ub:none, lb:none } if self.force_vars { ty::re_static }
+              { ub:none, lb:none } { ty::re_var(rid) }
+            };
             vec::pop(self.r_seen);
-            ret r;
+            ret r1;
         }
     }
 
@@ -670,43 +682,25 @@ fn resolve_ty_var(vid: ty_vid) -> ty::t {
         } else {
             vec::push(self.v_seen, vid);
             let tcx = self.infcx.tcx;
-            let t0 = self.resolve_var(
-                self.infcx.vb,
-                {|t| type_is_bot(t) },
-                vid,
-                {||
-                    if self.force_vars {ty::mk_bot(tcx)}
-                    else {ty::mk_var(tcx, vid)}
-                });
-            let t1 = self.resolve1(t0);
+
+            // Nonobvious: prefer the most specific type
+            // (i.e., the lower bound) to the more general
+            // one.  More general types in Rust (e.g., fn())
+            // tend to carry more restrictions or higher
+            // perf. penalties, so it pays to know more.
+
+            let {root:_, bounds} = self.infcx.get(self.infcx.vb, vid);
+            let t1 = alt bounds {
+              { ub:_, lb:some(t) } if !type_is_bot(t) { self.resolve1(t) }
+              { ub:some(t), lb:_ } { self.resolve1(t) }
+              { ub:_, lb:some(t) } { self.resolve1(t) }
+              { ub:none, lb:none } if self.force_vars { ty::mk_bot(tcx) }
+              { ub:none, lb:none } { ty::mk_var(tcx, vid) }
+            };
             vec::pop(self.v_seen);
             ret t1;
         }
     }
-
-    fn resolve_var<V: copy vid, T:copy to_str>(
-        vb: vals_and_bindings<V, T>, bot_guard: fn(T)->bool,
-        vid: V, unbound: fn() -> T) -> T {
-
-        let {root:_, bounds} = self.infcx.get(vb, vid);
-
-        #debug["resolve_var(%s) bounds=%s",
-               vid.to_str(),
-               bounds.to_str(self.infcx)];
-
-        // Nonobvious: prefer the most specific type
-        // (i.e., the lower bound) to the more general
-        // one.  More general types in Rust (e.g., fn())
-        // tend to carry more restrictions or higher
-        // perf. penalties, so it pays to know more.
-
-        alt bounds {
-          { ub:_, lb:some(t) } if !bot_guard(t) { t }
-          { ub:some(t), lb:_ } { t }
-          { ub:_, lb:some(t) } { t }
-          { ub:none, lb:none } { unbound() }
-        }
-    }
 }
 
 // ______________________________________________________________________
@@ -958,8 +952,9 @@ fn eq_opt_regions(infcx: infer_ctxt,
             ok(none)
           }
           (some(a), some(b)) {
-            infcx.eq_regions(a, b);
-            ok(some(a))
+            infcx.eq_regions(a, b).then {||
+                ok(some(a))
+            }
           }
           (_, _) {
             // If these two substitutions are for the same type (and
index 107ea65e1d9d083145d759e5f05b4f0a85a89cf1..9b25b057c3fd3eb3359415d3b15a6b8175b63c5f 100644 (file)
@@ -483,12 +483,26 @@ fn derive_flags(&has_params: bool, &has_vars: bool, &has_regions: bool,
         has_vars |= t.has_vars;
         has_regions |= t.has_regions;
     }
-    alt st {
-      ty_estr(vstore_slice(_)) {
+    fn derive_rflags(&has_vars: bool, &has_regions: bool, r: region) {
         has_regions = true;
+        alt r {
+          ty::re_var(_) { has_vars = true; }
+          _ { }
+        }
+    }
+    fn derive_sflags(&has_params: bool, &has_vars: bool, &has_regions: bool,
+                     substs: substs) {
+        for substs.tps.each {|tt|
+            derive_flags(has_params, has_vars, has_regions, tt);
+        }
+        substs.self_r.iter { |r| derive_rflags(has_vars, has_regions, r) }
+    }
+    alt st {
+      ty_estr(vstore_slice(r)) {
+        derive_rflags(has_vars, has_regions, r);
       }
-      ty_evec(mt, vstore_slice(_)) {
-        has_regions = true;
+      ty_evec(mt, vstore_slice(r)) {
+        derive_rflags(has_vars, has_regions, r);
         derive_flags(has_params, has_vars, has_regions, mt.ty);
       }
       ty_nil | ty_bot | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) |
@@ -497,10 +511,7 @@ fn derive_flags(&has_params: bool, &has_vars: bool, &has_regions: bool,
       ty_param(_, _) { has_params = true; }
       ty_var(_) | ty_self(_) { has_vars = true; }
       ty_enum(_, substs) | ty_class(_, substs) {
-        for substs.tps.each {|tt|
-            derive_flags(has_params, has_vars, has_regions, tt);
-        }
-        substs.self_r.iter { |_i| has_regions = true; }
+        derive_sflags(has_params, has_vars, has_regions, substs);
       }
       ty_iface(_, tys) {
         for tys.each {|tt|
@@ -511,11 +522,7 @@ fn derive_flags(&has_params: bool, &has_vars: bool, &has_regions: bool,
         derive_flags(has_params, has_vars, has_regions, m.ty);
       }
       ty_rptr(r, m) {
-        alt r {
-          ty::re_var(_) { has_vars = true; }
-          _ { }
-        }
-        has_regions = true;
+        derive_rflags(has_vars, has_regions, r);
         derive_flags(has_params, has_vars, has_regions, m.ty);
       }
       ty_rec(flds) {
@@ -535,9 +542,7 @@ fn derive_flags(&has_params: bool, &has_vars: bool, &has_regions: bool,
       }
       ty_res(_, tt, substs) {
         derive_flags(has_params, has_vars, has_regions, tt);
-        for substs.tps.each {|tt|
-            derive_flags(has_params, has_vars, has_regions, tt);
-        }
+        derive_sflags(has_params, has_vars, has_regions, substs);
       }
       ty_constr(tt, _) {
         derive_flags(has_params, has_vars, has_regions, tt);
@@ -933,10 +938,11 @@ fn subst(cx: ctxt,
          substs: substs,
          typ: t) -> t {
 
-    if substs_is_noop(substs) { ret typ; }
     #debug["subst(substs=%s, typ=%s)",
            substs_to_str(cx, substs),
            ty_to_str(cx, typ)];
+
+    if substs_is_noop(substs) { ret typ; }
     let r = do_subst(cx, substs, typ);
     #debug["  r = %s", ty_to_str(cx, r)];
     ret r;
index 3cfcb73e9ca903dfda3b6969b6f20ed11f9b8b6e..d9324a74d7b3d50e072b02fb4cbda6baf96a80d7 100644 (file)
@@ -258,7 +258,7 @@ fn instantiate_path(fcx: @fn_ctxt,
 
 // Type tests
 fn structurally_resolved_type(fcx: @fn_ctxt, sp: span, tp: ty::t) -> ty::t {
-    alt infer::resolve_shallow(fcx.infcx, tp) {
+    alt infer::resolve_shallow(fcx.infcx, tp, true) {
       // note: the bot type doesn't count as resolved; it's what we use when
       // there is no information about a variable.
       result::ok(t_s) if !ty::type_is_bot(t_s) { ret t_s; }
@@ -1348,7 +1348,7 @@ fn get_enum_variant_types(ccx: @crate_ctxt,
                                 constraints: []})
             };
             let tpt = {bounds: ty_param_bounds(ccx, ty_params),
-                       rp: ast::rp_none,
+                       rp: rp,
                        ty: result_ty};
             tcx.tcache.insert(local_def(variant.node.id), tpt);
             write_ty_to_tcx(tcx, variant.node.id, result_ty);
diff --git a/src/test/compile-fail/regions-creating-enums3.rs b/src/test/compile-fail/regions-creating-enums3.rs
new file mode 100644 (file)
index 0000000..d650441
--- /dev/null
@@ -0,0 +1,11 @@
+enum ast/& {
+    num(uint),
+    add(&ast, &ast)
+}
+
+fn mk_add_bad1(x: &a.ast, y: &b.ast) -> ast/&a {
+    add(x, y) //! ERROR mismatched types: expected `&a.ast/&a` but found `&b.ast/&b`
+}
+
+fn main() {
+}
\ No newline at end of file
diff --git a/src/test/compile-fail/regions-creating-enums4.rs b/src/test/compile-fail/regions-creating-enums4.rs
new file mode 100644 (file)
index 0000000..f80334d
--- /dev/null
@@ -0,0 +1,11 @@
+enum ast/& {
+    num(uint),
+    add(&ast, &ast)
+}
+
+fn mk_add_bad2(x: &a.ast, y: &a.ast, z: &ast) -> ast {
+    add(x, y) //! ERROR mismatched types: expected `ast/&` but found `ast/&a`
+}
+
+fn main() {
+}
\ No newline at end of file
diff --git a/src/test/run-pass/regions-creating-enums2.rs b/src/test/run-pass/regions-creating-enums2.rs
new file mode 100644 (file)
index 0000000..27559ea
--- /dev/null
@@ -0,0 +1,11 @@
+enum ast/& {
+    num(uint),
+    add(&ast, &ast)
+}
+
+fn mk_add_ok(x: &ast, y: &ast) -> ast {
+    add(x, y)
+}
+
+fn main() {
+}
\ No newline at end of file
diff --git a/src/test/run-pass/regions-creating-enums5.rs b/src/test/run-pass/regions-creating-enums5.rs
new file mode 100644 (file)
index 0000000..a7982cb
--- /dev/null
@@ -0,0 +1,11 @@
+enum ast/& {
+    num(uint),
+    add(&ast, &ast)
+}
+
+fn mk_add_ok(x: &a.ast, y: &a.ast, z: &ast) -> ast/&a {
+    add(x, y)
+}
+
+fn main() {
+}
\ No newline at end of file
diff --git a/src/test/run-pass/regions-nullary-variant.rs b/src/test/run-pass/regions-nullary-variant.rs
new file mode 100644 (file)
index 0000000..ad08ec1
--- /dev/null
@@ -0,0 +1,9 @@
+enum roption/& {
+    a, b(&uint)
+}
+
+fn mk(cond: bool, ptr: &uint) -> roption {
+    if cond {a} else {b(ptr)}
+}
+
+fn main() {}
\ No newline at end of file