From 741142e3faf2282bc6a87f5e83cb28274aa8205e Mon Sep 17 00:00:00 2001 From: Edward Wang Date: Mon, 21 Apr 2014 23:26:29 +0800 Subject: [PATCH] Fix ICE when reporting closure and proc mismatch Closes #13599 --- src/librustc/middle/ty.rs | 13 ++++++-- src/librustc/middle/typeck/check/mod.rs | 40 +++++++++++++------------ src/test/compile-fail/issue-13599.rs | 23 ++++++++++++++ 3 files changed, 54 insertions(+), 22 deletions(-) create mode 100644 src/test/compile-fail/issue-13599.rs diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 037182d8b7b..9756e2663b9 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -3329,6 +3329,13 @@ pub fn type_err_to_str(cx: &ctxt, err: &type_err) -> ~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 @@ pub fn type_err_to_str(cx: &ctxt, err: &type_err) -> ~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(), diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index fb470cbdfb1..432240f1d12 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -2182,7 +2182,6 @@ fn check_expr_with_unifier(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_with_unifier(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_with_unifier(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 index 00000000000..de1a9e13f9e --- /dev/null +++ b/src/test/compile-fail/issue-13599.rs @@ -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 or the MIT license +// , 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) +}