]> git.lizzy.rs Git - rust.git/commitdiff
Fix ICE when reporting closure and proc mismatch
authorEdward Wang <edward.yu.wang@gmail.com>
Mon, 21 Apr 2014 15:26:29 +0000 (23:26 +0800)
committerEdward Wang <edward.yu.wang@gmail.com>
Tue, 22 Apr 2014 07:54:02 +0000 (15:54 +0800)
Closes #13599

src/librustc/middle/ty.rs
src/librustc/middle/typeck/check/mod.rs
src/test/compile-fail/issue-13599.rs [new file with mode: 0644]

index 037182d8b7b80f9b6055bc96c227549cecfb236a..9756e2663b9a9d0b6feff17f7fa5d1f2a847675a 100644 (file)
@@ -3329,6 +3329,13 @@ fn terr_vstore_kind_to_str(k: terr_vstore_kind) -> ~str {
         }
     }
 
+    fn tstore_to_closure(s: &TraitStore) -> ~str {
+        match s {
+            &UniqTraitStore => "proc".to_owned(),
+            &RegionTraitStore(..) => "closure".to_owned()
+        }
+    }
+
     match *err {
         terr_mismatch => "types differ".to_owned(),
         terr_fn_style_mismatch(values) => {
@@ -3344,9 +3351,9 @@ fn terr_vstore_kind_to_str(k: terr_vstore_kind) -> ~str {
                  values.expected.to_str(), values.found.to_str())
         }
         terr_sigil_mismatch(values) => {
-            format!("expected {} closure, found {} closure",
-                 values.expected.to_str(),
-                 values.found.to_str())
+            format!("expected {}, found {}",
+                    tstore_to_closure(&values.expected),
+                    tstore_to_closure(&values.found))
         }
         terr_mutability => "values differ in mutability".to_owned(),
         terr_box_mutability => "boxed values differ in mutability".to_owned(),
index fb470cbdfb1aba62f598d545ee64f9f0d4606164..432240f1d12655e1a6dc0d81d3588a7b092e9a40 100644 (file)
@@ -2182,7 +2182,6 @@ fn check_expr_fn(fcx: &FnCtxt,
         let expected_sty = unpack_expected(fcx,
                                            expected,
                                            |x| Some((*x).clone()));
-        let error_happened = false;
         let (expected_sig,
              expected_onceness,
              expected_bounds) = {
@@ -2192,7 +2191,24 @@ fn check_expr_fn(fcx: &FnCtxt,
                         replace_late_bound_regions_in_fn_sig(
                             tcx, &cenv.sig,
                             |_| fcx.inh.infcx.fresh_bound_region(expr.id));
-                    (Some(sig), cenv.onceness, cenv.bounds)
+                    let onceness = match (&store, &cenv.store) {
+                        // As the closure type and onceness go, only three
+                        // combinations are legit:
+                        //      once closure
+                        //      many closure
+                        //      once proc
+                        // If the actual and expected closure type disagree with
+                        // each other, set expected onceness to be always Once or
+                        // Many according to the actual type. Otherwise, it will
+                        // yield either an illegal "many proc" or a less known
+                        // "once closure" in the error message.
+                        (&ty::UniqTraitStore, &ty::UniqTraitStore) |
+                        (&ty::RegionTraitStore(..), &ty::RegionTraitStore(..)) =>
+                            cenv.onceness,
+                        (&ty::UniqTraitStore, _) => ast::Once,
+                        (&ty::RegionTraitStore(..), _) => ast::Many,
+                    };
+                    (Some(sig), onceness, cenv.bounds)
                 }
                 _ => {
                     // Not an error! Means we're inferring the closure type
@@ -2218,23 +2234,9 @@ fn check_expr_fn(fcx: &FnCtxt,
                                            store,
                                            decl,
                                            expected_sig);
-
-        let fty_sig;
-        let fty = if error_happened {
-            fty_sig = FnSig {
-                binder_id: ast::CRATE_NODE_ID,
-                inputs: fn_ty.sig.inputs.iter().map(|_| ty::mk_err()).collect(),
-                output: ty::mk_err(),
-                variadic: false
-            };
-            ty::mk_err()
-        } else {
-            fty_sig = fn_ty.sig.clone();
-            ty::mk_closure(tcx, fn_ty.clone())
-        };
-
-        debug!("check_expr_fn_with_unifier fty={}",
-               fcx.infcx().ty_to_str(fty));
+        let fty_sig = fn_ty.sig.clone();
+        let fty = ty::mk_closure(tcx, fn_ty);
+        debug!("check_expr_fn fty={}", fcx.infcx().ty_to_str(fty));
 
         fcx.write_ty(expr.id, fty);
 
diff --git a/src/test/compile-fail/issue-13599.rs b/src/test/compile-fail/issue-13599.rs
new file mode 100644 (file)
index 0000000..de1a9e1
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that a mismatched proc / closure type is correctly reported.
+
+fn expect_closure(_: ||) {}
+
+fn expect_proc(_: proc()) {}
+
+fn main() {
+    expect_closure(proc() {});
+    //~^ ERROR mismatched types: expected `||` but found `proc()` (expected closure, found proc)
+
+    expect_proc(|| {});
+    //~^ ERROR mismatched types: expected `proc()` but found `||` (expected proc, found closure)
+}