diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2012-04-17 16:03:23 -0700 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2012-04-19 21:01:11 -0700 |
| commit | f3f34bf09b2512cac0e77281d8f2249d64cf2743 (patch) | |
| tree | db8bd95b729829e68e29b248b578360bce5361b1 /src | |
| parent | bbfb83c2c5501ce3944ea77e7610b83a3bdbfc04 (diff) | |
| download | rust-f3f34bf09b2512cac0e77281d8f2249d64cf2743.tar.gz rust-f3f34bf09b2512cac0e77281d8f2249d64cf2743.zip | |
correct universally_quantify to use structure_of, and introduce a test for this
Diffstat (limited to 'src')
| -rw-r--r-- | src/rustc/middle/typeck.rs | 91 | ||||
| -rw-r--r-- | src/test/compile-fail/regions-scoping.rs | 20 |
2 files changed, 60 insertions, 51 deletions
diff --git a/src/rustc/middle/typeck.rs b/src/rustc/middle/typeck.rs index 4e41129dd3c..b3e407b0c47 100644 --- a/src/rustc/middle/typeck.rs +++ b/src/rustc/middle/typeck.rs @@ -1975,13 +1975,17 @@ fn universally_quantify_from_sty(fcx: @fn_ctxt, bound_tys: [ty::t], sty: ty::sty) -> ty::t { - let tcx = fcx.tcx(); - let isr = collect_named_regions_in_tys(tcx, @nil, bound_tys) { |_id| - fcx.next_region_var() - }; - let anon_r = fcx.next_region_var(); - ty::fold_sty_to_ty(fcx.ccx.tcx, sty) {|t| - replace_bound_regions(tcx, span, anon_r, isr, t) + #debug["universally_quantify_from_sty(bound_tys=%?)", + bound_tys.map {|x| fcx.ty_to_str(x) }]; + indent {|| + let tcx = fcx.tcx(); + let isr = collect_named_regions_in_tys(tcx, @nil, bound_tys) { |_id| + fcx.next_region_var() + }; + let anon_r = fcx.next_region_var(); + ty::fold_sty_to_ty(fcx.ccx.tcx, sty) { |t| + replace_bound_regions(tcx, span, anon_r, isr, t) + } } } @@ -2000,7 +2004,9 @@ fn universally_quantify_regions(fcx: @fn_ctxt, fn universally_quantify_before_call(fcx: @fn_ctxt, span: span, ty: ty::t) -> ty::t { - if !ty::type_has_regions(ty) { ret ty; } + + #debug["universally_quantify_before_call(ty=%s)", + fcx.ty_to_str(ty)]; // This is subtle: we expect `ty` to be a function type, which normally // introduce a level of binding. In this case, we want to process the @@ -2018,12 +2024,14 @@ fn universally_quantify_before_call(fcx: @fn_ctxt, // - Finally, we can use fold_sty_to_ty() and replace_bound_regions() // to replace the bound regions as well as the bound anonymous region. // We have to use fold_sty_to_ty() to ignore the outer fn(). - alt ty::get(ty).struct { + alt structure_of(fcx, span, ty) { sty @ ty::ty_fn(fty) { let all_tys = fty.inputs.map({|a| a.ty}) + [fty.output]; universally_quantify_from_sty(fcx, span, all_tys, sty) } - _ { + sty { + #debug["not a fn ty: %?", sty]; + // if not a function type, we're gonna' report an error // at some point, since the user is trying to call this thing ty @@ -2719,45 +2727,44 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, let fty = universally_quantify_before_call(fcx, sp, fty); #debug["check_call_or_bind: after universal quant., fty=%s", fcx.ty_to_str(fty)]; - let sty = structure_of(fcx, sp, fty); + + let supplied_arg_count = vec::len(args); + // Grab the argument types - let mut arg_tys = alt sty { - ty::ty_fn({inputs: arg_tys, _}) { arg_tys } + let arg_tys = alt structure_of(fcx, sp, fty) { + ty::ty_fn({inputs: arg_tys, output: ret_ty, _}) { + let expected_arg_count = vec::len(arg_tys); + if expected_arg_count == supplied_arg_count { + arg_tys.map { |a| a.ty } + } else { + fcx.ccx.tcx.sess.span_err( + sp, #fmt["this function takes %u parameter%s but %u \ + parameter%s supplied", expected_arg_count, + if expected_arg_count == 1u { + "" + } else { + "s" + }, + supplied_arg_count, + if supplied_arg_count == 1u { + " was" + } else { + "s were" + }]); + fcx.next_ty_vars(supplied_arg_count) + } + } + _ { + // I would like to make this span_err, but it's really hard due to + // the way that expr_bind() is written. fcx.ccx.tcx.sess.span_fatal(sp, "mismatched types: \ expected function or native \ function but found " - + fcx.ty_to_str(fty)) + + fcx.ty_to_str(fty)); } }; - // Check that the correct number of arguments were supplied. - let expected_arg_count = vec::len(arg_tys); - let supplied_arg_count = vec::len(args); - if expected_arg_count != supplied_arg_count { - fcx.ccx.tcx.sess.span_err( - sp, #fmt["this function takes %u parameter%s but %u \ - parameter%s supplied", expected_arg_count, - if expected_arg_count == 1u { - "" - } else { - "s" - }, - supplied_arg_count, - if supplied_arg_count == 1u { - " was" - } else { - "s were" - }]); - - // Just use fresh type variables for the types, - // since we don't know them. - arg_tys = vec::from_fn(supplied_arg_count) {|_i| - {mode: ast::expl(ast::by_ref), - ty: fcx.next_ty_var()} - }; - } - // Check the arguments. // We do this in a pretty awful way: first we typecheck any arguments // that are not anonymous functions, then we typecheck the anonymous @@ -2775,7 +2782,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, _ { false } }; if is_block == check_blocks { - let arg_ty = arg_tys[i].ty; + let arg_ty = arg_tys[i]; bot |= check_expr_with_unifier(fcx, a, arg_ty) {|| demand::assign(fcx, a.span, arg_ty, a); }; diff --git a/src/test/compile-fail/regions-scoping.rs b/src/test/compile-fail/regions-scoping.rs index 31a642c69fd..2b1cf04c1db 100644 --- a/src/test/compile-fail/regions-scoping.rs +++ b/src/test/compile-fail/regions-scoping.rs @@ -1,5 +1,3 @@ -// xfail-test - fn with<T>(t: T, f: fn(T)) { f(t) } fn nested(x: &x.int) { // (1) @@ -26,15 +24,19 @@ fn nested(x: &x.int) { // (1) //!^ ERROR mismatched types: expected `&x.int` but found `&y.int` fail; } - ) {|f| + ) {|foo| + + let a: &x.int = foo(x, x) { |_x, _y, z| z }; + let b: &x.int = foo(x, a) { |_x, _y, z| z }; + let c: &x.int = foo(a, a) { |_x, _y, z| z }; - let a: &x.int = f(x, x) { |_x, _y, z| z }; - let b: &x.int = f(x, a) { |_x, _y, z| z }; - let c: &x.int = f(a, a) { |_x, _y, z| z }; + let z = 3; + let d: &x.int = foo(x, x) { |_x, _y, z| z }; + let e: &x.int = foo(x, &z) { |_x, _y, z| z }; + let f: &x.int = foo(&z, &z) { |_x, _y, z| z }; //! ERROR mismatched types: expected `&x.int` but found - let d: &x.int = f(x, x) { |_x, _y, z| z }; - let e: &x.int = f(x, &a) { |_x, _y, z| z }; - let f: &x.int = f(&a, &a) { |_x, _y, z| z }; + foo(x, &z) { |x, _y, _z| x }; //! ERROR mismatched types: expected `&z.int` but found `&x.int` + foo(x, &z) { |_x, y, _z| y }; //! ERROR mismatched types: expected `&z.int` but found `&<block at } } |
