about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2012-04-17 16:03:23 -0700
committerNiko Matsakis <niko@alum.mit.edu>2012-04-19 21:01:11 -0700
commitf3f34bf09b2512cac0e77281d8f2249d64cf2743 (patch)
treedb8bd95b729829e68e29b248b578360bce5361b1 /src
parentbbfb83c2c5501ce3944ea77e7610b83a3bdbfc04 (diff)
downloadrust-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.rs91
-rw-r--r--src/test/compile-fail/regions-scoping.rs20
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
     }
 }