Skip to content

Fix ICE when reporting closure and proc mismatch #13657

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 22, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions src/librustc/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand All @@ -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(),
Expand Down
40 changes: 21 additions & 19 deletions src/librustc/middle/typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) = {
Expand All @@ -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
Expand All @@ -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);

Expand Down
23 changes: 23 additions & 0 deletions src/test/compile-fail/issue-13599.rs
Original file line number Diff line number Diff line change
@@ -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)
}