Skip to content

Commit b079ebe

Browse files
committed
syntax: improve the spans of some #[deriving] traits.
This makes error messages about (e.g.) `#[deriving(Clone)] struct Foo { x: Type }` point at `x: Type` rather than `Clone` in the header (while still referring to the `#[deriving(Clone)]` in the expansion info).
1 parent 0b7f823 commit b079ebe

File tree

9 files changed

+138
-137
lines changed

9 files changed

+138
-137
lines changed

src/libsyntax/ext/deriving/clone.rs

+16-16
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,13 @@ pub fn expand_deriving_deep_clone(cx: &ExtCtxt,
7474

7575
fn cs_clone(
7676
name: &str,
77-
cx: &ExtCtxt, span: Span,
77+
cx: &ExtCtxt, trait_span: Span,
7878
substr: &Substructure) -> @Expr {
7979
let clone_ident = substr.method_ident;
8080
let ctor_ident;
8181
let all_fields;
82-
let subcall = |field|
83-
cx.expr_method_call(span, field, clone_ident, ~[]);
82+
let subcall = |field: &FieldInfo|
83+
cx.expr_method_call(field.span, field.self_, clone_ident, ~[]);
8484

8585
match *substr.fields {
8686
Struct(ref af) => {
@@ -91,37 +91,37 @@ fn cs_clone(
9191
ctor_ident = variant.node.name;
9292
all_fields = af;
9393
},
94-
EnumNonMatching(..) => cx.span_bug(span,
95-
format!("Non-matching enum variants in `deriving({})`",
96-
name)),
97-
StaticEnum(..) | StaticStruct(..) => cx.span_bug(span,
98-
format!("Static method in `deriving({})`",
99-
name))
94+
EnumNonMatching(..) => cx.span_bug(trait_span,
95+
format!("Non-matching enum variants in `deriving({})`",
96+
name)),
97+
StaticEnum(..) | StaticStruct(..) => cx.span_bug(trait_span,
98+
format!("Static method in `deriving({})`",
99+
name))
100100
}
101101

102102
match *all_fields {
103103
[FieldInfo { name: None, .. }, ..] => {
104104
// enum-like
105-
let subcalls = all_fields.map(|field| subcall(field.self_));
106-
cx.expr_call_ident(span, ctor_ident, subcalls)
105+
let subcalls = all_fields.map(subcall);
106+
cx.expr_call_ident(trait_span, ctor_ident, subcalls)
107107
},
108108
_ => {
109109
// struct-like
110110
let fields = all_fields.map(|field| {
111111
let ident = match field.name {
112112
Some(i) => i,
113-
None => cx.span_bug(span,
113+
None => cx.span_bug(trait_span,
114114
format!("unnamed field in normal struct in `deriving({})`",
115-
name))
115+
name))
116116
};
117-
cx.field_imm(span, ident, subcall(field.self_))
117+
cx.field_imm(field.span, ident, subcall(field))
118118
});
119119

120120
if fields.is_empty() {
121121
// no fields, so construct like `None`
122-
cx.expr_ident(span, ctor_ident)
122+
cx.expr_ident(trait_span, ctor_ident)
123123
} else {
124-
cx.expr_struct_ident(span, ctor_ident, fields)
124+
cx.expr_struct_ident(trait_span, ctor_ident, fields)
125125
}
126126
}
127127
}

src/libsyntax/ext/deriving/decodable.rs

+26-27
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ pub fn expand_deriving_decodable(cx: &ExtCtxt,
5151
trait_def.expand(mitem, in_items)
5252
}
5353

54-
fn decodable_substructure(cx: &ExtCtxt, span: Span,
54+
fn decodable_substructure(cx: &ExtCtxt, trait_span: Span,
5555
substr: &Substructure) -> @Expr {
5656
let decoder = substr.nonself_args[0];
5757
let recurse = ~[cx.ident_of("extra"),
@@ -60,9 +60,9 @@ fn decodable_substructure(cx: &ExtCtxt, span: Span,
6060
cx.ident_of("decode")];
6161
// throw an underscore in front to suppress unused variable warnings
6262
let blkarg = cx.ident_of("_d");
63-
let blkdecoder = cx.expr_ident(span, blkarg);
64-
let calldecode = cx.expr_call_global(span, recurse, ~[blkdecoder]);
65-
let lambdadecode = cx.lambda_expr_1(span, calldecode, blkarg);
63+
let blkdecoder = cx.expr_ident(trait_span, blkarg);
64+
let calldecode = cx.expr_call_global(trait_span, recurse, ~[blkdecoder]);
65+
let lambdadecode = cx.lambda_expr_1(trait_span, calldecode, blkarg);
6666

6767
return match *substr.fields {
6868
StaticStruct(_, ref summary) => {
@@ -73,7 +73,7 @@ fn decodable_substructure(cx: &ExtCtxt, span: Span,
7373
let read_struct_field = cx.ident_of("read_struct_field");
7474

7575
let result = decode_static_fields(cx,
76-
span,
76+
trait_span,
7777
substr.type_ident,
7878
summary,
7979
|span, name, field| {
@@ -82,10 +82,10 @@ fn decodable_substructure(cx: &ExtCtxt, span: Span,
8282
cx.expr_uint(span, field),
8383
lambdadecode])
8484
});
85-
cx.expr_method_call(span, decoder, cx.ident_of("read_struct"),
86-
~[cx.expr_str(span, cx.str_of(substr.type_ident)),
87-
cx.expr_uint(span, nfields),
88-
cx.lambda_expr_1(span, result, blkarg)])
85+
cx.expr_method_call(trait_span, decoder, cx.ident_of("read_struct"),
86+
~[cx.expr_str(trait_span, cx.str_of(substr.type_ident)),
87+
cx.expr_uint(trait_span, nfields),
88+
cx.lambda_expr_1(trait_span, result, blkarg)])
8989
}
9090
StaticEnum(_, ref fields) => {
9191
let variant = cx.ident_of("i");
@@ -94,12 +94,11 @@ fn decodable_substructure(cx: &ExtCtxt, span: Span,
9494
let mut variants = ~[];
9595
let rvariant_arg = cx.ident_of("read_enum_variant_arg");
9696

97-
for (i, f) in fields.iter().enumerate() {
98-
let (name, parts) = match *f { (i, ref p) => (i, p) };
99-
variants.push(cx.expr_str(span, cx.str_of(name)));
97+
for (i, &(name, v_span, ref parts)) in fields.iter().enumerate() {
98+
variants.push(cx.expr_str(v_span, cx.str_of(name)));
10099

101100
let decoded = decode_static_fields(cx,
102-
span,
101+
v_span,
103102
name,
104103
parts,
105104
|span, _, field| {
@@ -108,22 +107,22 @@ fn decodable_substructure(cx: &ExtCtxt, span: Span,
108107
lambdadecode])
109108
});
110109

111-
arms.push(cx.arm(span,
112-
~[cx.pat_lit(span, cx.expr_uint(span, i))],
110+
arms.push(cx.arm(v_span,
111+
~[cx.pat_lit(v_span, cx.expr_uint(v_span, i))],
113112
decoded));
114113
}
115114

116-
arms.push(cx.arm_unreachable(span));
115+
arms.push(cx.arm_unreachable(trait_span));
117116

118-
let result = cx.expr_match(span, cx.expr_ident(span, variant), arms);
119-
let lambda = cx.lambda_expr(span, ~[blkarg, variant], result);
120-
let variant_vec = cx.expr_vec(span, variants);
121-
let result = cx.expr_method_call(span, blkdecoder,
117+
let result = cx.expr_match(trait_span, cx.expr_ident(trait_span, variant), arms);
118+
let lambda = cx.lambda_expr(trait_span, ~[blkarg, variant], result);
119+
let variant_vec = cx.expr_vec(trait_span, variants);
120+
let result = cx.expr_method_call(trait_span, blkdecoder,
122121
cx.ident_of("read_enum_variant"),
123122
~[variant_vec, lambda]);
124-
cx.expr_method_call(span, decoder, cx.ident_of("read_enum"),
125-
~[cx.expr_str(span, cx.str_of(substr.type_ident)),
126-
cx.lambda_expr_1(span, result, blkarg)])
123+
cx.expr_method_call(trait_span, decoder, cx.ident_of("read_enum"),
124+
~[cx.expr_str(trait_span, cx.str_of(substr.type_ident)),
125+
cx.lambda_expr_1(trait_span, result, blkarg)])
127126
}
128127
_ => cx.bug("expected StaticEnum or StaticStruct in deriving(Decodable)")
129128
};
@@ -133,29 +132,29 @@ fn decodable_substructure(cx: &ExtCtxt, span: Span,
133132
/// - `outer_pat_ident` is the name of this enum variant/struct
134133
/// - `getarg` should retrieve the `uint`-th field with name `@str`.
135134
fn decode_static_fields(cx: &ExtCtxt,
136-
outer_span: Span,
135+
trait_span: Span,
137136
outer_pat_ident: Ident,
138137
fields: &StaticFields,
139138
getarg: |Span, @str, uint| -> @Expr)
140139
-> @Expr {
141140
match *fields {
142141
Unnamed(ref fields) => {
143142
if fields.is_empty() {
144-
cx.expr_ident(outer_span, outer_pat_ident)
143+
cx.expr_ident(trait_span, outer_pat_ident)
145144
} else {
146145
let fields = fields.iter().enumerate().map(|(i, &span)| {
147146
getarg(span, format!("_field{}", i).to_managed(), i)
148147
}).collect();
149148

150-
cx.expr_call_ident(outer_span, outer_pat_ident, fields)
149+
cx.expr_call_ident(trait_span, outer_pat_ident, fields)
151150
}
152151
}
153152
Named(ref fields) => {
154153
// use the field's span to get nicer error messages.
155154
let fields = fields.iter().enumerate().map(|(i, &(name, span))| {
156155
cx.field_imm(span, name, getarg(span, cx.str_of(name), i))
157156
}).collect();
158-
cx.expr_struct_ident(outer_span, outer_pat_ident, fields)
157+
cx.expr_struct_ident(trait_span, outer_pat_ident, fields)
159158
}
160159
}
161160
}

src/libsyntax/ext/deriving/default.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ pub fn expand_deriving_default(cx: &ExtCtxt,
4141
trait_def.expand(mitem, in_items)
4242
}
4343

44-
fn default_substructure(cx: &ExtCtxt, span: Span, substr: &Substructure) -> @Expr {
44+
fn default_substructure(cx: &ExtCtxt, trait_span: Span, substr: &Substructure) -> @Expr {
4545
let default_ident = ~[
4646
cx.ident_of("std"),
4747
cx.ident_of("default"),
@@ -55,25 +55,25 @@ fn default_substructure(cx: &ExtCtxt, span: Span, substr: &Substructure) -> @Exp
5555
match *summary {
5656
Unnamed(ref fields) => {
5757
if fields.is_empty() {
58-
cx.expr_ident(span, substr.type_ident)
58+
cx.expr_ident(trait_span, substr.type_ident)
5959
} else {
6060
let exprs = fields.map(|sp| default_call(*sp));
61-
cx.expr_call_ident(span, substr.type_ident, exprs)
61+
cx.expr_call_ident(trait_span, substr.type_ident, exprs)
6262
}
6363
}
6464
Named(ref fields) => {
6565
let default_fields = fields.map(|&(ident, span)| {
6666
cx.field_imm(span, ident, default_call(span))
6767
});
68-
cx.expr_struct_ident(span, substr.type_ident, default_fields)
68+
cx.expr_struct_ident(trait_span, substr.type_ident, default_fields)
6969
}
7070
}
7171
}
7272
StaticEnum(..) => {
73-
cx.span_err(span, "`Default` cannot be derived for enums, only structs");
73+
cx.span_err(trait_span, "`Default` cannot be derived for enums, only structs");
7474
// let compilation continue
75-
cx.expr_uint(span, 0)
75+
cx.expr_uint(trait_span, 0)
7676
}
77-
_ => cx.bug("Non-static method in `deriving(Default)`")
77+
_ => cx.span_bug(trait_span, "Non-static method in `deriving(Default)`")
7878
};
7979
}

src/libsyntax/ext/deriving/encodable.rs

+22-22
Original file line numberDiff line numberDiff line change
@@ -113,24 +113,24 @@ pub fn expand_deriving_encodable(cx: &ExtCtxt,
113113
trait_def.expand(mitem, in_items)
114114
}
115115

116-
fn encodable_substructure(cx: &ExtCtxt, span: Span,
116+
fn encodable_substructure(cx: &ExtCtxt, trait_span: Span,
117117
substr: &Substructure) -> @Expr {
118118
let encoder = substr.nonself_args[0];
119119
// throw an underscore in front to suppress unused variable warnings
120120
let blkarg = cx.ident_of("_e");
121-
let blkencoder = cx.expr_ident(span, blkarg);
121+
let blkencoder = cx.expr_ident(trait_span, blkarg);
122122
let encode = cx.ident_of("encode");
123123

124124
return match *substr.fields {
125125
Struct(ref fields) => {
126126
let emit_struct_field = cx.ident_of("emit_struct_field");
127127
let mut stmts = ~[];
128-
for (i, f) in fields.iter().enumerate() {
129-
let name = match f.name {
128+
for (i, &FieldInfo { name, self_, span, .. }) in fields.iter().enumerate() {
129+
let name = match name {
130130
Some(id) => cx.str_of(id),
131131
None => format!("_field{}", i).to_managed()
132132
};
133-
let enc = cx.expr_method_call(span, f.self_, encode, ~[blkencoder]);
133+
let enc = cx.expr_method_call(span, self_, encode, ~[blkencoder]);
134134
let lambda = cx.lambda_expr_1(span, enc, blkarg);
135135
let call = cx.expr_method_call(span, blkencoder,
136136
emit_struct_field,
@@ -140,10 +140,10 @@ fn encodable_substructure(cx: &ExtCtxt, span: Span,
140140
stmts.push(cx.stmt_expr(call));
141141
}
142142

143-
let blk = cx.lambda_stmts_1(span, stmts, blkarg);
144-
cx.expr_method_call(span, encoder, cx.ident_of("emit_struct"),
145-
~[cx.expr_str(span, cx.str_of(substr.type_ident)),
146-
cx.expr_uint(span, fields.len()),
143+
let blk = cx.lambda_stmts_1(trait_span, stmts, blkarg);
144+
cx.expr_method_call(trait_span, encoder, cx.ident_of("emit_struct"),
145+
~[cx.expr_str(trait_span, cx.str_of(substr.type_ident)),
146+
cx.expr_uint(trait_span, fields.len()),
147147
blk])
148148
}
149149

@@ -152,12 +152,12 @@ fn encodable_substructure(cx: &ExtCtxt, span: Span,
152152
// so we need to generate a unique local variable to take the
153153
// mutable loan out on, otherwise we get conflicts which don't
154154
// actually exist.
155-
let me = cx.stmt_let(span, false, blkarg, encoder);
156-
let encoder = cx.expr_ident(span, blkarg);
155+
let me = cx.stmt_let(trait_span, false, blkarg, encoder);
156+
let encoder = cx.expr_ident(trait_span, blkarg);
157157
let emit_variant_arg = cx.ident_of("emit_enum_variant_arg");
158158
let mut stmts = ~[];
159-
for (i, f) in fields.iter().enumerate() {
160-
let enc = cx.expr_method_call(span, f.self_, encode, ~[blkencoder]);
159+
for (i, &FieldInfo { self_, span, .. }) in fields.iter().enumerate() {
160+
let enc = cx.expr_method_call(span, self_, encode, ~[blkencoder]);
161161
let lambda = cx.lambda_expr_1(span, enc, blkarg);
162162
let call = cx.expr_method_call(span, blkencoder,
163163
emit_variant_arg,
@@ -166,21 +166,21 @@ fn encodable_substructure(cx: &ExtCtxt, span: Span,
166166
stmts.push(cx.stmt_expr(call));
167167
}
168168

169-
let blk = cx.lambda_stmts_1(span, stmts, blkarg);
170-
let name = cx.expr_str(span, cx.str_of(variant.node.name));
171-
let call = cx.expr_method_call(span, blkencoder,
169+
let blk = cx.lambda_stmts_1(trait_span, stmts, blkarg);
170+
let name = cx.expr_str(trait_span, cx.str_of(variant.node.name));
171+
let call = cx.expr_method_call(trait_span, blkencoder,
172172
cx.ident_of("emit_enum_variant"),
173173
~[name,
174-
cx.expr_uint(span, idx),
175-
cx.expr_uint(span, fields.len()),
174+
cx.expr_uint(trait_span, idx),
175+
cx.expr_uint(trait_span, fields.len()),
176176
blk]);
177-
let blk = cx.lambda_expr_1(span, call, blkarg);
178-
let ret = cx.expr_method_call(span, encoder,
177+
let blk = cx.lambda_expr_1(trait_span, call, blkarg);
178+
let ret = cx.expr_method_call(trait_span, encoder,
179179
cx.ident_of("emit_enum"),
180-
~[cx.expr_str(span,
180+
~[cx.expr_str(trait_span,
181181
cx.str_of(substr.type_ident)),
182182
blk]);
183-
cx.expr_block(cx.block(span, ~[me], Some(ret)))
183+
cx.expr_block(cx.block(trait_span, ~[me], Some(ret)))
184184
}
185185

186186
_ => cx.bug("expected Struct or EnumMatching in deriving(Encodable)")

src/libsyntax/ext/deriving/generic.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,9 @@ StaticStruct(<ast::StructDef of A>, Named(~[(<ident of x>, <span of x>)]))
169169
170170
StaticStruct(<ast::StructDef of B>, Unnamed(~[<span of x>]))
171171
172-
StaticEnum(<ast::EnumDef of C>, ~[(<ident of C0>, Unnamed(~[<span of int>])),
173-
(<ident of C1>, Named(~[(<ident of x>, <span of x>)]))])
172+
StaticEnum(<ast::EnumDef of C>, ~[(<ident of C0>, <span of C0>, Unnamed(~[<span of int>])),
173+
(<ident of C1>, <span of C1>,
174+
Named(~[(<ident of x>, <span of x>)]))])
174175
~~~
175176
176177
*/
@@ -291,7 +292,7 @@ pub enum SubstructureFields<'a> {
291292
/// A static method where Self is a struct.
292293
StaticStruct(&'a ast::StructDef, StaticFields),
293294
/// A static method where Self is an enum.
294-
StaticEnum(&'a ast::EnumDef, ~[(Ident, StaticFields)])
295+
StaticEnum(&'a ast::EnumDef, ~[(Ident, Span, StaticFields)])
295296
}
296297

297298

@@ -905,7 +906,7 @@ impl<'a> MethodDef<'a> {
905906
trait_.summarise_struct(struct_def)
906907
}
907908
};
908-
(ident, summary)
909+
(ident, v.span, summary)
909910
});
910911
self.call_substructure_method(trait_, type_ident,
911912
self_args, nonself_args,

0 commit comments

Comments
 (0)