]> git.lizzy.rs Git - rust.git/commitdiff
Do not use == and != to compare ty::t values
authorMarijn Haverbeke <marijnh@gmail.com>
Thu, 22 Dec 2011 13:52:30 +0000 (14:52 +0100)
committerMarijn Haverbeke <marijnh@gmail.com>
Thu, 22 Dec 2011 14:05:38 +0000 (15:05 +0100)
Issue #828

src/comp/middle/ty.rs
src/comp/middle/typeck.rs

index a1cb5cd371b6f3bade7c2e98720ae71cfb2d9703..070123439adc9778c3959dc634b7b8cdeecc292d 100644 (file)
 export ty_uniq;
 export ty_var;
 export ty_named;
+export same_type, same_method;
 export ty_var_id;
 export ty_param_substs_opt_and_ty_to_monotype;
 export ty_fn_args;
@@ -1683,7 +1684,7 @@ mod unify {
     type var_bindings =
         {sets: ufind::ufind, types: smallintmap::smallintmap<t>};
 
-    type ctxt = {vb: @var_bindings, tcx: ty_ctxt};
+    type ctxt = {vb: option::t<@var_bindings>, tcx: ty_ctxt};
 
     fn mk_var_bindings() -> @var_bindings {
         ret @{sets: ufind::make(), types: smallintmap::mk::<t>()};
@@ -1692,31 +1693,32 @@ fn mk_var_bindings() -> @var_bindings {
     // Unifies two sets.
     fn union(cx: @ctxt, set_a: uint, set_b: uint,
              variance: variance) -> union_result {
-        ufind::grow(cx.vb.sets, float::max(set_a, set_b) + 1u);
-        let root_a = ufind::find(cx.vb.sets, set_a);
-        let root_b = ufind::find(cx.vb.sets, set_b);
+        let vb = option::get(cx.vb);
+        ufind::grow(vb.sets, float::max(set_a, set_b) + 1u);
+        let root_a = ufind::find(vb.sets, set_a);
+        let root_b = ufind::find(vb.sets, set_b);
 
         let replace_type =
-            bind fn (cx: @ctxt, t: t, set_a: uint, set_b: uint) {
-                     ufind::union(cx.vb.sets, set_a, set_b);
-                     let root_c: uint = ufind::find(cx.vb.sets, set_a);
-                     smallintmap::insert::<t>(cx.vb.types, root_c, t);
+            bind fn (vb: @var_bindings, t: t, set_a: uint, set_b: uint) {
+                     ufind::union(vb.sets, set_a, set_b);
+                     let root_c: uint = ufind::find(vb.sets, set_a);
+                     smallintmap::insert::<t>(vb.types, root_c, t);
                  }(_, _, set_a, set_b);
 
 
-        alt smallintmap::find(cx.vb.types, root_a) {
+        alt smallintmap::find(vb.types, root_a) {
           none. {
-            alt smallintmap::find(cx.vb.types, root_b) {
-              none. { ufind::union(cx.vb.sets, set_a, set_b); ret unres_ok; }
-              some(t_b) { replace_type(cx, t_b); ret unres_ok; }
+            alt smallintmap::find(vb.types, root_b) {
+              none. { ufind::union(vb.sets, set_a, set_b); ret unres_ok; }
+              some(t_b) { replace_type(vb, t_b); ret unres_ok; }
             }
           }
           some(t_a) {
-            alt smallintmap::find(cx.vb.types, root_b) {
-              none. { replace_type(cx, t_a); ret unres_ok; }
+            alt smallintmap::find(vb.types, root_b) {
+              none. { replace_type(vb, t_a); ret unres_ok; }
               some(t_b) {
                 alt unify_step(cx, t_a, t_b, variance) {
-                  ures_ok(t_c) { replace_type(cx, t_c); ret unres_ok; }
+                  ures_ok(t_c) { replace_type(vb, t_c); ret unres_ok; }
                   ures_err(terr) { ret unres_err(terr); }
                 }
               }
@@ -1741,10 +1743,11 @@ fn record_var_binding_for_actual(
     fn record_var_binding(
         cx: @ctxt, key: int, typ: t, variance: variance) -> result {
 
-        ufind::grow(cx.vb.sets, (key as uint) + 1u);
-        let root = ufind::find(cx.vb.sets, key as uint);
+        let vb = option::get(cx.vb);
+        ufind::grow(vb.sets, (key as uint) + 1u);
+        let root = ufind::find(vb.sets, key as uint);
         let result_type = typ;
-        alt smallintmap::find::<t>(cx.vb.types, root) {
+        alt smallintmap::find(vb.types, root) {
           some(old_type) {
             alt unify_step(cx, old_type, typ, variance) {
               ures_ok(unified_type) { result_type = unified_type; }
@@ -1753,7 +1756,7 @@ fn record_var_binding(
           }
           none. {/* fall through */ }
         }
-        smallintmap::insert::<t>(cx.vb.types, root, result_type);
+        smallintmap::insert::<t>(vb.types, root, result_type);
         ret ures_ok(typ);
     }
 
@@ -2090,6 +2093,7 @@ fn unify_step(cx: @ctxt, expected: t, actual: t,
           // If the RHS is a variable type, then just do the
           // appropriate binding.
           ty::ty_var(actual_id) {
+            assert option::is_some(cx.vb);
             let actual_n = actual_id as uint;
             alt struct(cx.tcx, expected) {
               ty::ty_var(expected_id) {
@@ -2114,8 +2118,8 @@ fn unify_step(cx: @ctxt, expected: t, actual: t,
         }
         alt struct(cx.tcx, expected) {
           ty::ty_var(expected_id) {
+            assert option::is_some(cx.vb);
             // Add a binding. (`actual` can't actually be a var here.)
-
             alt record_var_binding_for_expected(
                 cx, expected_id, actual,
                 variance) {
@@ -2431,8 +2435,8 @@ fn unify_step(cx: @ctxt, expected: t, actual: t,
           }
         }
     }
-    fn unify(expected: t, actual: t, vb: @var_bindings, tcx: ty_ctxt) ->
-       result {
+    fn unify(expected: t, actual: t, vb: option::t<@var_bindings>,
+             tcx: ty_ctxt) -> result {
         let cx = @{vb: vb, tcx: tcx};
         ret unify_step(cx, expected, actual, covariant);
     }
@@ -2505,6 +2509,19 @@ fn resolve_type_var(tcx: ty_ctxt, sp: option::t<span>, vb: @var_bindings,
     }
 }
 
+fn same_type(cx: ctxt, a: t, b: t) -> bool {
+    alt unify::unify(a, b, none, cx) {
+      unify::ures_ok(_) { true }
+      _ { false }
+    }
+}
+fn same_method(cx: ctxt, a: method, b: method) -> bool {
+    a.proto == b.proto && a.ident == b.ident &&
+    vec::all2(a.inputs, b.inputs,
+              {|a, b| a.mode == b.mode && same_type(cx, a.ty, b.ty) }) &&
+    same_type(cx, a.output, b.output) && a.cf == b.cf
+}
+
 fn type_err_to_str(err: ty::type_err) -> str {
     alt err {
       terr_mismatch. { ret "types differ"; }
index d37482f0f1e8edb5833b28a73099d4a1d5dd1363..400411fa68ab11f451ec2ea0366a9ad9ee33df07 100644 (file)
@@ -791,7 +791,8 @@ fn collect_item_types(tcx: ty::ctxt, crate: @ast::crate) {
 mod unify {
     fn unify(fcx: @fn_ctxt, expected: ty::t, actual: ty::t) ->
        ty::unify::result {
-        ret ty::unify::unify(expected, actual, fcx.var_bindings, fcx.ccx.tcx);
+        ret ty::unify::unify(expected, actual, some(fcx.var_bindings),
+                             fcx.ccx.tcx);
     }
 }
 
@@ -1106,7 +1107,7 @@ fn gather_locals(ccx: @crate_ctxt,
             alt ty_opt {
               none. {/* nothing to do */ }
               some(typ) {
-                ty::unify::unify(ty::mk_var(tcx, var_id), typ, vb, tcx);
+                ty::unify::unify(ty::mk_var(tcx, var_id), typ, some(vb), tcx);
               }
             }
         };
@@ -1198,8 +1199,8 @@ fn check_pat(fcx: @fn_ctxt, map: ast_util::pat_id_map, pat: @ast::pat,
         check_expr_with(fcx, end, expected);
         let b_ty = resolve_type_vars_if_possible(fcx, expr_ty(fcx.ccx.tcx,
                                                               begin));
-        if b_ty != resolve_type_vars_if_possible(fcx, expr_ty(fcx.ccx.tcx,
-                                                              end)) {
+        if !ty::same_type(fcx.ccx.tcx, b_ty, resolve_type_vars_if_possible(
+            fcx, expr_ty(fcx.ccx.tcx, end))) {
             fcx.ccx.tcx.sess.span_err(pat.span, "mismatched types in range");
         } else if !ty::type_is_numeric(fcx.ccx.tcx, b_ty) {
             fcx.ccx.tcx.sess.span_err(pat.span,
@@ -2324,7 +2325,7 @@ fn filtering_fn(ccx: @crate_ctxt, m: ty::method,
                         // We'd better be overriding with one of the same
                         // type.  Check to make sure.
                         let new_type = ty_of_method(ccx.tcx, m_check, om);
-                        if new_type != m {
+                        if !ty::same_method(ccx.tcx, new_type, m) {
                             ccx.tcx.sess.span_fatal
                                 (om.span, "attempted to override method "
                                  + m.ident + " with one of a different type");