Rollup merge of #38171 - jseyfried:cleanup, r=nrc
Miscellaneous cleanup/refactoring in `resolve` and `syntax::ext` r? @nrc
This commit is contained in:
commit
551cb0646f
|
@ -365,7 +365,6 @@ pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate) {
|
|||
pub fn walk_macro_def<'v, V: Visitor<'v>>(visitor: &mut V, macro_def: &'v MacroDef) {
|
||||
visitor.visit_id(macro_def.id);
|
||||
visitor.visit_name(macro_def.span, macro_def.name);
|
||||
walk_opt_name(visitor, macro_def.span, macro_def.imported_from);
|
||||
walk_list!(visitor, visit_attribute, ¯o_def.attrs);
|
||||
}
|
||||
|
||||
|
|
|
@ -433,13 +433,19 @@ impl<'a> LoweringContext<'a> {
|
|||
segment: &PathSegment,
|
||||
param_mode: ParamMode)
|
||||
-> hir::PathSegment {
|
||||
let parameters = match segment.parameters {
|
||||
PathParameters::AngleBracketed(ref data) => {
|
||||
let data = self.lower_angle_bracketed_parameter_data(data, param_mode);
|
||||
hir::AngleBracketedParameters(data)
|
||||
let parameters = if let Some(ref parameters) = segment.parameters {
|
||||
match **parameters {
|
||||
PathParameters::AngleBracketed(ref data) => {
|
||||
let data = self.lower_angle_bracketed_parameter_data(data, param_mode);
|
||||
hir::AngleBracketedParameters(data)
|
||||
}
|
||||
PathParameters::Parenthesized(ref data) => {
|
||||
hir::ParenthesizedParameters(self.lower_parenthesized_parameter_data(data))
|
||||
}
|
||||
}
|
||||
PathParameters::Parenthesized(ref data) =>
|
||||
hir::ParenthesizedParameters(self.lower_parenthesized_parameter_data(data)),
|
||||
} else {
|
||||
let data = self.lower_angle_bracketed_parameter_data(&Default::default(), param_mode);
|
||||
hir::AngleBracketedParameters(data)
|
||||
};
|
||||
|
||||
hir::PathSegment {
|
||||
|
@ -987,8 +993,6 @@ impl<'a> LoweringContext<'a> {
|
|||
attrs: self.lower_attrs(&m.attrs),
|
||||
id: m.id,
|
||||
span: m.span,
|
||||
imported_from: m.imported_from.map(|x| x.name),
|
||||
allow_internal_unstable: m.allow_internal_unstable,
|
||||
body: m.body.clone().into(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -475,8 +475,6 @@ pub struct MacroDef {
|
|||
pub attrs: HirVec<Attribute>,
|
||||
pub id: NodeId,
|
||||
pub span: Span,
|
||||
pub imported_from: Option<Name>,
|
||||
pub allow_internal_unstable: bool,
|
||||
pub body: HirVec<TokenTree>,
|
||||
}
|
||||
|
||||
|
|
|
@ -302,9 +302,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
|
|||
}
|
||||
|
||||
fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef) {
|
||||
if md.imported_from.is_none() {
|
||||
self.annotate(md.id, &md.attrs, md.span, AnnotationKind::Required, |_| {});
|
||||
}
|
||||
self.annotate(md.id, &md.attrs, md.span, AnnotationKind::Required, |_| {});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -373,9 +371,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'a, 'tcx> {
|
|||
}
|
||||
|
||||
fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef) {
|
||||
if md.imported_from.is_none() {
|
||||
self.check_missing_stability(md.id, md.span);
|
||||
}
|
||||
self.check_missing_stability(md.id, md.span);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -762,11 +762,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
/// reference to the context, to allow formatting values that need it.
|
||||
pub fn create_and_enter<F, R>(s: &'tcx Session,
|
||||
arenas: &'tcx CtxtArenas<'tcx>,
|
||||
trait_map: TraitMap,
|
||||
resolutions: ty::Resolutions,
|
||||
named_region_map: resolve_lifetime::NamedRegionMap,
|
||||
map: ast_map::Map<'tcx>,
|
||||
freevars: FreevarMap,
|
||||
maybe_unused_trait_imports: NodeSet,
|
||||
region_maps: RegionMaps,
|
||||
lang_items: middle::lang_items::LanguageItems,
|
||||
stability: stability::Index<'tcx>,
|
||||
|
@ -790,7 +788,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
item_variance_map: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
|
||||
variance_computed: Cell::new(false),
|
||||
sess: s,
|
||||
trait_map: trait_map,
|
||||
trait_map: resolutions.trait_map,
|
||||
tables: RefCell::new(Tables::empty()),
|
||||
impl_trait_refs: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
|
||||
trait_defs: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
|
||||
|
@ -802,8 +800,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
fulfilled_predicates: RefCell::new(fulfilled_predicates),
|
||||
map: map,
|
||||
mir_map: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
|
||||
freevars: RefCell::new(freevars),
|
||||
maybe_unused_trait_imports: maybe_unused_trait_imports,
|
||||
freevars: RefCell::new(resolutions.freevars),
|
||||
maybe_unused_trait_imports: resolutions.maybe_unused_trait_imports,
|
||||
item_types: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
|
||||
rcache: RefCell::new(FxHashMap()),
|
||||
tc_cache: RefCell::new(FxHashMap()),
|
||||
|
|
|
@ -17,7 +17,7 @@ pub use self::LvaluePreference::*;
|
|||
pub use self::fold::TypeFoldable;
|
||||
|
||||
use dep_graph::{self, DepNode};
|
||||
use hir::map as ast_map;
|
||||
use hir::{map as ast_map, FreevarMap, TraitMap};
|
||||
use middle;
|
||||
use hir::def::{Def, CtorKind, ExportMap};
|
||||
use hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
|
||||
|
@ -112,6 +112,13 @@ pub struct CrateAnalysis<'tcx> {
|
|||
pub hir_ty_to_ty: NodeMap<Ty<'tcx>>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Resolutions {
|
||||
pub freevars: FreevarMap,
|
||||
pub trait_map: TraitMap,
|
||||
pub maybe_unused_trait_imports: NodeSet,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum DtorKind {
|
||||
NoDtor,
|
||||
|
|
|
@ -8,8 +8,7 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use rustc::hir;
|
||||
use rustc::hir::{map as hir_map, FreevarMap, TraitMap};
|
||||
use rustc::hir::{self, map as hir_map};
|
||||
use rustc::hir::lowering::lower_crate;
|
||||
use rustc_data_structures::stable_hasher::StableHasher;
|
||||
use rustc_mir as mir;
|
||||
|
@ -20,7 +19,7 @@ use rustc::session::search_paths::PathKind;
|
|||
use rustc::lint;
|
||||
use rustc::middle::{self, dependency_format, stability, reachable};
|
||||
use rustc::middle::privacy::AccessLevels;
|
||||
use rustc::ty::{self, TyCtxt};
|
||||
use rustc::ty::{self, TyCtxt, Resolutions};
|
||||
use rustc::util::common::time;
|
||||
use rustc::util::nodemap::{NodeSet, NodeMap};
|
||||
use rustc_borrowck as borrowck;
|
||||
|
@ -59,13 +58,6 @@ use syntax_ext;
|
|||
|
||||
use derive_registrar;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Resolutions {
|
||||
pub freevars: FreevarMap,
|
||||
pub trait_map: TraitMap,
|
||||
pub maybe_unused_trait_imports: NodeSet,
|
||||
}
|
||||
|
||||
pub fn compile_input(sess: &Session,
|
||||
cstore: &CStore,
|
||||
input: &Input,
|
||||
|
@ -864,11 +856,9 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
|
|||
|
||||
TyCtxt::create_and_enter(sess,
|
||||
arenas,
|
||||
resolutions.trait_map,
|
||||
resolutions,
|
||||
named_region_map,
|
||||
hir_map,
|
||||
resolutions.freevars,
|
||||
resolutions.maybe_unused_trait_imports,
|
||||
region_map,
|
||||
lang_items,
|
||||
index,
|
||||
|
|
|
@ -15,10 +15,9 @@ pub use self::PpSourceMode::*;
|
|||
pub use self::PpMode::*;
|
||||
use self::NodesMatchingUII::*;
|
||||
|
||||
use abort_on_err;
|
||||
use driver::{self, Resolutions};
|
||||
use {abort_on_err, driver};
|
||||
|
||||
use rustc::ty::{self, TyCtxt};
|
||||
use rustc::ty::{self, TyCtxt, Resolutions};
|
||||
use rustc::cfg;
|
||||
use rustc::cfg::graphviz::LabelledCFG;
|
||||
use rustc::dep_graph::DepGraph;
|
||||
|
|
|
@ -138,11 +138,9 @@ fn test_env<F>(source_string: &str,
|
|||
let index = stability::Index::new(&ast_map);
|
||||
TyCtxt::create_and_enter(&sess,
|
||||
&arenas,
|
||||
resolutions.trait_map,
|
||||
resolutions,
|
||||
named_region_map.unwrap(),
|
||||
ast_map,
|
||||
resolutions.freevars,
|
||||
resolutions.maybe_unused_trait_imports,
|
||||
region_map,
|
||||
lang_items,
|
||||
index,
|
||||
|
|
|
@ -418,8 +418,6 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
|
|||
ident: ast::Ident::with_empty_ctxt(name),
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
span: local_span,
|
||||
imported_from: None, // FIXME
|
||||
allow_internal_unstable: attr::contains_name(&attrs, "allow_internal_unstable"),
|
||||
attrs: attrs,
|
||||
body: body,
|
||||
})
|
||||
|
|
|
@ -171,7 +171,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
match item.node {
|
||||
ItemKind::Use(ref view_path) => {
|
||||
let path = view_path.node.path();
|
||||
if !path.segments.iter().all(|segment| segment.parameters.is_empty()) {
|
||||
if path.segments.iter().any(|segment| segment.parameters.is_some()) {
|
||||
self.err_handler()
|
||||
.span_err(path.span, "type or lifetime parameters in import path");
|
||||
}
|
||||
|
@ -275,7 +275,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
fn visit_vis(&mut self, vis: &'a Visibility) {
|
||||
match *vis {
|
||||
Visibility::Restricted { ref path, .. } => {
|
||||
if !path.segments.iter().all(|segment| segment.parameters.is_empty()) {
|
||||
if !path.segments.iter().all(|segment| segment.parameters.is_none()) {
|
||||
self.err_handler()
|
||||
.span_err(path.span, "type or lifetime parameters in visibility path");
|
||||
}
|
||||
|
|
|
@ -16,7 +16,8 @@
|
|||
use macros::{InvocationData, LegacyScope};
|
||||
use resolve_imports::ImportDirective;
|
||||
use resolve_imports::ImportDirectiveSubclass::{self, GlobImport, SingleImport};
|
||||
use {Resolver, Module, ModuleS, ModuleKind, NameBinding, NameBindingKind, ToNameBinding};
|
||||
use {Module, ModuleData, ModuleKind, NameBinding, NameBindingKind, ToNameBinding};
|
||||
use {Resolver, ResolverArenas};
|
||||
use Namespace::{self, TypeNS, ValueNS, MacroNS};
|
||||
use {resolve_error, resolve_struct_error, ResolutionError};
|
||||
|
||||
|
@ -28,7 +29,7 @@ use rustc::ty;
|
|||
use std::cell::Cell;
|
||||
use std::rc::Rc;
|
||||
|
||||
use syntax::ast::Name;
|
||||
use syntax::ast::{Name, Ident};
|
||||
use syntax::attr;
|
||||
|
||||
use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind};
|
||||
|
@ -45,24 +46,24 @@ use syntax::visit::{self, Visitor};
|
|||
use syntax_pos::{Span, DUMMY_SP};
|
||||
|
||||
impl<'a> ToNameBinding<'a> for (Module<'a>, ty::Visibility, Span, Mark) {
|
||||
fn to_name_binding(self) -> NameBinding<'a> {
|
||||
NameBinding {
|
||||
fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> {
|
||||
arenas.alloc_name_binding(NameBinding {
|
||||
kind: NameBindingKind::Module(self.0),
|
||||
vis: self.1,
|
||||
span: self.2,
|
||||
expansion: self.3,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ToNameBinding<'a> for (Def, ty::Visibility, Span, Mark) {
|
||||
fn to_name_binding(self) -> NameBinding<'a> {
|
||||
NameBinding {
|
||||
fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> {
|
||||
arenas.alloc_name_binding(NameBinding {
|
||||
kind: NameBindingKind::Def(self.0),
|
||||
vis: self.1,
|
||||
span: self.2,
|
||||
expansion: self.3,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -73,15 +74,15 @@ struct LegacyMacroImports {
|
|||
reexports: Vec<(Name, Span)>,
|
||||
}
|
||||
|
||||
impl<'b> Resolver<'b> {
|
||||
impl<'a> Resolver<'a> {
|
||||
/// Defines `name` in namespace `ns` of module `parent` to be `def` if it is not yet defined;
|
||||
/// otherwise, reports an error.
|
||||
fn define<T>(&mut self, parent: Module<'b>, name: Name, ns: Namespace, def: T)
|
||||
where T: ToNameBinding<'b>,
|
||||
fn define<T>(&mut self, parent: Module<'a>, ident: Ident, ns: Namespace, def: T)
|
||||
where T: ToNameBinding<'a>,
|
||||
{
|
||||
let binding = def.to_name_binding();
|
||||
if let Err(old_binding) = self.try_define(parent, name, ns, binding.clone()) {
|
||||
self.report_conflict(parent, name, ns, old_binding, &binding);
|
||||
let binding = def.to_name_binding(self.arenas);
|
||||
if let Err(old_binding) = self.try_define(parent, ident, ns, binding) {
|
||||
self.report_conflict(parent, ident, ns, old_binding, &binding);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -102,7 +103,7 @@ impl<'b> Resolver<'b> {
|
|||
/// Constructs the reduced graph for one item.
|
||||
fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) {
|
||||
let parent = self.current_module;
|
||||
let name = item.ident.name;
|
||||
let ident = item.ident;
|
||||
let sp = item.span;
|
||||
let vis = self.resolve_visibility(&item.vis);
|
||||
|
||||
|
@ -157,8 +158,8 @@ impl<'b> Resolver<'b> {
|
|||
}
|
||||
|
||||
let subclass = SingleImport {
|
||||
target: binding.name,
|
||||
source: source.name,
|
||||
target: binding,
|
||||
source: source,
|
||||
result: self.per_ns(|_, _| Cell::new(Err(Undetermined))),
|
||||
};
|
||||
self.add_import_directive(
|
||||
|
@ -187,13 +188,13 @@ impl<'b> Resolver<'b> {
|
|||
|
||||
for source_item in source_items {
|
||||
let node = source_item.node;
|
||||
let (module_path, name, rename) = {
|
||||
let (module_path, ident, rename) = {
|
||||
if node.name.name != keywords::SelfValue.name() {
|
||||
let rename = node.rename.unwrap_or(node.name).name;
|
||||
(module_path.clone(), node.name.name, rename)
|
||||
let rename = node.rename.unwrap_or(node.name);
|
||||
(module_path.clone(), node.name, rename)
|
||||
} else {
|
||||
let name = match module_path.last() {
|
||||
Some(ident) => ident.name,
|
||||
let ident = match module_path.last() {
|
||||
Some(&ident) => ident,
|
||||
None => {
|
||||
resolve_error(
|
||||
self,
|
||||
|
@ -205,13 +206,13 @@ impl<'b> Resolver<'b> {
|
|||
}
|
||||
};
|
||||
let module_path = module_path.split_last().unwrap().1;
|
||||
let rename = node.rename.map(|i| i.name).unwrap_or(name);
|
||||
(module_path.to_vec(), name, rename)
|
||||
let rename = node.rename.unwrap_or(ident);
|
||||
(module_path.to_vec(), ident, rename)
|
||||
}
|
||||
};
|
||||
let subclass = SingleImport {
|
||||
target: rename,
|
||||
source: name,
|
||||
source: ident,
|
||||
result: self.per_ns(|_, _| Cell::new(Err(Undetermined))),
|
||||
};
|
||||
let id = source_item.node.id;
|
||||
|
@ -238,8 +239,8 @@ impl<'b> Resolver<'b> {
|
|||
// n.b. we don't need to look at the path option here, because cstore already did
|
||||
let crate_id = self.session.cstore.extern_mod_stmt_cnum(item.id).unwrap();
|
||||
let module = self.get_extern_crate_root(crate_id);
|
||||
let binding = (module, ty::Visibility::Public, sp, expansion).to_name_binding();
|
||||
let binding = self.arenas.alloc_name_binding(binding);
|
||||
let binding =
|
||||
(module, ty::Visibility::Public, sp, expansion).to_name_binding(self.arenas);
|
||||
let directive = self.arenas.alloc_import_directive(ImportDirective {
|
||||
id: item.id,
|
||||
parent: parent,
|
||||
|
@ -251,7 +252,7 @@ impl<'b> Resolver<'b> {
|
|||
expansion: expansion,
|
||||
});
|
||||
let imported_binding = self.import(binding, directive);
|
||||
self.define(parent, name, TypeNS, imported_binding);
|
||||
self.define(parent, ident, TypeNS, imported_binding);
|
||||
self.populate_module_if_necessary(module);
|
||||
self.process_legacy_macro_imports(item, module, expansion);
|
||||
}
|
||||
|
@ -260,14 +261,14 @@ impl<'b> Resolver<'b> {
|
|||
|
||||
ItemKind::Mod(..) => {
|
||||
let def = Def::Mod(self.definitions.local_def_id(item.id));
|
||||
let module = self.arenas.alloc_module(ModuleS {
|
||||
let module = self.arenas.alloc_module(ModuleData {
|
||||
no_implicit_prelude: parent.no_implicit_prelude || {
|
||||
attr::contains_name(&item.attrs, "no_implicit_prelude")
|
||||
},
|
||||
normal_ancestor_id: Some(item.id),
|
||||
..ModuleS::new(Some(parent), ModuleKind::Def(def, name))
|
||||
..ModuleData::new(Some(parent), ModuleKind::Def(def, ident.name))
|
||||
});
|
||||
self.define(parent, name, TypeNS, (module, vis, sp, expansion));
|
||||
self.define(parent, ident, TypeNS, (module, vis, sp, expansion));
|
||||
self.module_map.insert(item.id, module);
|
||||
|
||||
// Descend into the module.
|
||||
|
@ -280,27 +281,27 @@ impl<'b> Resolver<'b> {
|
|||
ItemKind::Static(_, m, _) => {
|
||||
let mutbl = m == Mutability::Mutable;
|
||||
let def = Def::Static(self.definitions.local_def_id(item.id), mutbl);
|
||||
self.define(parent, name, ValueNS, (def, vis, sp, expansion));
|
||||
self.define(parent, ident, ValueNS, (def, vis, sp, expansion));
|
||||
}
|
||||
ItemKind::Const(..) => {
|
||||
let def = Def::Const(self.definitions.local_def_id(item.id));
|
||||
self.define(parent, name, ValueNS, (def, vis, sp, expansion));
|
||||
self.define(parent, ident, ValueNS, (def, vis, sp, expansion));
|
||||
}
|
||||
ItemKind::Fn(..) => {
|
||||
let def = Def::Fn(self.definitions.local_def_id(item.id));
|
||||
self.define(parent, name, ValueNS, (def, vis, sp, expansion));
|
||||
self.define(parent, ident, ValueNS, (def, vis, sp, expansion));
|
||||
}
|
||||
|
||||
// These items live in the type namespace.
|
||||
ItemKind::Ty(..) => {
|
||||
let def = Def::TyAlias(self.definitions.local_def_id(item.id));
|
||||
self.define(parent, name, TypeNS, (def, vis, sp, expansion));
|
||||
self.define(parent, ident, TypeNS, (def, vis, sp, expansion));
|
||||
}
|
||||
|
||||
ItemKind::Enum(ref enum_definition, _) => {
|
||||
let def = Def::Enum(self.definitions.local_def_id(item.id));
|
||||
let module = self.new_module(parent, ModuleKind::Def(def, name), true);
|
||||
self.define(parent, name, TypeNS, (module, vis, sp, expansion));
|
||||
let module = self.new_module(parent, ModuleKind::Def(def, ident.name), true);
|
||||
self.define(parent, ident, TypeNS, (module, vis, sp, expansion));
|
||||
|
||||
for variant in &(*enum_definition).variants {
|
||||
self.build_reduced_graph_for_variant(variant, module, vis, expansion);
|
||||
|
@ -311,14 +312,14 @@ impl<'b> Resolver<'b> {
|
|||
ItemKind::Struct(ref struct_def, _) => {
|
||||
// Define a name in the type namespace.
|
||||
let def = Def::Struct(self.definitions.local_def_id(item.id));
|
||||
self.define(parent, name, TypeNS, (def, vis, sp, expansion));
|
||||
self.define(parent, ident, TypeNS, (def, vis, sp, expansion));
|
||||
|
||||
// If this is a tuple or unit struct, define a name
|
||||
// in the value namespace as well.
|
||||
if !struct_def.is_struct() {
|
||||
let ctor_def = Def::StructCtor(self.definitions.local_def_id(struct_def.id()),
|
||||
CtorKind::from_ast(struct_def));
|
||||
self.define(parent, name, ValueNS, (ctor_def, vis, sp, expansion));
|
||||
self.define(parent, ident, ValueNS, (ctor_def, vis, sp, expansion));
|
||||
}
|
||||
|
||||
// Record field names for error reporting.
|
||||
|
@ -332,7 +333,7 @@ impl<'b> Resolver<'b> {
|
|||
|
||||
ItemKind::Union(ref vdata, _) => {
|
||||
let def = Def::Union(self.definitions.local_def_id(item.id));
|
||||
self.define(parent, name, TypeNS, (def, vis, sp, expansion));
|
||||
self.define(parent, ident, TypeNS, (def, vis, sp, expansion));
|
||||
|
||||
// Record field names for error reporting.
|
||||
let field_names = vdata.fields().iter().filter_map(|field| {
|
||||
|
@ -350,8 +351,8 @@ impl<'b> Resolver<'b> {
|
|||
|
||||
// Add all the items within to a new module.
|
||||
let module =
|
||||
self.new_module(parent, ModuleKind::Def(Def::Trait(def_id), name), true);
|
||||
self.define(parent, name, TypeNS, (module, vis, sp, expansion));
|
||||
self.new_module(parent, ModuleKind::Def(Def::Trait(def_id), ident.name), true);
|
||||
self.define(parent, ident, TypeNS, (module, vis, sp, expansion));
|
||||
self.current_module = module;
|
||||
}
|
||||
ItemKind::Mac(_) => panic!("unexpanded macro in resolve!"),
|
||||
|
@ -362,29 +363,26 @@ impl<'b> Resolver<'b> {
|
|||
// type and value namespaces.
|
||||
fn build_reduced_graph_for_variant(&mut self,
|
||||
variant: &Variant,
|
||||
parent: Module<'b>,
|
||||
parent: Module<'a>,
|
||||
vis: ty::Visibility,
|
||||
expansion: Mark) {
|
||||
let name = variant.node.name.name;
|
||||
let ident = variant.node.name;
|
||||
let def_id = self.definitions.local_def_id(variant.node.data.id());
|
||||
|
||||
// Define a name in the type namespace.
|
||||
let def = Def::Variant(def_id);
|
||||
self.define(parent, name, TypeNS, (def, vis, variant.span, expansion));
|
||||
self.define(parent, ident, TypeNS, (def, vis, variant.span, expansion));
|
||||
|
||||
// Define a constructor name in the value namespace.
|
||||
// Braced variants, unlike structs, generate unusable names in
|
||||
// value namespace, they are reserved for possible future use.
|
||||
let ctor_kind = CtorKind::from_ast(&variant.node.data);
|
||||
let ctor_def = Def::VariantCtor(def_id, ctor_kind);
|
||||
self.define(parent, name, ValueNS, (ctor_def, vis, variant.span, expansion));
|
||||
self.define(parent, ident, ValueNS, (ctor_def, vis, variant.span, expansion));
|
||||
}
|
||||
|
||||
/// Constructs the reduced graph for one foreign item.
|
||||
fn build_reduced_graph_for_foreign_item(&mut self, item: &ForeignItem, expansion: Mark) {
|
||||
let parent = self.current_module;
|
||||
let name = item.ident.name;
|
||||
|
||||
let def = match item.node {
|
||||
ForeignItemKind::Fn(..) => {
|
||||
Def::Fn(self.definitions.local_def_id(item.id))
|
||||
|
@ -393,8 +391,9 @@ impl<'b> Resolver<'b> {
|
|||
Def::Static(self.definitions.local_def_id(item.id), m)
|
||||
}
|
||||
};
|
||||
let parent = self.current_module;
|
||||
let vis = self.resolve_visibility(&item.vis);
|
||||
self.define(parent, name, ValueNS, (def, vis, item.span, expansion));
|
||||
self.define(parent, item.ident, ValueNS, (def, vis, item.span, expansion));
|
||||
}
|
||||
|
||||
fn build_reduced_graph_for_block(&mut self, block: &Block) {
|
||||
|
@ -413,8 +412,8 @@ impl<'b> Resolver<'b> {
|
|||
}
|
||||
|
||||
/// Builds the reduced graph for a single item in an external crate.
|
||||
fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'b>, child: Export) {
|
||||
let name = child.name;
|
||||
fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'a>, child: Export) {
|
||||
let ident = Ident::with_empty_ctxt(child.name);
|
||||
let def = child.def;
|
||||
let def_id = def.def_id();
|
||||
let vis = match def {
|
||||
|
@ -425,25 +424,25 @@ impl<'b> Resolver<'b> {
|
|||
|
||||
match def {
|
||||
Def::Mod(..) | Def::Enum(..) => {
|
||||
let module = self.new_module(parent, ModuleKind::Def(def, name), false);
|
||||
self.define(parent, name, TypeNS, (module, vis, DUMMY_SP, Mark::root()));
|
||||
let module = self.new_module(parent, ModuleKind::Def(def, ident.name), false);
|
||||
self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, Mark::root()));
|
||||
}
|
||||
Def::Variant(..) => {
|
||||
self.define(parent, name, TypeNS, (def, vis, DUMMY_SP, Mark::root()));
|
||||
self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, Mark::root()));
|
||||
}
|
||||
Def::VariantCtor(..) => {
|
||||
self.define(parent, name, ValueNS, (def, vis, DUMMY_SP, Mark::root()));
|
||||
self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, Mark::root()));
|
||||
}
|
||||
Def::Fn(..) |
|
||||
Def::Static(..) |
|
||||
Def::Const(..) |
|
||||
Def::AssociatedConst(..) |
|
||||
Def::Method(..) => {
|
||||
self.define(parent, name, ValueNS, (def, vis, DUMMY_SP, Mark::root()));
|
||||
self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, Mark::root()));
|
||||
}
|
||||
Def::Trait(..) => {
|
||||
let module = self.new_module(parent, ModuleKind::Def(def, name), false);
|
||||
self.define(parent, name, TypeNS, (module, vis, DUMMY_SP, Mark::root()));
|
||||
let module = self.new_module(parent, ModuleKind::Def(def, ident.name), false);
|
||||
self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, Mark::root()));
|
||||
|
||||
// If this is a trait, add all the trait item names to the trait info.
|
||||
let trait_item_def_ids = self.session.cstore.associated_item_def_ids(def_id);
|
||||
|
@ -455,27 +454,27 @@ impl<'b> Resolver<'b> {
|
|||
}
|
||||
}
|
||||
Def::TyAlias(..) | Def::AssociatedTy(..) => {
|
||||
self.define(parent, name, TypeNS, (def, vis, DUMMY_SP, Mark::root()));
|
||||
self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, Mark::root()));
|
||||
}
|
||||
Def::Struct(..) => {
|
||||
self.define(parent, name, TypeNS, (def, vis, DUMMY_SP, Mark::root()));
|
||||
self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, Mark::root()));
|
||||
|
||||
// Record field names for error reporting.
|
||||
let field_names = self.session.cstore.struct_field_names(def_id);
|
||||
self.insert_field_names(def_id, field_names);
|
||||
}
|
||||
Def::StructCtor(..) => {
|
||||
self.define(parent, name, ValueNS, (def, vis, DUMMY_SP, Mark::root()));
|
||||
self.define(parent, ident, ValueNS, (def, vis, DUMMY_SP, Mark::root()));
|
||||
}
|
||||
Def::Union(..) => {
|
||||
self.define(parent, name, TypeNS, (def, vis, DUMMY_SP, Mark::root()));
|
||||
self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, Mark::root()));
|
||||
|
||||
// Record field names for error reporting.
|
||||
let field_names = self.session.cstore.struct_field_names(def_id);
|
||||
self.insert_field_names(def_id, field_names);
|
||||
}
|
||||
Def::Macro(..) => {
|
||||
self.define(parent, name, MacroNS, (def, vis, DUMMY_SP, Mark::root()));
|
||||
self.define(parent, ident, MacroNS, (def, vis, DUMMY_SP, Mark::root()));
|
||||
}
|
||||
Def::Local(..) |
|
||||
Def::PrimTy(..) |
|
||||
|
@ -489,14 +488,15 @@ impl<'b> Resolver<'b> {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_extern_crate_root(&mut self, cnum: CrateNum) -> Module<'b> {
|
||||
fn get_extern_crate_root(&mut self, cnum: CrateNum) -> Module<'a> {
|
||||
let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX };
|
||||
let name = self.session.cstore.crate_name(cnum);
|
||||
let macros_only = self.session.cstore.dep_kind(cnum).macros_only();
|
||||
let arenas = self.arenas;
|
||||
*self.extern_crate_roots.entry((cnum, macros_only)).or_insert_with(|| {
|
||||
arenas.alloc_module(ModuleS {
|
||||
arenas.alloc_module(ModuleData {
|
||||
populated: Cell::new(false),
|
||||
..ModuleS::new(None, ModuleKind::Def(Def::Mod(def_id), keywords::Invalid.name()))
|
||||
..ModuleData::new(None, ModuleKind::Def(Def::Mod(def_id), name))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -532,7 +532,7 @@ impl<'b> Resolver<'b> {
|
|||
|
||||
/// Ensures that the reduced graph rooted at the given external module
|
||||
/// is built, building it if it is not.
|
||||
pub fn populate_module_if_necessary(&mut self, module: Module<'b>) {
|
||||
pub fn populate_module_if_necessary(&mut self, module: Module<'a>) {
|
||||
if module.populated.get() { return }
|
||||
for child in self.session.cstore.item_children(module.def_id().unwrap()) {
|
||||
self.build_reduced_graph_for_external_crate_def(module, child);
|
||||
|
@ -542,7 +542,7 @@ impl<'b> Resolver<'b> {
|
|||
|
||||
fn legacy_import_macro(&mut self,
|
||||
name: Name,
|
||||
binding: &'b NameBinding<'b>,
|
||||
binding: &'a NameBinding<'a>,
|
||||
span: Span,
|
||||
allow_shadowing: bool) {
|
||||
self.used_crates.insert(binding.def().def_id().krate);
|
||||
|
@ -555,7 +555,7 @@ impl<'b> Resolver<'b> {
|
|||
}
|
||||
}
|
||||
|
||||
fn process_legacy_macro_imports(&mut self, item: &Item, module: Module<'b>, expansion: Mark) {
|
||||
fn process_legacy_macro_imports(&mut self, item: &Item, module: Module<'a>, expansion: Mark) {
|
||||
let allow_shadowing = expansion == Mark::root();
|
||||
let legacy_imports = self.legacy_macro_imports(&item.attrs);
|
||||
let cnum = module.def_id().unwrap().krate;
|
||||
|
@ -574,12 +574,13 @@ impl<'b> Resolver<'b> {
|
|||
}
|
||||
|
||||
if let Some(span) = legacy_imports.import_all {
|
||||
module.for_each_child(|name, ns, binding| if ns == MacroNS {
|
||||
self.legacy_import_macro(name, binding, span, allow_shadowing);
|
||||
module.for_each_child(|ident, ns, binding| if ns == MacroNS {
|
||||
self.legacy_import_macro(ident.name, binding, span, allow_shadowing);
|
||||
});
|
||||
} else {
|
||||
for (name, span) in legacy_imports.imports {
|
||||
let result = self.resolve_name_in_module(module, name, MacroNS, false, None);
|
||||
let ident = Ident::with_empty_ctxt(name);
|
||||
let result = self.resolve_ident_in_module(module, ident, MacroNS, false, None);
|
||||
if let Ok(binding) = result {
|
||||
self.legacy_import_macro(name, binding, span, allow_shadowing);
|
||||
} else {
|
||||
|
@ -591,7 +592,8 @@ impl<'b> Resolver<'b> {
|
|||
let krate = module.def_id().unwrap().krate;
|
||||
self.used_crates.insert(krate);
|
||||
self.session.cstore.export_macros(krate);
|
||||
let result = self.resolve_name_in_module(module, name, MacroNS, false, None);
|
||||
let ident = Ident::with_empty_ctxt(name);
|
||||
let result = self.resolve_ident_in_module(module, ident, MacroNS, false, None);
|
||||
if let Ok(binding) = result {
|
||||
self.macro_exports.push(Export { name: name, def: binding.def() });
|
||||
} else {
|
||||
|
@ -696,9 +698,13 @@ impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> {
|
|||
|
||||
fn visit_item(&mut self, item: &'a Item) {
|
||||
let macro_use = match item.node {
|
||||
ItemKind::Mac(..) if item.id == ast::DUMMY_NODE_ID => return, // Scope placeholder
|
||||
ItemKind::Mac(..) => {
|
||||
return self.legacy_scope = LegacyScope::Expansion(self.visit_invoc(item.id));
|
||||
ItemKind::Mac(ref mac) => {
|
||||
if mac.node.path.segments.is_empty() {
|
||||
self.legacy_scope = LegacyScope::Expansion(self.visit_invoc(item.id));
|
||||
} else {
|
||||
self.resolver.define_macro(item, &mut self.legacy_scope);
|
||||
}
|
||||
return
|
||||
}
|
||||
ItemKind::Mod(..) => self.resolver.contains_macro_use(&item.attrs),
|
||||
_ => false,
|
||||
|
@ -759,7 +765,7 @@ impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> {
|
|||
self.resolver.trait_item_map.insert((item.ident.name, def_id), is_static_method);
|
||||
|
||||
let vis = ty::Visibility::Public;
|
||||
self.resolver.define(parent, item.ident.name, ns, (def, vis, item.span, self.expansion));
|
||||
self.resolver.define(parent, item.ident, ns, (def, vis, item.span, self.expansion));
|
||||
|
||||
self.resolver.current_module = parent.parent.unwrap(); // nearest normal ancestor
|
||||
visit::walk_trait_item(self, item);
|
||||
|
|
|
@ -62,7 +62,7 @@ use syntax::ast::{Arm, BindingMode, Block, Crate, Expr, ExprKind};
|
|||
use syntax::ast::{FnDecl, ForeignItem, ForeignItemKind, Generics};
|
||||
use syntax::ast::{Item, ItemKind, ImplItem, ImplItemKind};
|
||||
use syntax::ast::{Local, Mutability, Pat, PatKind, Path};
|
||||
use syntax::ast::{PathSegment, PathParameters, QSelf, TraitItemKind, TraitRef, Ty, TyKind};
|
||||
use syntax::ast::{QSelf, TraitItemKind, TraitRef, Ty, TyKind};
|
||||
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
use errors::DiagnosticBuilder;
|
||||
|
@ -774,15 +774,15 @@ enum ModuleKind {
|
|||
}
|
||||
|
||||
/// One node in the tree of modules.
|
||||
pub struct ModuleS<'a> {
|
||||
pub struct ModuleData<'a> {
|
||||
parent: Option<Module<'a>>,
|
||||
kind: ModuleKind,
|
||||
|
||||
// The node id of the closest normal module (`mod`) ancestor (including this module).
|
||||
normal_ancestor_id: Option<NodeId>,
|
||||
|
||||
resolutions: RefCell<FxHashMap<(Name, Namespace), &'a RefCell<NameResolution<'a>>>>,
|
||||
legacy_macro_resolutions: RefCell<Vec<(Mark, Name, Span)>>,
|
||||
resolutions: RefCell<FxHashMap<(Ident, Namespace), &'a RefCell<NameResolution<'a>>>>,
|
||||
legacy_macro_resolutions: RefCell<Vec<(Mark, Ident, Span)>>,
|
||||
macro_resolutions: RefCell<Vec<(Box<[Ident]>, PathScope, Span)>>,
|
||||
|
||||
// Macro invocations that can expand into items in this module.
|
||||
|
@ -794,7 +794,7 @@ pub struct ModuleS<'a> {
|
|||
globs: RefCell<Vec<&'a ImportDirective<'a>>>,
|
||||
|
||||
// Used to memoize the traits in this module for faster searches through all traits in scope.
|
||||
traits: RefCell<Option<Box<[(Name, &'a NameBinding<'a>)]>>>,
|
||||
traits: RefCell<Option<Box<[(Ident, &'a NameBinding<'a>)]>>>,
|
||||
|
||||
// Whether this module is populated. If not populated, any attempt to
|
||||
// access the children must be preceded with a
|
||||
|
@ -802,11 +802,11 @@ pub struct ModuleS<'a> {
|
|||
populated: Cell<bool>,
|
||||
}
|
||||
|
||||
pub type Module<'a> = &'a ModuleS<'a>;
|
||||
pub type Module<'a> = &'a ModuleData<'a>;
|
||||
|
||||
impl<'a> ModuleS<'a> {
|
||||
impl<'a> ModuleData<'a> {
|
||||
fn new(parent: Option<Module<'a>>, kind: ModuleKind) -> Self {
|
||||
ModuleS {
|
||||
ModuleData {
|
||||
parent: parent,
|
||||
kind: kind,
|
||||
normal_ancestor_id: None,
|
||||
|
@ -822,9 +822,9 @@ impl<'a> ModuleS<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn for_each_child<F: FnMut(Name, Namespace, &'a NameBinding<'a>)>(&self, mut f: F) {
|
||||
for (&(name, ns), name_resolution) in self.resolutions.borrow().iter() {
|
||||
name_resolution.borrow().binding.map(|binding| f(name, ns, binding));
|
||||
fn for_each_child<F: FnMut(Ident, Namespace, &'a NameBinding<'a>)>(&self, mut f: F) {
|
||||
for (&(ident, ns), name_resolution) in self.resolutions.borrow().iter() {
|
||||
name_resolution.borrow().binding.map(|binding| f(ident, ns, binding));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -859,7 +859,7 @@ impl<'a> ModuleS<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> fmt::Debug for ModuleS<'a> {
|
||||
impl<'a> fmt::Debug for ModuleData<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{:?}", self.def())
|
||||
}
|
||||
|
@ -875,11 +875,11 @@ pub struct NameBinding<'a> {
|
|||
}
|
||||
|
||||
pub trait ToNameBinding<'a> {
|
||||
fn to_name_binding(self) -> NameBinding<'a>;
|
||||
fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a>;
|
||||
}
|
||||
|
||||
impl<'a> ToNameBinding<'a> for NameBinding<'a> {
|
||||
fn to_name_binding(self) -> NameBinding<'a> {
|
||||
impl<'a> ToNameBinding<'a> for &'a NameBinding<'a> {
|
||||
fn to_name_binding(self, _: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
@ -1116,7 +1116,7 @@ pub struct Resolver<'a> {
|
|||
}
|
||||
|
||||
pub struct ResolverArenas<'a> {
|
||||
modules: arena::TypedArena<ModuleS<'a>>,
|
||||
modules: arena::TypedArena<ModuleData<'a>>,
|
||||
local_modules: RefCell<Vec<Module<'a>>>,
|
||||
name_bindings: arena::TypedArena<NameBinding<'a>>,
|
||||
import_directives: arena::TypedArena<ImportDirective<'a>>,
|
||||
|
@ -1126,7 +1126,7 @@ pub struct ResolverArenas<'a> {
|
|||
}
|
||||
|
||||
impl<'a> ResolverArenas<'a> {
|
||||
fn alloc_module(&'a self, module: ModuleS<'a>) -> Module<'a> {
|
||||
fn alloc_module(&'a self, module: ModuleData<'a>) -> Module<'a> {
|
||||
let module = self.modules.alloc(module);
|
||||
if module.def_id().map(|def_id| def_id.is_local()).unwrap_or(true) {
|
||||
self.local_modules.borrow_mut().push(module);
|
||||
|
@ -1206,10 +1206,10 @@ impl<'a> Resolver<'a> {
|
|||
arenas: &'a ResolverArenas<'a>)
|
||||
-> Resolver<'a> {
|
||||
let root_def = Def::Mod(DefId::local(CRATE_DEF_INDEX));
|
||||
let graph_root = arenas.alloc_module(ModuleS {
|
||||
let graph_root = arenas.alloc_module(ModuleData {
|
||||
normal_ancestor_id: Some(CRATE_NODE_ID),
|
||||
no_implicit_prelude: attr::contains_name(&krate.attrs, "no_implicit_prelude"),
|
||||
..ModuleS::new(None, ModuleKind::Def(root_def, keywords::Invalid.name()))
|
||||
..ModuleData::new(None, ModuleKind::Def(root_def, keywords::Invalid.name()))
|
||||
});
|
||||
let mut module_map = NodeMap();
|
||||
module_map.insert(CRATE_NODE_ID, graph_root);
|
||||
|
@ -1327,17 +1327,17 @@ impl<'a> Resolver<'a> {
|
|||
}
|
||||
|
||||
fn new_module(&self, parent: Module<'a>, kind: ModuleKind, local: bool) -> Module<'a> {
|
||||
self.arenas.alloc_module(ModuleS {
|
||||
self.arenas.alloc_module(ModuleData {
|
||||
normal_ancestor_id: if local { self.current_module.normal_ancestor_id } else { None },
|
||||
populated: Cell::new(local),
|
||||
..ModuleS::new(Some(parent), kind)
|
||||
..ModuleData::new(Some(parent), kind)
|
||||
})
|
||||
}
|
||||
|
||||
fn record_use(&mut self, name: Name, ns: Namespace, binding: &'a NameBinding<'a>, span: Span)
|
||||
fn record_use(&mut self, ident: Ident, ns: Namespace, binding: &'a NameBinding<'a>, span: Span)
|
||||
-> bool /* true if an error was reported */ {
|
||||
// track extern crates for unused_extern_crate lint
|
||||
if let Some(DefId { krate, .. }) = binding.module().and_then(ModuleS::def_id) {
|
||||
if let Some(DefId { krate, .. }) = binding.module().and_then(ModuleData::def_id) {
|
||||
self.used_crates.insert(krate);
|
||||
}
|
||||
|
||||
|
@ -1345,13 +1345,13 @@ impl<'a> Resolver<'a> {
|
|||
NameBindingKind::Import { directive, binding, ref used } if !used.get() => {
|
||||
used.set(true);
|
||||
self.used_imports.insert((directive.id, ns));
|
||||
self.add_to_glob_map(directive.id, name);
|
||||
self.record_use(name, ns, binding, span)
|
||||
self.add_to_glob_map(directive.id, ident);
|
||||
self.record_use(ident, ns, binding, span)
|
||||
}
|
||||
NameBindingKind::Import { .. } => false,
|
||||
NameBindingKind::Ambiguity { b1, b2 } => {
|
||||
self.ambiguity_errors.push(AmbiguityError {
|
||||
span: span, name: name, lexical: false, b1: b1, b2: b2,
|
||||
span: span, name: ident.name, lexical: false, b1: b1, b2: b2,
|
||||
});
|
||||
true
|
||||
}
|
||||
|
@ -1359,9 +1359,9 @@ impl<'a> Resolver<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn add_to_glob_map(&mut self, id: NodeId, name: Name) {
|
||||
fn add_to_glob_map(&mut self, id: NodeId, ident: Ident) {
|
||||
if self.make_glob_map {
|
||||
self.glob_map.entry(id).or_insert_with(FxHashSet).insert(name);
|
||||
self.glob_map.entry(id).or_insert_with(FxHashSet).insert(ident.name);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1388,7 +1388,7 @@ impl<'a> Resolver<'a> {
|
|||
record_used: Option<Span>)
|
||||
-> Option<LexicalScopeBinding<'a>> {
|
||||
if ns == TypeNS {
|
||||
ident = Ident::with_empty_ctxt(ident.name);
|
||||
ident = ident.unhygienize();
|
||||
}
|
||||
|
||||
// Walk backwards up the ribs in scope.
|
||||
|
@ -1403,8 +1403,7 @@ impl<'a> Resolver<'a> {
|
|||
}
|
||||
|
||||
if let ModuleRibKind(module) = self.ribs[ns][i].kind {
|
||||
let name = ident.name;
|
||||
let item = self.resolve_name_in_module(module, name, ns, false, record_used);
|
||||
let item = self.resolve_ident_in_module(module, ident, ns, false, record_used);
|
||||
if let Ok(binding) = item {
|
||||
// The ident resolves to an item.
|
||||
return Some(LexicalScopeBinding::Item(binding));
|
||||
|
@ -1413,7 +1412,7 @@ impl<'a> Resolver<'a> {
|
|||
if let ModuleKind::Block(..) = module.kind { // We can see through blocks
|
||||
} else if !module.no_implicit_prelude {
|
||||
return self.prelude.and_then(|prelude| {
|
||||
self.resolve_name_in_module(prelude, name, ns, false, None).ok()
|
||||
self.resolve_ident_in_module(prelude, ident, ns, false, None).ok()
|
||||
}).map(LexicalScopeBinding::Item)
|
||||
} else {
|
||||
return None;
|
||||
|
@ -2183,8 +2182,7 @@ impl<'a> Resolver<'a> {
|
|||
Def::VariantCtor(_, CtorKind::Const) |
|
||||
Def::Const(..) if !always_binding => {
|
||||
// A unit struct/variant or constant pattern.
|
||||
let name = ident.node.name;
|
||||
self.record_use(name, ValueNS, binding.unwrap(), ident.span);
|
||||
self.record_use(ident.node, ValueNS, binding.unwrap(), ident.span);
|
||||
Some(PathResolution::new(def))
|
||||
}
|
||||
Def::StructCtor(..) | Def::VariantCtor(..) |
|
||||
|
@ -2363,9 +2361,9 @@ impl<'a> Resolver<'a> {
|
|||
allow_super = false;
|
||||
|
||||
let binding = if let Some(module) = module {
|
||||
self.resolve_name_in_module(module, ident.name, ns, false, record_used)
|
||||
self.resolve_ident_in_module(module, ident, ns, false, record_used)
|
||||
} else if opt_ns == Some(MacroNS) {
|
||||
self.resolve_lexical_macro_path_segment(ident.name, ns, record_used)
|
||||
self.resolve_lexical_macro_path_segment(ident, ns, record_used)
|
||||
} else {
|
||||
match self.resolve_ident_in_lexical_scope(ident, ns, record_used) {
|
||||
Some(LexicalScopeBinding::Item(binding)) => Ok(binding),
|
||||
|
@ -2405,7 +2403,7 @@ impl<'a> Resolver<'a> {
|
|||
});
|
||||
}
|
||||
}
|
||||
let msg = if module.and_then(ModuleS::def) == self.graph_root.def() {
|
||||
let msg = if module.and_then(ModuleData::def) == self.graph_root.def() {
|
||||
let is_mod = |def| match def { Def::Mod(..) => true, _ => false };
|
||||
let mut candidates =
|
||||
self.lookup_candidates(ident.name, TypeNS, is_mod).candidates;
|
||||
|
@ -2865,72 +2863,64 @@ impl<'a> Resolver<'a> {
|
|||
fn get_traits_containing_item(&mut self, name: Name) -> Vec<TraitCandidate> {
|
||||
debug!("(getting traits containing item) looking for '{}'", name);
|
||||
|
||||
fn add_trait_info(found_traits: &mut Vec<TraitCandidate>,
|
||||
trait_def_id: DefId,
|
||||
import_id: Option<NodeId>,
|
||||
name: Name) {
|
||||
debug!("(adding trait info) found trait {:?} for method '{}'",
|
||||
trait_def_id,
|
||||
name);
|
||||
found_traits.push(TraitCandidate {
|
||||
def_id: trait_def_id,
|
||||
import_id: import_id,
|
||||
});
|
||||
}
|
||||
|
||||
let mut found_traits = Vec::new();
|
||||
// Look for the current trait.
|
||||
if let Some((trait_def_id, _)) = self.current_trait_ref {
|
||||
if self.trait_item_map.contains_key(&(name, trait_def_id)) {
|
||||
add_trait_info(&mut found_traits, trait_def_id, None, name);
|
||||
found_traits.push(TraitCandidate { def_id: trait_def_id, import_id: None });
|
||||
}
|
||||
}
|
||||
|
||||
let mut search_module = self.current_module;
|
||||
loop {
|
||||
// Look for trait children.
|
||||
let mut search_in_module = |this: &mut Self, module: Module<'a>| {
|
||||
let mut traits = module.traits.borrow_mut();
|
||||
if traits.is_none() {
|
||||
let mut collected_traits = Vec::new();
|
||||
module.for_each_child(|name, ns, binding| {
|
||||
if ns != TypeNS { return }
|
||||
if let Def::Trait(_) = binding.def() {
|
||||
collected_traits.push((name, binding));
|
||||
}
|
||||
});
|
||||
*traits = Some(collected_traits.into_boxed_slice());
|
||||
}
|
||||
self.get_traits_in_module_containing_item(name, search_module, &mut found_traits);
|
||||
match search_module.kind {
|
||||
ModuleKind::Block(..) => search_module = search_module.parent.unwrap(),
|
||||
_ => break,
|
||||
}
|
||||
}
|
||||
|
||||
for &(trait_name, binding) in traits.as_ref().unwrap().iter() {
|
||||
let trait_def_id = binding.def().def_id();
|
||||
if this.trait_item_map.contains_key(&(name, trait_def_id)) {
|
||||
let mut import_id = None;
|
||||
if let NameBindingKind::Import { directive, .. } = binding.kind {
|
||||
let id = directive.id;
|
||||
this.maybe_unused_trait_imports.insert(id);
|
||||
this.add_to_glob_map(id, trait_name);
|
||||
import_id = Some(id);
|
||||
}
|
||||
add_trait_info(&mut found_traits, trait_def_id, import_id, name);
|
||||
}
|
||||
}
|
||||
};
|
||||
search_in_module(self, search_module);
|
||||
|
||||
if let ModuleKind::Block(..) = search_module.kind {
|
||||
search_module = search_module.parent.unwrap();
|
||||
} else {
|
||||
if !search_module.no_implicit_prelude {
|
||||
self.prelude.map(|prelude| search_in_module(self, prelude));
|
||||
}
|
||||
break;
|
||||
if let Some(prelude) = self.prelude {
|
||||
if !search_module.no_implicit_prelude {
|
||||
self.get_traits_in_module_containing_item(name, prelude, &mut found_traits);
|
||||
}
|
||||
}
|
||||
|
||||
found_traits
|
||||
}
|
||||
|
||||
fn get_traits_in_module_containing_item(&mut self,
|
||||
name: Name,
|
||||
module: Module,
|
||||
found_traits: &mut Vec<TraitCandidate>) {
|
||||
let mut traits = module.traits.borrow_mut();
|
||||
if traits.is_none() {
|
||||
let mut collected_traits = Vec::new();
|
||||
module.for_each_child(|name, ns, binding| {
|
||||
if ns != TypeNS { return }
|
||||
if let Def::Trait(_) = binding.def() {
|
||||
collected_traits.push((name, binding));
|
||||
}
|
||||
});
|
||||
*traits = Some(collected_traits.into_boxed_slice());
|
||||
}
|
||||
|
||||
for &(trait_name, binding) in traits.as_ref().unwrap().iter() {
|
||||
let trait_def_id = binding.def().def_id();
|
||||
if self.trait_item_map.contains_key(&(name, trait_def_id)) {
|
||||
let import_id = match binding.kind {
|
||||
NameBindingKind::Import { directive, .. } => {
|
||||
self.maybe_unused_trait_imports.insert(directive.id);
|
||||
self.add_to_glob_map(directive.id, trait_name);
|
||||
Some(directive.id)
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
found_traits.push(TraitCandidate { def_id: trait_def_id, import_id: import_id });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// When name resolution fails, this method can be used to look up candidate
|
||||
/// entities with the expected name. It allows filtering them using the
|
||||
/// supplied predicate (which should be used to only accept the types of
|
||||
|
@ -2953,24 +2943,18 @@ impl<'a> Resolver<'a> {
|
|||
in_module_is_extern)) = worklist.pop() {
|
||||
self.populate_module_if_necessary(in_module);
|
||||
|
||||
in_module.for_each_child(|name, ns, name_binding| {
|
||||
in_module.for_each_child(|ident, ns, name_binding| {
|
||||
|
||||
// avoid imports entirely
|
||||
if name_binding.is_import() && !name_binding.is_extern_crate() { return; }
|
||||
|
||||
// collect results based on the filter function
|
||||
if name == lookup_name && ns == namespace {
|
||||
if ident.name == lookup_name && ns == namespace {
|
||||
if filter_fn(name_binding.def()) {
|
||||
// create the path
|
||||
let ident = Ident::with_empty_ctxt(name);
|
||||
let params = PathParameters::none();
|
||||
let segment = PathSegment {
|
||||
identifier: ident,
|
||||
parameters: params,
|
||||
};
|
||||
let span = name_binding.span;
|
||||
let mut segms = path_segments.clone();
|
||||
segms.push(segment);
|
||||
segms.push(ident.into());
|
||||
let path = Path {
|
||||
span: span,
|
||||
global: false,
|
||||
|
@ -2993,10 +2977,7 @@ impl<'a> Resolver<'a> {
|
|||
if let Some(module) = name_binding.module() {
|
||||
// form the path
|
||||
let mut path_segments = path_segments.clone();
|
||||
path_segments.push(PathSegment {
|
||||
identifier: Ident::with_empty_ctxt(name),
|
||||
parameters: PathParameters::none(),
|
||||
});
|
||||
path_segments.push(ident.into());
|
||||
|
||||
if !in_module_is_extern || name_binding.vis == ty::Visibility::Public {
|
||||
// add the module to the lookup
|
||||
|
@ -3124,13 +3105,13 @@ impl<'a> Resolver<'a> {
|
|||
|
||||
fn report_conflict(&mut self,
|
||||
parent: Module,
|
||||
name: Name,
|
||||
ident: Ident,
|
||||
ns: Namespace,
|
||||
binding: &NameBinding,
|
||||
old_binding: &NameBinding) {
|
||||
// Error on the second of two conflicting names
|
||||
if old_binding.span.lo > binding.span.lo {
|
||||
return self.report_conflict(parent, name, ns, old_binding, binding);
|
||||
return self.report_conflict(parent, ident, ns, old_binding, binding);
|
||||
}
|
||||
|
||||
let container = match parent.kind {
|
||||
|
@ -3145,7 +3126,7 @@ impl<'a> Resolver<'a> {
|
|||
false => ("defined", "definition"),
|
||||
};
|
||||
|
||||
let span = binding.span;
|
||||
let (name, span) = (ident.name, binding.span);
|
||||
|
||||
if let Some(s) = self.name_already_seen.get(&name) {
|
||||
if s == &span {
|
||||
|
@ -3167,40 +3148,19 @@ impl<'a> Resolver<'a> {
|
|||
};
|
||||
|
||||
let mut err = match (old_binding.is_extern_crate(), binding.is_extern_crate()) {
|
||||
(true, true) => {
|
||||
let mut e = struct_span_err!(self.session, span, E0259, "{}", msg);
|
||||
e.span_label(span, &format!("`{}` was already imported", name));
|
||||
e
|
||||
},
|
||||
(true, _) | (_, true) if binding.is_import() && old_binding.is_import() => {
|
||||
let mut e = struct_span_err!(self.session, span, E0254, "{}", msg);
|
||||
e.span_label(span, &"already imported");
|
||||
e
|
||||
},
|
||||
(true, _) | (_, true) => {
|
||||
let mut e = struct_span_err!(self.session, span, E0260, "{}", msg);
|
||||
e.span_label(span, &format!("`{}` already imported", name));
|
||||
e
|
||||
(true, true) => struct_span_err!(self.session, span, E0259, "{}", msg),
|
||||
(true, _) | (_, true) => match binding.is_import() && old_binding.is_import() {
|
||||
true => struct_span_err!(self.session, span, E0254, "{}", msg),
|
||||
false => struct_span_err!(self.session, span, E0260, "{}", msg),
|
||||
},
|
||||
_ => match (old_binding.is_import(), binding.is_import()) {
|
||||
(false, false) => {
|
||||
let mut e = struct_span_err!(self.session, span, E0428, "{}", msg);
|
||||
e.span_label(span, &format!("already defined"));
|
||||
e
|
||||
},
|
||||
(true, true) => {
|
||||
let mut e = struct_span_err!(self.session, span, E0252, "{}", msg);
|
||||
e.span_label(span, &format!("already imported"));
|
||||
e
|
||||
},
|
||||
_ => {
|
||||
let mut e = struct_span_err!(self.session, span, E0255, "{}", msg);
|
||||
e.span_label(span, &format!("`{}` was already imported", name));
|
||||
e
|
||||
}
|
||||
(false, false) => struct_span_err!(self.session, span, E0428, "{}", msg),
|
||||
(true, true) => struct_span_err!(self.session, span, E0252, "{}", msg),
|
||||
_ => struct_span_err!(self.session, span, E0255, "{}", msg),
|
||||
},
|
||||
};
|
||||
|
||||
err.span_label(span, &format!("`{}` already {}", name, participle));
|
||||
if old_binding.span != syntax_pos::DUMMY_SP {
|
||||
err.span_label(old_binding.span, &format!("previous {} of `{}` here", noun, name));
|
||||
}
|
||||
|
|
|
@ -19,11 +19,12 @@ use rustc::hir::map::{self, DefCollector};
|
|||
use rustc::ty;
|
||||
use std::cell::Cell;
|
||||
use std::rc::Rc;
|
||||
use syntax::ast::{self, Name};
|
||||
use syntax::ast::{self, Name, Ident};
|
||||
use syntax::attr;
|
||||
use syntax::errors::DiagnosticBuilder;
|
||||
use syntax::ext::base::{self, Determinacy, MultiModifier, MultiDecorator};
|
||||
use syntax::ext::base::{NormalTT, SyntaxExtension};
|
||||
use syntax::ext::expand::Expansion;
|
||||
use syntax::ext::base::{NormalTT, Resolver as SyntaxResolver, SyntaxExtension};
|
||||
use syntax::ext::expand::{Expansion, mark_tts};
|
||||
use syntax::ext::hygiene::Mark;
|
||||
use syntax::ext::tt::macro_rules;
|
||||
use syntax::feature_gate::{emit_feature_err, GateIssue};
|
||||
|
@ -138,34 +139,6 @@ impl<'a> base::Resolver for Resolver<'a> {
|
|||
invocation.expansion.set(visitor.legacy_scope);
|
||||
}
|
||||
|
||||
fn add_macro(&mut self, scope: Mark, mut def: ast::MacroDef, export: bool) {
|
||||
if def.ident.name == "macro_rules" {
|
||||
self.session.span_err(def.span, "user-defined macros may not be named `macro_rules`");
|
||||
}
|
||||
|
||||
let invocation = self.invocations[&scope];
|
||||
let binding = self.arenas.alloc_legacy_binding(LegacyBinding {
|
||||
parent: Cell::new(invocation.legacy_scope.get()),
|
||||
name: def.ident.name,
|
||||
ext: Rc::new(macro_rules::compile(&self.session.parse_sess, &def)),
|
||||
span: def.span,
|
||||
});
|
||||
invocation.legacy_scope.set(LegacyScope::Binding(binding));
|
||||
self.macro_names.insert(def.ident.name);
|
||||
|
||||
if export {
|
||||
def.id = self.next_node_id();
|
||||
DefCollector::new(&mut self.definitions).with_parent(CRATE_DEF_INDEX, |collector| {
|
||||
collector.visit_macro_def(&def)
|
||||
});
|
||||
self.macro_exports.push(Export {
|
||||
name: def.ident.name,
|
||||
def: Def::Macro(self.definitions.local_def_id(def.id)),
|
||||
});
|
||||
self.exported_macros.push(def);
|
||||
}
|
||||
}
|
||||
|
||||
fn add_ext(&mut self, ident: ast::Ident, ext: Rc<SyntaxExtension>) {
|
||||
if let NormalTT(..) = *ext {
|
||||
self.macro_names.insert(ident.name);
|
||||
|
@ -210,9 +183,9 @@ impl<'a> base::Resolver for Resolver<'a> {
|
|||
fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, force: bool)
|
||||
-> Result<Rc<SyntaxExtension>, Determinacy> {
|
||||
let ast::Path { ref segments, global, span } = *path;
|
||||
if segments.iter().any(|segment| !segment.parameters.is_empty()) {
|
||||
if segments.iter().any(|segment| segment.parameters.is_some()) {
|
||||
let kind =
|
||||
if segments.last().unwrap().parameters.is_empty() { "module" } else { "macro" };
|
||||
if segments.last().unwrap().parameters.is_some() { "macro" } else { "module" };
|
||||
let msg = format!("type parameters are not allowed on {}s", kind);
|
||||
self.session.span_err(path.span, &msg);
|
||||
return Err(Determinacy::Determined);
|
||||
|
@ -232,7 +205,10 @@ impl<'a> base::Resolver for Resolver<'a> {
|
|||
}
|
||||
|
||||
let ext = match self.resolve_path(&path, path_scope, Some(MacroNS), None) {
|
||||
PathResult::NonModule(path_res) => Ok(self.get_macro(path_res.base_def)),
|
||||
PathResult::NonModule(path_res) => match path_res.base_def {
|
||||
Def::Err => Err(Determinacy::Determined),
|
||||
def @ _ => Ok(self.get_macro(def)),
|
||||
},
|
||||
PathResult::Module(..) => unreachable!(),
|
||||
PathResult::Indeterminate if !force => return Err(Determinacy::Undetermined),
|
||||
_ => Err(Determinacy::Determined),
|
||||
|
@ -246,7 +222,7 @@ impl<'a> base::Resolver for Resolver<'a> {
|
|||
let result = match self.resolve_legacy_scope(&invocation.legacy_scope, name, false) {
|
||||
Some(MacroBinding::Legacy(binding)) => Ok(binding.ext.clone()),
|
||||
Some(MacroBinding::Modern(binding)) => Ok(binding.get_macro(self)),
|
||||
None => match self.resolve_lexical_macro_path_segment(name, MacroNS, None) {
|
||||
None => match self.resolve_lexical_macro_path_segment(path[0], MacroNS, None) {
|
||||
Ok(binding) => Ok(binding.get_macro(self)),
|
||||
Err(Determinacy::Undetermined) if !force => return Err(Determinacy::Undetermined),
|
||||
_ => {
|
||||
|
@ -260,7 +236,7 @@ impl<'a> base::Resolver for Resolver<'a> {
|
|||
};
|
||||
|
||||
if self.use_extern_macros {
|
||||
self.current_module.legacy_macro_resolutions.borrow_mut().push((scope, name, span));
|
||||
self.current_module.legacy_macro_resolutions.borrow_mut().push((scope, path[0], span));
|
||||
}
|
||||
result
|
||||
}
|
||||
|
@ -269,7 +245,7 @@ impl<'a> base::Resolver for Resolver<'a> {
|
|||
impl<'a> Resolver<'a> {
|
||||
// Resolve the initial segment of a non-global macro path (e.g. `foo` in `foo::bar!();`)
|
||||
pub fn resolve_lexical_macro_path_segment(&mut self,
|
||||
name: Name,
|
||||
ident: Ident,
|
||||
ns: Namespace,
|
||||
record_used: Option<Span>)
|
||||
-> Result<&'a NameBinding<'a>, Determinacy> {
|
||||
|
@ -278,7 +254,7 @@ impl<'a> Resolver<'a> {
|
|||
loop {
|
||||
// Since expanded macros may not shadow the lexical scope (enforced below),
|
||||
// we can ignore unresolved invocations (indicated by the penultimate argument).
|
||||
match self.resolve_name_in_module(module, name, ns, true, record_used) {
|
||||
match self.resolve_ident_in_module(module, ident, ns, true, record_used) {
|
||||
Ok(binding) => {
|
||||
let span = match record_used {
|
||||
Some(span) => span,
|
||||
|
@ -286,6 +262,7 @@ impl<'a> Resolver<'a> {
|
|||
};
|
||||
match potential_expanded_shadower {
|
||||
Some(shadower) if shadower.def() != binding.def() => {
|
||||
let name = ident.name;
|
||||
self.ambiguity_errors.push(AmbiguityError {
|
||||
span: span, name: name, b1: shadower, b2: binding, lexical: true,
|
||||
});
|
||||
|
@ -383,10 +360,10 @@ impl<'a> Resolver<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
for &(mark, name, span) in module.legacy_macro_resolutions.borrow().iter() {
|
||||
for &(mark, ident, span) in module.legacy_macro_resolutions.borrow().iter() {
|
||||
let legacy_scope = &self.invocations[&mark].legacy_scope;
|
||||
let legacy_resolution = self.resolve_legacy_scope(legacy_scope, name, true);
|
||||
let resolution = self.resolve_lexical_macro_path_segment(name, MacroNS, Some(span));
|
||||
let legacy_resolution = self.resolve_legacy_scope(legacy_scope, ident.name, true);
|
||||
let resolution = self.resolve_lexical_macro_path_segment(ident, MacroNS, Some(span));
|
||||
let (legacy_resolution, resolution) = match (legacy_resolution, resolution) {
|
||||
(Some(legacy_resolution), Ok(resolution)) => (legacy_resolution, resolution),
|
||||
_ => continue,
|
||||
|
@ -396,9 +373,9 @@ impl<'a> Resolver<'a> {
|
|||
MacroBinding::Modern(binding) => (binding.span, "imported"),
|
||||
MacroBinding::Legacy(binding) => (binding.span, "defined"),
|
||||
};
|
||||
let msg1 = format!("`{}` could resolve to the macro {} here", name, participle);
|
||||
let msg2 = format!("`{}` could also resolve to the macro imported here", name);
|
||||
self.session.struct_span_err(span, &format!("`{}` is ambiguous", name))
|
||||
let msg1 = format!("`{}` could resolve to the macro {} here", ident, participle);
|
||||
let msg2 = format!("`{}` could also resolve to the macro imported here", ident);
|
||||
self.session.struct_span_err(span, &format!("`{}` is ambiguous", ident))
|
||||
.span_note(legacy_span, &msg1)
|
||||
.span_note(resolution.span, &msg2)
|
||||
.emit();
|
||||
|
@ -442,4 +419,47 @@ impl<'a> Resolver<'a> {
|
|||
expansion.visit_with(def_collector)
|
||||
});
|
||||
}
|
||||
|
||||
pub fn define_macro(&mut self, item: &ast::Item, legacy_scope: &mut LegacyScope<'a>) {
|
||||
let tts = match item.node {
|
||||
ast::ItemKind::Mac(ref mac) => &mac.node.tts,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
if item.ident.name == "macro_rules" {
|
||||
self.session.span_err(item.span, "user-defined macros may not be named `macro_rules`");
|
||||
}
|
||||
|
||||
let mark = Mark::from_placeholder_id(item.id);
|
||||
let invocation = self.invocations[&mark];
|
||||
invocation.module.set(self.current_module);
|
||||
|
||||
let mut def = ast::MacroDef {
|
||||
ident: item.ident,
|
||||
attrs: item.attrs.clone(),
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
span: item.span,
|
||||
body: mark_tts(tts, mark),
|
||||
};
|
||||
|
||||
*legacy_scope = LegacyScope::Binding(self.arenas.alloc_legacy_binding(LegacyBinding {
|
||||
parent: Cell::new(*legacy_scope),
|
||||
name: def.ident.name,
|
||||
ext: Rc::new(macro_rules::compile(&self.session.parse_sess, &def)),
|
||||
span: def.span,
|
||||
}));
|
||||
self.macro_names.insert(def.ident.name);
|
||||
|
||||
if attr::contains_name(&def.attrs, "macro_export") {
|
||||
def.id = self.next_node_id();
|
||||
DefCollector::new(&mut self.definitions).with_parent(CRATE_DEF_INDEX, |collector| {
|
||||
collector.visit_macro_def(&def)
|
||||
});
|
||||
self.macro_exports.push(Export {
|
||||
name: def.ident.name,
|
||||
def: Def::Macro(self.definitions.local_def_id(def.id)),
|
||||
});
|
||||
self.exported_macros.push(def);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ use self::ImportDirectiveSubclass::*;
|
|||
|
||||
use {AmbiguityError, Module, PerNS};
|
||||
use Namespace::{self, TypeNS, MacroNS};
|
||||
use {NameBinding, NameBindingKind, PathResult, PathScope, PrivacyError, ToNameBinding};
|
||||
use {NameBinding, NameBindingKind, PathResult, PathScope, PrivacyError};
|
||||
use Resolver;
|
||||
use {names_to_string, module_to_string};
|
||||
use {resolve_error, ResolutionError};
|
||||
|
@ -21,7 +21,7 @@ use rustc::ty;
|
|||
use rustc::lint::builtin::PRIVATE_IN_PUBLIC;
|
||||
use rustc::hir::def::*;
|
||||
|
||||
use syntax::ast::{Ident, NodeId, Name};
|
||||
use syntax::ast::{Ident, NodeId};
|
||||
use syntax::ext::base::Determinacy::{self, Determined, Undetermined};
|
||||
use syntax::ext::hygiene::Mark;
|
||||
use syntax::symbol::keywords;
|
||||
|
@ -35,8 +35,8 @@ use std::mem;
|
|||
#[derive(Clone, Debug)]
|
||||
pub enum ImportDirectiveSubclass<'a> {
|
||||
SingleImport {
|
||||
target: Name,
|
||||
source: Name,
|
||||
target: Ident,
|
||||
source: Ident,
|
||||
result: PerNS<Cell<Result<&'a NameBinding<'a>, Determinacy>>>,
|
||||
},
|
||||
GlobImport {
|
||||
|
@ -126,31 +126,32 @@ impl<'a> NameResolution<'a> {
|
|||
}
|
||||
|
||||
impl<'a> Resolver<'a> {
|
||||
fn resolution(&self, module: Module<'a>, name: Name, ns: Namespace)
|
||||
fn resolution(&self, module: Module<'a>, ident: Ident, ns: Namespace)
|
||||
-> &'a RefCell<NameResolution<'a>> {
|
||||
*module.resolutions.borrow_mut().entry((name, ns))
|
||||
*module.resolutions.borrow_mut().entry((ident, ns))
|
||||
.or_insert_with(|| self.arenas.alloc_name_resolution())
|
||||
}
|
||||
|
||||
/// Attempts to resolve the supplied name in the given module for the given namespace.
|
||||
/// If successful, returns the binding corresponding to the name.
|
||||
/// Attempts to resolve `ident` in namespaces `ns` of `module`.
|
||||
/// Invariant: if `record_used` is `Some`, import resolution must be complete.
|
||||
pub fn resolve_name_in_module(&mut self,
|
||||
module: Module<'a>,
|
||||
name: Name,
|
||||
ns: Namespace,
|
||||
ignore_unresolved_invocations: bool,
|
||||
record_used: Option<Span>)
|
||||
-> Result<&'a NameBinding<'a>, Determinacy> {
|
||||
pub fn resolve_ident_in_module(&mut self,
|
||||
module: Module<'a>,
|
||||
ident: Ident,
|
||||
ns: Namespace,
|
||||
ignore_unresolved_invocations: bool,
|
||||
record_used: Option<Span>)
|
||||
-> Result<&'a NameBinding<'a>, Determinacy> {
|
||||
let ident = ident.unhygienize();
|
||||
self.populate_module_if_necessary(module);
|
||||
|
||||
let resolution = self.resolution(module, name, ns)
|
||||
let resolution = self.resolution(module, ident, ns)
|
||||
.try_borrow_mut()
|
||||
.map_err(|_| Determined)?; // This happens when there is a cycle of imports
|
||||
|
||||
if let Some(span) = record_used {
|
||||
if let Some(binding) = resolution.binding {
|
||||
if let Some(shadowed_glob) = resolution.shadows_glob {
|
||||
let name = ident.name;
|
||||
// If we ignore unresolved invocations, we must forbid
|
||||
// expanded shadowing to avoid time travel.
|
||||
if ignore_unresolved_invocations &&
|
||||
|
@ -162,11 +163,11 @@ impl<'a> Resolver<'a> {
|
|||
});
|
||||
}
|
||||
}
|
||||
if self.record_use(name, ns, binding, span) {
|
||||
if self.record_use(ident, ns, binding, span) {
|
||||
return Ok(self.dummy_binding);
|
||||
}
|
||||
if !self.is_accessible(binding.vis) {
|
||||
self.privacy_errors.push(PrivacyError(span, name, binding));
|
||||
self.privacy_errors.push(PrivacyError(span, ident.name, binding));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -194,11 +195,11 @@ impl<'a> Resolver<'a> {
|
|||
Some(module) => module,
|
||||
None => return Err(Undetermined),
|
||||
};
|
||||
let name = match directive.subclass {
|
||||
let ident = match directive.subclass {
|
||||
SingleImport { source, .. } => source,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
match self.resolve_name_in_module(module, name, ns, false, None) {
|
||||
match self.resolve_ident_in_module(module, ident, ns, false, None) {
|
||||
Err(Determined) => {}
|
||||
_ => return Err(Undetermined),
|
||||
}
|
||||
|
@ -220,7 +221,7 @@ impl<'a> Resolver<'a> {
|
|||
for directive in module.globs.borrow().iter() {
|
||||
if self.is_accessible(directive.vis.get()) {
|
||||
if let Some(module) = directive.imported_module.get() {
|
||||
let result = self.resolve_name_in_module(module, name, ns, false, None);
|
||||
let result = self.resolve_ident_in_module(module, ident, ns, false, None);
|
||||
if let Err(Undetermined) = result {
|
||||
return Err(Undetermined);
|
||||
}
|
||||
|
@ -272,7 +273,7 @@ impl<'a> Resolver<'a> {
|
|||
// Given a binding and an import directive that resolves to it,
|
||||
// return the corresponding binding defined by the import directive.
|
||||
pub fn import(&mut self, binding: &'a NameBinding<'a>, directive: &'a ImportDirective<'a>)
|
||||
-> NameBinding<'a> {
|
||||
-> &'a NameBinding<'a> {
|
||||
let vis = if binding.pseudo_vis().is_at_least(directive.vis.get(), self) ||
|
||||
!directive.is_glob() && binding.is_extern_crate() { // c.f. `PRIVATE_IN_PUBLIC`
|
||||
directive.vis.get()
|
||||
|
@ -286,7 +287,7 @@ impl<'a> Resolver<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
NameBinding {
|
||||
self.arenas.alloc_name_binding(NameBinding {
|
||||
kind: NameBindingKind::Import {
|
||||
binding: binding,
|
||||
directive: directive,
|
||||
|
@ -295,16 +296,18 @@ impl<'a> Resolver<'a> {
|
|||
span: directive.span,
|
||||
vis: vis,
|
||||
expansion: directive.expansion,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Define the name or return the existing binding if there is a collision.
|
||||
pub fn try_define<T>(&mut self, module: Module<'a>, name: Name, ns: Namespace, binding: T)
|
||||
-> Result<(), &'a NameBinding<'a>>
|
||||
where T: ToNameBinding<'a>
|
||||
{
|
||||
let binding = self.arenas.alloc_name_binding(binding.to_name_binding());
|
||||
self.update_resolution(module, name, ns, |this, resolution| {
|
||||
pub fn try_define(&mut self,
|
||||
module: Module<'a>,
|
||||
ident: Ident,
|
||||
ns: Namespace,
|
||||
binding: &'a NameBinding<'a>)
|
||||
-> Result<(), &'a NameBinding<'a>> {
|
||||
let ident = ident.unhygienize();
|
||||
self.update_resolution(module, ident, ns, |this, resolution| {
|
||||
if let Some(old_binding) = resolution.binding {
|
||||
if binding.is_glob_import() {
|
||||
if !old_binding.is_glob_import() &&
|
||||
|
@ -347,13 +350,14 @@ impl<'a> Resolver<'a> {
|
|||
|
||||
// Use `f` to mutate the resolution of the name in the module.
|
||||
// If the resolution becomes a success, define it in the module's glob importers.
|
||||
fn update_resolution<T, F>(&mut self, module: Module<'a>, name: Name, ns: Namespace, f: F) -> T
|
||||
fn update_resolution<T, F>(&mut self, module: Module<'a>, ident: Ident, ns: Namespace, f: F)
|
||||
-> T
|
||||
where F: FnOnce(&mut Resolver<'a>, &mut NameResolution<'a>) -> T
|
||||
{
|
||||
// Ensure that `resolution` isn't borrowed when defining in the module's glob importers,
|
||||
// during which the resolution might end up getting re-defined via a glob cycle.
|
||||
let (binding, t) = {
|
||||
let mut resolution = &mut *self.resolution(module, name, ns).borrow_mut();
|
||||
let mut resolution = &mut *self.resolution(module, ident, ns).borrow_mut();
|
||||
let old_binding = resolution.binding();
|
||||
|
||||
let t = f(self, resolution);
|
||||
|
@ -372,7 +376,7 @@ impl<'a> Resolver<'a> {
|
|||
for directive in module.glob_importers.borrow_mut().iter() {
|
||||
if self.is_accessible_from(binding.vis, directive.parent) {
|
||||
let imported_binding = self.import(binding, directive);
|
||||
let _ = self.try_define(directive.parent, name, ns, imported_binding);
|
||||
let _ = self.try_define(directive.parent, ident, ns, imported_binding);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -386,7 +390,7 @@ impl<'a> Resolver<'a> {
|
|||
let dummy_binding = self.dummy_binding;
|
||||
let dummy_binding = self.import(dummy_binding, directive);
|
||||
self.per_ns(|this, ns| {
|
||||
let _ = this.try_define(directive.parent, target, ns, dummy_binding.clone());
|
||||
let _ = this.try_define(directive.parent, target, ns, dummy_binding);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -508,15 +512,16 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
|
|||
let mut indeterminate = false;
|
||||
self.per_ns(|this, ns| {
|
||||
if let Err(Undetermined) = result[ns].get() {
|
||||
result[ns].set(this.resolve_name_in_module(module, source, ns, false, None));
|
||||
result[ns].set(this.resolve_ident_in_module(module, source, ns, false, None));
|
||||
} else {
|
||||
return
|
||||
};
|
||||
|
||||
let parent = directive.parent;
|
||||
match result[ns].get() {
|
||||
Err(Undetermined) => indeterminate = true,
|
||||
Err(Determined) => {
|
||||
this.update_resolution(directive.parent, target, ns, |_, resolution| {
|
||||
this.update_resolution(parent, target, ns, |_, resolution| {
|
||||
resolution.single_imports.directive_failed()
|
||||
});
|
||||
}
|
||||
|
@ -531,10 +536,9 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
|
|||
}
|
||||
Ok(binding) => {
|
||||
let imported_binding = this.import(binding, directive);
|
||||
let conflict = this.try_define(directive.parent, target, ns, imported_binding);
|
||||
let conflict = this.try_define(parent, target, ns, imported_binding);
|
||||
if let Err(old_binding) = conflict {
|
||||
let binding = &this.import(binding, directive);
|
||||
this.report_conflict(directive.parent, target, ns, binding, old_binding);
|
||||
this.report_conflict(parent, target, ns, imported_binding, old_binding);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -564,7 +568,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
|
|||
_ => return None,
|
||||
};
|
||||
|
||||
let (name, result) = match directive.subclass {
|
||||
let (ident, result) = match directive.subclass {
|
||||
SingleImport { source, ref result, .. } => (source, result),
|
||||
GlobImport { .. } if module.def_id() == directive.parent.def_id() => {
|
||||
// Importing a module into itself is not allowed.
|
||||
|
@ -586,8 +590,8 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
|
|||
self.per_ns(|this, ns| {
|
||||
if let Ok(binding) = result[ns].get() {
|
||||
all_ns_err = false;
|
||||
if this.record_use(name, ns, binding, directive.span) {
|
||||
this.resolution(module, name, ns).borrow_mut().binding =
|
||||
if this.record_use(ident, ns, binding, directive.span) {
|
||||
this.resolution(module, ident, ns).borrow_mut().binding =
|
||||
Some(this.dummy_binding);
|
||||
}
|
||||
}
|
||||
|
@ -596,7 +600,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
|
|||
if all_ns_err {
|
||||
let mut all_ns_failed = true;
|
||||
self.per_ns(|this, ns| {
|
||||
match this.resolve_name_in_module(module, name, ns, false, Some(span)) {
|
||||
match this.resolve_ident_in_module(module, ident, ns, false, Some(span)) {
|
||||
Ok(_) => all_ns_failed = false,
|
||||
_ => {}
|
||||
}
|
||||
|
@ -604,27 +608,28 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
|
|||
|
||||
return if all_ns_failed {
|
||||
let resolutions = module.resolutions.borrow();
|
||||
let names = resolutions.iter().filter_map(|(&(ref n, _), resolution)| {
|
||||
if *n == name { return None; } // Never suggest the same name
|
||||
let names = resolutions.iter().filter_map(|(&(ref i, _), resolution)| {
|
||||
if *i == ident { return None; } // Never suggest the same name
|
||||
match *resolution.borrow() {
|
||||
NameResolution { binding: Some(_), .. } => Some(n),
|
||||
NameResolution { binding: Some(_), .. } => Some(&i.name),
|
||||
NameResolution { single_imports: SingleImports::None, .. } => None,
|
||||
_ => Some(n),
|
||||
_ => Some(&i.name),
|
||||
}
|
||||
});
|
||||
let lev_suggestion = match find_best_match_for_name(names, &name.as_str(), None) {
|
||||
Some(name) => format!(". Did you mean to use `{}`?", name),
|
||||
None => "".to_owned(),
|
||||
};
|
||||
let lev_suggestion =
|
||||
match find_best_match_for_name(names, &ident.name.as_str(), None) {
|
||||
Some(name) => format!(". Did you mean to use `{}`?", name),
|
||||
None => "".to_owned(),
|
||||
};
|
||||
let module_str = module_to_string(module);
|
||||
let msg = if &module_str == "???" {
|
||||
format!("no `{}` in the root{}", name, lev_suggestion)
|
||||
format!("no `{}` in the root{}", ident, lev_suggestion)
|
||||
} else {
|
||||
format!("no `{}` in `{}`{}", name, module_str, lev_suggestion)
|
||||
format!("no `{}` in `{}`{}", ident, module_str, lev_suggestion)
|
||||
};
|
||||
Some(msg)
|
||||
} else {
|
||||
// `resolve_name_in_module` reported a privacy error.
|
||||
// `resolve_ident_in_module` reported a privacy error.
|
||||
self.import_dummy_binding(directive);
|
||||
None
|
||||
}
|
||||
|
@ -649,18 +654,18 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
|
|||
if ns == TypeNS && binding.is_extern_crate() {
|
||||
let msg = format!("extern crate `{}` is private, and cannot be reexported \
|
||||
(error E0364), consider declaring with `pub`",
|
||||
name);
|
||||
ident);
|
||||
self.session.add_lint(PRIVATE_IN_PUBLIC, directive.id, directive.span, msg);
|
||||
} else if ns == TypeNS {
|
||||
struct_span_err!(self.session, directive.span, E0365,
|
||||
"`{}` is private, and cannot be reexported", name)
|
||||
.span_label(directive.span, &format!("reexport of private `{}`", name))
|
||||
.note(&format!("consider declaring type or module `{}` with `pub`", name))
|
||||
"`{}` is private, and cannot be reexported", ident)
|
||||
.span_label(directive.span, &format!("reexport of private `{}`", ident))
|
||||
.note(&format!("consider declaring type or module `{}` with `pub`", ident))
|
||||
.emit();
|
||||
} else {
|
||||
let msg = format!("`{}` is private, and cannot be reexported", name);
|
||||
let msg = format!("`{}` is private, and cannot be reexported", ident);
|
||||
let note_msg =
|
||||
format!("consider marking `{}` as `pub` in the imported module", name);
|
||||
format!("consider marking `{}` as `pub` in the imported module", ident);
|
||||
struct_span_err!(self.session, directive.span, E0364, "{}", &msg)
|
||||
.span_note(directive.span, ¬e_msg)
|
||||
.emit();
|
||||
|
@ -697,21 +702,18 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
|
|||
|
||||
// Ensure that `resolutions` isn't borrowed during `try_define`,
|
||||
// since it might get updated via a glob cycle.
|
||||
let bindings = module.resolutions.borrow().iter().filter_map(|(name, resolution)| {
|
||||
resolution.borrow().binding().map(|binding| (*name, binding))
|
||||
let bindings = module.resolutions.borrow().iter().filter_map(|(&ident, resolution)| {
|
||||
resolution.borrow().binding().map(|binding| (ident, binding))
|
||||
}).collect::<Vec<_>>();
|
||||
for ((name, ns), binding) in bindings {
|
||||
for ((ident, ns), binding) in bindings {
|
||||
if binding.pseudo_vis() == ty::Visibility::Public || self.is_accessible(binding.vis) {
|
||||
let imported_binding = self.import(binding, directive);
|
||||
let _ = self.try_define(directive.parent, name, ns, imported_binding);
|
||||
let _ = self.try_define(directive.parent, ident, ns, imported_binding);
|
||||
}
|
||||
}
|
||||
|
||||
// Record the destination of this import
|
||||
if let Some(did) = module.def_id() {
|
||||
let resolution = PathResolution::new(Def::Mod(did));
|
||||
self.def_map.insert(directive.id, resolution);
|
||||
}
|
||||
self.def_map.insert(directive.id, PathResolution::new(module.def().unwrap()));
|
||||
}
|
||||
|
||||
// Miscellaneous post-processing, including recording reexports, reporting conflicts,
|
||||
|
@ -725,7 +727,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
|
|||
reexports = mem::replace(&mut self.macro_exports, Vec::new());
|
||||
}
|
||||
|
||||
for (&(name, ns), resolution) in module.resolutions.borrow().iter() {
|
||||
for (&(ident, ns), resolution) in module.resolutions.borrow().iter() {
|
||||
let resolution = resolution.borrow();
|
||||
let binding = match resolution.binding {
|
||||
Some(binding) => binding,
|
||||
|
@ -739,7 +741,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
|
|||
if !def.def_id().is_local() {
|
||||
self.session.cstore.export_macros(def.def_id().krate);
|
||||
}
|
||||
reexports.push(Export { name: name, def: def });
|
||||
reexports.push(Export { name: ident.name, def: def });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -748,7 +750,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
|
|||
!orig_binding.vis.is_at_least(binding.vis, self) {
|
||||
let msg = format!("variant `{}` is private, and cannot be reexported \
|
||||
(error E0364), consider declaring its enum as `pub`",
|
||||
name);
|
||||
ident);
|
||||
self.session.add_lint(PRIVATE_IN_PUBLIC, directive.id, binding.span, msg);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -201,6 +201,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
|||
if def_id.krate == LOCAL_CRATE {
|
||||
continue // These are `krate.exported_macros`, handled in `self.visit()`.
|
||||
}
|
||||
let imported_from = self.cx.sess().cstore.original_crate_name(def_id.krate);
|
||||
let def = match self.cx.sess().cstore.load_macro(def_id, self.cx.sess()) {
|
||||
LoadedMacro::MacroRules(macro_rules) => macro_rules,
|
||||
// FIXME(jseyfried): document proc macro reexports
|
||||
|
@ -217,7 +218,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
|||
matchers: matchers,
|
||||
stab: self.stability(def.id),
|
||||
depr: self.deprecation(def.id),
|
||||
imported_from: def.imported_from.map(|ident| ident.name),
|
||||
imported_from: Some(imported_from),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -525,7 +526,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
|||
matchers: matchers,
|
||||
stab: self.stability(def.id),
|
||||
depr: self.deprecation(def.id),
|
||||
imported_from: def.imported_from,
|
||||
imported_from: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,10 +47,14 @@ impl Ident {
|
|||
Ident { name: name, ctxt: SyntaxContext::empty() }
|
||||
}
|
||||
|
||||
/// Maps a string to an identifier with an empty syntax context.
|
||||
pub fn from_str(s: &str) -> Ident {
|
||||
Ident::with_empty_ctxt(Symbol::intern(s))
|
||||
}
|
||||
/// Maps a string to an identifier with an empty syntax context.
|
||||
pub fn from_str(s: &str) -> Ident {
|
||||
Ident::with_empty_ctxt(Symbol::intern(s))
|
||||
}
|
||||
|
||||
pub fn unhygienize(&self) -> Ident {
|
||||
Ident { name: self.name, ctxt: SyntaxContext::empty() }
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Ident {
|
||||
|
@ -133,12 +137,7 @@ impl Path {
|
|||
Path {
|
||||
span: s,
|
||||
global: false,
|
||||
segments: vec![
|
||||
PathSegment {
|
||||
identifier: identifier,
|
||||
parameters: PathParameters::none()
|
||||
}
|
||||
],
|
||||
segments: vec![identifier.into()],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -156,7 +155,15 @@ pub struct PathSegment {
|
|||
/// this is more than just simple syntactic sugar; the use of
|
||||
/// parens affects the region binding rules, so we preserve the
|
||||
/// distinction.
|
||||
pub parameters: PathParameters,
|
||||
/// The `Option<P<..>>` wrapper is purely a size optimization;
|
||||
/// `None` is used to represent both `Path` and `Path<>`.
|
||||
pub parameters: Option<P<PathParameters>>,
|
||||
}
|
||||
|
||||
impl From<Ident> for PathSegment {
|
||||
fn from(id: Ident) -> Self {
|
||||
PathSegment { identifier: id, parameters: None }
|
||||
}
|
||||
}
|
||||
|
||||
/// Parameters of a path segment.
|
||||
|
@ -170,79 +177,8 @@ pub enum PathParameters {
|
|||
Parenthesized(ParenthesizedParameterData),
|
||||
}
|
||||
|
||||
impl PathParameters {
|
||||
pub fn none() -> PathParameters {
|
||||
PathParameters::AngleBracketed(AngleBracketedParameterData {
|
||||
lifetimes: Vec::new(),
|
||||
types: P::new(),
|
||||
bindings: P::new(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
match *self {
|
||||
PathParameters::AngleBracketed(ref data) => data.is_empty(),
|
||||
|
||||
// Even if the user supplied no types, something like
|
||||
// `X()` is equivalent to `X<(),()>`.
|
||||
PathParameters::Parenthesized(..) => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn has_lifetimes(&self) -> bool {
|
||||
match *self {
|
||||
PathParameters::AngleBracketed(ref data) => !data.lifetimes.is_empty(),
|
||||
PathParameters::Parenthesized(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn has_types(&self) -> bool {
|
||||
match *self {
|
||||
PathParameters::AngleBracketed(ref data) => !data.types.is_empty(),
|
||||
PathParameters::Parenthesized(..) => true,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the types that the user wrote. Note that these do not necessarily map to the type
|
||||
/// parameters in the parenthesized case.
|
||||
pub fn types(&self) -> Vec<&P<Ty>> {
|
||||
match *self {
|
||||
PathParameters::AngleBracketed(ref data) => {
|
||||
data.types.iter().collect()
|
||||
}
|
||||
PathParameters::Parenthesized(ref data) => {
|
||||
data.inputs.iter()
|
||||
.chain(data.output.iter())
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lifetimes(&self) -> Vec<&Lifetime> {
|
||||
match *self {
|
||||
PathParameters::AngleBracketed(ref data) => {
|
||||
data.lifetimes.iter().collect()
|
||||
}
|
||||
PathParameters::Parenthesized(_) => {
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bindings(&self) -> Vec<&TypeBinding> {
|
||||
match *self {
|
||||
PathParameters::AngleBracketed(ref data) => {
|
||||
data.bindings.iter().collect()
|
||||
}
|
||||
PathParameters::Parenthesized(_) => {
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A path like `Foo<'a, T>`
|
||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Default)]
|
||||
pub struct AngleBracketedParameterData {
|
||||
/// The lifetime parameters for this path segment.
|
||||
pub lifetimes: Vec<Lifetime>,
|
||||
|
@ -254,9 +190,10 @@ pub struct AngleBracketedParameterData {
|
|||
pub bindings: P<[TypeBinding]>,
|
||||
}
|
||||
|
||||
impl AngleBracketedParameterData {
|
||||
fn is_empty(&self) -> bool {
|
||||
self.lifetimes.is_empty() && self.types.is_empty() && self.bindings.is_empty()
|
||||
impl Into<Option<P<PathParameters>>> for AngleBracketedParameterData {
|
||||
fn into(self) -> Option<P<PathParameters>> {
|
||||
let empty = self.lifetimes.is_empty() && self.types.is_empty() && self.bindings.is_empty();
|
||||
if empty { None } else { Some(P(PathParameters::AngleBracketed(self))) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1968,8 +1905,6 @@ pub struct MacroDef {
|
|||
pub attrs: Vec<Attribute>,
|
||||
pub id: NodeId,
|
||||
pub span: Span,
|
||||
pub imported_from: Option<Ident>,
|
||||
pub allow_internal_unstable: bool,
|
||||
pub body: Vec<TokenTree>,
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,6 @@ use symbol::Symbol;
|
|||
use util::ThinVec;
|
||||
|
||||
use std::cell::{RefCell, Cell};
|
||||
use std::collections::HashSet;
|
||||
|
||||
thread_local! {
|
||||
static USED_ATTRS: RefCell<Vec<u64>> = RefCell::new(Vec::new());
|
||||
|
@ -372,16 +371,6 @@ pub fn mk_spanned_attr_outer(sp: Span, id: AttrId, item: MetaItem) -> Attribute
|
|||
}
|
||||
}
|
||||
|
||||
pub fn mk_doc_attr_outer(id: AttrId, item: MetaItem, is_sugared_doc: bool) -> Attribute {
|
||||
Attribute {
|
||||
id: id,
|
||||
style: ast::AttrStyle::Outer,
|
||||
value: item,
|
||||
is_sugared_doc: is_sugared_doc,
|
||||
span: DUMMY_SP,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mk_sugared_doc_attr(id: AttrId, text: Symbol, lo: BytePos, hi: BytePos)
|
||||
-> Attribute {
|
||||
let style = doc_comment_style(&text.as_str());
|
||||
|
@ -421,13 +410,6 @@ pub fn first_attr_value_str_by_name(attrs: &[Attribute], name: &str) -> Option<S
|
|||
.and_then(|at| at.value_str())
|
||||
}
|
||||
|
||||
pub fn last_meta_item_value_str_by_name(items: &[MetaItem], name: &str) -> Option<Symbol> {
|
||||
items.iter()
|
||||
.rev()
|
||||
.find(|mi| mi.check_name(name))
|
||||
.and_then(|i| i.value_str())
|
||||
}
|
||||
|
||||
/* Higher-level applications */
|
||||
|
||||
pub fn find_crate_name(attrs: &[Attribute]) -> Option<Symbol> {
|
||||
|
@ -856,18 +838,6 @@ pub fn find_deprecation(diagnostic: &Handler, attrs: &[Attribute],
|
|||
find_deprecation_generic(diagnostic, attrs.iter(), item_sp)
|
||||
}
|
||||
|
||||
pub fn require_unique_names(diagnostic: &Handler, metas: &[MetaItem]) {
|
||||
let mut set = HashSet::new();
|
||||
for meta in metas {
|
||||
let name = meta.name();
|
||||
|
||||
if !set.insert(name.clone()) {
|
||||
panic!(diagnostic.span_fatal(meta.span,
|
||||
&format!("duplicate meta item `{}`", name)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Parse #[repr(...)] forms.
|
||||
///
|
||||
|
|
|
@ -217,8 +217,7 @@ pub trait IdentMacroExpander {
|
|||
cx: &'cx mut ExtCtxt,
|
||||
sp: Span,
|
||||
ident: ast::Ident,
|
||||
token_tree: Vec<tokenstream::TokenTree>,
|
||||
attrs: Vec<ast::Attribute>)
|
||||
token_tree: Vec<tokenstream::TokenTree>)
|
||||
-> Box<MacResult+'cx>;
|
||||
}
|
||||
|
||||
|
@ -234,8 +233,7 @@ impl<F> IdentMacroExpander for F
|
|||
cx: &'cx mut ExtCtxt,
|
||||
sp: Span,
|
||||
ident: ast::Ident,
|
||||
token_tree: Vec<tokenstream::TokenTree>,
|
||||
_attrs: Vec<ast::Attribute>)
|
||||
token_tree: Vec<tokenstream::TokenTree>)
|
||||
-> Box<MacResult+'cx>
|
||||
{
|
||||
(*self)(cx, sp, ident, token_tree)
|
||||
|
@ -520,7 +518,6 @@ pub trait Resolver {
|
|||
fn eliminate_crate_var(&mut self, item: P<ast::Item>) -> P<ast::Item>;
|
||||
|
||||
fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion);
|
||||
fn add_macro(&mut self, scope: Mark, def: ast::MacroDef, export: bool);
|
||||
fn add_ext(&mut self, ident: ast::Ident, ext: Rc<SyntaxExtension>);
|
||||
fn add_expansions_at_stmt(&mut self, id: ast::NodeId, macros: Vec<Mark>);
|
||||
|
||||
|
@ -544,7 +541,6 @@ impl Resolver for DummyResolver {
|
|||
fn eliminate_crate_var(&mut self, item: P<ast::Item>) -> P<ast::Item> { item }
|
||||
|
||||
fn visit_expansion(&mut self, _invoc: Mark, _expansion: &Expansion) {}
|
||||
fn add_macro(&mut self, _scope: Mark, _def: ast::MacroDef, _export: bool) {}
|
||||
fn add_ext(&mut self, _ident: ast::Ident, _ext: Rc<SyntaxExtension>) {}
|
||||
fn add_expansions_at_stmt(&mut self, _id: ast::NodeId, _macros: Vec<Mark>) {}
|
||||
|
||||
|
|
|
@ -322,21 +322,17 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
|||
bindings: Vec<ast::TypeBinding> )
|
||||
-> ast::Path {
|
||||
let last_identifier = idents.pop().unwrap();
|
||||
let mut segments: Vec<ast::PathSegment> = idents.into_iter()
|
||||
.map(|ident| {
|
||||
ast::PathSegment {
|
||||
identifier: ident,
|
||||
parameters: ast::PathParameters::none(),
|
||||
}
|
||||
}).collect();
|
||||
segments.push(ast::PathSegment {
|
||||
identifier: last_identifier,
|
||||
parameters: ast::PathParameters::AngleBracketed(ast::AngleBracketedParameterData {
|
||||
let mut segments: Vec<ast::PathSegment> = idents.into_iter().map(Into::into).collect();
|
||||
let parameters = if lifetimes.is_empty() && types.is_empty() && bindings.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(P(ast::PathParameters::AngleBracketed(ast::AngleBracketedParameterData {
|
||||
lifetimes: lifetimes,
|
||||
types: P::from_vec(types),
|
||||
bindings: P::from_vec(bindings),
|
||||
})
|
||||
});
|
||||
})))
|
||||
};
|
||||
segments.push(ast::PathSegment { identifier: last_identifier, parameters: parameters });
|
||||
ast::Path {
|
||||
span: sp,
|
||||
global: global,
|
||||
|
@ -367,13 +363,14 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
|||
bindings: Vec<ast::TypeBinding>)
|
||||
-> (ast::QSelf, ast::Path) {
|
||||
let mut path = trait_path;
|
||||
let parameters = ast::AngleBracketedParameterData {
|
||||
lifetimes: lifetimes,
|
||||
types: P::from_vec(types),
|
||||
bindings: P::from_vec(bindings),
|
||||
};
|
||||
path.segments.push(ast::PathSegment {
|
||||
identifier: ident,
|
||||
parameters: ast::PathParameters::AngleBracketed(ast::AngleBracketedParameterData {
|
||||
lifetimes: lifetimes,
|
||||
types: P::from_vec(types),
|
||||
bindings: P::from_vec(bindings),
|
||||
})
|
||||
parameters: Some(P(ast::PathParameters::AngleBracketed(parameters))),
|
||||
});
|
||||
|
||||
(ast::QSelf {
|
||||
|
|
|
@ -158,7 +158,6 @@ pub struct Invocation {
|
|||
|
||||
pub enum InvocationKind {
|
||||
Bang {
|
||||
attrs: Vec<ast::Attribute>,
|
||||
mac: ast::Mac,
|
||||
ident: Option<Ident>,
|
||||
span: Span,
|
||||
|
@ -276,7 +275,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
if expansions.len() < depth {
|
||||
expansions.push(Vec::new());
|
||||
}
|
||||
expansions[depth - 1].push((mark.as_u32(), expansion));
|
||||
expansions[depth - 1].push((mark, expansion));
|
||||
if !self.cx.ecfg.single_step {
|
||||
invocations.extend(new_invocations.into_iter().rev());
|
||||
}
|
||||
|
@ -287,7 +286,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
let mut placeholder_expander = PlaceholderExpander::new(self.cx, self.monotonic);
|
||||
while let Some(expansions) = expansions.pop() {
|
||||
for (mark, expansion) in expansions.into_iter().rev() {
|
||||
placeholder_expander.add(ast::NodeId::from_u32(mark), expansion);
|
||||
placeholder_expander.add(mark.as_placeholder_id(), expansion);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -386,20 +385,12 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
/// Expand a macro invocation. Returns the result of expansion.
|
||||
fn expand_bang_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) -> Expansion {
|
||||
let (mark, kind) = (invoc.expansion_data.mark, invoc.expansion_kind);
|
||||
let (attrs, mac, ident, span) = match invoc.kind {
|
||||
InvocationKind::Bang { attrs, mac, ident, span } => (attrs, mac, ident, span),
|
||||
let (mac, ident, span) = match invoc.kind {
|
||||
InvocationKind::Bang { mac, ident, span } => (mac, ident, span),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let Mac_ { path, tts, .. } = mac.node;
|
||||
|
||||
// Detect use of feature-gated or invalid attributes on macro invoations
|
||||
// since they will not be detected after macro expansion.
|
||||
for attr in attrs.iter() {
|
||||
feature_gate::check_attribute(&attr, &self.cx.parse_sess,
|
||||
&self.cx.parse_sess.codemap(),
|
||||
&self.cx.ecfg.features.unwrap());
|
||||
}
|
||||
|
||||
let extname = path.segments.last().unwrap().identifier.name;
|
||||
let ident = ident.unwrap_or(keywords::Invalid.ident());
|
||||
let marked_tts = mark_tts(&tts, mark);
|
||||
|
@ -440,7 +431,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
}
|
||||
});
|
||||
|
||||
kind.make_from(expander.expand(self.cx, span, ident, marked_tts, attrs))
|
||||
kind.make_from(expander.expand(self.cx, span, ident, marked_tts))
|
||||
}
|
||||
|
||||
MultiDecorator(..) | MultiModifier(..) | SyntaxExtension::AttrProcMacro(..) => {
|
||||
|
@ -595,13 +586,11 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
|
|||
..self.cx.current_expansion.clone()
|
||||
},
|
||||
});
|
||||
placeholder(expansion_kind, ast::NodeId::from_u32(mark.as_u32()))
|
||||
placeholder(expansion_kind, mark.as_placeholder_id())
|
||||
}
|
||||
|
||||
fn collect_bang(
|
||||
&mut self, mac: ast::Mac, attrs: Vec<ast::Attribute>, span: Span, kind: ExpansionKind,
|
||||
) -> Expansion {
|
||||
self.collect(kind, InvocationKind::Bang { attrs: attrs, mac: mac, ident: None, span: span })
|
||||
fn collect_bang(&mut self, mac: ast::Mac, span: Span, kind: ExpansionKind) -> Expansion {
|
||||
self.collect(kind, InvocationKind::Bang { mac: mac, ident: None, span: span })
|
||||
}
|
||||
|
||||
fn collect_attr(&mut self, attr: ast::Attribute, item: Annotatable, kind: ExpansionKind)
|
||||
|
@ -622,6 +611,16 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
|
|||
fn configure<T: HasAttrs>(&mut self, node: T) -> Option<T> {
|
||||
self.cfg.configure(node)
|
||||
}
|
||||
|
||||
// Detect use of feature-gated or invalid attributes on macro invocations
|
||||
// since they will not be detected after macro expansion.
|
||||
fn check_attributes(&mut self, attrs: &[ast::Attribute]) {
|
||||
let codemap = &self.cx.parse_sess.codemap();
|
||||
let features = self.cx.ecfg.features.unwrap();
|
||||
for attr in attrs.iter() {
|
||||
feature_gate::check_attribute(&attr, &self.cx.parse_sess, codemap, features);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// These are pretty nasty. Ideally, we would keep the tokens around, linked from
|
||||
|
@ -660,7 +659,8 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
|
|||
expr.node = self.cfg.configure_expr_kind(expr.node);
|
||||
|
||||
if let ast::ExprKind::Mac(mac) = expr.node {
|
||||
self.collect_bang(mac, expr.attrs.into(), expr.span, ExpansionKind::Expr).make_expr()
|
||||
self.check_attributes(&expr.attrs);
|
||||
self.collect_bang(mac, expr.span, ExpansionKind::Expr).make_expr()
|
||||
} else {
|
||||
P(noop_fold_expr(expr, self))
|
||||
}
|
||||
|
@ -671,8 +671,8 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
|
|||
expr.node = self.cfg.configure_expr_kind(expr.node);
|
||||
|
||||
if let ast::ExprKind::Mac(mac) = expr.node {
|
||||
self.collect_bang(mac, expr.attrs.into(), expr.span, ExpansionKind::OptExpr)
|
||||
.make_opt_expr()
|
||||
self.check_attributes(&expr.attrs);
|
||||
self.collect_bang(mac, expr.span, ExpansionKind::OptExpr).make_opt_expr()
|
||||
} else {
|
||||
Some(P(noop_fold_expr(expr, self)))
|
||||
}
|
||||
|
@ -685,8 +685,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
|
|||
}
|
||||
|
||||
pat.and_then(|pat| match pat.node {
|
||||
PatKind::Mac(mac) =>
|
||||
self.collect_bang(mac, Vec::new(), pat.span, ExpansionKind::Pat).make_pat(),
|
||||
PatKind::Mac(mac) => self.collect_bang(mac, pat.span, ExpansionKind::Pat).make_pat(),
|
||||
_ => unreachable!(),
|
||||
})
|
||||
}
|
||||
|
@ -707,8 +706,8 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
|
|||
}).collect()
|
||||
};
|
||||
|
||||
let mut placeholder =
|
||||
self.collect_bang(mac, attrs.into(), stmt.span, ExpansionKind::Stmts).make_stmts();
|
||||
self.check_attributes(&attrs);
|
||||
let mut placeholder = self.collect_bang(mac, stmt.span, ExpansionKind::Stmts).make_stmts();
|
||||
|
||||
// If this is a macro invocation with a semicolon, then apply that
|
||||
// semicolon to the final statement produced by expansion.
|
||||
|
@ -740,18 +739,21 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
|
|||
|
||||
match item.node {
|
||||
ast::ItemKind::Mac(..) => {
|
||||
if match item.node {
|
||||
ItemKind::Mac(ref mac) => mac.node.path.segments.is_empty(),
|
||||
_ => unreachable!(),
|
||||
} {
|
||||
return SmallVector::one(item);
|
||||
}
|
||||
self.check_attributes(&item.attrs);
|
||||
let is_macro_def = if let ItemKind::Mac(ref mac) = item.node {
|
||||
mac.node.path.segments[0].identifier.name == "macro_rules"
|
||||
} else {
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
item.and_then(|item| match item.node {
|
||||
item.and_then(|mut item| match item.node {
|
||||
ItemKind::Mac(_) if is_macro_def => {
|
||||
item.id = Mark::fresh().as_placeholder_id();
|
||||
SmallVector::one(P(item))
|
||||
}
|
||||
ItemKind::Mac(mac) => {
|
||||
self.collect(ExpansionKind::Items, InvocationKind::Bang {
|
||||
mac: mac,
|
||||
attrs: item.attrs,
|
||||
ident: Some(item.ident),
|
||||
span: item.span,
|
||||
}).make_items()
|
||||
|
@ -823,7 +825,8 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
|
|||
match item.node {
|
||||
ast::TraitItemKind::Macro(mac) => {
|
||||
let ast::TraitItem { attrs, span, .. } = item;
|
||||
self.collect_bang(mac, attrs, span, ExpansionKind::TraitItems).make_trait_items()
|
||||
self.check_attributes(&attrs);
|
||||
self.collect_bang(mac, span, ExpansionKind::TraitItems).make_trait_items()
|
||||
}
|
||||
_ => fold::noop_fold_trait_item(item, self),
|
||||
}
|
||||
|
@ -841,7 +844,8 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
|
|||
match item.node {
|
||||
ast::ImplItemKind::Macro(mac) => {
|
||||
let ast::ImplItem { attrs, span, .. } = item;
|
||||
self.collect_bang(mac, attrs, span, ExpansionKind::ImplItems).make_impl_items()
|
||||
self.check_attributes(&attrs);
|
||||
self.collect_bang(mac, span, ExpansionKind::ImplItems).make_impl_items()
|
||||
}
|
||||
_ => fold::noop_fold_impl_item(item, self),
|
||||
}
|
||||
|
@ -854,8 +858,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
|
|||
};
|
||||
|
||||
match ty.node {
|
||||
ast::TyKind::Mac(mac) =>
|
||||
self.collect_bang(mac, Vec::new(), ty.span, ExpansionKind::Ty).make_ty(),
|
||||
ast::TyKind::Mac(mac) => self.collect_bang(mac, ty.span, ExpansionKind::Ty).make_ty(),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,7 +51,11 @@ impl Mark {
|
|||
Mark(id.as_u32())
|
||||
}
|
||||
|
||||
pub fn as_u32(&self) -> u32 {
|
||||
pub fn as_placeholder_id(self) -> NodeId {
|
||||
NodeId::from_u32(self.0)
|
||||
}
|
||||
|
||||
pub fn as_u32(self) -> u32 {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
@ -115,12 +119,12 @@ impl SyntaxContext {
|
|||
})
|
||||
}
|
||||
|
||||
/// If `ident` is macro expanded, return the source ident from the macro definition
|
||||
/// and the mark of the expansion that created the macro definition.
|
||||
pub fn source(self) -> (Self /* source context */, Mark /* source macro */) {
|
||||
let macro_def_ctxt = self.data().prev_ctxt.data();
|
||||
(macro_def_ctxt.prev_ctxt, macro_def_ctxt.outer_mark)
|
||||
}
|
||||
/// If `ident` is macro expanded, return the source ident from the macro definition
|
||||
/// and the mark of the expansion that created the macro definition.
|
||||
pub fn source(self) -> (Self /* source context */, Mark /* source macro */) {
|
||||
let macro_def_ctxt = self.data().prev_ctxt.data();
|
||||
(macro_def_ctxt.prev_ctxt, macro_def_ctxt.outer_mark)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for SyntaxContext {
|
||||
|
|
|
@ -12,9 +12,10 @@ use ast;
|
|||
use codemap::{DUMMY_SP, dummy_spanned};
|
||||
use ext::base::ExtCtxt;
|
||||
use ext::expand::{Expansion, ExpansionKind};
|
||||
use ext::hygiene::Mark;
|
||||
use fold::*;
|
||||
use ptr::P;
|
||||
use symbol::{Symbol, keywords};
|
||||
use symbol::keywords;
|
||||
use util::move_map::MoveMap;
|
||||
use util::small_vector::SmallVector;
|
||||
|
||||
|
@ -68,10 +69,6 @@ pub fn placeholder(kind: ExpansionKind, id: ast::NodeId) -> Expansion {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn macro_scope_placeholder() -> Expansion {
|
||||
placeholder(ExpansionKind::Items, ast::DUMMY_NODE_ID)
|
||||
}
|
||||
|
||||
pub struct PlaceholderExpander<'a, 'b: 'a> {
|
||||
expansions: HashMap<ast::NodeId, Expansion>,
|
||||
cx: &'a mut ExtCtxt<'b>,
|
||||
|
@ -100,11 +97,12 @@ impl<'a, 'b> PlaceholderExpander<'a, 'b> {
|
|||
impl<'a, 'b> Folder for PlaceholderExpander<'a, 'b> {
|
||||
fn fold_item(&mut self, item: P<ast::Item>) -> SmallVector<P<ast::Item>> {
|
||||
match item.node {
|
||||
// Scope placeholder
|
||||
ast::ItemKind::Mac(_) if item.id == ast::DUMMY_NODE_ID => SmallVector::one(item),
|
||||
ast::ItemKind::Mac(_) => self.remove(item.id).make_items(),
|
||||
_ => noop_fold_item(item, self),
|
||||
ast::ItemKind::Mac(ref mac) if !mac.node.path.segments.is_empty() => {}
|
||||
ast::ItemKind::Mac(_) => return self.remove(item.id).make_items(),
|
||||
_ => {}
|
||||
}
|
||||
|
||||
noop_fold_item(item, self)
|
||||
}
|
||||
|
||||
fn fold_trait_item(&mut self, item: ast::TraitItem) -> SmallVector<ast::TraitItem> {
|
||||
|
@ -172,10 +170,10 @@ impl<'a, 'b> Folder for PlaceholderExpander<'a, 'b> {
|
|||
block.stmts = block.stmts.move_flat_map(|mut stmt| {
|
||||
remaining_stmts -= 1;
|
||||
|
||||
// Scope placeholder
|
||||
// `macro_rules!` macro definition
|
||||
if let ast::StmtKind::Item(ref item) = stmt.node {
|
||||
if let ast::ItemKind::Mac(..) = item.node {
|
||||
macros.push(item.ident.ctxt.data().outer_mark);
|
||||
if let ast::ItemKind::Mac(_) = item.node {
|
||||
macros.push(Mark::from_placeholder_id(item.id));
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
@ -208,33 +206,13 @@ impl<'a, 'b> Folder for PlaceholderExpander<'a, 'b> {
|
|||
fn fold_mod(&mut self, module: ast::Mod) -> ast::Mod {
|
||||
let mut module = noop_fold_mod(module, self);
|
||||
module.items = module.items.move_flat_map(|item| match item.node {
|
||||
ast::ItemKind::Mac(_) => None, // remove scope placeholders from modules
|
||||
ast::ItemKind::Mac(_) if !self.cx.ecfg.keep_macs => None, // remove macro definitions
|
||||
_ => Some(item),
|
||||
});
|
||||
module
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reconstructed_macro_rules(def: &ast::MacroDef) -> Expansion {
|
||||
Expansion::Items(SmallVector::one(P(ast::Item {
|
||||
ident: def.ident,
|
||||
attrs: def.attrs.clone(),
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
node: ast::ItemKind::Mac(ast::Mac {
|
||||
span: def.span,
|
||||
node: ast::Mac_ {
|
||||
path: ast::Path {
|
||||
span: DUMMY_SP,
|
||||
global: false,
|
||||
segments: vec![ast::PathSegment {
|
||||
identifier: ast::Ident::with_empty_ctxt(Symbol::intern("macro_rules")),
|
||||
parameters: ast::PathParameters::none(),
|
||||
}],
|
||||
},
|
||||
tts: def.body.clone(),
|
||||
}
|
||||
}),
|
||||
vis: ast::Visibility::Inherited,
|
||||
span: def.span,
|
||||
})))
|
||||
fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
|
||||
mac
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,10 +10,9 @@
|
|||
|
||||
use {ast, attr};
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
use ext::base::{DummyResult, ExtCtxt, MacEager, MacResult, SyntaxExtension};
|
||||
use ext::base::{IdentMacroExpander, NormalTT, TTMacroExpander};
|
||||
use ext::base::{DummyResult, ExtCtxt, MacResult, SyntaxExtension};
|
||||
use ext::base::{NormalTT, TTMacroExpander};
|
||||
use ext::expand::{Expansion, ExpansionKind};
|
||||
use ext::placeholders;
|
||||
use ext::tt::macro_parser::{Success, Error, Failure};
|
||||
use ext::tt::macro_parser::{MatchedSeq, MatchedNonterminal};
|
||||
use ext::tt::macro_parser::{parse, parse_failure_msg};
|
||||
|
@ -151,38 +150,6 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt,
|
|||
cx.span_fatal(best_fail_spot.substitute_dummy(sp), &best_fail_msg);
|
||||
}
|
||||
|
||||
pub struct MacroRulesExpander;
|
||||
impl IdentMacroExpander for MacroRulesExpander {
|
||||
fn expand(&self,
|
||||
cx: &mut ExtCtxt,
|
||||
span: Span,
|
||||
ident: ast::Ident,
|
||||
tts: Vec<tokenstream::TokenTree>,
|
||||
attrs: Vec<ast::Attribute>)
|
||||
-> Box<MacResult> {
|
||||
let export = attr::contains_name(&attrs, "macro_export");
|
||||
let def = ast::MacroDef {
|
||||
ident: ident,
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
span: span,
|
||||
imported_from: None,
|
||||
body: tts,
|
||||
allow_internal_unstable: attr::contains_name(&attrs, "allow_internal_unstable"),
|
||||
attrs: attrs,
|
||||
};
|
||||
|
||||
// If keep_macs is true, expands to a MacEager::items instead.
|
||||
let result = if cx.ecfg.keep_macs {
|
||||
MacEager::items(placeholders::reconstructed_macro_rules(&def).make_items())
|
||||
} else {
|
||||
MacEager::items(placeholders::macro_scope_placeholder().make_items())
|
||||
};
|
||||
|
||||
cx.resolver.add_macro(cx.current_expansion.mark, def, export);
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
// Note that macro-by-example's input is also matched against a token tree:
|
||||
// $( $lhs:tt => $rhs:tt );+
|
||||
//
|
||||
|
@ -282,7 +249,7 @@ pub fn compile(sess: &ParseSess, def: &ast::MacroDef) -> SyntaxExtension {
|
|||
valid: valid,
|
||||
});
|
||||
|
||||
NormalTT(exp, Some(def.span), def.allow_internal_unstable)
|
||||
NormalTT(exp, Some(def.span), attr::contains_name(&def.attrs, "allow_internal_unstable"))
|
||||
}
|
||||
|
||||
fn check_lhs_nt_follows(sess: &ParseSess, lhs: &TokenTree) -> bool {
|
||||
|
|
|
@ -438,7 +438,7 @@ pub fn noop_fold_path<T: Folder>(Path {global, segments, span}: Path, fld: &mut
|
|||
global: global,
|
||||
segments: segments.move_map(|PathSegment {identifier, parameters}| PathSegment {
|
||||
identifier: fld.fold_ident(identifier),
|
||||
parameters: fld.fold_path_parameters(parameters),
|
||||
parameters: parameters.map(|ps| ps.map(|ps| fld.fold_path_parameters(ps))),
|
||||
}),
|
||||
span: fld.new_span(span)
|
||||
}
|
||||
|
|
|
@ -634,12 +634,7 @@ mod tests {
|
|||
node: ast::ExprKind::Path(None, ast::Path {
|
||||
span: sp(0, 1),
|
||||
global: false,
|
||||
segments: vec![
|
||||
ast::PathSegment {
|
||||
identifier: Ident::from_str("a"),
|
||||
parameters: ast::PathParameters::none(),
|
||||
}
|
||||
],
|
||||
segments: vec![Ident::from_str("a").into()],
|
||||
}),
|
||||
span: sp(0, 1),
|
||||
attrs: ThinVec::new(),
|
||||
|
@ -651,19 +646,10 @@ mod tests {
|
|||
P(ast::Expr {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
node: ast::ExprKind::Path(None, ast::Path {
|
||||
span: sp(0, 6),
|
||||
global: true,
|
||||
segments: vec![
|
||||
ast::PathSegment {
|
||||
identifier: Ident::from_str("a"),
|
||||
parameters: ast::PathParameters::none(),
|
||||
},
|
||||
ast::PathSegment {
|
||||
identifier: Ident::from_str("b"),
|
||||
parameters: ast::PathParameters::none(),
|
||||
}
|
||||
]
|
||||
}),
|
||||
span: sp(0, 6),
|
||||
global: true,
|
||||
segments: vec![Ident::from_str("a").into(), Ident::from_str("b").into()],
|
||||
}),
|
||||
span: sp(0, 6),
|
||||
attrs: ThinVec::new(),
|
||||
}))
|
||||
|
@ -772,12 +758,7 @@ mod tests {
|
|||
node:ast::ExprKind::Path(None, ast::Path{
|
||||
span: sp(7, 8),
|
||||
global: false,
|
||||
segments: vec![
|
||||
ast::PathSegment {
|
||||
identifier: Ident::from_str("d"),
|
||||
parameters: ast::PathParameters::none(),
|
||||
}
|
||||
],
|
||||
segments: vec![Ident::from_str("d").into()],
|
||||
}),
|
||||
span:sp(7,8),
|
||||
attrs: ThinVec::new(),
|
||||
|
@ -795,12 +776,7 @@ mod tests {
|
|||
node: ast::ExprKind::Path(None, ast::Path {
|
||||
span:sp(0,1),
|
||||
global:false,
|
||||
segments: vec![
|
||||
ast::PathSegment {
|
||||
identifier: Ident::from_str("b"),
|
||||
parameters: ast::PathParameters::none(),
|
||||
}
|
||||
],
|
||||
segments: vec![Ident::from_str("b").into()],
|
||||
}),
|
||||
span: sp(0,1),
|
||||
attrs: ThinVec::new()})),
|
||||
|
@ -842,12 +818,7 @@ mod tests {
|
|||
node: ast::TyKind::Path(None, ast::Path{
|
||||
span:sp(10,13),
|
||||
global:false,
|
||||
segments: vec![
|
||||
ast::PathSegment {
|
||||
identifier: Ident::from_str("i32"),
|
||||
parameters: ast::PathParameters::none(),
|
||||
}
|
||||
],
|
||||
segments: vec![Ident::from_str("i32").into()],
|
||||
}),
|
||||
span:sp(10,13)
|
||||
}),
|
||||
|
@ -890,13 +861,7 @@ mod tests {
|
|||
ast::Path{
|
||||
span:sp(17,18),
|
||||
global:false,
|
||||
segments: vec![
|
||||
ast::PathSegment {
|
||||
identifier: Ident::from_str("b"),
|
||||
parameters:
|
||||
ast::PathParameters::none(),
|
||||
}
|
||||
],
|
||||
segments: vec![Ident::from_str("b").into()],
|
||||
}),
|
||||
span: sp(17,18),
|
||||
attrs: ThinVec::new()})),
|
||||
|
|
|
@ -1705,12 +1705,11 @@ impl<'a> Parser<'a> {
|
|||
// Parse types, optionally.
|
||||
let parameters = if self.eat_lt() {
|
||||
let (lifetimes, types, bindings) = self.parse_generic_values_after_lt()?;
|
||||
|
||||
ast::PathParameters::AngleBracketed(ast::AngleBracketedParameterData {
|
||||
ast::AngleBracketedParameterData {
|
||||
lifetimes: lifetimes,
|
||||
types: P::from_vec(types),
|
||||
bindings: P::from_vec(bindings),
|
||||
})
|
||||
}.into()
|
||||
} else if self.eat(&token::OpenDelim(token::Paren)) {
|
||||
let lo = self.prev_span.lo;
|
||||
|
||||
|
@ -1727,18 +1726,17 @@ impl<'a> Parser<'a> {
|
|||
|
||||
let hi = self.prev_span.hi;
|
||||
|
||||
ast::PathParameters::Parenthesized(ast::ParenthesizedParameterData {
|
||||
Some(P(ast::PathParameters::Parenthesized(ast::ParenthesizedParameterData {
|
||||
span: mk_sp(lo, hi),
|
||||
inputs: inputs,
|
||||
output: output_ty,
|
||||
})
|
||||
})))
|
||||
} else {
|
||||
ast::PathParameters::none()
|
||||
None
|
||||
};
|
||||
|
||||
// Assemble and push the result.
|
||||
segments.push(ast::PathSegment { identifier: identifier,
|
||||
parameters: parameters });
|
||||
segments.push(ast::PathSegment { identifier: identifier, parameters: parameters });
|
||||
|
||||
// Continue only if we see a `::`
|
||||
if !self.eat(&token::ModSep) {
|
||||
|
@ -1757,10 +1755,7 @@ impl<'a> Parser<'a> {
|
|||
|
||||
// If we do not see a `::`, stop.
|
||||
if !self.eat(&token::ModSep) {
|
||||
segments.push(ast::PathSegment {
|
||||
identifier: identifier,
|
||||
parameters: ast::PathParameters::none()
|
||||
});
|
||||
segments.push(identifier.into());
|
||||
return Ok(segments);
|
||||
}
|
||||
|
||||
|
@ -1768,14 +1763,13 @@ impl<'a> Parser<'a> {
|
|||
if self.eat_lt() {
|
||||
// Consumed `a::b::<`, go look for types
|
||||
let (lifetimes, types, bindings) = self.parse_generic_values_after_lt()?;
|
||||
let parameters = ast::AngleBracketedParameterData {
|
||||
lifetimes: lifetimes,
|
||||
types: P::from_vec(types),
|
||||
bindings: P::from_vec(bindings),
|
||||
};
|
||||
segments.push(ast::PathSegment {
|
||||
identifier: identifier,
|
||||
parameters: ast::PathParameters::AngleBracketed(parameters),
|
||||
parameters: ast::AngleBracketedParameterData {
|
||||
lifetimes: lifetimes,
|
||||
types: P::from_vec(types),
|
||||
bindings: P::from_vec(bindings),
|
||||
}.into(),
|
||||
});
|
||||
|
||||
// Consumed `a::b::<T,U>`, check for `::` before proceeding
|
||||
|
@ -1784,10 +1778,7 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
} else {
|
||||
// Consumed `a::`, go look for `b`
|
||||
segments.push(ast::PathSegment {
|
||||
identifier: identifier,
|
||||
parameters: ast::PathParameters::none(),
|
||||
});
|
||||
segments.push(identifier.into());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1802,10 +1793,7 @@ impl<'a> Parser<'a> {
|
|||
let identifier = self.parse_path_segment_ident()?;
|
||||
|
||||
// Assemble and push the result.
|
||||
segments.push(ast::PathSegment {
|
||||
identifier: identifier,
|
||||
parameters: ast::PathParameters::none()
|
||||
});
|
||||
segments.push(identifier.into());
|
||||
|
||||
// If we do not see a `::` or see `::{`/`::*`, stop.
|
||||
if !self.check(&token::ModSep) || self.is_import_coupler() {
|
||||
|
|
|
@ -2349,7 +2349,9 @@ impl<'a> State<'a> {
|
|||
|
||||
try!(self.print_ident(segment.identifier));
|
||||
|
||||
try!(self.print_path_parameters(&segment.parameters, colons_before_params));
|
||||
if let Some(ref parameters) = segment.parameters {
|
||||
try!(self.print_path_parameters(parameters, colons_before_params))
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -2373,7 +2375,10 @@ impl<'a> State<'a> {
|
|||
try!(word(&mut self.s, "::"));
|
||||
let item_segment = path.segments.last().unwrap();
|
||||
try!(self.print_ident(item_segment.identifier));
|
||||
self.print_path_parameters(&item_segment.parameters, colons_before_params)
|
||||
match item_segment.parameters {
|
||||
Some(ref parameters) => self.print_path_parameters(parameters, colons_before_params),
|
||||
None => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
fn print_path_parameters(&mut self,
|
||||
|
@ -2381,10 +2386,6 @@ impl<'a> State<'a> {
|
|||
colons_before_params: bool)
|
||||
-> io::Result<()>
|
||||
{
|
||||
if parameters.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if colons_before_params {
|
||||
try!(word(&mut self.s, "::"))
|
||||
}
|
||||
|
|
|
@ -81,9 +81,8 @@ pub fn maybe_inject_crates_ref(sess: &ParseSess,
|
|||
vis: ast::Visibility::Inherited,
|
||||
node: ast::ItemKind::Use(P(codemap::dummy_spanned(ast::ViewPathGlob(ast::Path {
|
||||
global: false,
|
||||
segments: vec![name, "prelude", "v1"].into_iter().map(|name| ast::PathSegment {
|
||||
identifier: ast::Ident::from_str(name),
|
||||
parameters: ast::PathParameters::none(),
|
||||
segments: vec![name, "prelude", "v1"].into_iter().map(|name| {
|
||||
ast::Ident::from_str(name).into()
|
||||
}).collect(),
|
||||
span: span,
|
||||
})))),
|
||||
|
|
|
@ -580,10 +580,7 @@ fn path_node(ids: Vec<Ident>) -> ast::Path {
|
|||
ast::Path {
|
||||
span: DUMMY_SP,
|
||||
global: false,
|
||||
segments: ids.into_iter().map(|identifier| ast::PathSegment {
|
||||
identifier: identifier,
|
||||
parameters: ast::PathParameters::none(),
|
||||
}).collect()
|
||||
segments: ids.into_iter().map(Into::into).collect(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -178,7 +178,6 @@ pub fn walk_crate<'a, V: Visitor<'a>>(visitor: &mut V, krate: &'a Crate) {
|
|||
|
||||
pub fn walk_macro_def<'a, V: Visitor<'a>>(visitor: &mut V, macro_def: &'a MacroDef) {
|
||||
visitor.visit_ident(macro_def.span, macro_def.ident);
|
||||
walk_opt_ident(visitor, macro_def.span, macro_def.imported_from);
|
||||
walk_list!(visitor, visit_attribute, ¯o_def.attrs);
|
||||
}
|
||||
|
||||
|
@ -384,7 +383,9 @@ pub fn walk_path_segment<'a, V: Visitor<'a>>(visitor: &mut V,
|
|||
path_span: Span,
|
||||
segment: &'a PathSegment) {
|
||||
visitor.visit_ident(path_span, segment.identifier);
|
||||
visitor.visit_path_parameters(path_span, &segment.parameters);
|
||||
if let Some(ref parameters) = segment.parameters {
|
||||
visitor.visit_path_parameters(path_span, parameters);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn walk_path_parameters<'a, V>(visitor: &mut V,
|
||||
|
|
|
@ -59,14 +59,10 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt,
|
|||
|
||||
impl Result {
|
||||
fn path(&self) -> ast::Path {
|
||||
let segment = ast::PathSegment {
|
||||
identifier: self.ident,
|
||||
parameters: ast::PathParameters::none(),
|
||||
};
|
||||
ast::Path {
|
||||
span: self.span,
|
||||
global: false,
|
||||
segments: vec![segment],
|
||||
segments: vec![self.ident.into()],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,8 +50,7 @@ pub mod deriving;
|
|||
|
||||
use std::rc::Rc;
|
||||
use syntax::ast;
|
||||
use syntax::ext::base::{MacroExpanderFn, NormalTT, IdentTT, MultiModifier, NamedSyntaxExtension};
|
||||
use syntax::ext::tt::macro_rules::MacroRulesExpander;
|
||||
use syntax::ext::base::{MacroExpanderFn, NormalTT, MultiModifier, NamedSyntaxExtension};
|
||||
use syntax::symbol::Symbol;
|
||||
|
||||
pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver,
|
||||
|
@ -61,8 +60,6 @@ pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver,
|
|||
resolver.add_ext(ast::Ident::with_empty_ctxt(name), Rc::new(ext));
|
||||
};
|
||||
|
||||
register(Symbol::intern("macro_rules"), IdentTT(Box::new(MacroRulesExpander), None, false));
|
||||
|
||||
macro_rules! register {
|
||||
($( $name:ident: $f:expr, )*) => { $(
|
||||
register(Symbol::intern(stringify!($name)),
|
||||
|
|
|
@ -15,6 +15,6 @@ extern crate collections;
|
|||
|
||||
extern crate libc as collections;
|
||||
//~^ ERROR E0259
|
||||
//~| NOTE `collections` was already imported
|
||||
//~| NOTE `collections` already imported
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -12,6 +12,6 @@ mod foo { pub mod foo { } } //~ NOTE previous definition of `foo` here
|
|||
|
||||
use foo::foo;
|
||||
//~^ ERROR a module named `foo` has already been defined in this module
|
||||
//~| was already imported
|
||||
//~| `foo` already defined
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -11,13 +11,13 @@
|
|||
use self::A; //~ NOTE previous import of `A` here
|
||||
use self::B; //~ NOTE previous import of `B` here
|
||||
mod A {} //~ ERROR a module named `A` has already been imported in this module
|
||||
//~| `A` was already imported
|
||||
//~| `A` already imported
|
||||
pub mod B {} //~ ERROR a module named `B` has already been imported in this module
|
||||
//~| `B` was already imported
|
||||
//~| `B` already imported
|
||||
mod C {
|
||||
use C::D; //~ NOTE previous import of `D` here
|
||||
mod D {} //~ ERROR a module named `D` has already been imported in this module
|
||||
//~| `D` was already imported
|
||||
//~| `D` already imported
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -15,14 +15,14 @@ use std::ops::Div; //~ NOTE previous import
|
|||
use std::ops::Rem; //~ NOTE previous import
|
||||
|
||||
type Add = bool; //~ ERROR a trait named `Add` has already been imported in this module
|
||||
//~| was already imported
|
||||
//~| `Add` already imported
|
||||
struct Sub { x: f32 } //~ ERROR a trait named `Sub` has already been imported in this module
|
||||
//~| was already imported
|
||||
//~| `Sub` already imported
|
||||
enum Mul { A, B } //~ ERROR a trait named `Mul` has already been imported in this module
|
||||
//~| was already imported
|
||||
//~| `Mul` already imported
|
||||
mod Div { } //~ ERROR a trait named `Div` has already been imported in this module
|
||||
//~| was already imported
|
||||
//~| `Div` already imported
|
||||
trait Rem { } //~ ERROR a trait named `Rem` has already been imported in this module
|
||||
//~| was already imported
|
||||
//~| `Rem` already imported
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -13,6 +13,6 @@ use std::mem::transmute;
|
|||
|
||||
fn transmute() {}
|
||||
//~^ ERROR a value named `transmute` has already been imported in this module
|
||||
//~| was already imported
|
||||
//~| `transmute` already imported
|
||||
fn main() {
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue