about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2015-01-01 04:01:02 +0000
committerbors <bors@rust-lang.org>2015-01-01 04:01:02 +0000
commit47b8479e73e40395f1b1b2d0c6281f28f80301e4 (patch)
treea8ae69e94286da9d3b153e39300130271ad1f3f8 /src/libsyntax
parent7d4f4876d65bddf101784230c0347adcb01e5c21 (diff)
parent10bbf69488b4863378e4acd9d55bde36b4a20909 (diff)
downloadrust-47b8479e73e40395f1b1b2d0c6281f28f80301e4.tar.gz
rust-47b8479e73e40395f1b1b2d0c6281f28f80301e4.zip
auto merge of #20363 : japaric/rust/moar-uc, r=nmatsakis
The the last argument of the `ItemDecorator::expand` method has changed to `Box<FnMut>`. Syntax extensions will break.

[breaking-change]

---

This PR removes pretty much all the remaining uses of boxed closures from the libraries. There are still boxed closures under the `test` directory, but I think those should be removed or replaced with unboxed closures at the same time we remove boxed closures from the language.

In a few places I had to do some contortions (see the first commit for an example) to work around issue #19596. I have marked those workarounds with FIXMEs. In the future when `&mut F where F: FnMut` implements the `FnMut` trait, we should be able to remove those workarounds. I've take care to avoid placing the workaround functions in the public API.

Since `let f = || {}` always gets type checked as a boxed closure, I have explictly annotated those closures (with e.g. `|&:| {}`) to force the compiler to type check them as unboxed closures.

Instead of removing the type aliases (like `GetCrateDataCb`), I could have replaced them with newtypes. But this seemed like overcomplicating things for little to no gain.

I think we should be able to remove the boxed closures from the languge after this PR lands. (I'm being optimistic here)

r? @alexcrichton or @aturon 
cc @nikomatsakis 
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ast_util.rs54
-rw-r--r--src/libsyntax/ext/base.rs6
-rw-r--r--src/libsyntax/ext/deriving/default.rs2
-rw-r--r--src/libsyntax/ext/deriving/generic/mod.rs2
-rw-r--r--src/libsyntax/ext/deriving/hash.rs2
-rw-r--r--src/libsyntax/ext/deriving/mod.rs4
-rw-r--r--src/libsyntax/ext/deriving/zero.rs2
-rw-r--r--src/libsyntax/ext/expand.rs4
-rw-r--r--src/libsyntax/ext/quote.rs4
-rw-r--r--src/libsyntax/parse/mod.rs10
-rw-r--r--src/libsyntax/test.rs6
11 files changed, 50 insertions, 46 deletions
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index 9196055267f..a8393ed9d39 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -618,34 +618,38 @@ pub fn compute_id_range_for_fn_body(fk: visit::FnKind,
     id_visitor.operation.result
 }
 
-// FIXME(#19596) unbox `it`
-pub fn walk_pat(pat: &Pat, it: |&Pat| -> bool) -> bool {
-    if !it(pat) {
-        return false;
-    }
-
-    match pat.node {
-        PatIdent(_, _, Some(ref p)) => walk_pat(&**p, it),
-        PatStruct(_, ref fields, _) => {
-            fields.iter().all(|field| walk_pat(&*field.node.pat, |p| it(p)))
-        }
-        PatEnum(_, Some(ref s)) | PatTup(ref s) => {
-            s.iter().all(|p| walk_pat(&**p, |p| it(p)))
+pub fn walk_pat<F>(pat: &Pat, mut it: F) -> bool where F: FnMut(&Pat) -> bool {
+    // FIXME(#19596) this is a workaround, but there should be a better way
+    fn walk_pat_<G>(pat: &Pat, it: &mut G) -> bool where G: FnMut(&Pat) -> bool {
+        if !(*it)(pat) {
+            return false;
         }
-        PatBox(ref s) | PatRegion(ref s) => {
-            walk_pat(&**s, it)
-        }
-        PatVec(ref before, ref slice, ref after) => {
-            before.iter().all(|p| walk_pat(&**p, |p| it(p))) &&
-            slice.iter().all(|p| walk_pat(&**p, |p| it(p))) &&
-            after.iter().all(|p| walk_pat(&**p, |p| it(p)))
-        }
-        PatMac(_) => panic!("attempted to analyze unexpanded pattern"),
-        PatWild(_) | PatLit(_) | PatRange(_, _) | PatIdent(_, _, _) |
-        PatEnum(_, _) => {
-            true
+
+        match pat.node {
+            PatIdent(_, _, Some(ref p)) => walk_pat_(&**p, it),
+            PatStruct(_, ref fields, _) => {
+                fields.iter().all(|field| walk_pat_(&*field.node.pat, it))
+            }
+            PatEnum(_, Some(ref s)) | PatTup(ref s) => {
+                s.iter().all(|p| walk_pat_(&**p, it))
+            }
+            PatBox(ref s) | PatRegion(ref s) => {
+                walk_pat_(&**s, it)
+            }
+            PatVec(ref before, ref slice, ref after) => {
+                before.iter().all(|p| walk_pat_(&**p, it)) &&
+                slice.iter().all(|p| walk_pat_(&**p, it)) &&
+                after.iter().all(|p| walk_pat_(&**p, it))
+            }
+            PatMac(_) => panic!("attempted to analyze unexpanded pattern"),
+            PatWild(_) | PatLit(_) | PatRange(_, _) | PatIdent(_, _, _) |
+            PatEnum(_, _) => {
+                true
+            }
         }
     }
+
+    walk_pat_(pat, &mut it)
 }
 
 pub trait EachViewItem {
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index 8e69076a2c5..5134897893f 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -47,18 +47,18 @@ pub trait ItemDecorator {
               sp: Span,
               meta_item: &ast::MetaItem,
               item: &ast::Item,
-              push: |P<ast::Item>|);
+              push: Box<FnMut(P<ast::Item>)>);
 }
 
 impl<F> ItemDecorator for F
-    where F : Fn(&mut ExtCtxt, Span, &ast::MetaItem, &ast::Item, |P<ast::Item>|)
+    where F : Fn(&mut ExtCtxt, Span, &ast::MetaItem, &ast::Item, Box<FnMut(P<ast::Item>)>)
 {
     fn expand(&self,
               ecx: &mut ExtCtxt,
               sp: Span,
               meta_item: &ast::MetaItem,
               item: &ast::Item,
-              push: |P<ast::Item>|) {
+              push: Box<FnMut(P<ast::Item>)>) {
         (*self)(ecx, sp, meta_item, item, push)
     }
 }
diff --git a/src/libsyntax/ext/deriving/default.rs b/src/libsyntax/ext/deriving/default.rs
index b3621490ce3..49bcb26a4c2 100644
--- a/src/libsyntax/ext/deriving/default.rs
+++ b/src/libsyntax/ext/deriving/default.rs
@@ -55,7 +55,7 @@ fn default_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructur
         cx.ident_of("Default"),
         cx.ident_of("default")
     );
-    let default_call = |span| cx.expr_call_global(span, default_ident.clone(), Vec::new());
+    let default_call = |&: span| cx.expr_call_global(span, default_ident.clone(), Vec::new());
 
     return match *substr.fields {
         StaticStruct(_, ref summary) => {
diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs
index e4e31139d82..9149c20ce1b 100644
--- a/src/libsyntax/ext/deriving/generic/mod.rs
+++ b/src/libsyntax/ext/deriving/generic/mod.rs
@@ -935,7 +935,7 @@ impl<'a> MethodDef<'a> {
         // where each tuple has length = self_args.len()
         let mut match_arms: Vec<ast::Arm> = variants.iter().enumerate()
             .map(|(index, variant)| {
-                let mk_self_pat = |cx: &mut ExtCtxt, self_arg_name: &str| {
+                let mk_self_pat = |&: cx: &mut ExtCtxt, self_arg_name: &str| {
                     let (p, idents) = trait_.create_enum_variant_pattern(cx, type_ident,
                                                                          &**variant,
                                                                          self_arg_name,
diff --git a/src/libsyntax/ext/deriving/hash.rs b/src/libsyntax/ext/deriving/hash.rs
index 72e3b45dc91..9ad0ad16217 100644
--- a/src/libsyntax/ext/deriving/hash.rs
+++ b/src/libsyntax/ext/deriving/hash.rs
@@ -71,7 +71,7 @@ fn hash_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure)
         _ => cx.span_bug(trait_span, "incorrect number of arguments in `deriving(Hash)`")
     };
     let hash_ident = substr.method_ident;
-    let call_hash = |span, thing_expr| {
+    let call_hash = |&: span, thing_expr| {
         let expr = cx.expr_method_call(span, thing_expr, hash_ident, vec!(state_expr.clone()));
         cx.stmt_expr(expr)
     };
diff --git a/src/libsyntax/ext/deriving/mod.rs b/src/libsyntax/ext/deriving/mod.rs
index edf29e670eb..75f763b5c38 100644
--- a/src/libsyntax/ext/deriving/mod.rs
+++ b/src/libsyntax/ext/deriving/mod.rs
@@ -45,7 +45,7 @@ pub fn expand_meta_deriving(cx: &mut ExtCtxt,
                             _span: Span,
                             mitem: &MetaItem,
                             item: &Item,
-                            push: |P<Item>|) {
+                            mut push: Box<FnMut(P<Item>)>) {
     match mitem.node {
         MetaNameValue(_, ref l) => {
             cx.span_err(l.span, "unexpected value in `deriving`");
@@ -64,7 +64,7 @@ pub fn expand_meta_deriving(cx: &mut ExtCtxt,
                     MetaWord(ref tname) => {
                         macro_rules! expand(($func:path) => ($func(cx, titem.span,
                                                                    &**titem, item,
-                                                                   |i| push(i))));
+                                                                   |i| push.call_mut((i,)))));
                         match tname.get() {
                             "Clone" => expand!(clone::expand_deriving_clone),
 
diff --git a/src/libsyntax/ext/deriving/zero.rs b/src/libsyntax/ext/deriving/zero.rs
index ea32549cad2..73331f06aa4 100644
--- a/src/libsyntax/ext/deriving/zero.rs
+++ b/src/libsyntax/ext/deriving/zero.rs
@@ -71,7 +71,7 @@ fn zero_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure)
         cx.ident_of("Zero"),
         cx.ident_of("zero")
     );
-    let zero_call = |span| cx.expr_call_global(span, zero_ident.clone(), Vec::new());
+    let zero_call = |&: span| cx.expr_call_global(span, zero_ident.clone(), Vec::new());
 
     return match *substr.fields {
         StaticStruct(_, ref summary) => {
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 9fcaf2210c1..5de7068563d 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -424,7 +424,7 @@ pub fn expand_item(it: P<ast::Item>, fld: &mut MacroExpander)
                     // but that double-mut-borrows fld
                     let mut items: SmallVector<P<ast::Item>> = SmallVector::zero();
                     dec.expand(fld.cx, attr.span, &*attr.node.value, &*it,
-                               |item| items.push(item));
+                               box |&mut : item| items.push(item));
                     decorator_items.extend(items.into_iter()
                         .flat_map(|item| expand_item(item, fld).into_iter()));
 
@@ -1660,7 +1660,7 @@ mod test {
             assert!((shouldmatch.len() == 0) ||
                     (varrefs.len() > *shouldmatch.iter().max().unwrap()));
             for (idx,varref) in varrefs.iter().enumerate() {
-                let print_hygiene_debug_info = || {
+                let print_hygiene_debug_info = |&:| {
                     // good lord, you can't make a path with 0 segments, can you?
                     let final_varref_ident = match varref.segments.last() {
                         Some(pathsegment) => pathsegment.identifier,
diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs
index 368d4fa8447..d87960ebdb8 100644
--- a/src/libsyntax/ext/quote.rs
+++ b/src/libsyntax/ext/quote.rs
@@ -800,11 +800,11 @@ fn expand_parse_call(cx: &ExtCtxt,
                      tts: &[ast::TokenTree]) -> P<ast::Expr> {
     let (cx_expr, tts_expr) = expand_tts(cx, sp, tts);
 
-    let cfg_call = || cx.expr_method_call(
+    let cfg_call = |&:| cx.expr_method_call(
         sp, cx.expr_ident(sp, id_ext("ext_cx")),
         id_ext("cfg"), Vec::new());
 
-    let parse_sess_call = || cx.expr_method_call(
+    let parse_sess_call = |&:| cx.expr_method_call(
         sp, cx.expr_ident(sp, id_ext("ext_cx")),
         id_ext("parse_sess"), Vec::new());
 
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index 8cefb111fd1..88c485a07ac 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -240,7 +240,7 @@ pub fn new_parser_from_tts<'a>(sess: &'a ParseSess,
 /// add the path to the session's codemap and return the new filemap.
 pub fn file_to_filemap(sess: &ParseSess, path: &Path, spanopt: Option<Span>)
     -> Rc<FileMap> {
-    let err = |msg: &str| {
+    let err = |&: msg: &str| {
         match spanopt {
             Some(sp) => sess.span_diagnostic.span_fatal(sp, msg),
             None => sess.span_diagnostic.handler().fatal(msg),
@@ -399,7 +399,7 @@ pub fn char_lit(lit: &str) -> (char, int) {
         .map(|x| (x, len as int))
     }
 
-    let unicode_escape: || -> Option<(char, int)> = ||
+    let unicode_escape = |&: | -> Option<(char, int)>
         if lit.as_bytes()[2] == b'{' {
             let idx = lit.find('}').expect(msg2);
             let subslice = lit[3..idx];
@@ -426,7 +426,7 @@ pub fn str_lit(lit: &str) -> String {
     let mut res = String::with_capacity(lit.len());
 
     // FIXME #8372: This could be a for-loop if it didn't borrow the iterator
-    let error = |i| format!("lexer should have rejected {} at {}", lit, i);
+    let error = |&: i| format!("lexer should have rejected {} at {}", lit, i);
 
     /// Eat everything up to a non-whitespace
     fn eat<'a>(it: &mut iter::Peekable<(uint, char), str::CharIndices<'a>>) {
@@ -561,7 +561,7 @@ pub fn float_lit(s: &str, suffix: Option<&str>, sd: &SpanHandler, sp: Span) -> a
 
 /// Parse a string representing a byte literal into its final form. Similar to `char_lit`
 pub fn byte_lit(lit: &str) -> (u8, uint) {
-    let err = |i| format!("lexer accepted invalid byte literal {} step {}", lit, i);
+    let err = |&: i| format!("lexer accepted invalid byte literal {} step {}", lit, i);
 
     if lit.len() == 1 {
         (lit.as_bytes()[0], 1)
@@ -595,7 +595,7 @@ pub fn binary_lit(lit: &str) -> Rc<Vec<u8>> {
     let mut res = Vec::with_capacity(lit.len());
 
     // FIXME #8372: This could be a for-loop if it didn't borrow the iterator
-    let error = |i| format!("lexer should have rejected {} at {}", lit, i);
+    let error = |&: i| format!("lexer should have rejected {} at {}", lit, i);
 
     /// Eat everything up to a non-whitespace
     fn eat<'a, I: Iterator<(uint, u8)>>(it: &mut iter::Peekable<(uint, u8), I>) {
diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs
index bc7dda8c44a..93fe868f52c 100644
--- a/src/libsyntax/test.rs
+++ b/src/libsyntax/test.rs
@@ -545,11 +545,11 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P<ast::Expr> {
     let test_id = ecx.ident_of("test");
 
     // creates self::test::$name
-    let test_path = |name| {
+    let test_path = |&: name| {
         ecx.path(span, vec![self_id, test_id, ecx.ident_of(name)])
     };
     // creates $name: $expr
-    let field = |name, expr| ecx.field_imm(span, ecx.ident_of(name), expr);
+    let field = |&: name, expr| ecx.field_imm(span, ecx.ident_of(name), expr);
 
     debug!("encoding {}", ast_util::path_name_i(path[]));
 
@@ -563,7 +563,7 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P<ast::Expr> {
                                   vec![name_expr]);
 
     let ignore_expr = ecx.expr_bool(span, test.ignore);
-    let should_fail_path = |name| {
+    let should_fail_path = |&: name| {
         ecx.path(span, vec![self_id, test_id, ecx.ident_of("ShouldFail"), ecx.ident_of(name)])
     };
     let fail_expr = match test.should_fail {