diff --git a/src/librustc_trans/save/dump_csv.rs b/src/librustc_trans/save/dump_csv.rs index e88b3980737..c5196d09e00 100644 --- a/src/librustc_trans/save/dump_csv.rs +++ b/src/librustc_trans/save/dump_csv.rs @@ -28,19 +28,17 @@ //! DumpCsvVisitor walks the AST and processes it. -use super::{escape, generated_code, recorder, SaveContext, PathCollector}; +use super::{escape, generated_code, recorder, SaveContext, PathCollector, Data}; use session::Session; use middle::def; use middle::ty::{self, Ty}; -use rustc::ast_map::NodeItem; use std::cell::Cell; use std::fs::File; use std::path::Path; -use syntax::ast_util; use syntax::ast::{self, NodeId, DefId}; use syntax::codemap::*; use syntax::parse::token::{self, get_ident, keywords}; @@ -298,9 +296,11 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> { } } - fn process_method(&mut self, sig: &ast::MethodSig, + fn process_method(&mut self, + sig: &ast::MethodSig, body: Option<&ast::Block>, - id: ast::NodeId, name: ast::Name, + id: ast::NodeId, + name: ast::Name, span: Span) { if generated_code(span) { return; @@ -308,91 +308,22 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> { debug!("process_method: {}:{}", id, token::get_name(name)); - let scope_id; - // The qualname for a method is the trait name or name of the struct in an impl in - // which the method is declared in, followed by the method's name. - let qualname = match self.tcx.impl_of_method(ast_util::local_def(id)) { - Some(impl_id) => match self.tcx.map.get(impl_id.node) { - NodeItem(item) => { - scope_id = item.id; - match item.node { - ast::ItemImpl(_, _, _, _, ref ty, _) => { - let mut result = String::from("<"); - result.push_str(&ty_to_string(&**ty)); + let method_data = self.save_ctxt.get_method_data(id, name, span); - match self.tcx.trait_of_item(ast_util::local_def(id)) { - Some(def_id) => { - result.push_str(" as "); - result.push_str( - &self.tcx.item_path_str(def_id)); - }, - None => {} - } - result.push_str(">"); - result - } - _ => { - self.sess.span_bug(span, - &format!("Container {} for method {} not an impl?", - impl_id.node, id)); - }, - } - }, - _ => { - self.sess.span_bug(span, - &format!("Container {} for method {} is not a node item {:?}", - impl_id.node, id, self.tcx.map.get(impl_id.node))); - }, - }, - None => match self.tcx.trait_of_item(ast_util::local_def(id)) { - Some(def_id) => { - scope_id = def_id.node; - match self.tcx.map.get(def_id.node) { - NodeItem(_) => { - format!("::{}", self.tcx.item_path_str(def_id)) - } - _ => { - self.sess.span_bug(span, - &format!("Could not find container {} for method {}", - def_id.node, id)); - } - } - }, - None => { - self.sess.span_bug(span, - &format!("Could not find container for method {}", id)); - }, - }, - }; - - let qualname = &format!("{}::{}", qualname, &token::get_name(name)); - - // record the decl for this def (if it has one) - let decl_id = self.tcx.trait_item_of_item(ast_util::local_def(id)) - .and_then(|new_id| { - let def_id = new_id.def_id(); - if def_id.node != 0 && def_id != ast_util::local_def(id) { - Some(def_id) - } else { - None - } - }); - - let sub_span = self.span.sub_span_after_keyword(span, keywords::Fn); if body.is_some() { self.fmt.method_str(span, - sub_span, - id, - qualname, - decl_id, - scope_id); - self.process_formals(&sig.decl.inputs, qualname); + Some(method_data.span), + method_data.id, + &method_data.qualname, + method_data.declaration, + method_data.scope); + self.process_formals(&sig.decl.inputs, &method_data.qualname); } else { self.fmt.method_decl_str(span, - sub_span, - id, - qualname, - scope_id); + Some(method_data.span), + method_data.id, + &method_data.qualname, + method_data.scope); } // walk arg and return types @@ -411,7 +342,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> { self.process_generic_params(&sig.generics, span, - qualname, + &method_data.qualname, id); } @@ -432,7 +363,6 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> { parent_id: NodeId) { let field_data = self.save_ctxt.get_field_data(field, parent_id); if let Some(field_data) = field_data { - down_cast_data!(field_data, VariableData, self, field.span); self.fmt.field_str(field.span, Some(field_data.span), field_data.id, @@ -738,90 +668,51 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> { fn process_path(&mut self, id: NodeId, - span: Span, path: &ast::Path, ref_kind: Option<recorder::Row>) { - if generated_code(span) { - return + if generated_code(path.span) { + return; } - let def_map = self.tcx.def_map.borrow(); - if !def_map.contains_key(&id) { - self.sess.span_bug(span, - &format!("def_map has no key for {} in visit_expr", id)); - } - let def = def_map.get(&id).unwrap().full_def(); - let sub_span = self.span.span_for_last_ident(span); - match def { - def::DefUpvar(..) | - def::DefLocal(..) | - def::DefStatic(..) | - def::DefConst(..) | - def::DefAssociatedConst(..) | - def::DefVariant(..) => self.fmt.ref_str(ref_kind.unwrap_or(recorder::VarRef), - span, - sub_span, - def.def_id(), - self.cur_scope), - def::DefStruct(def_id) => self.fmt.ref_str(recorder::TypeRef, - span, - sub_span, - def_id, - self.cur_scope), - def::DefTy(def_id, _) => self.fmt.ref_str(recorder::TypeRef, - span, - sub_span, - def_id, - self.cur_scope), - def::DefMethod(declid, provenence) => { - let sub_span = self.span.sub_span_for_meth_name(span); - let defid = if declid.krate == ast::LOCAL_CRATE { - let ti = self.tcx.impl_or_trait_item(declid); - match provenence { - def::FromTrait(def_id) => { - Some(self.tcx.trait_items(def_id) - .iter() - .find(|mr| { - mr.name() == ti.name() - }) - .unwrap() - .def_id()) - } - def::FromImpl(def_id) => { - let impl_items = self.tcx.impl_items.borrow(); - Some(impl_items.get(&def_id) - .unwrap() - .iter() - .find(|mr| { - self.tcx.impl_or_trait_item(mr.def_id()).name() - == ti.name() - }) - .unwrap() - .def_id()) - } - } - } else { - None - }; - self.fmt.meth_call_str(span, - sub_span, - defid, - Some(declid), - self.cur_scope); - }, - def::DefFn(def_id, _) => { - self.fmt.fn_call_str(span, - sub_span, - def_id, - self.cur_scope) + let path_data = self.save_ctxt.get_path_data(id, path); + match path_data { + Data::VariableRefData(ref vrd) => { + self.fmt.ref_str(ref_kind.unwrap_or(recorder::VarRef), + path.span, + Some(vrd.span), + vrd.ref_id, + vrd.scope); + + } + Data::TypeRefData(ref trd) => { + self.fmt.ref_str(recorder::TypeRef, + path.span, + Some(trd.span), + trd.ref_id, + trd.scope); + } + Data::MethodCallData(ref mcd) => { + self.fmt.meth_call_str(path.span, + Some(mcd.span), + mcd.ref_id, + mcd.decl_id, + mcd.scope); + } + Data::FunctionCallData(fcd) => { + self.fmt.fn_call_str(path.span, + Some(fcd.span), + fcd.ref_id, + fcd.scope); + } + _ => { + self.sess.span_bug(path.span, + &format!("Unexpected data: {:?}", path_data)); } - _ => self.sess.span_bug(span, - &format!("Unexpected def kind while looking \ - up path in `{}`: `{:?}`", - self.span.snippet(span), - def)), } - // modules or types in the path prefix + + // Modules or types in the path prefix. + let def_map = self.tcx.def_map.borrow(); + let def = def_map.get(&id).unwrap().full_def(); match def { def::DefMethod(did, _) => { let ti = self.tcx.impl_or_trait_item(did); @@ -861,6 +752,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> { struct_lit_data.ref_id, struct_lit_data.scope); let struct_def = struct_lit_data.ref_id; + let scope = self.save_ctxt.enclosing_scope(ex.id); for field in fields { if generated_code(field.ident.span) { @@ -869,7 +761,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> { let field_data = self.save_ctxt.get_field_ref_data(field, struct_def, - self.cur_scope); + scope); self.fmt.ref_str(recorder::VarRef, field.ident.span, Some(field_data.span), @@ -886,18 +778,14 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> { fn process_method_call(&mut self, ex: &ast::Expr, args: &Vec<P<ast::Expr>>) { - let method_call = ty::MethodCall::expr(ex.id); - let method_id = self.tcx.tables.borrow().method_map[&method_call].def_id; - let (def_id, decl_id) = match self.tcx.impl_or_trait_item(method_id).container() { - ty::ImplContainer(_) => (Some(method_id), None), - ty::TraitContainer(_) => (None, Some(method_id)) - }; - let sub_span = self.span.sub_span_for_meth_name(ex.span); - self.fmt.meth_call_str(ex.span, - sub_span, - def_id, - decl_id, - self.cur_scope); + if let Some(call_data) = self.save_ctxt.get_expr_data(ex) { + down_cast_data!(call_data, MethodCallData, self, ex.span); + self.fmt.meth_call_str(ex.span, + Some(call_data.span), + call_data.ref_id, + call_data.decl_id, + call_data.scope); + } // walk receiver and args visit::walk_exprs(self, &args); @@ -1129,8 +1017,11 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> { trait_item.span, &*ty, &*expr); } ast::MethodTraitItem(ref sig, ref body) => { - self.process_method(sig, body.as_ref().map(|x| &**x), - trait_item.id, trait_item.ident.name, trait_item.span); + self.process_method(sig, + body.as_ref().map(|x| &**x), + trait_item.id, + trait_item.ident.name, + trait_item.span); } ast::ConstTraitItem(_, None) | ast::TypeTraitItem(..) => {} @@ -1144,8 +1035,11 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> { impl_item.span, &ty, &expr); } ast::MethodImplItem(ref sig, ref body) => { - self.process_method(sig, Some(body), impl_item.id, - impl_item.ident.name, impl_item.span); + self.process_method(sig, + Some(body), + impl_item.id, + impl_item.ident.name, + impl_item.span); } ast::TypeImplItem(_) | ast::MacImplItem(_) => {} @@ -1191,7 +1085,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> { visit::walk_expr(self, ex); } ast::ExprPath(_, ref path) => { - self.process_path(ex.id, path.span, path, None); + self.process_path(ex.id, path, None); visit::walk_expr(self, ex); } ast::ExprStruct(ref path, ref fields, ref base) => @@ -1287,6 +1181,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> { // This is to get around borrow checking, because we need mut self to call process_path. let mut paths_to_process = vec![]; + // process collected paths for &(id, ref p, immut, ref_kind) in &collector.collected_paths { let def_map = self.tcx.def_map.borrow(); @@ -1323,11 +1218,12 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> { def) } } + for &(id, ref path, ref_kind) in &paths_to_process { - self.process_path(id, path.span, path, ref_kind); + self.process_path(id, path, ref_kind); } visit::walk_expr_opt(self, &arm.guard); - self.visit_expr(&*arm.body); + self.visit_expr(&arm.body); } fn visit_stmt(&mut self, s: &ast::Stmt) { diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs index 9d66e99df30..4e0b34b7ef8 100644 --- a/src/librustc_trans/save/mod.rs +++ b/src/librustc_trans/save/mod.rs @@ -15,6 +15,8 @@ use std::env; use std::fs::{self, File}; use std::path::{Path, PathBuf}; +use rustc::ast_map::NodeItem; + use syntax::{attr}; use syntax::ast::{self, NodeId, DefId}; use syntax::ast_util; @@ -61,6 +63,10 @@ pub enum Data { VariableRefData(VariableRefData), /// Data for a reference to a type or trait. TypeRefData(TypeRefData), + /// Data about a function call. + FunctionCallData(FunctionCallData), + /// Data about a method call. + MethodCallData(MethodCallData), } /// Data for all kinds of functions and methods. @@ -120,7 +126,7 @@ pub struct ImplData { } /// Data for the use of some item (e.g., the use of a local variable, which -/// will refere to that variables declaration (by ref_id)). +/// will refer to that variables declaration (by ref_id)). #[derive(Debug)] pub struct VariableRefData { pub name: String, @@ -137,6 +143,24 @@ pub struct TypeRefData { pub ref_id: DefId, } +/// Data about a function call. +#[derive(Debug)] +pub struct FunctionCallData { + pub span: Span, + pub scope: NodeId, + pub ref_id: DefId, +} + +/// Data about a method call. +#[derive(Debug)] +pub struct MethodCallData { + pub span: Span, + pub scope: NodeId, + pub ref_id: Option<DefId>, + pub decl_id: Option<DefId>, +} + + impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { pub fn new(tcx: &'l ty::ctxt<'tcx>, @@ -172,7 +196,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { qualname: qualname, declaration: None, span: sub_span.unwrap(), - scope: self.tcx.map.get_enclosing_scope(item.id).unwrap_or(0), + scope: self.enclosing_scope(item.id), }) } ast::ItemStatic(ref typ, mt, ref expr) => { @@ -191,7 +215,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { name: get_ident(item.ident).to_string(), qualname: qualname, span: sub_span.unwrap(), - scope: self.tcx.map.get_enclosing_scope(item.id).unwrap_or(0), + scope: self.enclosing_scope(item.id), value: value, type_value: ty_to_string(&typ), }) @@ -205,7 +229,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { name: get_ident(item.ident).to_string(), qualname: qualname, span: sub_span.unwrap(), - scope: self.tcx.map.get_enclosing_scope(item.id).unwrap_or(0), + scope: self.enclosing_scope(item.id), value: self.span_utils.snippet(expr.span), type_value: ty_to_string(&typ), }) @@ -223,7 +247,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { name: get_ident(item.ident).to_string(), qualname: qualname, span: sub_span.unwrap(), - scope: self.tcx.map.get_enclosing_scope(item.id).unwrap_or(0), + scope: self.enclosing_scope(item.id), filename: filename, }) }, @@ -237,14 +261,14 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { value: val, span: sub_span.unwrap(), qualname: enum_name, - scope: self.tcx.map.get_enclosing_scope(item.id).unwrap_or(0), + scope: self.enclosing_scope(item.id), }) }, ast::ItemImpl(_, _, _, ref trait_ref, ref typ, _) => { let mut type_data = None; let sub_span; - let parent = self.tcx.map.get_enclosing_scope(item.id).unwrap_or(0); + let parent = self.enclosing_scope(item.id); match typ.node { // Common case impl for a struct or something basic. @@ -281,34 +305,114 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } } - // FIXME: we ought to be able to get the parent id ourselves, but we can't - // for now. - pub fn get_field_data(&self, field: &ast::StructField, parent: NodeId) -> Option<Data> { + pub fn get_field_data(&self, field: &ast::StructField, scope: NodeId) -> Option<VariableData> { match field.node.kind { ast::NamedField(ident, _) => { let name = get_ident(ident); let qualname = format!("::{}::{}", - self.tcx.map.path_to_string(parent), + self.tcx.map.path_to_string(scope), name); let typ = self.tcx.node_types().get(&field.node.id).unwrap() .to_string(); let sub_span = self.span_utils.sub_span_before_token(field.span, token::Colon); - Some(Data::VariableData(VariableData { + Some(VariableData { id: field.node.id, name: get_ident(ident).to_string(), qualname: qualname, span: sub_span.unwrap(), - scope: parent, + scope: scope, value: "".to_owned(), type_value: typ, - })) + }) }, _ => None, } } - // FIXME: we ought to be able to get the parent id ourselves, but we can't - // for now. + // FIXME would be nice to take a MethodItem here, but the ast provides both + // trait and impl flavours, so the caller must do the disassembly. + pub fn get_method_data(&self, + id: ast::NodeId, + name: ast::Name, + span: Span) -> FunctionData { + // The qualname for a method is the trait name or name of the struct in an impl in + // which the method is declared in, followed by the method's name. + let qualname = match self.tcx.impl_of_method(ast_util::local_def(id)) { + Some(impl_id) => match self.tcx.map.get(impl_id.node) { + NodeItem(item) => { + match item.node { + ast::ItemImpl(_, _, _, _, ref ty, _) => { + let mut result = String::from("<"); + result.push_str(&ty_to_string(&**ty)); + + match self.tcx.trait_of_item(ast_util::local_def(id)) { + Some(def_id) => { + result.push_str(" as "); + result.push_str( + &self.tcx.item_path_str(def_id)); + }, + None => {} + } + result.push_str(">"); + result + } + _ => { + self.tcx.sess.span_bug(span, + &format!("Container {} for method {} not an impl?", + impl_id.node, id)); + }, + } + }, + _ => { + self.tcx.sess.span_bug(span, + &format!("Container {} for method {} is not a node item {:?}", + impl_id.node, id, self.tcx.map.get(impl_id.node))); + }, + }, + None => match self.tcx.trait_of_item(ast_util::local_def(id)) { + Some(def_id) => { + match self.tcx.map.get(def_id.node) { + NodeItem(_) => { + format!("::{}", self.tcx.item_path_str(def_id)) + } + _ => { + self.tcx.sess.span_bug(span, + &format!("Could not find container {} for method {}", + def_id.node, id)); + } + } + }, + None => { + self.tcx.sess.span_bug(span, + &format!("Could not find container for method {}", id)); + }, + }, + }; + + let qualname = format!("{}::{}", qualname, &token::get_name(name)); + + let decl_id = self.tcx.trait_item_of_item(ast_util::local_def(id)) + .and_then(|new_id| { + let def_id = new_id.def_id(); + if def_id.node != 0 && def_id != ast_util::local_def(id) { + Some(def_id) + } else { + None + } + }); + + let sub_span = self.span_utils.sub_span_after_keyword(span, keywords::Fn); + + FunctionData { + id: id, + name: token::get_name(name).to_string(), + qualname: qualname, + declaration: decl_id, + span: sub_span.unwrap(), + scope: self.enclosing_scope(id), + } + } + pub fn get_trait_ref_data(&self, trait_ref: &ast::TraitRef, parent: NodeId) @@ -337,7 +441,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { return Some(Data::VariableRefData(VariableRefData { name: get_ident(ident.node).to_string(), span: sub_span.unwrap(), - scope: self.tcx.map.get_enclosing_scope(expr.id).unwrap_or(0), + scope: self.enclosing_scope(expr.id), ref_id: f.id, })); } @@ -360,7 +464,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { let sub_span = self.span_utils.span_for_last_ident(path.span); Some(Data::TypeRefData(TypeRefData { span: sub_span.unwrap(), - scope: self.tcx.map.get_enclosing_scope(expr.id).unwrap_or(0), + scope: self.enclosing_scope(expr.id), ref_id: def_id, })) } @@ -372,6 +476,25 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } } } + ast::ExprMethodCall(..) => { + let method_call = ty::MethodCall::expr(expr.id); + let method_id = self.tcx.tables.borrow().method_map[&method_call].def_id; + let (def_id, decl_id) = match self.tcx.impl_or_trait_item(method_id).container() { + ty::ImplContainer(_) => (Some(method_id), None), + ty::TraitContainer(_) => (None, Some(method_id)) + }; + let sub_span = self.span_utils.sub_span_for_meth_name(expr.span); + let parent = self.enclosing_scope(expr.id); + Some(Data::MethodCallData(MethodCallData { + span: sub_span.unwrap(), + scope: parent, + ref_id: def_id, + decl_id: decl_id, + })) + } + ast::ExprPath(_, ref path) => { + Some(self.get_path_data(expr.id, path)) + } _ => { // FIXME unimplemented!(); @@ -379,6 +502,90 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } } + pub fn get_path_data(&self, + id: NodeId, + path: &ast::Path) + -> Data { + let def_map = self.tcx.def_map.borrow(); + if !def_map.contains_key(&id) { + self.tcx.sess.span_bug(path.span, + &format!("def_map has no key for {} in visit_expr", id)); + } + let def = def_map.get(&id).unwrap().full_def(); + let sub_span = self.span_utils.span_for_last_ident(path.span); + match def { + def::DefUpvar(..) | + def::DefLocal(..) | + def::DefStatic(..) | + def::DefConst(..) | + def::DefAssociatedConst(..) | + def::DefVariant(..) => { + Data::VariableRefData(VariableRefData { + name: self.span_utils.snippet(sub_span.unwrap()), + span: sub_span.unwrap(), + scope: self.enclosing_scope(id), + ref_id: def.def_id(), + }) + } + def::DefStruct(def_id) | def::DefTy(def_id, _) => { + Data::TypeRefData(TypeRefData { + span: sub_span.unwrap(), + ref_id: def_id, + scope: self.enclosing_scope(id), + }) + } + def::DefMethod(decl_id, provenence) => { + let sub_span = self.span_utils.sub_span_for_meth_name(path.span); + let def_id = if decl_id.krate == ast::LOCAL_CRATE { + let ti = self.tcx.impl_or_trait_item(decl_id); + match provenence { + def::FromTrait(def_id) => { + Some(self.tcx.trait_items(def_id) + .iter() + .find(|mr| { + mr.name() == ti.name() + }) + .unwrap() + .def_id()) + } + def::FromImpl(def_id) => { + let impl_items = self.tcx.impl_items.borrow(); + Some(impl_items.get(&def_id) + .unwrap() + .iter() + .find(|mr| { + self.tcx.impl_or_trait_item(mr.def_id()).name() + == ti.name() + }) + .unwrap() + .def_id()) + } + } + } else { + None + }; + Data::MethodCallData(MethodCallData { + span: sub_span.unwrap(), + scope: self.enclosing_scope(id), + ref_id: def_id, + decl_id: Some(decl_id), + }) + }, + def::DefFn(def_id, _) => { + Data::FunctionCallData(FunctionCallData { + ref_id: def_id, + span: sub_span.unwrap(), + scope: self.enclosing_scope(id), + }) + } + _ => self.tcx.sess.span_bug(path.span, + &format!("Unexpected def kind while looking \ + up path in `{}`: `{:?}`", + self.span_utils.snippet(path.span), + def)), + } + } + pub fn get_field_ref_data(&self, field_ref: &ast::Field, struct_id: DefId, @@ -420,6 +627,10 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } } + #[inline] + fn enclosing_scope(&self, id: NodeId) -> NodeId { + self.tcx.map.get_enclosing_scope(id).unwrap_or(0) + } } // An AST visitor for collecting paths from patterns. diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 4aa313f3e66..53befc092da 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -60,14 +60,14 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> { }; // Keep going, outside-in. - // let fully_expanded = fld.fold_expr(expanded_expr); + let span = fld.new_span(span); fld.cx.bt_pop(); fully_expanded.map(|e| ast::Expr { id: ast::DUMMY_NODE_ID, node: e.node, - span: fld.new_span(span), + span: span, }) } @@ -367,7 +367,8 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> { /// of expansion and the mark which must be applied to the result. /// Our current interface doesn't allow us to apply the mark to the /// result until after calling make_expr, make_items, etc. -fn expand_mac_invoc<T, F, G>(mac: ast::Mac, span: codemap::Span, +fn expand_mac_invoc<T, F, G>(mac: ast::Mac, + span: codemap::Span, parse_thunk: F, mark_thunk: G, fld: &mut MacroExpander) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 03c788aee58..81ae607fea2 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1566,12 +1566,13 @@ impl<'a> Parser<'a> { // Assumes that the leading `<` has been parsed already. pub fn parse_qualified_path(&mut self, mode: PathParsingMode) -> PResult<(QSelf, ast::Path)> { + let span = self.last_span; let self_type = try!(self.parse_ty_sum()); let mut path = if try!(self.eat_keyword(keywords::As)) { try!(self.parse_path(LifetimeAndTypesWithoutColons)) } else { ast::Path { - span: self.span, + span: span, global: false, segments: vec![] } @@ -1598,9 +1599,6 @@ impl<'a> Parser<'a> { }; path.segments.extend(segments); - if path.segments.len() == 1 { - path.span.lo = self.last_span.lo; - } path.span.hi = self.last_span.hi; Ok((qself, path)) diff --git a/src/test/run-make/save-analysis/foo.rs b/src/test/run-make/save-analysis/foo.rs index 07b99dff4e0..4981ea475d3 100644 --- a/src/test/run-make/save-analysis/foo.rs +++ b/src/test/run-make/save-analysis/foo.rs @@ -364,3 +364,18 @@ impl<'a> Pattern<'a> for CharEqPattern { } struct CharSearcher<'a>(<CharEqPattern as Pattern<'a>>::Searcher); + +pub trait Error { +} + +impl Error + 'static { + pub fn is<T: Error + 'static>(&self) -> bool { + panic!() + } +} + +impl Error + 'static + Send { + pub fn is<T: Error + 'static>(&self) -> bool { + <Error + 'static>::is::<T>(self) + } +}