about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-10-04 17:47:06 +0000
committerbors <bors@rust-lang.org>2014-10-04 17:47:06 +0000
commite434aa1cf737b050ef79c3d7a0a7eca48c7f8e49 (patch)
treeefaf6637b0ba8bf9a24e49c17d06192944cd7a6b
parent20f4c45bade89f0a8df5297811af3d9f8b91d075 (diff)
parent404db68da40130b0fa45053ea3a894cd0dd74a0e (diff)
downloadrust-e434aa1cf737b050ef79c3d7a0a7eca48c7f8e49.tar.gz
rust-e434aa1cf737b050ef79c3d7a0a7eca48c7f8e49.zip
auto merge of #17760 : bkoropoff/rust/issue-17737, r=eddyb
This is a quick fix.  In the long term, the `TyVisitor` interface should be expanded to better represent closure types.

Closes issue #17737
-rw-r--r--src/librustc/middle/trans/reflect.rs54
-rw-r--r--src/test/run-pass/issue-17737.rs24
2 files changed, 60 insertions, 18 deletions
diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs
index f004bea23c7..bff1a0400a9 100644
--- a/src/librustc/middle/trans/reflect.rs
+++ b/src/librustc/middle/trans/reflect.rs
@@ -127,6 +127,22 @@ impl<'a, 'blk, 'tcx> Reflector<'a, 'blk, 'tcx> {
         self.visit(name, []);
     }
 
+    fn visit_closure_ty(&mut self, fty: &ty::ClosureTy, is_unboxed: bool) {
+        let pureval = ast_fn_style_constant(fty.fn_style);
+        let sigilval = match fty.store {
+            ty::UniqTraitStore => 2u,
+            ty::RegionTraitStore(..) => 4u,
+        };
+        let retval = if ty::type_is_bot(fty.sig.output) {0u} else {1u};
+        let extra = vec!(self.c_uint(pureval),
+                         self.c_uint(sigilval),
+                         self.c_uint(fty.sig.inputs.len()),
+                         self.c_uint(retval));
+        self.visit("enter_fn", extra.as_slice());
+        self.visit_sig(retval, &fty.sig, is_unboxed);
+        self.visit("leave_fn", extra.as_slice());
+    }
+
     // Entrypoint
     pub fn visit_ty(&mut self, t: ty::t) {
         let bcx = self.bcx;
@@ -247,20 +263,8 @@ impl<'a, 'blk, 'tcx> Reflector<'a, 'blk, 'tcx> {
 
           // FIXME (#2594): fetch constants out of intrinsic
           // FIXME (#4809): visitor should break out bare fns from other fns
-          ty::ty_closure(ref fty) => {
-            let pureval = ast_fn_style_constant(fty.fn_style);
-            let sigilval = match fty.store {
-                ty::UniqTraitStore => 2u,
-                ty::RegionTraitStore(..) => 4u,
-            };
-            let retval = if ty::type_is_bot(fty.sig.output) {0u} else {1u};
-            let extra = vec!(self.c_uint(pureval),
-                          self.c_uint(sigilval),
-                          self.c_uint(fty.sig.inputs.len()),
-                          self.c_uint(retval));
-            self.visit("enter_fn", extra.as_slice());
-            self.visit_sig(retval, &fty.sig);
-            self.visit("leave_fn", extra.as_slice());
+          ty::ty_closure(box ref fty) => {
+              self.visit_closure_ty(fty, false);
           }
 
           // FIXME (#2594): fetch constants out of intrinsic:: for the
@@ -274,7 +278,7 @@ impl<'a, 'blk, 'tcx> Reflector<'a, 'blk, 'tcx> {
                           self.c_uint(fty.sig.inputs.len()),
                           self.c_uint(retval));
             self.visit("enter_fn", extra.as_slice());
-            self.visit_sig(retval, &fty.sig);
+            self.visit_sig(retval, &fty.sig, false);
             self.visit("leave_fn", extra.as_slice());
           }
 
@@ -388,7 +392,11 @@ impl<'a, 'blk, 'tcx> Reflector<'a, 'blk, 'tcx> {
           // Miscellaneous extra types
           ty::ty_infer(_) => self.leaf("infer"),
           ty::ty_err => self.leaf("err"),
-          ty::ty_unboxed_closure(..) => self.leaf("err"),
+          ty::ty_unboxed_closure(ref def_id, _) => {
+              let closure_map = tcx.unboxed_closures.borrow();
+              let fty = &closure_map.find(def_id).unwrap().closure_type;
+              self.visit_closure_ty(fty, true);
+          }
           ty::ty_param(ref p) => {
               let extra = vec!(self.c_uint(p.idx));
               self.visit("param", extra.as_slice())
@@ -396,8 +404,18 @@ impl<'a, 'blk, 'tcx> Reflector<'a, 'blk, 'tcx> {
         }
     }
 
-    pub fn visit_sig(&mut self, retval: uint, sig: &ty::FnSig) {
-        for (i, arg) in sig.inputs.iter().enumerate() {
+    pub fn visit_sig(&mut self, retval: uint, sig: &ty::FnSig, is_unboxed: bool) {
+        let args = if is_unboxed {
+            match ty::get(sig.inputs[0]).sty {
+                ty::ty_tup(ref contents) => contents.iter(),
+                ty::ty_nil => [].iter(),
+                _ => unreachable!()
+            }
+        } else {
+            sig.inputs.iter()
+        };
+
+        for (i, arg) in args.enumerate() {
             let modeval = 5u;   // "by copy"
             let extra = vec!(self.c_uint(i),
                          self.c_uint(modeval),
diff --git a/src/test/run-pass/issue-17737.rs b/src/test/run-pass/issue-17737.rs
new file mode 100644
index 00000000000..ec0cb488c68
--- /dev/null
+++ b/src/test/run-pass/issue-17737.rs
@@ -0,0 +1,24 @@
+// Copyright 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.
+
+#![feature(unboxed_closures)]
+
+// Test generating type visitor glue for unboxed closures
+
+extern crate debug;
+
+fn main() {
+    let expected = "fn(); fn(uint, uint) -> uint; fn() -> !";
+    let result = format!("{:?}; {:?}; {:?}",
+                         |:| {},
+                         |&: x: uint, y: uint| { x + y },
+                         |&mut:| -> ! { fail!() });
+    assert_eq!(expected, result.as_slice());
+}