Skip to content

Commit ec60976

Browse files
pcwaltonpnkfelix
authored andcommitted
libsyntax: manually copy lambda exprs to accommodate by-val upvars.
1 parent efa9baf commit ec60976

File tree

5 files changed

+88
-23
lines changed

5 files changed

+88
-23
lines changed

src/libsyntax/ext/deriving/clone.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,6 @@ fn cs_clone(
5454
let clone_ident = substr.method_ident;
5555
let ctor_ident;
5656
let all_fields;
57-
let subcall = |field: &FieldInfo|
58-
cx.expr_method_call(field.span, field.self_, clone_ident, Vec::new());
5957

6058
match *substr.fields {
6159
Struct(ref af) => {
@@ -81,7 +79,15 @@ fn cs_clone(
8179

8280
if all_fields.len() >= 1 && all_fields.get(0).name.is_none() {
8381
// enum-like
84-
let subcalls = all_fields.iter().map(subcall).collect();
82+
let subcalls = {
83+
let subcall = |field: &FieldInfo| {
84+
cx.expr_method_call(field.span,
85+
field.self_,
86+
clone_ident,
87+
Vec::new())
88+
};
89+
all_fields.iter().map(subcall).collect()
90+
};
8591
cx.expr_call_ident(trait_span, ctor_ident, subcalls)
8692
} else {
8793
// struct-like
@@ -95,6 +101,12 @@ fn cs_clone(
95101
name).as_slice())
96102
}
97103
};
104+
let subcall = |field: &FieldInfo| {
105+
cx.expr_method_call(field.span,
106+
field.self_,
107+
clone_ident,
108+
Vec::new())
109+
};
98110
cx.field_imm(field.span, ident, subcall(field))
99111
}).collect::<Vec<_>>();
100112

src/libsyntax/ext/deriving/default.rs

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ fn default_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructur
5252
cx.ident_of("Default"),
5353
cx.ident_of("default")
5454
);
55-
let default_call = |span| cx.expr_call_global(span, default_ident.clone(), Vec::new());
5655

5756
return match *substr.fields {
5857
StaticStruct(_, ref summary) => {
@@ -61,14 +60,35 @@ fn default_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructur
6160
if fields.is_empty() {
6261
cx.expr_ident(trait_span, substr.type_ident)
6362
} else {
64-
let exprs = fields.iter().map(|sp| default_call(*sp)).collect();
65-
cx.expr_call_ident(trait_span, substr.type_ident, exprs)
63+
let exprs = {
64+
let default_call = |span| {
65+
cx.expr_call_global(span,
66+
default_ident.clone(),
67+
Vec::new())
68+
};
69+
fields.iter()
70+
.map(|sp| default_call(*sp))
71+
.collect()
72+
};
73+
cx.expr_call_ident(trait_span,
74+
substr.type_ident,
75+
exprs)
6676
}
6777
}
6878
Named(ref fields) => {
69-
let default_fields = fields.iter().map(|&(ident, span)| {
70-
cx.field_imm(span, ident, default_call(span))
71-
}).collect();
79+
let default_fields = {
80+
let cx: &ExtCtxt = cx;
81+
let default_ident_ref = &default_ident;
82+
fields.iter().map(|&(ident, span)| {
83+
let default_call = |span| {
84+
cx.expr_call_global(
85+
span,
86+
(*default_ident_ref).clone(),
87+
Vec::new())
88+
};
89+
cx.field_imm(span, ident, default_call(span))
90+
}).collect()
91+
};
7292
cx.expr_struct_ident(trait_span, substr.type_ident, default_fields)
7393
}
7494
}

src/libsyntax/ext/deriving/hash.rs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,6 @@ fn hash_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure)
6969
_ => cx.span_bug(trait_span, "incorrect number of arguments in `deriving(Hash)`")
7070
};
7171
let hash_ident = substr.method_ident;
72-
let call_hash = |span, thing_expr| {
73-
let expr = cx.expr_method_call(span, thing_expr, hash_ident, vec!(state_expr));
74-
cx.stmt_expr(expr)
75-
};
7672
let mut stmts = Vec::new();
7773

7874
let fields = match *substr.fields {
@@ -85,6 +81,13 @@ fn hash_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure)
8581
None => cx.expr_uint(trait_span, index)
8682
};
8783

84+
let call_hash = |span, thing_expr| {
85+
let expr = cx.expr_method_call(span,
86+
thing_expr,
87+
hash_ident,
88+
vec!(state_expr));
89+
cx.stmt_expr(expr)
90+
};
8891
stmts.push(call_hash(trait_span, discriminant));
8992

9093
fs
@@ -93,6 +96,13 @@ fn hash_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure)
9396
};
9497

9598
for &FieldInfo { self_, span, .. } in fields.iter() {
99+
let call_hash = |span, thing_expr| {
100+
let expr = cx.expr_method_call(span,
101+
thing_expr,
102+
hash_ident,
103+
vec!(state_expr));
104+
cx.stmt_expr(expr)
105+
};
96106
stmts.push(call_hash(span, self_));
97107
}
98108

src/libsyntax/ext/deriving/rand.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,14 @@ fn rand_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure)
6262
cx.ident_of("Rand"),
6363
cx.ident_of("rand")
6464
);
65-
let rand_call = |cx: &mut ExtCtxt, span| {
66-
cx.expr_call_global(span,
67-
rand_ident.clone(),
68-
vec!( *rng.get(0) ))
69-
};
7065

7166
return match *substr.fields {
7267
StaticStruct(_, ref summary) => {
68+
let rand_call = |cx: &mut ExtCtxt, span| {
69+
cx.expr_call_global(span,
70+
rand_ident.clone(),
71+
vec!( *rng.get(0) ))
72+
};
7373
rand_thing(cx, trait_span, substr.type_ident, summary, rand_call)
7474
}
7575
StaticEnum(_, ref variants) => {
@@ -113,6 +113,13 @@ fn rand_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure)
113113
let i_expr = cx.expr_uint(v_span, i);
114114
let pat = cx.pat_lit(v_span, i_expr);
115115

116+
let rand_ident_ptr = &rand_ident;
117+
let rng_ptr = &rng;
118+
let rand_call = |cx: &mut ExtCtxt, span| {
119+
cx.expr_call_global(span,
120+
(*rand_ident_ptr).clone(),
121+
vec!( *(*rng_ptr).get(0) ))
122+
};
116123
let thing = rand_thing(cx, v_span, ident, summary, |cx, sp| rand_call(cx, sp));
117124
cx.arm(v_span, vec!( pat ), thing)
118125
}).collect::<Vec<ast::Arm> >();

src/libsyntax/ext/deriving/zero.rs

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ fn zero_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure)
6969
cx.ident_of("Zero"),
7070
cx.ident_of("zero")
7171
);
72-
let zero_call = |span| cx.expr_call_global(span, zero_ident.clone(), Vec::new());
7372

7473
return match *substr.fields {
7574
StaticStruct(_, ref summary) => {
@@ -78,14 +77,31 @@ fn zero_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure)
7877
if fields.is_empty() {
7978
cx.expr_ident(trait_span, substr.type_ident)
8079
} else {
81-
let exprs = fields.iter().map(|sp| zero_call(*sp)).collect();
80+
let exprs = {
81+
let zero_call = |span| {
82+
cx.expr_call_global(span,
83+
zero_ident.clone(),
84+
Vec::new())
85+
};
86+
fields.iter().map(|sp| zero_call(*sp)).collect()
87+
};
8288
cx.expr_call_ident(trait_span, substr.type_ident, exprs)
8389
}
8490
}
8591
Named(ref fields) => {
86-
let zero_fields = fields.iter().map(|&(ident, span)| {
87-
cx.field_imm(span, ident, zero_call(span))
88-
}).collect();
92+
let zero_fields = {
93+
let cx: &ExtCtxt = cx;
94+
let zero_ident_ref = &zero_ident;
95+
fields.iter().map(|&(ident, span)| {
96+
let zero_call = |span| {
97+
cx.expr_call_global(
98+
span,
99+
(*zero_ident_ref).clone(),
100+
Vec::new())
101+
};
102+
cx.field_imm(span, ident, zero_call(span))
103+
}).collect()
104+
};
89105
cx.expr_struct_ident(trait_span, substr.type_ident, zero_fields)
90106
}
91107
}

0 commit comments

Comments
 (0)