diff --git a/src/librustc/front/test.rs b/src/librustc/front/test.rs index ca82502f84be1..cf8dbfdcad6a5 100644 --- a/src/librustc/front/test.rs +++ b/src/librustc/front/test.rs @@ -18,7 +18,7 @@ use std::vec; use syntax::ast_util::*; use syntax::attr::AttrMetaMethods; use syntax::attr; -use syntax::codemap::{dummy_sp, Span, ExpnInfo, NameAndSpan}; +use syntax::codemap::{dummy_sp, Span, ExpnInfo, NameAndSpan, MacroAttribute}; use syntax::codemap; use syntax::ext::base::ExtCtxt; use syntax::fold::ast_fold; @@ -158,6 +158,7 @@ fn generate_test_harness(sess: session::Session, crate: ast::Crate) call_site: dummy_sp(), callee: NameAndSpan { name: @"test", + format: MacroAttribute, span: None } }); diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index f7590e7b4ed55..f4cb19bfa2474 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -161,8 +161,22 @@ pub struct LocWithOpt { // used to be structural records. Better names, anyone? pub struct FileMapAndLine {fm: @FileMap, line: uint} pub struct FileMapAndBytePos {fm: @FileMap, pos: BytePos} + #[deriving(IterBytes)] -pub struct NameAndSpan {name: @str, span: Option} +pub enum MacroFormat { + // e.g. #[deriving(...)] + MacroAttribute, + // e.g. `format!()` + MacroBang +} + +#[deriving(IterBytes)] +pub struct NameAndSpan { + name: @str, + // the format with which the macro was invoked. + format: MacroFormat, + span: Option +} /// Extra information for tracking macro expansion of spans #[deriving(IterBytes)] diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index 36e6bf32451f9..59f33bc77696f 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -342,8 +342,13 @@ fn highlight_lines(cm: @codemap::CodeMap, fn print_macro_backtrace(cm: @codemap::CodeMap, sp: Span) { for ei in sp.expn_info.iter() { let ss = ei.callee.span.as_ref().map_default(~"", |span| cm.span_to_str(*span)); + let (pre, post) = match ei.callee.format { + codemap::MacroAttribute => ("#[", "]"), + codemap::MacroBang => ("", "!") + }; + print_diagnostic(ss, note, - format!("in expansion of {}!", ei.callee.name)); + format!("in expansion of {}{}{}", pre, ei.callee.name, post)); let ss = cm.span_to_str(ei.call_site); print_diagnostic(ss, note, "expansion site"); print_macro_backtrace(cm, ei.call_site); diff --git a/src/libsyntax/ext/deriving/clone.rs b/src/libsyntax/ext/deriving/clone.rs index 0f83f72522347..9285defe69ea1 100644 --- a/src/libsyntax/ext/deriving/clone.rs +++ b/src/libsyntax/ext/deriving/clone.rs @@ -20,6 +20,8 @@ pub fn expand_deriving_clone(cx: @ExtCtxt, in_items: ~[@item]) -> ~[@item] { let trait_def = TraitDef { + cx: cx, span: span, + path: Path::new(~["std", "clone", "Clone"]), additional_bounds: ~[], generics: LifetimeBounds::empty(), @@ -37,7 +39,7 @@ pub fn expand_deriving_clone(cx: @ExtCtxt, ] }; - trait_def.expand(cx, span, mitem, in_items) + trait_def.expand(mitem, in_items) } pub fn expand_deriving_deep_clone(cx: @ExtCtxt, @@ -46,6 +48,8 @@ pub fn expand_deriving_deep_clone(cx: @ExtCtxt, in_items: ~[@item]) -> ~[@item] { let trait_def = TraitDef { + cx: cx, span: span, + path: Path::new(~["std", "clone", "DeepClone"]), additional_bounds: ~[], generics: LifetimeBounds::empty(), @@ -65,7 +69,7 @@ pub fn expand_deriving_deep_clone(cx: @ExtCtxt, ] }; - trait_def.expand(cx, span, mitem, in_items) + trait_def.expand(mitem, in_items) } fn cs_clone( diff --git a/src/libsyntax/ext/deriving/cmp/eq.rs b/src/libsyntax/ext/deriving/cmp/eq.rs index eb07d2d209cfd..74680266cb709 100644 --- a/src/libsyntax/ext/deriving/cmp/eq.rs +++ b/src/libsyntax/ext/deriving/cmp/eq.rs @@ -45,6 +45,8 @@ pub fn expand_deriving_eq(cx: @ExtCtxt, ); let trait_def = TraitDef { + cx: cx, span: span, + path: Path::new(~["std", "cmp", "Eq"]), additional_bounds: ~[], generics: LifetimeBounds::empty(), @@ -53,5 +55,5 @@ pub fn expand_deriving_eq(cx: @ExtCtxt, md!("ne", cs_ne) ] }; - trait_def.expand(cx, span, mitem, in_items) + trait_def.expand(mitem, in_items) } diff --git a/src/libsyntax/ext/deriving/cmp/ord.rs b/src/libsyntax/ext/deriving/cmp/ord.rs index 95d617af0c794..d48cfbd7dd707 100644 --- a/src/libsyntax/ext/deriving/cmp/ord.rs +++ b/src/libsyntax/ext/deriving/cmp/ord.rs @@ -35,6 +35,8 @@ pub fn expand_deriving_ord(cx: @ExtCtxt, ); let trait_def = TraitDef { + cx: cx, span: span, + path: Path::new(~["std", "cmp", "Ord"]), additional_bounds: ~[], generics: LifetimeBounds::empty(), @@ -45,7 +47,7 @@ pub fn expand_deriving_ord(cx: @ExtCtxt, md!("ge", false, true) ] }; - trait_def.expand(cx, span, mitem, in_items) + trait_def.expand(mitem, in_items) } /// Strict inequality. diff --git a/src/libsyntax/ext/deriving/cmp/totaleq.rs b/src/libsyntax/ext/deriving/cmp/totaleq.rs index 51965e1b582a4..ab822d14b4845 100644 --- a/src/libsyntax/ext/deriving/cmp/totaleq.rs +++ b/src/libsyntax/ext/deriving/cmp/totaleq.rs @@ -24,6 +24,8 @@ pub fn expand_deriving_totaleq(cx: @ExtCtxt, } let trait_def = TraitDef { + cx: cx, span: span, + path: Path::new(~["std", "cmp", "TotalEq"]), additional_bounds: ~[], generics: LifetimeBounds::empty(), @@ -40,5 +42,5 @@ pub fn expand_deriving_totaleq(cx: @ExtCtxt, } ] }; - trait_def.expand(cx, span, mitem, in_items) + trait_def.expand(mitem, in_items) } diff --git a/src/libsyntax/ext/deriving/cmp/totalord.rs b/src/libsyntax/ext/deriving/cmp/totalord.rs index 217acd98c68cc..2ace39a348688 100644 --- a/src/libsyntax/ext/deriving/cmp/totalord.rs +++ b/src/libsyntax/ext/deriving/cmp/totalord.rs @@ -21,6 +21,8 @@ pub fn expand_deriving_totalord(cx: @ExtCtxt, mitem: @MetaItem, in_items: ~[@item]) -> ~[@item] { let trait_def = TraitDef { + cx: cx, span: span, + path: Path::new(~["std", "cmp", "TotalOrd"]), additional_bounds: ~[], generics: LifetimeBounds::empty(), @@ -38,7 +40,7 @@ pub fn expand_deriving_totalord(cx: @ExtCtxt, ] }; - trait_def.expand(cx, span, mitem, in_items) + trait_def.expand(mitem, in_items) } diff --git a/src/libsyntax/ext/deriving/decodable.rs b/src/libsyntax/ext/deriving/decodable.rs index 4ab0cc3bc67f5..0aade760b7ba6 100644 --- a/src/libsyntax/ext/deriving/decodable.rs +++ b/src/libsyntax/ext/deriving/decodable.rs @@ -24,6 +24,8 @@ pub fn expand_deriving_decodable(cx: @ExtCtxt, mitem: @MetaItem, in_items: ~[@item]) -> ~[@item] { let trait_def = TraitDef { + cx: cx, span: span, + path: Path::new_(~["extra", "serialize", "Decodable"], None, ~[~Literal(Path::new_local("__D"))], true), additional_bounds: ~[], @@ -46,7 +48,7 @@ pub fn expand_deriving_decodable(cx: @ExtCtxt, ] }; - trait_def.expand(cx, span, mitem, in_items) + trait_def.expand(mitem, in_items) } fn decodable_substructure(cx: @ExtCtxt, span: Span, diff --git a/src/libsyntax/ext/deriving/default.rs b/src/libsyntax/ext/deriving/default.rs index 3ecdd5e60fe97..393d808a0254e 100644 --- a/src/libsyntax/ext/deriving/default.rs +++ b/src/libsyntax/ext/deriving/default.rs @@ -20,6 +20,8 @@ pub fn expand_deriving_default(cx: @ExtCtxt, in_items: ~[@item]) -> ~[@item] { let trait_def = TraitDef { + cx: cx, span: span, + path: Path::new(~["std", "default", "Default"]), additional_bounds: ~[], generics: LifetimeBounds::empty(), @@ -36,7 +38,7 @@ pub fn expand_deriving_default(cx: @ExtCtxt, }, ] }; - trait_def.expand(cx, span, mitem, in_items) + trait_def.expand(mitem, in_items) } fn default_substructure(cx: @ExtCtxt, span: Span, substr: &Substructure) -> @Expr { diff --git a/src/libsyntax/ext/deriving/encodable.rs b/src/libsyntax/ext/deriving/encodable.rs index 96b77c4c16246..09210116c3767 100644 --- a/src/libsyntax/ext/deriving/encodable.rs +++ b/src/libsyntax/ext/deriving/encodable.rs @@ -86,6 +86,8 @@ pub fn expand_deriving_encodable(cx: @ExtCtxt, mitem: @MetaItem, in_items: ~[@item]) -> ~[@item] { let trait_def = TraitDef { + cx: cx, span: span, + path: Path::new_(~["extra", "serialize", "Encodable"], None, ~[~Literal(Path::new_local("__E"))], true), additional_bounds: ~[], @@ -108,7 +110,7 @@ pub fn expand_deriving_encodable(cx: @ExtCtxt, ] }; - trait_def.expand(cx, span, mitem, in_items) + trait_def.expand(mitem, in_items) } fn encodable_substructure(cx: @ExtCtxt, span: Span, diff --git a/src/libsyntax/ext/deriving/generic.rs b/src/libsyntax/ext/deriving/generic.rs index 627e799f2d36e..fefc4a9bafb69 100644 --- a/src/libsyntax/ext/deriving/generic.rs +++ b/src/libsyntax/ext/deriving/generic.rs @@ -179,7 +179,8 @@ use ast::{P, enum_def, Expr, Ident, Generics, struct_def}; use ext::base::ExtCtxt; use ext::build::AstBuilder; -use codemap::{Span,respan}; +use codemap; +use codemap::Span; use opt_vec; use std::vec; @@ -188,6 +189,11 @@ pub use self::ty::*; mod ty; pub struct TraitDef<'self> { + /// The extension context + cx: @ExtCtxt, + /// The span for the current #[deriving(Foo)] header. + span: Span, + /// Path of the trait, including any type parameters path: Path<'self>, /// Additional bounds required of any type parameters of the type, @@ -310,8 +316,7 @@ pub type EnumNonMatchFunc<'self> = impl<'self> TraitDef<'self> { - pub fn expand(&self, cx: @ExtCtxt, - trait_span: Span, + pub fn expand(&self, _mitem: @ast::MetaItem, in_items: ~[@ast::item]) -> ~[@ast::item] { let mut result = ~[]; @@ -319,14 +324,12 @@ impl<'self> TraitDef<'self> { result.push(*item); match item.node { ast::item_struct(struct_def, ref generics) => { - result.push(self.expand_struct_def(cx, trait_span, - struct_def, + result.push(self.expand_struct_def(struct_def, item.ident, generics)); } ast::item_enum(ref enum_def, ref generics) => { - result.push(self.expand_enum_def(cx, trait_span, - enum_def, + result.push(self.expand_enum_def(enum_def, item.ident, generics)); } @@ -346,12 +349,14 @@ impl<'self> TraitDef<'self> { * where B1, B2, ... are the bounds given by `bounds_paths`.' * */ - fn create_derived_impl(&self, cx: @ExtCtxt, trait_span: Span, + fn create_derived_impl(&self, type_ident: Ident, generics: &Generics, methods: ~[@ast::method]) -> @ast::item { - let trait_path = self.path.to_path(cx, trait_span, type_ident, generics); + let cx = self.cx; + let trait_path = self.path.to_path(cx, self.span, type_ident, generics); - let mut trait_generics = self.generics.to_generics(cx, trait_span, type_ident, generics); + let mut trait_generics = self.generics.to_generics(cx, self.span, + type_ident, generics); // Copy the lifetimes for l in generics.lifetimes.iter() { trait_generics.lifetimes.push(*l) @@ -363,7 +368,7 @@ impl<'self> TraitDef<'self> { let mut bounds = opt_vec::from( // extra restrictions on the generics parameters to the type being derived upon self.additional_bounds.map(|p| { - cx.typarambound(p.to_path(cx, trait_span, type_ident, generics)) + cx.typarambound(p.to_path(cx, self.span, type_ident, generics)) })); // require the current trait bounds.push(cx.typarambound(trait_path.clone())); @@ -376,22 +381,23 @@ impl<'self> TraitDef<'self> { // Create the type parameters on the `self` path. let self_ty_params = generics.ty_params.map(|ty_param| { - cx.ty_ident(trait_span, ty_param.ident) + cx.ty_ident(self.span, ty_param.ident) }); let self_lifetimes = generics.lifetimes.clone(); // Create the type of `self`. - let self_type = cx.ty_path(cx.path_all(trait_span, false, ~[ type_ident ], self_lifetimes, - opt_vec::take_vec(self_ty_params)), None); + let self_type = cx.ty_path( + cx.path_all(self.span, false, ~[ type_ident ], self_lifetimes, + opt_vec::take_vec(self_ty_params)), None); let doc_attr = cx.attribute( - trait_span, - cx.meta_name_value(trait_span, + self.span, + cx.meta_name_value(self.span, @"doc", ast::lit_str(@"Automatically derived.", ast::CookedStr))); cx.item( - trait_span, + self.span, ::parse::token::special_idents::clownshoes_extensions, ~[doc_attr], ast::item_impl(trait_generics, @@ -400,73 +406,70 @@ impl<'self> TraitDef<'self> { methods.map(|x| *x))) } - fn expand_struct_def(&self, cx: @ExtCtxt, - trait_span: Span, + fn expand_struct_def(&self, struct_def: &struct_def, type_ident: Ident, generics: &Generics) -> @ast::item { let methods = self.methods.map(|method_def| { let (explicit_self, self_args, nonself_args, tys) = - method_def.split_self_nonself_args(cx, trait_span, type_ident, generics); + method_def.split_self_nonself_args(self, type_ident, generics); let body = if method_def.is_static() { method_def.expand_static_struct_method_body( - cx, trait_span, + self, struct_def, type_ident, self_args, nonself_args) } else { - method_def.expand_struct_method_body(cx, trait_span, + method_def.expand_struct_method_body(self, struct_def, type_ident, self_args, nonself_args) }; - method_def.create_method(cx, trait_span, + method_def.create_method(self, type_ident, generics, explicit_self, tys, body) }); - self.create_derived_impl(cx, trait_span, type_ident, generics, methods) + self.create_derived_impl(type_ident, generics, methods) } fn expand_enum_def(&self, - cx: @ExtCtxt, trait_span: Span, enum_def: &enum_def, type_ident: Ident, generics: &Generics) -> @ast::item { let methods = self.methods.map(|method_def| { let (explicit_self, self_args, nonself_args, tys) = - method_def.split_self_nonself_args(cx, trait_span, type_ident, generics); + method_def.split_self_nonself_args(self, type_ident, generics); let body = if method_def.is_static() { method_def.expand_static_enum_method_body( - cx, trait_span, + self, enum_def, type_ident, self_args, nonself_args) } else { - method_def.expand_enum_method_body(cx, trait_span, + method_def.expand_enum_method_body(self, enum_def, type_ident, self_args, nonself_args) }; - method_def.create_method(cx, trait_span, + method_def.create_method(self, type_ident, generics, explicit_self, tys, body) }); - self.create_derived_impl(cx, trait_span, type_ident, generics, methods) + self.create_derived_impl(type_ident, generics, methods) } } impl<'self> MethodDef<'self> { fn call_substructure_method(&self, - cx: @ExtCtxt, - trait_span: Span, + trait_: &TraitDef, type_ident: Ident, self_args: &[@Expr], nonself_args: &[@Expr], @@ -474,25 +477,25 @@ impl<'self> MethodDef<'self> { -> @Expr { let substructure = Substructure { type_ident: type_ident, - method_ident: cx.ident_of(self.name), + method_ident: trait_.cx.ident_of(self.name), self_args: self_args, nonself_args: nonself_args, fields: fields }; - (self.combine_substructure)(cx, trait_span, + (self.combine_substructure)(trait_.cx, trait_.span, &substructure) } - fn get_ret_ty(&self, cx: @ExtCtxt, trait_span: Span, + fn get_ret_ty(&self, trait_: &TraitDef, generics: &Generics, type_ident: Ident) -> P { - self.ret_ty.to_ty(cx, trait_span, type_ident, generics) + self.ret_ty.to_ty(trait_.cx, trait_.span, type_ident, generics) } fn is_static(&self) -> bool { self.explicit_self.is_none() } - fn split_self_nonself_args(&self, cx: @ExtCtxt, trait_span: Span, + fn split_self_nonself_args(&self, trait_: &TraitDef, type_ident: Ident, generics: &Generics) -> (ast::explicit_self, ~[@Expr], ~[@Expr], ~[(Ident, P)]) { @@ -503,22 +506,23 @@ impl<'self> MethodDef<'self> { let ast_explicit_self = match self.explicit_self { Some(ref self_ptr) => { - let (self_expr, explicit_self) = ty::get_explicit_self(cx, trait_span, self_ptr); + let (self_expr, explicit_self) = + ty::get_explicit_self(trait_.cx, trait_.span, self_ptr); self_args.push(self_expr); nonstatic = true; explicit_self } - None => respan(trait_span, ast::sty_static), + None => codemap::respan(trait_.span, ast::sty_static), }; for (i, ty) in self.args.iter().enumerate() { - let ast_ty = ty.to_ty(cx, trait_span, type_ident, generics); - let ident = cx.ident_of(format!("__arg_{}", i)); + let ast_ty = ty.to_ty(trait_.cx, trait_.span, type_ident, generics); + let ident = trait_.cx.ident_of(format!("__arg_{}", i)); arg_tys.push((ident, ast_ty)); - let arg_expr = cx.expr_ident(trait_span, ident); + let arg_expr = trait_.cx.expr_ident(trait_.span, ident); match *ty { // for static methods, just treat any Self @@ -527,7 +531,7 @@ impl<'self> MethodDef<'self> { self_args.push(arg_expr); } Ptr(~Self, _) if nonstatic => { - self_args.push(cx.expr_deref(trait_span, arg_expr)) + self_args.push(trait_.cx.expr_deref(trait_.span, arg_expr)) } _ => { nonself_args.push(arg_expr); @@ -538,27 +542,27 @@ impl<'self> MethodDef<'self> { (ast_explicit_self, self_args, nonself_args, arg_tys) } - fn create_method(&self, cx: @ExtCtxt, trait_span: Span, + fn create_method(&self, trait_: &TraitDef, type_ident: Ident, generics: &Generics, explicit_self: ast::explicit_self, arg_types: ~[(Ident, P)], body: @Expr) -> @ast::method { // create the generics that aren't for Self - let fn_generics = self.generics.to_generics(cx, trait_span, type_ident, generics); + let fn_generics = self.generics.to_generics(trait_.cx, trait_.span, type_ident, generics); let args = arg_types.move_iter().map(|(name, ty)| { - cx.arg(trait_span, name, ty) + trait_.cx.arg(trait_.span, name, ty) }).collect(); - let ret_type = self.get_ret_ty(cx, trait_span, generics, type_ident); + let ret_type = self.get_ret_ty(trait_, generics, type_ident); - let method_ident = cx.ident_of(self.name); - let fn_decl = cx.fn_decl(args, ret_type); - let body_block = cx.block_expr(body); + let method_ident = trait_.cx.ident_of(self.name); + let fn_decl = trait_.cx.fn_decl(args, ret_type); + let body_block = trait_.cx.block_expr(body); let attrs = if self.inline { - ~[cx.attribute(trait_span, cx.meta_word(trait_span, @"inline"))] + ~[trait_.cx.attribute(trait_.span, trait_.cx.meta_word(trait_.span, @"inline"))] } else { ~[] }; @@ -573,7 +577,7 @@ impl<'self> MethodDef<'self> { decl: fn_decl, body: body_block, id: ast::DUMMY_NODE_ID, - span: trait_span, + span: trait_.span, self_id: ast::DUMMY_NODE_ID, vis: ast::inherited, } @@ -601,8 +605,7 @@ impl<'self> MethodDef<'self> { ~~~ */ fn expand_struct_method_body(&self, - cx: @ExtCtxt, - trait_span: Span, + trait_: &TraitDef, struct_def: &struct_def, type_ident: Ident, self_args: &[@Expr], @@ -613,10 +616,9 @@ impl<'self> MethodDef<'self> { // [fields of next Self arg], [etc]] let mut patterns = ~[]; for i in range(0u, self_args.len()) { - let (pat, ident_expr) = create_struct_pattern(cx, trait_span, - type_ident, struct_def, - format!("__self_{}", i), - ast::MutImmutable); + let (pat, ident_expr) = trait_.create_struct_pattern(type_ident, struct_def, + format!("__self_{}", i), + ast::MutImmutable); patterns.push(pat); raw_fields.push(ident_expr); } @@ -638,13 +640,14 @@ impl<'self> MethodDef<'self> { } }).collect() } - [] => { cx.span_bug(trait_span, "No self arguments to non-static \ - method in generic `deriving`") } + [] => { trait_.cx.span_bug(trait_.span, + "No self arguments to non-static method \ + in generic `deriving`") } }; // body of the inner most destructuring match let mut body = self.call_substructure_method( - cx, trait_span, + trait_, type_ident, self_args, nonself_args, @@ -654,23 +657,22 @@ impl<'self> MethodDef<'self> { // structs. This is actually right-to-left, but it shoudn't // matter. for (&arg_expr, &pat) in self_args.iter().zip(patterns.iter()) { - body = cx.expr_match(trait_span, arg_expr, - ~[ cx.arm(trait_span, ~[pat], body) ]) + body = trait_.cx.expr_match(trait_.span, arg_expr, + ~[ trait_.cx.arm(trait_.span, ~[pat], body) ]) } body } fn expand_static_struct_method_body(&self, - cx: @ExtCtxt, - trait_span: Span, + trait_: &TraitDef, struct_def: &struct_def, type_ident: Ident, self_args: &[@Expr], nonself_args: &[@Expr]) -> @Expr { - let summary = summarise_struct(cx, trait_span, struct_def); + let summary = trait_.summarise_struct(struct_def); - self.call_substructure_method(cx, trait_span, + self.call_substructure_method(trait_, type_ident, self_args, nonself_args, &StaticStruct(struct_def, summary)) @@ -703,15 +705,14 @@ impl<'self> MethodDef<'self> { ~~~ */ fn expand_enum_method_body(&self, - cx: @ExtCtxt, - trait_span: Span, + trait_: &TraitDef, enum_def: &enum_def, type_ident: Ident, self_args: &[@Expr], nonself_args: &[@Expr]) -> @Expr { let mut matches = ~[]; - self.build_enum_match(cx, trait_span, enum_def, type_ident, + self.build_enum_match(trait_, enum_def, type_ident, self_args, nonself_args, None, &mut matches, 0) } @@ -739,7 +740,7 @@ impl<'self> MethodDef<'self> { the first call). */ fn build_enum_match(&self, - cx: @ExtCtxt, trait_span: Span, + trait_: &TraitDef, enum_def: &enum_def, type_ident: Ident, self_args: &[@Expr], @@ -748,12 +749,13 @@ impl<'self> MethodDef<'self> { matches_so_far: &mut ~[(uint, P, ~[(Span, Option, @Expr)])], match_count: uint) -> @Expr { + let cx = trait_.cx; if match_count == self_args.len() { // we've matched against all arguments, so make the final // expression at the bottom of the match tree if matches_so_far.len() == 0 { - cx.span_bug(trait_span, "no self match on an enum in generic \ - `deriving`"); + cx.span_bug(trait_.span, + "no self match on an enum in generic `deriving`"); } // we currently have a vec of vecs, where each // subvec is the fields of one of the arguments, @@ -803,7 +805,7 @@ impl<'self> MethodDef<'self> { substructure = EnumNonMatching(*matches_so_far); } } - self.call_substructure_method(cx, trait_span, type_ident, + self.call_substructure_method(trait_, type_ident, self_args, nonself_args, &substructure) @@ -822,20 +824,19 @@ impl<'self> MethodDef<'self> { // make a matching-variant match, and a _ match. let index = match matching { Some(i) => i, - None => cx.span_bug(trait_span, + None => cx.span_bug(trait_.span, "Non-matching variants when required to \ be matching in generic `deriving`") }; // matching-variant match let variant = enum_def.variants[index]; - let (pattern, idents) = create_enum_variant_pattern(cx, - variant, - current_match_str, - ast::MutImmutable); + let (pattern, idents) = trait_.create_enum_variant_pattern(variant, + current_match_str, + ast::MutImmutable); matches_so_far.push((index, variant, idents)); - let arm_expr = self.build_enum_match(cx, trait_span, + let arm_expr = self.build_enum_match(trait_, enum_def, type_ident, self_args, nonself_args, @@ -843,25 +844,24 @@ impl<'self> MethodDef<'self> { matches_so_far, match_count + 1); matches_so_far.pop(); - arms.push(cx.arm(trait_span, ~[ pattern ], arm_expr)); + arms.push(cx.arm(trait_.span, ~[ pattern ], arm_expr)); if enum_def.variants.len() > 1 { let e = &EnumNonMatching(&[]); - let wild_expr = self.call_substructure_method(cx, trait_span, type_ident, + let wild_expr = self.call_substructure_method(trait_, type_ident, self_args, nonself_args, e); - let wild_arm = cx.arm(trait_span, - ~[ cx.pat_wild(trait_span) ], + let wild_arm = cx.arm(trait_.span, + ~[ cx.pat_wild(trait_.span) ], wild_expr); arms.push(wild_arm); } } else { // create an arm matching on each variant for (index, &variant) in enum_def.variants.iter().enumerate() { - let (pattern, idents) = create_enum_variant_pattern(cx, - variant, - current_match_str, - ast::MutImmutable); + let (pattern, idents) = trait_.create_enum_variant_pattern(variant, + current_match_str, + ast::MutImmutable); matches_so_far.push((index, variant, idents)); let new_matching = @@ -870,7 +870,7 @@ impl<'self> MethodDef<'self> { Some(i) if index == i => Some(i), _ => None }; - let arm_expr = self.build_enum_match(cx, trait_span, + let arm_expr = self.build_enum_match(trait_, enum_def, type_ident, self_args, nonself_args, @@ -879,19 +879,18 @@ impl<'self> MethodDef<'self> { match_count + 1); matches_so_far.pop(); - let arm = cx.arm(trait_span, ~[ pattern ], arm_expr); + let arm = cx.arm(trait_.span, ~[ pattern ], arm_expr); arms.push(arm); } } // match foo { arm, arm, arm, ... } - cx.expr_match(trait_span, self_args[match_count], arms) + cx.expr_match(trait_.span, self_args[match_count], arms) } } fn expand_static_enum_method_body(&self, - cx: @ExtCtxt, - trait_span: Span, + trait_: &TraitDef, enum_def: &enum_def, type_ident: Ident, self_args: &[@Expr], @@ -900,160 +899,176 @@ impl<'self> MethodDef<'self> { let summary = enum_def.variants.map(|v| { let ident = v.node.name; let summary = match v.node.kind { - ast::tuple_variant_kind(ref args) => Unnamed(args.map(|va| va.ty.span)), + ast::tuple_variant_kind(ref args) => { + Unnamed(args.map(|va| trait_.set_expn_info(va.ty.span))) + } ast::struct_variant_kind(struct_def) => { - summarise_struct(cx, trait_span, struct_def) + trait_.summarise_struct(struct_def) } }; (ident, summary) }); - self.call_substructure_method(cx, - trait_span, type_ident, + self.call_substructure_method(trait_, type_ident, self_args, nonself_args, &StaticEnum(enum_def, summary)) } } -fn summarise_struct(cx: @ExtCtxt, trait_span: Span, - struct_def: &struct_def) -> StaticFields { - let mut named_idents = ~[]; - let mut just_spans = ~[]; - for field in struct_def.fields.iter() { - match field.node.kind { - ast::named_field(ident, _) => named_idents.push((ident, field.span)), - ast::unnamed_field => just_spans.push(field.span), - } +#[deriving(Eq)] // dogfooding! +enum StructType { + Unknown, Record, Tuple +} + +// general helper methods. +impl<'a> TraitDef<'a> { + fn set_expn_info(&self, mut to_set: Span) -> Span { + let trait_name = match self.path.path.last_opt() { + None => self.cx.span_bug(self.span, "trait with empty path in generic `deriving`"), + Some(name) => *name + }; + to_set.expn_info = Some(@codemap::ExpnInfo { + call_site: to_set, + callee: codemap::NameAndSpan { + name: format!("deriving({})", trait_name).to_managed(), + format: codemap::MacroAttribute, + span: Some(self.span) + } + }); + to_set } - match (just_spans.is_empty(), named_idents.is_empty()) { - (false, false) => cx.span_bug(trait_span, - "A struct with named and unnamed \ - fields in generic `deriving`"), - // named fields - (_, false) => Named(named_idents), - // tuple structs (includes empty structs) - (_, _) => Unnamed(just_spans) + fn summarise_struct(&self, struct_def: &struct_def) -> StaticFields { + let mut named_idents = ~[]; + let mut just_spans = ~[]; + for field in struct_def.fields.iter(){ + let sp = self.set_expn_info(field.span); + match field.node.kind { + ast::named_field(ident, _) => named_idents.push((ident, sp)), + ast::unnamed_field => just_spans.push(sp), + } + } + + match (just_spans.is_empty(), named_idents.is_empty()) { + (false, false) => self.cx.span_bug(self.span, + "A struct with named and unnamed \ + fields in generic `deriving`"), + // named fields + (_, false) => Named(named_idents), + // tuple structs (includes empty structs) + (_, _) => Unnamed(just_spans) + } } -} -pub fn create_subpatterns(cx: @ExtCtxt, + fn create_subpatterns(&self, field_paths: ~[ast::Path], mutbl: ast::Mutability) - -> ~[@ast::Pat] { - field_paths.map(|path| { - cx.pat(path.span, - ast::PatIdent(ast::BindByRef(mutbl), (*path).clone(), None)) - }) -} + -> ~[@ast::Pat] { + field_paths.map(|path| { + self.cx.pat(path.span, + ast::PatIdent(ast::BindByRef(mutbl), (*path).clone(), None)) + }) + } -#[deriving(Eq)] // dogfooding! -enum StructType { - Unknown, Record, Tuple -} + fn create_struct_pattern(&self, + struct_ident: Ident, + struct_def: &struct_def, + prefix: &str, + mutbl: ast::Mutability) + -> (@ast::Pat, ~[(Span, Option, @Expr)]) { + let cx = self.cx; + + if struct_def.fields.is_empty() { + return ( + cx.pat_ident_binding_mode( + self.span, struct_ident, ast::BindByValue(ast::MutImmutable)), + ~[]); + } -fn create_struct_pattern(cx: @ExtCtxt, - trait_span: Span, - struct_ident: Ident, - struct_def: &struct_def, - prefix: &str, - mutbl: ast::Mutability) - -> (@ast::Pat, ~[(Span, Option, @Expr)]) { - if struct_def.fields.is_empty() { - return ( - cx.pat_ident_binding_mode( - trait_span, struct_ident, ast::BindByValue(ast::MutImmutable)), - ~[]); - } + let matching_path = cx.path(self.span, ~[ struct_ident ]); - let matching_path = cx.path(trait_span, ~[ struct_ident ]); + let mut paths = ~[]; + let mut ident_expr = ~[]; + let mut struct_type = Unknown; - let mut paths = ~[]; - let mut ident_expr = ~[]; - let mut struct_type = Unknown; + for (i, struct_field) in struct_def.fields.iter().enumerate() { + let sp = self.set_expn_info(struct_field.span); + let opt_id = match struct_field.node.kind { + ast::named_field(ident, _) if (struct_type == Unknown || + struct_type == Record) => { + struct_type = Record; + Some(ident) + } + ast::unnamed_field if (struct_type == Unknown || + struct_type == Tuple) => { + struct_type = Tuple; + None + } + _ => { + cx.span_bug(sp, "A struct with named and unnamed fields in `deriving`"); + } + }; + let path = cx.path_ident(sp, cx.ident_of(format!("{}_{}", prefix, i))); + paths.push(path.clone()); + ident_expr.push((sp, opt_id, cx.expr_path(path))); + } - for (i, struct_field) in struct_def.fields.iter().enumerate() { - let opt_id = match struct_field.node.kind { - ast::named_field(ident, _) if (struct_type == Unknown || - struct_type == Record) => { - struct_type = Record; - Some(ident) - } - ast::unnamed_field if (struct_type == Unknown || - struct_type == Tuple) => { - struct_type = Tuple; - None - } - _ => { - cx.span_bug(struct_field.span, - "A struct with named and unnamed fields in `deriving`"); - } + let subpats = self.create_subpatterns(paths, mutbl); + + // struct_type is definitely not Unknown, since struct_def.fields + // must be nonempty to reach here + let pattern = if struct_type == Record { + let field_pats = subpats.iter().zip(ident_expr.iter()).map(|(&pat, &(_, id, _))| { + // id is guaranteed to be Some + ast::FieldPat { ident: id.unwrap(), pat: pat } + }).collect(); + cx.pat_struct(self.span, matching_path, field_pats) + } else { + cx.pat_enum(self.span, matching_path, subpats) }; - let path = cx.path_ident(struct_field.span, - cx.ident_of(format!("{}_{}", prefix, i))); - paths.push(path.clone()); - ident_expr.push((struct_field.span, opt_id, cx.expr_path(path))); - } - let subpats = create_subpatterns(cx, paths, mutbl); + (pattern, ident_expr) + } - // struct_type is definitely not Unknown, since struct_def.fields - // must be nonempty to reach here - let pattern = if struct_type == Record { - let field_pats = subpats.iter().zip(ident_expr.iter()).map(|(&pat, &(_, id, _))| { - // id is guaranteed to be Some - ast::FieldPat { ident: id.unwrap(), pat: pat } - }).collect(); - cx.pat_struct(trait_span, matching_path, field_pats) - } else { - cx.pat_enum(trait_span, matching_path, subpats) - }; + fn create_enum_variant_pattern(&self, + variant: &ast::variant, + prefix: &str, + mutbl: ast::Mutability) + -> (@ast::Pat, ~[(Span, Option, @Expr)]) { + let cx = self.cx; + let variant_ident = variant.node.name; + match variant.node.kind { + ast::tuple_variant_kind(ref variant_args) => { + if variant_args.is_empty() { + return (cx.pat_ident_binding_mode(variant.span, variant_ident, + ast::BindByValue(ast::MutImmutable)), + ~[]); + } - (pattern, ident_expr) -} + let matching_path = cx.path_ident(variant.span, variant_ident); -fn create_enum_variant_pattern(cx: @ExtCtxt, - variant: &ast::variant, - prefix: &str, - mutbl: ast::Mutability) - -> (@ast::Pat, ~[(Span, Option, @Expr)]) { - - let variant_ident = variant.node.name; - match variant.node.kind { - ast::tuple_variant_kind(ref variant_args) => { - if variant_args.is_empty() { - return (cx.pat_ident_binding_mode(variant.span, variant_ident, - ast::BindByValue(ast::MutImmutable)), - ~[]); - } + let mut paths = ~[]; + let mut ident_expr = ~[]; + for (i, va) in variant_args.iter().enumerate() { + let sp = self.set_expn_info(va.ty.span); + let path = cx.path_ident(sp, cx.ident_of(format!("{}_{}", prefix, i))); - let matching_path = cx.path_ident(variant.span, variant_ident); + paths.push(path.clone()); + ident_expr.push((sp, None, cx.expr_path(path))); + } - let mut paths = ~[]; - let mut ident_expr = ~[]; - for (i, va) in variant_args.iter().enumerate() { - let path = cx.path_ident(va.ty.span, - cx.ident_of(format!("{}_{}", prefix, i))); + let subpats = self.create_subpatterns(paths, mutbl); - paths.push(path.clone()); - ident_expr.push((va.ty.span, None, cx.expr_path(path))); + (cx.pat_enum(variant.span, matching_path, subpats), + ident_expr) + } + ast::struct_variant_kind(struct_def) => { + self.create_struct_pattern(variant_ident, struct_def, + prefix, mutbl) } - - let subpats = create_subpatterns(cx, paths, mutbl); - - (cx.pat_enum(variant.span, matching_path, subpats), - ident_expr) - } - ast::struct_variant_kind(struct_def) => { - create_struct_pattern(cx, variant.span, - variant_ident, struct_def, - prefix, - mutbl) } } } - - /* helpful premade recipes */ /** diff --git a/src/libsyntax/ext/deriving/iter_bytes.rs b/src/libsyntax/ext/deriving/iter_bytes.rs index f291d2b751db2..837b8bd59ec9a 100644 --- a/src/libsyntax/ext/deriving/iter_bytes.rs +++ b/src/libsyntax/ext/deriving/iter_bytes.rs @@ -20,6 +20,8 @@ pub fn expand_deriving_iter_bytes(cx: @ExtCtxt, mitem: @MetaItem, in_items: ~[@item]) -> ~[@item] { let trait_def = TraitDef { + cx: cx, span: span, + path: Path::new(~["std", "to_bytes", "IterBytes"]), additional_bounds: ~[], generics: LifetimeBounds::empty(), @@ -40,7 +42,7 @@ pub fn expand_deriving_iter_bytes(cx: @ExtCtxt, ] }; - trait_def.expand(cx, span, mitem, in_items) + trait_def.expand(mitem, in_items) } fn iter_bytes_substructure(cx: @ExtCtxt, span: Span, substr: &Substructure) -> @Expr { diff --git a/src/libsyntax/ext/deriving/primitive.rs b/src/libsyntax/ext/deriving/primitive.rs index b26a3a09f045b..73ea627ff5457 100644 --- a/src/libsyntax/ext/deriving/primitive.rs +++ b/src/libsyntax/ext/deriving/primitive.rs @@ -20,6 +20,8 @@ pub fn expand_deriving_from_primitive(cx: @ExtCtxt, mitem: @MetaItem, in_items: ~[@item]) -> ~[@item] { let trait_def = TraitDef { + cx: cx, span: span, + path: Path::new(~["std", "num", "FromPrimitive"]), additional_bounds: ~[], generics: LifetimeBounds::empty(), @@ -59,7 +61,7 @@ pub fn expand_deriving_from_primitive(cx: @ExtCtxt, ] }; - trait_def.expand(cx, span, mitem, in_items) + trait_def.expand(mitem, in_items) } fn cs_from(name: &str, cx: @ExtCtxt, span: Span, substr: &Substructure) -> @Expr { diff --git a/src/libsyntax/ext/deriving/rand.rs b/src/libsyntax/ext/deriving/rand.rs index 40fdee481edd9..91ed60324cf1a 100644 --- a/src/libsyntax/ext/deriving/rand.rs +++ b/src/libsyntax/ext/deriving/rand.rs @@ -22,6 +22,8 @@ pub fn expand_deriving_rand(cx: @ExtCtxt, in_items: ~[@item]) -> ~[@item] { let trait_def = TraitDef { + cx: cx, span: span, + path: Path::new(~["std", "rand", "Rand"]), additional_bounds: ~[], generics: LifetimeBounds::empty(), @@ -45,7 +47,7 @@ pub fn expand_deriving_rand(cx: @ExtCtxt, } ] }; - trait_def.expand(cx, span, mitem, in_items) + trait_def.expand(mitem, in_items) } fn rand_substructure(cx: @ExtCtxt, span: Span, substr: &Substructure) -> @Expr { diff --git a/src/libsyntax/ext/deriving/to_str.rs b/src/libsyntax/ext/deriving/to_str.rs index 193dc4965fc63..fd8c21f4f9867 100644 --- a/src/libsyntax/ext/deriving/to_str.rs +++ b/src/libsyntax/ext/deriving/to_str.rs @@ -21,6 +21,8 @@ pub fn expand_deriving_to_str(cx: @ExtCtxt, in_items: ~[@item]) -> ~[@item] { let trait_def = TraitDef { + cx: cx, span: span, + path: Path::new(~["std", "to_str", "ToStr"]), additional_bounds: ~[], generics: LifetimeBounds::empty(), @@ -37,7 +39,7 @@ pub fn expand_deriving_to_str(cx: @ExtCtxt, } ] }; - trait_def.expand(cx, span, mitem, in_items) + trait_def.expand(mitem, in_items) } // It used to be the case that this deriving implementation invoked diff --git a/src/libsyntax/ext/deriving/zero.rs b/src/libsyntax/ext/deriving/zero.rs index 1fdb41316891c..67f14a8d48645 100644 --- a/src/libsyntax/ext/deriving/zero.rs +++ b/src/libsyntax/ext/deriving/zero.rs @@ -20,6 +20,8 @@ pub fn expand_deriving_zero(cx: @ExtCtxt, in_items: ~[@item]) -> ~[@item] { let trait_def = TraitDef { + cx: cx, span: span, + path: Path::new(~["std", "num", "Zero"]), additional_bounds: ~[], generics: LifetimeBounds::empty(), @@ -52,7 +54,7 @@ pub fn expand_deriving_zero(cx: @ExtCtxt, } ] }; - trait_def.expand(cx, span, mitem, in_items) + trait_def.expand(mitem, in_items) } fn zero_substructure(cx: @ExtCtxt, span: Span, substr: &Substructure) -> @Expr { diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 1d040c109847a..4bb35457182f7 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -18,7 +18,7 @@ use ext::build::AstBuilder; use attr; use attr::AttrMetaMethods; use codemap; -use codemap::{Span, Spanned, ExpnInfo, NameAndSpan}; +use codemap::{Span, Spanned, ExpnInfo, NameAndSpan, MacroBang, MacroAttribute}; use ext::base::*; use fold::*; use opt_vec; @@ -69,6 +69,7 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv, call_site: e.span, callee: NameAndSpan { name: extnamestr, + format: MacroBang, span: exp_span, }, }); @@ -257,6 +258,7 @@ pub fn expand_mod_items(extsbox: @mut SyntaxEnv, call_site: attr.span, callee: NameAndSpan { name: mname, + format: MacroAttribute, span: None } }); @@ -352,6 +354,7 @@ pub fn expand_item_mac(extsbox: @mut SyntaxEnv, call_site: it.span, callee: NameAndSpan { name: extnamestr, + format: MacroBang, span: span } }); @@ -370,6 +373,7 @@ pub fn expand_item_mac(extsbox: @mut SyntaxEnv, call_site: it.span, callee: NameAndSpan { name: extnamestr, + format: MacroBang, span: span } }); @@ -459,6 +463,7 @@ pub fn expand_stmt(extsbox: @mut SyntaxEnv, call_site: s.span, callee: NameAndSpan { name: extnamestr, + format: MacroBang, span: exp_span, } });