Auto merge of #26907 - nrc:save-fns, r=brson

r? @huonw
This commit is contained in:
bors 2015-07-10 00:47:35 +00:00
commit 736886c84b
5 changed files with 331 additions and 210 deletions

View File

@ -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) {

View File

@ -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.

View File

@ -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)

View File

@ -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))

View File

@ -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)
}
}