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:
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)`")
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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)")
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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)")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)`")
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user