auto merge of #11834 : huonw/rust/deriving-spans, r=alexcrichton

I'd forgotten to update them when I changed this a while ago; it now displays error messages linked to the struct/variant field, rather than the `#[deriving(Trait)]` line, for all traits.

This also adds a very large number of autogenerated tests. I can easily remove/tone down that commit if necessary.
This commit is contained in:
bors
2014-01-27 01:21:31 -08:00
42 changed files with 1053 additions and 167 deletions

View File

@@ -74,13 +74,13 @@ pub fn expand_deriving_deep_clone(cx: &ExtCtxt,
fn cs_clone(
name: &str,
cx: &ExtCtxt, span: Span,
cx: &ExtCtxt, trait_span: Span,
substr: &Substructure) -> @Expr {
let clone_ident = substr.method_ident;
let ctor_ident;
let all_fields;
let subcall = |field|
cx.expr_method_call(span, field, clone_ident, ~[]);
let subcall = |field: &FieldInfo|
cx.expr_method_call(field.span, field.self_, clone_ident, ~[]);
match *substr.fields {
Struct(ref af) => {
@@ -91,37 +91,37 @@ fn cs_clone(
ctor_ident = variant.node.name;
all_fields = af;
},
EnumNonMatching(..) => cx.span_bug(span,
format!("Non-matching enum variants in `deriving({})`",
name)),
StaticEnum(..) | StaticStruct(..) => cx.span_bug(span,
format!("Static method in `deriving({})`",
name))
EnumNonMatching(..) => cx.span_bug(trait_span,
format!("Non-matching enum variants in `deriving({})`",
name)),
StaticEnum(..) | StaticStruct(..) => cx.span_bug(trait_span,
format!("Static method in `deriving({})`",
name))
}
match *all_fields {
[FieldInfo { name: None, .. }, ..] => {
// enum-like
let subcalls = all_fields.map(|field| subcall(field.self_));
cx.expr_call_ident(span, ctor_ident, subcalls)
let subcalls = all_fields.map(subcall);
cx.expr_call_ident(trait_span, ctor_ident, subcalls)
},
_ => {
// struct-like
let fields = all_fields.map(|field| {
let ident = match field.name {
Some(i) => i,
None => cx.span_bug(span,
None => cx.span_bug(trait_span,
format!("unnamed field in normal struct in `deriving({})`",
name))
name))
};
cx.field_imm(span, ident, subcall(field.self_))
cx.field_imm(field.span, ident, subcall(field))
});
if fields.is_empty() {
// no fields, so construct like `None`
cx.expr_ident(span, ctor_ident)
cx.expr_ident(trait_span, ctor_ident)
} else {
cx.expr_struct_ident(span, ctor_ident, fields)
cx.expr_struct_ident(trait_span, ctor_ident, fields)
}
}
}

View File

@@ -51,7 +51,7 @@ pub fn expand_deriving_decodable(cx: &ExtCtxt,
trait_def.expand(mitem, in_items)
}
fn decodable_substructure(cx: &ExtCtxt, span: Span,
fn decodable_substructure(cx: &ExtCtxt, trait_span: Span,
substr: &Substructure) -> @Expr {
let decoder = substr.nonself_args[0];
let recurse = ~[cx.ident_of("extra"),
@@ -60,9 +60,9 @@ fn decodable_substructure(cx: &ExtCtxt, span: Span,
cx.ident_of("decode")];
// throw an underscore in front to suppress unused variable warnings
let blkarg = cx.ident_of("_d");
let blkdecoder = cx.expr_ident(span, blkarg);
let calldecode = cx.expr_call_global(span, recurse, ~[blkdecoder]);
let lambdadecode = cx.lambda_expr_1(span, calldecode, blkarg);
let blkdecoder = cx.expr_ident(trait_span, blkarg);
let calldecode = cx.expr_call_global(trait_span, recurse, ~[blkdecoder]);
let lambdadecode = cx.lambda_expr_1(trait_span, calldecode, blkarg);
return match *substr.fields {
StaticStruct(_, ref summary) => {
@@ -73,7 +73,7 @@ fn decodable_substructure(cx: &ExtCtxt, span: Span,
let read_struct_field = cx.ident_of("read_struct_field");
let result = decode_static_fields(cx,
span,
trait_span,
substr.type_ident,
summary,
|span, name, field| {
@@ -82,10 +82,10 @@ fn decodable_substructure(cx: &ExtCtxt, span: Span,
cx.expr_uint(span, field),
lambdadecode])
});
cx.expr_method_call(span, decoder, cx.ident_of("read_struct"),
~[cx.expr_str(span, cx.str_of(substr.type_ident)),
cx.expr_uint(span, nfields),
cx.lambda_expr_1(span, result, blkarg)])
cx.expr_method_call(trait_span, decoder, cx.ident_of("read_struct"),
~[cx.expr_str(trait_span, cx.str_of(substr.type_ident)),
cx.expr_uint(trait_span, nfields),
cx.lambda_expr_1(trait_span, result, blkarg)])
}
StaticEnum(_, ref fields) => {
let variant = cx.ident_of("i");
@@ -94,12 +94,11 @@ fn decodable_substructure(cx: &ExtCtxt, span: Span,
let mut variants = ~[];
let rvariant_arg = cx.ident_of("read_enum_variant_arg");
for (i, f) in fields.iter().enumerate() {
let (name, parts) = match *f { (i, ref p) => (i, p) };
variants.push(cx.expr_str(span, cx.str_of(name)));
for (i, &(name, v_span, ref parts)) in fields.iter().enumerate() {
variants.push(cx.expr_str(v_span, cx.str_of(name)));
let decoded = decode_static_fields(cx,
span,
v_span,
name,
parts,
|span, _, field| {
@@ -108,22 +107,22 @@ fn decodable_substructure(cx: &ExtCtxt, span: Span,
lambdadecode])
});
arms.push(cx.arm(span,
~[cx.pat_lit(span, cx.expr_uint(span, i))],
arms.push(cx.arm(v_span,
~[cx.pat_lit(v_span, cx.expr_uint(v_span, i))],
decoded));
}
arms.push(cx.arm_unreachable(span));
arms.push(cx.arm_unreachable(trait_span));
let result = cx.expr_match(span, cx.expr_ident(span, variant), arms);
let lambda = cx.lambda_expr(span, ~[blkarg, variant], result);
let variant_vec = cx.expr_vec(span, variants);
let result = cx.expr_method_call(span, blkdecoder,
let result = cx.expr_match(trait_span, cx.expr_ident(trait_span, variant), arms);
let lambda = cx.lambda_expr(trait_span, ~[blkarg, variant], result);
let variant_vec = cx.expr_vec(trait_span, variants);
let result = cx.expr_method_call(trait_span, blkdecoder,
cx.ident_of("read_enum_variant"),
~[variant_vec, lambda]);
cx.expr_method_call(span, decoder, cx.ident_of("read_enum"),
~[cx.expr_str(span, cx.str_of(substr.type_ident)),
cx.lambda_expr_1(span, result, blkarg)])
cx.expr_method_call(trait_span, decoder, cx.ident_of("read_enum"),
~[cx.expr_str(trait_span, cx.str_of(substr.type_ident)),
cx.lambda_expr_1(trait_span, result, blkarg)])
}
_ => cx.bug("expected StaticEnum or StaticStruct in deriving(Decodable)")
};
@@ -133,7 +132,7 @@ fn decodable_substructure(cx: &ExtCtxt, span: Span,
/// - `outer_pat_ident` is the name of this enum variant/struct
/// - `getarg` should retrieve the `uint`-th field with name `@str`.
fn decode_static_fields(cx: &ExtCtxt,
outer_span: Span,
trait_span: Span,
outer_pat_ident: Ident,
fields: &StaticFields,
getarg: |Span, @str, uint| -> @Expr)
@@ -141,13 +140,13 @@ fn decode_static_fields(cx: &ExtCtxt,
match *fields {
Unnamed(ref fields) => {
if fields.is_empty() {
cx.expr_ident(outer_span, outer_pat_ident)
cx.expr_ident(trait_span, outer_pat_ident)
} else {
let fields = fields.iter().enumerate().map(|(i, &span)| {
getarg(span, format!("_field{}", i).to_managed(), i)
}).collect();
cx.expr_call_ident(outer_span, outer_pat_ident, fields)
cx.expr_call_ident(trait_span, outer_pat_ident, fields)
}
}
Named(ref fields) => {
@@ -155,7 +154,7 @@ fn decode_static_fields(cx: &ExtCtxt,
let fields = fields.iter().enumerate().map(|(i, &(name, span))| {
cx.field_imm(span, name, getarg(span, cx.str_of(name), i))
}).collect();
cx.expr_struct_ident(outer_span, outer_pat_ident, fields)
cx.expr_struct_ident(trait_span, outer_pat_ident, fields)
}
}
}

View File

@@ -41,7 +41,7 @@ pub fn expand_deriving_default(cx: &ExtCtxt,
trait_def.expand(mitem, in_items)
}
fn default_substructure(cx: &ExtCtxt, span: Span, substr: &Substructure) -> @Expr {
fn default_substructure(cx: &ExtCtxt, trait_span: Span, substr: &Substructure) -> @Expr {
let default_ident = ~[
cx.ident_of("std"),
cx.ident_of("default"),
@@ -55,25 +55,25 @@ fn default_substructure(cx: &ExtCtxt, span: Span, substr: &Substructure) -> @Exp
match *summary {
Unnamed(ref fields) => {
if fields.is_empty() {
cx.expr_ident(span, substr.type_ident)
cx.expr_ident(trait_span, substr.type_ident)
} else {
let exprs = fields.map(|sp| default_call(*sp));
cx.expr_call_ident(span, substr.type_ident, exprs)
cx.expr_call_ident(trait_span, substr.type_ident, exprs)
}
}
Named(ref fields) => {
let default_fields = fields.map(|&(ident, span)| {
cx.field_imm(span, ident, default_call(span))
});
cx.expr_struct_ident(span, substr.type_ident, default_fields)
cx.expr_struct_ident(trait_span, substr.type_ident, default_fields)
}
}
}
StaticEnum(..) => {
cx.span_err(span, "`Default` cannot be derived for enums, only structs");
cx.span_err(trait_span, "`Default` cannot be derived for enums, only structs");
// let compilation continue
cx.expr_uint(span, 0)
cx.expr_uint(trait_span, 0)
}
_ => cx.bug("Non-static method in `deriving(Default)`")
_ => cx.span_bug(trait_span, "Non-static method in `deriving(Default)`")
};
}

View File

@@ -113,24 +113,24 @@ pub fn expand_deriving_encodable(cx: &ExtCtxt,
trait_def.expand(mitem, in_items)
}
fn encodable_substructure(cx: &ExtCtxt, span: Span,
fn encodable_substructure(cx: &ExtCtxt, trait_span: Span,
substr: &Substructure) -> @Expr {
let encoder = substr.nonself_args[0];
// throw an underscore in front to suppress unused variable warnings
let blkarg = cx.ident_of("_e");
let blkencoder = cx.expr_ident(span, blkarg);
let blkencoder = cx.expr_ident(trait_span, blkarg);
let encode = cx.ident_of("encode");
return match *substr.fields {
Struct(ref fields) => {
let emit_struct_field = cx.ident_of("emit_struct_field");
let mut stmts = ~[];
for (i, f) in fields.iter().enumerate() {
let name = match f.name {
for (i, &FieldInfo { name, self_, span, .. }) in fields.iter().enumerate() {
let name = match name {
Some(id) => cx.str_of(id),
None => format!("_field{}", i).to_managed()
};
let enc = cx.expr_method_call(span, f.self_, encode, ~[blkencoder]);
let enc = cx.expr_method_call(span, self_, encode, ~[blkencoder]);
let lambda = cx.lambda_expr_1(span, enc, blkarg);
let call = cx.expr_method_call(span, blkencoder,
emit_struct_field,
@@ -140,10 +140,10 @@ fn encodable_substructure(cx: &ExtCtxt, span: Span,
stmts.push(cx.stmt_expr(call));
}
let blk = cx.lambda_stmts_1(span, stmts, blkarg);
cx.expr_method_call(span, encoder, cx.ident_of("emit_struct"),
~[cx.expr_str(span, cx.str_of(substr.type_ident)),
cx.expr_uint(span, fields.len()),
let blk = cx.lambda_stmts_1(trait_span, stmts, blkarg);
cx.expr_method_call(trait_span, encoder, cx.ident_of("emit_struct"),
~[cx.expr_str(trait_span, cx.str_of(substr.type_ident)),
cx.expr_uint(trait_span, fields.len()),
blk])
}
@@ -152,12 +152,12 @@ fn encodable_substructure(cx: &ExtCtxt, span: Span,
// so we need to generate a unique local variable to take the
// mutable loan out on, otherwise we get conflicts which don't
// actually exist.
let me = cx.stmt_let(span, false, blkarg, encoder);
let encoder = cx.expr_ident(span, blkarg);
let me = cx.stmt_let(trait_span, false, blkarg, encoder);
let encoder = cx.expr_ident(trait_span, blkarg);
let emit_variant_arg = cx.ident_of("emit_enum_variant_arg");
let mut stmts = ~[];
for (i, f) in fields.iter().enumerate() {
let enc = cx.expr_method_call(span, f.self_, encode, ~[blkencoder]);
for (i, &FieldInfo { self_, span, .. }) in fields.iter().enumerate() {
let enc = cx.expr_method_call(span, self_, encode, ~[blkencoder]);
let lambda = cx.lambda_expr_1(span, enc, blkarg);
let call = cx.expr_method_call(span, blkencoder,
emit_variant_arg,
@@ -166,21 +166,21 @@ fn encodable_substructure(cx: &ExtCtxt, span: Span,
stmts.push(cx.stmt_expr(call));
}
let blk = cx.lambda_stmts_1(span, stmts, blkarg);
let name = cx.expr_str(span, cx.str_of(variant.node.name));
let call = cx.expr_method_call(span, blkencoder,
let blk = cx.lambda_stmts_1(trait_span, stmts, blkarg);
let name = cx.expr_str(trait_span, cx.str_of(variant.node.name));
let call = cx.expr_method_call(trait_span, blkencoder,
cx.ident_of("emit_enum_variant"),
~[name,
cx.expr_uint(span, idx),
cx.expr_uint(span, fields.len()),
cx.expr_uint(trait_span, idx),
cx.expr_uint(trait_span, fields.len()),
blk]);
let blk = cx.lambda_expr_1(span, call, blkarg);
let ret = cx.expr_method_call(span, encoder,
let blk = cx.lambda_expr_1(trait_span, call, blkarg);
let ret = cx.expr_method_call(trait_span, encoder,
cx.ident_of("emit_enum"),
~[cx.expr_str(span,
~[cx.expr_str(trait_span,
cx.str_of(substr.type_ident)),
blk]);
cx.expr_block(cx.block(span, ~[me], Some(ret)))
cx.expr_block(cx.block(trait_span, ~[me], Some(ret)))
}
_ => cx.bug("expected Struct or EnumMatching in deriving(Encodable)")

View File

@@ -68,6 +68,7 @@ enum C {
C0(int),
C1 { x: int }
}
~~~
The `int`s in `B` and `C0` don't have an identifier, so the
`Option<ident>`s would be `None` for them.
@@ -168,8 +169,9 @@ StaticStruct(<ast::StructDef of A>, Named(~[(<ident of x>, <span of x>)]))
StaticStruct(<ast::StructDef of B>, Unnamed(~[<span of x>]))
StaticEnum(<ast::EnumDef of C>, ~[(<ident of C0>, Unnamed(~[<span of int>])),
(<ident of C1>, Named(~[(<ident of x>, <span of x>)]))])
StaticEnum(<ast::EnumDef of C>, ~[(<ident of C0>, <span of C0>, Unnamed(~[<span of int>])),
(<ident of C1>, <span of C1>,
Named(~[(<ident of x>, <span of x>)]))])
~~~
*/
@@ -290,7 +292,7 @@ pub enum SubstructureFields<'a> {
/// A static method where Self is a struct.
StaticStruct(&'a ast::StructDef, StaticFields),
/// A static method where Self is an enum.
StaticEnum(&'a ast::EnumDef, ~[(Ident, StaticFields)])
StaticEnum(&'a ast::EnumDef, ~[(Ident, Span, StaticFields)])
}
@@ -904,7 +906,7 @@ impl<'a> MethodDef<'a> {
trait_.summarise_struct(struct_def)
}
};
(ident, summary)
(ident, v.span, summary)
});
self.call_substructure_method(trait_, type_ident,
self_args, nonself_args,

View File

@@ -45,19 +45,20 @@ pub fn expand_deriving_iter_bytes(cx: &ExtCtxt,
trait_def.expand(mitem, in_items)
}
fn iter_bytes_substructure(cx: &ExtCtxt, span: Span, substr: &Substructure) -> @Expr {
fn iter_bytes_substructure(cx: &ExtCtxt, trait_span: Span, substr: &Substructure) -> @Expr {
let (lsb0, f)= match substr.nonself_args {
[l, f] => (l, f),
_ => cx.span_bug(span, "Incorrect number of arguments in `deriving(IterBytes)`")
_ => cx.span_bug(trait_span, "Incorrect number of arguments in `deriving(IterBytes)`")
};
// Build the "explicitly borrowed" stack closure, "|_buf| f(_buf)".
let blk_arg = cx.ident_of("_buf");
let borrowed_f =
cx.lambda_expr_1(span, cx.expr_call(span, f, ~[cx.expr_ident(span, blk_arg)]),
cx.lambda_expr_1(trait_span,
cx.expr_call(trait_span, f, ~[cx.expr_ident(trait_span, blk_arg)]),
blk_arg);
let iter_bytes_ident = substr.method_ident;
let call_iterbytes = |thing_expr| {
let call_iterbytes = |span, thing_expr| {
cx.expr_method_call(span,
thing_expr,
iter_bytes_ident,
@@ -74,25 +75,25 @@ fn iter_bytes_substructure(cx: &ExtCtxt, span: Span, substr: &Substructure) -> @
// iteration function.
let discriminant = match variant.node.disr_expr {
Some(d)=> d,
None => cx.expr_uint(span, index)
None => cx.expr_uint(trait_span, index)
};
exprs.push(call_iterbytes(discriminant));
exprs.push(call_iterbytes(trait_span, discriminant));
fields = fs;
}
_ => cx.span_bug(span, "Impossible substructure in `deriving(IterBytes)`")
_ => cx.span_bug(trait_span, "Impossible substructure in `deriving(IterBytes)`")
}
for &FieldInfo { self_, .. } in fields.iter() {
exprs.push(call_iterbytes(self_));
for &FieldInfo { self_, span, .. } in fields.iter() {
exprs.push(call_iterbytes(span, self_));
}
if exprs.len() == 0 {
cx.span_bug(span, "#[deriving(IterBytes)] needs at least one field");
cx.span_bug(trait_span, "#[deriving(IterBytes)] needs at least one field");
}
exprs.slice(1, exprs.len()).iter().fold(exprs[0], |prev, me| {
cx.expr_binary(span, BiAnd, prev, *me)
cx.expr_binary(trait_span, BiAnd, prev, *me)
})
}

View File

@@ -64,21 +64,22 @@ pub fn expand_deriving_from_primitive(cx: &ExtCtxt,
trait_def.expand(mitem, in_items)
}
fn cs_from(name: &str, cx: &ExtCtxt, span: Span, substr: &Substructure) -> @Expr {
fn cs_from(name: &str, cx: &ExtCtxt, trait_span: Span, substr: &Substructure) -> @Expr {
let n = match substr.nonself_args {
[n] => n,
_ => cx.span_bug(span, "Incorrect number of arguments in `deriving(FromPrimitive)`")
_ => cx.span_bug(trait_span, "Incorrect number of arguments in `deriving(FromPrimitive)`")
};
match *substr.fields {
StaticStruct(..) => {
cx.span_err(span, "`FromPrimitive` cannot be derived for structs");
return cx.expr_fail(span, @"");
cx.span_err(trait_span, "`FromPrimitive` cannot be derived for structs");
return cx.expr_fail(trait_span, @"");
}
StaticEnum(enum_def, _) => {
if enum_def.variants.is_empty() {
cx.span_err(span, "`FromPrimitive` cannot be derived for enums with no variants");
return cx.expr_fail(span, @"");
cx.span_err(trait_span,
"`FromPrimitive` cannot be derived for enums with no variants");
return cx.expr_fail(trait_span, @"");
}
let mut arms = ~[];
@@ -87,10 +88,12 @@ fn cs_from(name: &str, cx: &ExtCtxt, span: Span, substr: &Substructure) -> @Expr
match variant.node.kind {
ast::TupleVariantKind(ref args) => {
if !args.is_empty() {
cx.span_err(span, "`FromPrimitive` cannot be derived for \
enum variants with arguments");
return cx.expr_fail(span, @"");
cx.span_err(trait_span,
"`FromPrimitive` cannot be derived for \
enum variants with arguments");
return cx.expr_fail(trait_span, @"");
}
let span = variant.span;
// expr for `$n == $variant as $name`
let variant = cx.expr_ident(span, variant.node.name);
@@ -111,23 +114,24 @@ fn cs_from(name: &str, cx: &ExtCtxt, span: Span, substr: &Substructure) -> @Expr
arms.push(arm);
}
ast::StructVariantKind(_) => {
cx.span_err(span, "`FromPrimitive` cannot be derived for enums \
with struct variants");
return cx.expr_fail(span, @"");
cx.span_err(trait_span,
"`FromPrimitive` cannot be derived for enums \
with struct variants");
return cx.expr_fail(trait_span, @"");
}
}
}
// arm for `_ => None`
let arm = ast::Arm {
pats: ~[cx.pat_wild(span)],
pats: ~[cx.pat_wild(trait_span)],
guard: None,
body: cx.block_expr(cx.expr_none(span)),
body: cx.block_expr(cx.expr_none(trait_span)),
};
arms.push(arm);
cx.expr_match(span, n, arms)
cx.expr_match(trait_span, n, arms)
}
_ => cx.bug("expected StaticEnum in deriving(FromPrimitive)")
_ => cx.span_bug(trait_span, "expected StaticEnum in deriving(FromPrimitive)")
}
}

View File

@@ -50,7 +50,7 @@ pub fn expand_deriving_rand(cx: &ExtCtxt,
trait_def.expand(mitem, in_items)
}
fn rand_substructure(cx: &ExtCtxt, span: Span, substr: &Substructure) -> @Expr {
fn rand_substructure(cx: &ExtCtxt, trait_span: Span, substr: &Substructure) -> @Expr {
let rng = match substr.nonself_args {
[rng] => ~[ rng ],
_ => cx.bug("Incorrect number of arguments to `rand` in `deriving(Rand)`")
@@ -69,18 +69,18 @@ fn rand_substructure(cx: &ExtCtxt, span: Span, substr: &Substructure) -> @Expr {
return match *substr.fields {
StaticStruct(_, ref summary) => {
rand_thing(cx, span, substr.type_ident, summary, rand_call)
rand_thing(cx, trait_span, substr.type_ident, summary, rand_call)
}
StaticEnum(_, ref variants) => {
if variants.is_empty() {
cx.span_err(span, "`Rand` cannot be derived for enums with no variants");
cx.span_err(trait_span, "`Rand` cannot be derived for enums with no variants");
// let compilation continue
return cx.expr_uint(span, 0);
return cx.expr_uint(trait_span, 0);
}
let variant_count = cx.expr_uint(span, variants.len());
let variant_count = cx.expr_uint(trait_span, variants.len());
let rand_name = cx.path_all(span,
let rand_name = cx.path_all(trait_span,
true,
rand_ident.clone(),
opt_vec::Empty,
@@ -88,52 +88,48 @@ fn rand_substructure(cx: &ExtCtxt, span: Span, substr: &Substructure) -> @Expr {
let rand_name = cx.expr_path(rand_name);
// ::std::rand::Rand::rand(rng)
let rv_call = cx.expr_call(span,
let rv_call = cx.expr_call(trait_span,
rand_name,
~[ rng[0] ]);
// need to specify the uint-ness of the random number
let uint_ty = cx.ty_ident(span, cx.ident_of("uint"));
let uint_ty = cx.ty_ident(trait_span, cx.ident_of("uint"));
let value_ident = cx.ident_of("__value");
let let_statement = cx.stmt_let_typed(span,
let let_statement = cx.stmt_let_typed(trait_span,
false,
value_ident,
uint_ty,
rv_call);
// rand() % variants.len()
let value_ref = cx.expr_ident(span, value_ident);
let rand_variant = cx.expr_binary(span,
let value_ref = cx.expr_ident(trait_span, value_ident);
let rand_variant = cx.expr_binary(trait_span,
ast::BiRem,
value_ref,
variant_count);
let mut arms = variants.iter().enumerate().map(|(i, id_sum)| {
let i_expr = cx.expr_uint(span, i);
let pat = cx.pat_lit(span, i_expr);
let mut arms = variants.iter().enumerate().map(|(i, &(ident, v_span, ref summary))| {
let i_expr = cx.expr_uint(v_span, i);
let pat = cx.pat_lit(v_span, i_expr);
match *id_sum {
(ident, ref summary) => {
cx.arm(span,
~[ pat ],
rand_thing(cx, span, ident, summary, |sp| rand_call(sp)))
}
}
cx.arm(v_span,
~[ pat ],
rand_thing(cx, v_span, ident, summary, |sp| rand_call(sp)))
}).collect::<~[ast::Arm]>();
// _ => {} at the end. Should never occur
arms.push(cx.arm_unreachable(span));
arms.push(cx.arm_unreachable(trait_span));
let match_expr = cx.expr_match(span, rand_variant, arms);
let match_expr = cx.expr_match(trait_span, rand_variant, arms);
let block = cx.block(span, ~[ let_statement ], Some(match_expr));
let block = cx.block(trait_span, ~[ let_statement ], Some(match_expr));
cx.expr_block(block)
}
_ => cx.bug("Non-static method in `deriving(Rand)`")
};
fn rand_thing(cx: &ExtCtxt,
span: Span,
trait_span: Span,
ctor_ident: Ident,
summary: &StaticFields,
rand_call: |Span| -> @Expr)
@@ -141,17 +137,17 @@ fn rand_substructure(cx: &ExtCtxt, span: Span, substr: &Substructure) -> @Expr {
match *summary {
Unnamed(ref fields) => {
if fields.is_empty() {
cx.expr_ident(span, ctor_ident)
cx.expr_ident(trait_span, ctor_ident)
} else {
let exprs = fields.map(|span| rand_call(*span));
cx.expr_call_ident(span, ctor_ident, exprs)
cx.expr_call_ident(trait_span, ctor_ident, exprs)
}
}
Named(ref fields) => {
let rand_fields = fields.map(|&(ident, span)| {
cx.field_imm(span, ident, rand_call(span))
});
cx.expr_struct_ident(span, ctor_ident, rand_fields)
cx.expr_struct_ident(trait_span, ctor_ident, rand_fields)
}
}
}

View File

@@ -57,7 +57,7 @@ pub fn expand_deriving_zero(cx: &ExtCtxt,
trait_def.expand(mitem, in_items)
}
fn zero_substructure(cx: &ExtCtxt, span: Span, substr: &Substructure) -> @Expr {
fn zero_substructure(cx: &ExtCtxt, trait_span: Span, substr: &Substructure) -> @Expr {
let zero_ident = ~[
cx.ident_of("std"),
cx.ident_of("num"),
@@ -71,24 +71,24 @@ fn zero_substructure(cx: &ExtCtxt, span: Span, substr: &Substructure) -> @Expr {
match *summary {
Unnamed(ref fields) => {
if fields.is_empty() {
cx.expr_ident(span, substr.type_ident)
cx.expr_ident(trait_span, substr.type_ident)
} else {
let exprs = fields.map(|sp| zero_call(*sp));
cx.expr_call_ident(span, substr.type_ident, exprs)
cx.expr_call_ident(trait_span, substr.type_ident, exprs)
}
}
Named(ref fields) => {
let zero_fields = fields.map(|&(ident, span)| {
cx.field_imm(span, ident, zero_call(span))
});
cx.expr_struct_ident(span, substr.type_ident, zero_fields)
cx.expr_struct_ident(trait_span, substr.type_ident, zero_fields)
}
}
}
StaticEnum(..) => {
cx.span_err(span, "`Zero` cannot be derived for enums, only structs");
cx.span_err(trait_span, "`Zero` cannot be derived for enums, only structs");
// let compilation continue
cx.expr_uint(span, 0)
cx.expr_uint(trait_span, 0)
}
_ => cx.bug("Non-static method in `deriving(Zero)`")
};