Improve intercrate hygiene.
This commit is contained in:
parent
dde8dc61dd
commit
3eb235b45e
@ -117,7 +117,7 @@ pub type ExportMap = NodeMap<Vec<Export>>;
|
||||
|
||||
#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
|
||||
pub struct Export {
|
||||
pub name: ast::Name, // The name of the target.
|
||||
pub ident: ast::Ident, // The name of the target.
|
||||
pub def: Def, // The definition of the target.
|
||||
pub span: Span, // The span of the target definition.
|
||||
}
|
||||
|
@ -2662,7 +2662,7 @@ impl<'a> LoweringContext<'a> {
|
||||
let parent_def = self.parent_def.unwrap();
|
||||
let def_id = {
|
||||
let defs = self.resolver.definitions();
|
||||
let def_path_data = DefPathData::Binding(name.as_str());
|
||||
let def_path_data = DefPathData::Binding(Ident::with_empty_ctxt(name));
|
||||
let def_index = defs
|
||||
.create_def_with_parent(parent_def, id, def_path_data, REGULAR_SPACE, Mark::root());
|
||||
DefId::local(def_index)
|
||||
|
@ -14,7 +14,7 @@ use hir::def_id::{CRATE_DEF_INDEX, DefIndex, DefIndexAddressSpace};
|
||||
use syntax::ast::*;
|
||||
use syntax::ext::hygiene::Mark;
|
||||
use syntax::visit;
|
||||
use syntax::symbol::{Symbol, keywords};
|
||||
use syntax::symbol::keywords;
|
||||
|
||||
use hir::map::{ITEM_LIKE_SPACE, REGULAR_SPACE};
|
||||
|
||||
@ -103,14 +103,14 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
||||
DefPathData::Impl,
|
||||
ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) | ItemKind::Trait(..) |
|
||||
ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | ItemKind::Ty(..) =>
|
||||
DefPathData::TypeNs(i.ident.name.as_str()),
|
||||
DefPathData::TypeNs(i.ident.modern()),
|
||||
ItemKind::Mod(..) if i.ident == keywords::Invalid.ident() => {
|
||||
return visit::walk_item(self, i);
|
||||
}
|
||||
ItemKind::Mod(..) => DefPathData::Module(i.ident.name.as_str()),
|
||||
ItemKind::Mod(..) => DefPathData::Module(i.ident.modern()),
|
||||
ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) =>
|
||||
DefPathData::ValueNs(i.ident.name.as_str()),
|
||||
ItemKind::MacroDef(..) => DefPathData::MacroDef(i.ident.name.as_str()),
|
||||
DefPathData::ValueNs(i.ident.modern()),
|
||||
ItemKind::MacroDef(..) => DefPathData::MacroDef(i.ident.modern()),
|
||||
ItemKind::Mac(..) => return self.visit_macro_invoc(i.id, false),
|
||||
ItemKind::GlobalAsm(..) => DefPathData::Misc,
|
||||
ItemKind::Use(ref view_path) => {
|
||||
@ -138,15 +138,13 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
||||
for v in &enum_definition.variants {
|
||||
let variant_def_index =
|
||||
this.create_def(v.node.data.id(),
|
||||
DefPathData::EnumVariant(v.node.name.name.as_str()),
|
||||
DefPathData::EnumVariant(v.node.name.modern()),
|
||||
REGULAR_SPACE);
|
||||
this.with_parent(variant_def_index, |this| {
|
||||
for (index, field) in v.node.data.fields().iter().enumerate() {
|
||||
let name = field.ident.map(|ident| ident.name)
|
||||
.unwrap_or_else(|| Symbol::intern(&index.to_string()));
|
||||
this.create_def(field.id,
|
||||
DefPathData::Field(name.as_str()),
|
||||
REGULAR_SPACE);
|
||||
let ident = field.ident.map(Ident::modern)
|
||||
.unwrap_or_else(|| Ident::from_str(&index.to_string()));
|
||||
this.create_def(field.id, DefPathData::Field(ident), REGULAR_SPACE);
|
||||
}
|
||||
|
||||
if let Some(ref expr) = v.node.disr_expr {
|
||||
@ -164,9 +162,9 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
||||
}
|
||||
|
||||
for (index, field) in struct_def.fields().iter().enumerate() {
|
||||
let name = field.ident.map(|ident| ident.name.as_str())
|
||||
.unwrap_or(Symbol::intern(&index.to_string()).as_str());
|
||||
this.create_def(field.id, DefPathData::Field(name), REGULAR_SPACE);
|
||||
let ident = field.ident.map(Ident::modern)
|
||||
.unwrap_or_else(|| Ident::from_str(&index.to_string()));
|
||||
this.create_def(field.id, DefPathData::Field(ident), REGULAR_SPACE);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
@ -177,7 +175,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
||||
|
||||
fn visit_foreign_item(&mut self, foreign_item: &'a ForeignItem) {
|
||||
let def = self.create_def(foreign_item.id,
|
||||
DefPathData::ValueNs(foreign_item.ident.name.as_str()),
|
||||
DefPathData::ValueNs(foreign_item.ident.modern()),
|
||||
REGULAR_SPACE);
|
||||
|
||||
self.with_parent(def, |this| {
|
||||
@ -188,7 +186,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
||||
fn visit_generics(&mut self, generics: &'a Generics) {
|
||||
for ty_param in generics.ty_params.iter() {
|
||||
self.create_def(ty_param.id,
|
||||
DefPathData::TypeParam(ty_param.ident.name.as_str()),
|
||||
DefPathData::TypeParam(ty_param.ident.modern()),
|
||||
REGULAR_SPACE);
|
||||
}
|
||||
|
||||
@ -198,8 +196,8 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
||||
fn visit_trait_item(&mut self, ti: &'a TraitItem) {
|
||||
let def_data = match ti.node {
|
||||
TraitItemKind::Method(..) | TraitItemKind::Const(..) =>
|
||||
DefPathData::ValueNs(ti.ident.name.as_str()),
|
||||
TraitItemKind::Type(..) => DefPathData::TypeNs(ti.ident.name.as_str()),
|
||||
DefPathData::ValueNs(ti.ident.modern()),
|
||||
TraitItemKind::Type(..) => DefPathData::TypeNs(ti.ident.modern()),
|
||||
TraitItemKind::Macro(..) => return self.visit_macro_invoc(ti.id, false),
|
||||
};
|
||||
|
||||
@ -216,8 +214,8 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
||||
fn visit_impl_item(&mut self, ii: &'a ImplItem) {
|
||||
let def_data = match ii.node {
|
||||
ImplItemKind::Method(..) | ImplItemKind::Const(..) =>
|
||||
DefPathData::ValueNs(ii.ident.name.as_str()),
|
||||
ImplItemKind::Type(..) => DefPathData::TypeNs(ii.ident.name.as_str()),
|
||||
DefPathData::ValueNs(ii.ident.modern()),
|
||||
ImplItemKind::Type(..) => DefPathData::TypeNs(ii.ident.modern()),
|
||||
ImplItemKind::Macro(..) => return self.visit_macro_invoc(ii.id, false),
|
||||
};
|
||||
|
||||
@ -238,7 +236,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
||||
PatKind::Mac(..) => return self.visit_macro_invoc(pat.id, false),
|
||||
PatKind::Ident(_, id, _) => {
|
||||
let def = self.create_def(pat.id,
|
||||
DefPathData::Binding(id.node.name.as_str()),
|
||||
DefPathData::Binding(id.node.modern()),
|
||||
REGULAR_SPACE);
|
||||
self.parent_def = Some(def);
|
||||
}
|
||||
@ -283,7 +281,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
|
||||
|
||||
fn visit_lifetime_def(&mut self, def: &'a LifetimeDef) {
|
||||
self.create_def(def.lifetime.id,
|
||||
DefPathData::LifetimeDef(def.lifetime.ident.name.as_str()),
|
||||
DefPathData::LifetimeDef(def.lifetime.ident.modern()),
|
||||
REGULAR_SPACE);
|
||||
}
|
||||
|
||||
|
@ -23,8 +23,8 @@ use rustc_data_structures::stable_hasher::StableHasher;
|
||||
use serialize::{Encodable, Decodable, Encoder, Decoder};
|
||||
use std::fmt::Write;
|
||||
use std::hash::Hash;
|
||||
use syntax::ast;
|
||||
use syntax::ext::hygiene::Mark;
|
||||
use syntax::ast::{self, Ident};
|
||||
use syntax::ext::hygiene::{Mark, SyntaxContext};
|
||||
use syntax::symbol::{Symbol, InternedString};
|
||||
use ty::TyCtxt;
|
||||
use util::nodemap::NodeMap;
|
||||
@ -327,7 +327,7 @@ impl DefPath {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
|
||||
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
|
||||
pub enum DefPathData {
|
||||
// Root: these should only be used for the root nodes, because
|
||||
// they are treated specially by the `def_path` function.
|
||||
@ -341,31 +341,31 @@ pub enum DefPathData {
|
||||
/// An impl
|
||||
Impl,
|
||||
/// Something in the type NS
|
||||
TypeNs(InternedString),
|
||||
TypeNs(Ident),
|
||||
/// Something in the value NS
|
||||
ValueNs(InternedString),
|
||||
ValueNs(Ident),
|
||||
/// A module declaration
|
||||
Module(InternedString),
|
||||
Module(Ident),
|
||||
/// A macro rule
|
||||
MacroDef(InternedString),
|
||||
MacroDef(Ident),
|
||||
/// A closure expression
|
||||
ClosureExpr,
|
||||
|
||||
// Subportions of items
|
||||
/// A type parameter (generic parameter)
|
||||
TypeParam(InternedString),
|
||||
TypeParam(Ident),
|
||||
/// A lifetime definition
|
||||
LifetimeDef(InternedString),
|
||||
LifetimeDef(Ident),
|
||||
/// A variant of a enum
|
||||
EnumVariant(InternedString),
|
||||
EnumVariant(Ident),
|
||||
/// A struct field
|
||||
Field(InternedString),
|
||||
Field(Ident),
|
||||
/// Implicit ctor for a tuple-like struct
|
||||
StructCtor,
|
||||
/// Initializer for a const
|
||||
Initializer,
|
||||
/// Pattern binding
|
||||
Binding(InternedString),
|
||||
Binding(Ident),
|
||||
/// An `impl Trait` type node.
|
||||
ImplTrait,
|
||||
/// A `typeof` type node.
|
||||
@ -551,18 +551,18 @@ impl Definitions {
|
||||
}
|
||||
|
||||
impl DefPathData {
|
||||
pub fn get_opt_name(&self) -> Option<ast::Name> {
|
||||
pub fn get_opt_ident(&self) -> Option<Ident> {
|
||||
use self::DefPathData::*;
|
||||
match *self {
|
||||
TypeNs(ref name) |
|
||||
ValueNs(ref name) |
|
||||
Module(ref name) |
|
||||
MacroDef(ref name) |
|
||||
TypeParam(ref name) |
|
||||
LifetimeDef(ref name) |
|
||||
EnumVariant(ref name) |
|
||||
Binding(ref name) |
|
||||
Field(ref name) => Some(Symbol::intern(name)),
|
||||
TypeNs(ident) |
|
||||
ValueNs(ident) |
|
||||
Module(ident) |
|
||||
MacroDef(ident) |
|
||||
TypeParam(ident) |
|
||||
LifetimeDef(ident) |
|
||||
EnumVariant(ident) |
|
||||
Binding(ident) |
|
||||
Field(ident) => Some(ident),
|
||||
|
||||
Impl |
|
||||
CrateRoot |
|
||||
@ -575,19 +575,23 @@ impl DefPathData {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_opt_name(&self) -> Option<ast::Name> {
|
||||
self.get_opt_ident().map(|ident| ident.name)
|
||||
}
|
||||
|
||||
pub fn as_interned_str(&self) -> InternedString {
|
||||
use self::DefPathData::*;
|
||||
let s = match *self {
|
||||
TypeNs(ref name) |
|
||||
ValueNs(ref name) |
|
||||
Module(ref name) |
|
||||
MacroDef(ref name) |
|
||||
TypeParam(ref name) |
|
||||
LifetimeDef(ref name) |
|
||||
EnumVariant(ref name) |
|
||||
Binding(ref name) |
|
||||
Field(ref name) => {
|
||||
return name.clone();
|
||||
TypeNs(ident) |
|
||||
ValueNs(ident) |
|
||||
Module(ident) |
|
||||
MacroDef(ident) |
|
||||
TypeParam(ident) |
|
||||
LifetimeDef(ident) |
|
||||
EnumVariant(ident) |
|
||||
Binding(ident) |
|
||||
Field(ident) => {
|
||||
return ident.name.as_str();
|
||||
}
|
||||
|
||||
// note that this does not show up in user printouts
|
||||
@ -609,3 +613,25 @@ impl DefPathData {
|
||||
self.as_interned_str().to_string()
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for DefPathData {}
|
||||
impl PartialEq for DefPathData {
|
||||
fn eq(&self, other: &DefPathData) -> bool {
|
||||
::std::mem::discriminant(self) == ::std::mem::discriminant(other) &&
|
||||
self.get_opt_ident() == other.get_opt_ident()
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::hash::Hash for DefPathData {
|
||||
fn hash<H: ::std::hash::Hasher>(&self, hasher: &mut H) {
|
||||
::std::mem::discriminant(self).hash(hasher);
|
||||
if let Some(ident) = self.get_opt_ident() {
|
||||
if ident.ctxt == SyntaxContext::empty() && ident.name == ident.name.interned() {
|
||||
ident.name.as_str().hash(hasher)
|
||||
} else {
|
||||
// FIXME(jseyfried) implement stable hashing for idents with macros 2.0 hygiene info
|
||||
ident.hash(hasher)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1118,7 +1118,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for hir::def_id::DefIn
|
||||
}
|
||||
|
||||
impl_stable_hash_for!(struct hir::def::Export {
|
||||
name,
|
||||
ident,
|
||||
def,
|
||||
span
|
||||
});
|
||||
|
@ -28,6 +28,7 @@
|
||||
#![feature(conservative_impl_trait)]
|
||||
#![feature(const_fn)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(discriminant_value)]
|
||||
#![feature(i128_type)]
|
||||
#![feature(libc)]
|
||||
#![feature(never_type)]
|
||||
|
@ -39,7 +39,7 @@ use std::u32;
|
||||
|
||||
use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque};
|
||||
use syntax::attr;
|
||||
use syntax::ast;
|
||||
use syntax::ast::{self, Ident};
|
||||
use syntax::codemap;
|
||||
use syntax::ext::base::MacroKind;
|
||||
use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP, NO_EXPANSION};
|
||||
@ -667,7 +667,8 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
},
|
||||
ext.kind()
|
||||
);
|
||||
callback(def::Export { name: name, def: def, span: DUMMY_SP });
|
||||
let ident = Ident::with_empty_ctxt(name);
|
||||
callback(def::Export { ident: ident, def: def, span: DUMMY_SP });
|
||||
}
|
||||
}
|
||||
return
|
||||
@ -703,7 +704,7 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
if let Some(def) = self.get_def(child_index) {
|
||||
callback(def::Export {
|
||||
def: def,
|
||||
name: self.item_name(child_index),
|
||||
ident: Ident::with_empty_ctxt(self.item_name(child_index)),
|
||||
span: self.entry(child_index).span.decode(self),
|
||||
});
|
||||
}
|
||||
@ -720,7 +721,8 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
let span = child.span.decode(self);
|
||||
if let (Some(def), Some(name)) =
|
||||
(self.get_def(child_index), def_key.disambiguated_data.data.get_opt_name()) {
|
||||
callback(def::Export { def: def, name: name, span: span });
|
||||
let ident = Ident::with_empty_ctxt(name);
|
||||
callback(def::Export { def: def, ident: ident, span: span });
|
||||
// For non-reexport structs and variants add their constructors to children.
|
||||
// Reexport lists automatically contain constructors when necessary.
|
||||
match def {
|
||||
@ -728,7 +730,7 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
if let Some(ctor_def_id) = self.get_struct_ctor_def_id(child_index) {
|
||||
let ctor_kind = self.get_ctor_kind(child_index);
|
||||
let ctor_def = Def::StructCtor(ctor_def_id, ctor_kind);
|
||||
callback(def::Export { def: ctor_def, name: name, span: span });
|
||||
callback(def::Export { def: ctor_def, ident: ident, span: span });
|
||||
}
|
||||
}
|
||||
Def::Variant(def_id) => {
|
||||
@ -736,7 +738,7 @@ impl<'a, 'tcx> CrateMetadata {
|
||||
// value namespace, they are reserved for possible future use.
|
||||
let ctor_kind = self.get_ctor_kind(child_index);
|
||||
let ctor_def = Def::VariantCtor(def_id, ctor_kind);
|
||||
callback(def::Export { def: ctor_def, name: name, span: span });
|
||||
callback(def::Export { def: ctor_def, ident: ident, span: span });
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
@ -439,7 +439,7 @@ impl<'a> Resolver<'a> {
|
||||
|
||||
/// Builds the reduced graph for a single item in an external crate.
|
||||
fn build_reduced_graph_for_external_crate_def(&mut self, parent: Module<'a>, child: Export) {
|
||||
let ident = Ident::with_empty_ctxt(child.name);
|
||||
let ident = child.ident;
|
||||
let def = child.def;
|
||||
let def_id = def.def_id();
|
||||
let vis = self.session.cstore.visibility(def_id);
|
||||
@ -480,9 +480,8 @@ impl<'a> Resolver<'a> {
|
||||
|
||||
for child in self.session.cstore.item_children(def_id) {
|
||||
let ns = if let Def::AssociatedTy(..) = child.def { TypeNS } else { ValueNS };
|
||||
let ident = Ident::with_empty_ctxt(child.name);
|
||||
self.define(module, ident, ns, (child.def, ty::Visibility::Public,
|
||||
DUMMY_SP, expansion));
|
||||
self.define(module, child.ident, ns,
|
||||
(child.def, ty::Visibility::Public, DUMMY_SP, expansion));
|
||||
|
||||
if self.session.cstore.associated_item_cloned(child.def.def_id())
|
||||
.method_has_self_argument {
|
||||
@ -643,7 +642,7 @@ impl<'a> Resolver<'a> {
|
||||
let ident = Ident::with_empty_ctxt(name);
|
||||
let result = self.resolve_ident_in_module(module, ident, MacroNS, false, false, span);
|
||||
if let Ok(binding) = result {
|
||||
self.macro_exports.push(Export { name: name, def: binding.def(), span: span });
|
||||
self.macro_exports.push(Export { ident: ident, def: binding.def(), span: span });
|
||||
} else {
|
||||
span_err!(self.session, span, E0470, "reexported macro not found");
|
||||
}
|
||||
|
@ -726,7 +726,8 @@ impl<'a> Resolver<'a> {
|
||||
}));
|
||||
if attr::contains_name(&item.attrs, "macro_export") {
|
||||
let def = Def::Macro(def_id, MacroKind::Bang);
|
||||
self.macro_exports.push(Export { name: ident.name, def: def, span: item.span });
|
||||
self.macro_exports
|
||||
.push(Export { ident: ident.modern(), def: def, span: item.span });
|
||||
} else {
|
||||
self.unused_macros.insert(def_id);
|
||||
}
|
||||
|
@ -803,7 +803,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
|
||||
if module as *const _ == self.graph_root as *const _ {
|
||||
let macro_exports = mem::replace(&mut self.macro_exports, Vec::new());
|
||||
for export in macro_exports.into_iter().rev() {
|
||||
if exported_macro_names.insert(export.name, export.span).is_none() {
|
||||
if exported_macro_names.insert(export.ident.modern(), export.span).is_none() {
|
||||
reexports.push(export);
|
||||
}
|
||||
}
|
||||
@ -824,7 +824,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
|
||||
self.session.cstore.export_macros(def.def_id().krate);
|
||||
}
|
||||
if let Def::Macro(..) = def {
|
||||
if let Some(&span) = exported_macro_names.get(&ident.name) {
|
||||
if let Some(&span) = exported_macro_names.get(&ident.modern()) {
|
||||
let msg =
|
||||
format!("a macro named `{}` has already been exported", ident);
|
||||
self.session.struct_span_err(span, &msg)
|
||||
@ -833,7 +833,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
reexports.push(Export { name: ident.name, def: def, span: binding.span });
|
||||
reexports.push(Export { ident: ident.modern(), def: def, span: binding.span });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,13 +54,24 @@ impl fmt::Display for Ident {
|
||||
|
||||
impl Encodable for Ident {
|
||||
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
|
||||
self.name.encode(s)
|
||||
if self.ctxt.modern() == SyntaxContext::empty() {
|
||||
s.emit_str(&self.name.as_str())
|
||||
} else { // FIXME(jseyfried) intercrate hygiene
|
||||
let mut string = "#".to_owned();
|
||||
string.push_str(&self.name.as_str());
|
||||
s.emit_str(&string)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Decodable for Ident {
|
||||
fn decode<D: Decoder>(d: &mut D) -> Result<Ident, D::Error> {
|
||||
Ok(Ident::with_empty_ctxt(Symbol::decode(d)?))
|
||||
let string = d.read_str()?;
|
||||
Ok(if !string.starts_with('#') {
|
||||
Ident::from_str(&string)
|
||||
} else { // FIXME(jseyfried) intercrate hygiene
|
||||
Ident::with_empty_ctxt(Symbol::gensym(&string[1..]))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user