summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-04-23 12:01:53 -0700
committerbors <bors@rust-lang.org>2014-04-23 12:01:53 -0700
commit6beb376b5c27c6b028092f227f865ba564fea17b (patch)
treeb52fa55b56bb4c1b21d1753c7d5c2402894d3c9b /src/libsyntax
parentb5dd3f05fe95168b5569d0f519636149479eb6ac (diff)
parent823c7eee6a040862abb5a5309693030394200e62 (diff)
downloadrust-6beb376b5c27c6b028092f227f865ba564fea17b.tar.gz
rust-6beb376b5c27c6b028092f227f865ba564fea17b.zip
auto merge of #13686 : alexcrichton/rust/issue-12224, r=nikomatsakis
This alters the borrow checker's requirements on invoking closures from
requiring an immutable borrow to requiring a unique immutable borrow. This means 
that it is illegal to invoke a closure through a `&` pointer because there is no 
guarantee that is not aliased. This does not mean that a closure is required to
be in a mutable location, but rather a location which can be proven to be
unique (often through a mutable pointer).
                                                                                 
For example, the following code is unsound and is no longer allowed:             
                                                                                 
    type Fn<'a> = ||:'a;                                                         
                                                                                 
    fn call(f: |Fn|) {                                                           
        f(|| {                                                                   
            f(|| {})                                                             
        });                                                                      
    }                                                                            
                                                                                 
    fn main() {                                                                  
        call(|a| {                                                               
            a();                                                                 
        });                                                                      
    }                                                                            
                                                                                 
There is no replacement for this pattern. For all closures which are stored in
structures, it was previously allowed to invoke the closure through `&self` but
it now requires invocation through `&mut self`.

The standard library has a good number of violations of this new rule, but the
fixes will be separated into multiple breaking change commits.
                                                                                 
Closes #12224                                                                    
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ext/deriving/clone.rs4
-rw-r--r--src/libsyntax/ext/deriving/cmp/eq.rs4
-rw-r--r--src/libsyntax/ext/deriving/cmp/ord.rs4
-rw-r--r--src/libsyntax/ext/deriving/cmp/totaleq.rs4
-rw-r--r--src/libsyntax/ext/deriving/cmp/totalord.rs4
-rw-r--r--src/libsyntax/ext/deriving/decodable.rs4
-rw-r--r--src/libsyntax/ext/deriving/default.rs4
-rw-r--r--src/libsyntax/ext/deriving/encodable.rs4
-rw-r--r--src/libsyntax/ext/deriving/generic.rs14
-rw-r--r--src/libsyntax/ext/deriving/hash.rs4
-rw-r--r--src/libsyntax/ext/deriving/primitive.rs8
-rw-r--r--src/libsyntax/ext/deriving/rand.rs4
-rw-r--r--src/libsyntax/ext/deriving/show.rs4
-rw-r--r--src/libsyntax/ext/deriving/zero.rs8
14 files changed, 55 insertions, 19 deletions
diff --git a/src/libsyntax/ext/deriving/clone.rs b/src/libsyntax/ext/deriving/clone.rs
index 367accb4b19..e0b493cd8d9 100644
--- a/src/libsyntax/ext/deriving/clone.rs
+++ b/src/libsyntax/ext/deriving/clone.rs
@@ -34,7 +34,9 @@ pub fn expand_deriving_clone(cx: &mut ExtCtxt,
                 ret_ty: Self,
                 inline: true,
                 const_nonmatching: false,
-                combine_substructure: |c, s, sub| cs_clone("Clone", c, s, sub)
+                combine_substructure: combine_substructure(|c, s, sub| {
+                    cs_clone("Clone", c, s, sub)
+                }),
             }
         )
     };
diff --git a/src/libsyntax/ext/deriving/cmp/eq.rs b/src/libsyntax/ext/deriving/cmp/eq.rs
index 975b8885de7..35b7e7c1a66 100644
--- a/src/libsyntax/ext/deriving/cmp/eq.rs
+++ b/src/libsyntax/ext/deriving/cmp/eq.rs
@@ -40,7 +40,9 @@ pub fn expand_deriving_eq(cx: &mut ExtCtxt,
                 ret_ty: Literal(Path::new(vec!("bool"))),
                 inline: true,
                 const_nonmatching: true,
-                combine_substructure: $f
+                combine_substructure: combine_substructure(|a, b, c| {
+                    $f(a, b, c)
+                })
             }
         }
     );
diff --git a/src/libsyntax/ext/deriving/cmp/ord.rs b/src/libsyntax/ext/deriving/cmp/ord.rs
index 5605c0b6107..afe2d3dae6a 100644
--- a/src/libsyntax/ext/deriving/cmp/ord.rs
+++ b/src/libsyntax/ext/deriving/cmp/ord.rs
@@ -30,7 +30,9 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt,
                 ret_ty: Literal(Path::new(vec!("bool"))),
                 inline: true,
                 const_nonmatching: false,
-                combine_substructure: |cx, span, substr| cs_op($op, $equal, cx, span, substr)
+                combine_substructure: combine_substructure(|cx, span, substr| {
+                    cs_op($op, $equal, cx, span, substr)
+                })
             }
         }
     );
diff --git a/src/libsyntax/ext/deriving/cmp/totaleq.rs b/src/libsyntax/ext/deriving/cmp/totaleq.rs
index 33512b3df5e..d161f966850 100644
--- a/src/libsyntax/ext/deriving/cmp/totaleq.rs
+++ b/src/libsyntax/ext/deriving/cmp/totaleq.rs
@@ -48,7 +48,9 @@ pub fn expand_deriving_totaleq(cx: &mut ExtCtxt,
                 ret_ty: nil_ty(),
                 inline: true,
                 const_nonmatching: true,
-                combine_substructure: cs_total_eq_assert
+                combine_substructure: combine_substructure(|a, b, c| {
+                    cs_total_eq_assert(a, b, c)
+                })
             }
         )
     };
diff --git a/src/libsyntax/ext/deriving/cmp/totalord.rs b/src/libsyntax/ext/deriving/cmp/totalord.rs
index a584f8abe05..69c413890e9 100644
--- a/src/libsyntax/ext/deriving/cmp/totalord.rs
+++ b/src/libsyntax/ext/deriving/cmp/totalord.rs
@@ -37,7 +37,9 @@ pub fn expand_deriving_totalord(cx: &mut ExtCtxt,
                 ret_ty: Literal(Path::new(vec!("std", "cmp", "Ordering"))),
                 inline: true,
                 const_nonmatching: false,
-                combine_substructure: cs_cmp
+                combine_substructure: combine_substructure(|a, b, c| {
+                    cs_cmp(a, b, c)
+                }),
             }
         )
     };
diff --git a/src/libsyntax/ext/deriving/decodable.rs b/src/libsyntax/ext/deriving/decodable.rs
index 35a1eb0bb83..6d6cdc55d40 100644
--- a/src/libsyntax/ext/deriving/decodable.rs
+++ b/src/libsyntax/ext/deriving/decodable.rs
@@ -52,7 +52,9 @@ pub fn expand_deriving_decodable(cx: &mut ExtCtxt,
                                           vec!(~Self, ~Literal(Path::new_local("__E"))), true)),
                 inline: false,
                 const_nonmatching: true,
-                combine_substructure: decodable_substructure,
+                combine_substructure: combine_substructure(|a, b, c| {
+                    decodable_substructure(a, b, c)
+                }),
             })
     };
 
diff --git a/src/libsyntax/ext/deriving/default.rs b/src/libsyntax/ext/deriving/default.rs
index 94675f91e9d..633674eff5c 100644
--- a/src/libsyntax/ext/deriving/default.rs
+++ b/src/libsyntax/ext/deriving/default.rs
@@ -34,7 +34,9 @@ pub fn expand_deriving_default(cx: &mut ExtCtxt,
                 ret_ty: Self,
                 inline: true,
                 const_nonmatching: false,
-                combine_substructure: default_substructure
+                combine_substructure: combine_substructure(|a, b, c| {
+                    default_substructure(a, b, c)
+                })
             })
     };
     trait_def.expand(cx, mitem, item, push)
diff --git a/src/libsyntax/ext/deriving/encodable.rs b/src/libsyntax/ext/deriving/encodable.rs
index 806560f6826..acdef8c8645 100644
--- a/src/libsyntax/ext/deriving/encodable.rs
+++ b/src/libsyntax/ext/deriving/encodable.rs
@@ -123,7 +123,9 @@ pub fn expand_deriving_encodable(cx: &mut ExtCtxt,
                                            true)),
                 inline: false,
                 const_nonmatching: true,
-                combine_substructure: encodable_substructure,
+                combine_substructure: combine_substructure(|a, b, c| {
+                    encodable_substructure(a, b, c)
+                }),
             })
     };
 
diff --git a/src/libsyntax/ext/deriving/generic.rs b/src/libsyntax/ext/deriving/generic.rs
index 914451fb402..673745b41e8 100644
--- a/src/libsyntax/ext/deriving/generic.rs
+++ b/src/libsyntax/ext/deriving/generic.rs
@@ -177,6 +177,8 @@ StaticEnum(<ast::EnumDef of C>, ~[(<ident of C0>, <span of C0>, Unnamed(~[<span
 
 */
 
+use std::cell::RefCell;
+
 use ast;
 use ast::{P, EnumDef, Expr, Ident, Generics, StructDef};
 use ast_util;
@@ -234,7 +236,7 @@ pub struct MethodDef<'a> {
     /// actual enum variants, i.e. can use _ => .. match.
     pub const_nonmatching: bool,
 
-    pub combine_substructure: CombineSubstructureFunc<'a>,
+    pub combine_substructure: RefCell<CombineSubstructureFunc<'a>>,
 }
 
 /// All the data about the data structure/method being derived upon.
@@ -317,6 +319,11 @@ pub type EnumNonMatchFunc<'a> =
            &[@Expr]|: 'a
            -> @Expr;
 
+pub fn combine_substructure<'a>(f: CombineSubstructureFunc<'a>)
+    -> RefCell<CombineSubstructureFunc<'a>> {
+    RefCell::new(f)
+}
+
 
 impl<'a> TraitDef<'a> {
     pub fn expand(&self,
@@ -509,8 +516,9 @@ impl<'a> MethodDef<'a> {
             nonself_args: nonself_args,
             fields: fields
         };
-        (self.combine_substructure)(cx, trait_.span,
-                                    &substructure)
+        let mut f = self.combine_substructure.borrow_mut();
+        let f: &mut CombineSubstructureFunc = &mut *f;
+        (*f)(cx, trait_.span, &substructure)
     }
 
     fn get_ret_ty(&self,
diff --git a/src/libsyntax/ext/deriving/hash.rs b/src/libsyntax/ext/deriving/hash.rs
index d22027d203f..9e160b0e35d 100644
--- a/src/libsyntax/ext/deriving/hash.rs
+++ b/src/libsyntax/ext/deriving/hash.rs
@@ -49,7 +49,9 @@ pub fn expand_deriving_hash(cx: &mut ExtCtxt,
                 ret_ty: nil_ty(),
                 inline: true,
                 const_nonmatching: false,
-                combine_substructure: hash_substructure
+                combine_substructure: combine_substructure(|a, b, c| {
+                    hash_substructure(a, b, c)
+                })
             }
         )
     };
diff --git a/src/libsyntax/ext/deriving/primitive.rs b/src/libsyntax/ext/deriving/primitive.rs
index 267a12fdff9..e42a3c67e34 100644
--- a/src/libsyntax/ext/deriving/primitive.rs
+++ b/src/libsyntax/ext/deriving/primitive.rs
@@ -41,7 +41,9 @@ pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt,
                 // liable to cause code-bloat
                 inline: true,
                 const_nonmatching: false,
-                combine_substructure: |c, s, sub| cs_from("i64", c, s, sub),
+                combine_substructure: combine_substructure(|c, s, sub| {
+                    cs_from("i64", c, s, sub)
+                }),
             },
             MethodDef {
                 name: "from_u64",
@@ -56,7 +58,9 @@ pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt,
                 // liable to cause code-bloat
                 inline: true,
                 const_nonmatching: false,
-                combine_substructure: |c, s, sub| cs_from("u64", c, s, sub),
+                combine_substructure: combine_substructure(|c, s, sub| {
+                    cs_from("u64", c, s, sub)
+                }),
             })
     };
 
diff --git a/src/libsyntax/ext/deriving/rand.rs b/src/libsyntax/ext/deriving/rand.rs
index e81aa55d10d..09c3abf42b8 100644
--- a/src/libsyntax/ext/deriving/rand.rs
+++ b/src/libsyntax/ext/deriving/rand.rs
@@ -43,7 +43,9 @@ pub fn expand_deriving_rand(cx: &mut ExtCtxt,
                 ret_ty: Self,
                 inline: false,
                 const_nonmatching: false,
-                combine_substructure: rand_substructure
+                combine_substructure: combine_substructure(|a, b, c| {
+                    rand_substructure(a, b, c)
+                })
             }
         )
     };
diff --git a/src/libsyntax/ext/deriving/show.rs b/src/libsyntax/ext/deriving/show.rs
index 067958e4bde..7098d0dd6ef 100644
--- a/src/libsyntax/ext/deriving/show.rs
+++ b/src/libsyntax/ext/deriving/show.rs
@@ -44,7 +44,9 @@ pub fn expand_deriving_show(cx: &mut ExtCtxt,
                 ret_ty: Literal(Path::new(vec!("std", "fmt", "Result"))),
                 inline: false,
                 const_nonmatching: false,
-                combine_substructure: show_substructure
+                combine_substructure: combine_substructure(|a, b, c| {
+                    show_substructure(a, b, c)
+                })
             }
         )
     };
diff --git a/src/libsyntax/ext/deriving/zero.rs b/src/libsyntax/ext/deriving/zero.rs
index 10692bd7f93..0aeeabcaeab 100644
--- a/src/libsyntax/ext/deriving/zero.rs
+++ b/src/libsyntax/ext/deriving/zero.rs
@@ -34,7 +34,9 @@ pub fn expand_deriving_zero(cx: &mut ExtCtxt,
                 ret_ty: Self,
                 inline: true,
                 const_nonmatching: false,
-                combine_substructure: zero_substructure
+                combine_substructure: combine_substructure(|a, b, c| {
+                    zero_substructure(a, b, c)
+                })
             },
             MethodDef {
                 name: "is_zero",
@@ -44,13 +46,13 @@ pub fn expand_deriving_zero(cx: &mut ExtCtxt,
                 ret_ty: Literal(Path::new(vec!("bool"))),
                 inline: true,
                 const_nonmatching: false,
-                combine_substructure: |cx, span, substr| {
+                combine_substructure: combine_substructure(|cx, span, substr| {
                     cs_and(|cx, span, _, _| cx.span_bug(span,
                                                         "Non-matching enum \
                                                          variant in \
                                                          deriving(Zero)"),
                            cx, span, substr)
-                }
+                })
             }
         )
     };