auto merge of #18481 : sfackler/rust/enum-namespace, r=pcwalton

After a snapshot, everything can be switched over and the small bit of hackery in resolve dealing with `ENUM_STAGING_HACK` can be removed.

cc #18478
This commit is contained in:
bors 2014-11-02 19:22:16 +00:00
commit 0c1268451b
17 changed files with 584 additions and 94 deletions

View file

@ -15,6 +15,7 @@
use metadata::common::*; use metadata::common::*;
use metadata::cstore; use metadata::cstore;
use metadata::decoder; use metadata::decoder;
use middle::def;
use middle::lang_items; use middle::lang_items;
use middle::resolve; use middle::resolve;
use middle::ty; use middle::ty;
@ -114,6 +115,12 @@ pub fn maybe_get_item_ast<'tcx>(tcx: &ty::ctxt<'tcx>, def: ast::DefId,
decoder::maybe_get_item_ast(&*cdata, tcx, def.node, decode_inlined_item) decoder::maybe_get_item_ast(&*cdata, tcx, def.node, decode_inlined_item)
} }
pub fn get_enum_variant_defs(cstore: &cstore::CStore, enum_id: ast::DefId)
-> Vec<(def::Def, ast::Name, ast::Visibility)> {
let cdata = cstore.get_crate_data(enum_id.krate);
decoder::get_enum_variant_defs(&*cstore.intr, &*cdata, enum_id.node)
}
pub fn get_enum_variants(tcx: &ty::ctxt, def: ast::DefId) pub fn get_enum_variants(tcx: &ty::ctxt, def: ast::DefId)
-> Vec<Rc<ty::VariantInfo>> { -> Vec<Rc<ty::VariantInfo>> {
let cstore = &tcx.sess.cstore; let cstore = &tcx.sess.cstore;

View file

@ -659,6 +659,24 @@ pub fn maybe_get_item_ast<'tcx>(cdata: Cmd, tcx: &ty::ctxt<'tcx>, id: ast::NodeI
} }
} }
pub fn get_enum_variant_defs(intr: &IdentInterner,
cdata: Cmd,
id: ast::NodeId)
-> Vec<(def::Def, ast::Name, ast::Visibility)> {
let data = cdata.data();
let items = reader::get_doc(rbml::Doc::new(data), tag_items);
let item = find_item(id, items);
enum_variant_ids(item, cdata).iter().map(|did| {
let item = find_item(did.node, items);
let name = item_name(intr, item);
let visibility = item_visibility(item);
match item_to_def_like(item, *did, cdata.cnum) {
DlDef(def @ def::DefVariant(..)) => (def, name, visibility),
_ => unreachable!()
}
}).collect()
}
pub fn get_enum_variants(intr: Rc<IdentInterner>, cdata: Cmd, id: ast::NodeId, pub fn get_enum_variants(intr: Rc<IdentInterner>, cdata: Cmd, id: ast::NodeId,
tcx: &ty::ctxt) -> Vec<Rc<ty::VariantInfo>> { tcx: &ty::ctxt) -> Vec<Rc<ty::VariantInfo>> {
let data = cdata.data(); let data = cdata.data();

View file

@ -492,6 +492,7 @@ enum ModuleKind {
NormalModuleKind, NormalModuleKind,
TraitModuleKind, TraitModuleKind,
ImplModuleKind, ImplModuleKind,
EnumModuleKind,
AnonymousModuleKind, AnonymousModuleKind,
} }
@ -568,10 +569,19 @@ impl Module {
} }
} }
bitflags! {
#[deriving(Show)]
flags DefModifiers: u8 {
const PUBLIC = 0b0000_0001,
const IMPORTABLE = 0b0000_0010,
const ENUM_STAGING_HACK = 0b0000_0100,
}
}
// Records a possibly-private type definition. // Records a possibly-private type definition.
#[deriving(Clone)] #[deriving(Clone)]
struct TypeNsDef { struct TypeNsDef {
is_public: bool, // see note in ImportResolution about how to use this modifiers: DefModifiers, // see note in ImportResolution about how to use this
module_def: Option<Rc<Module>>, module_def: Option<Rc<Module>>,
type_def: Option<Def>, type_def: Option<Def>,
type_span: Option<Span> type_span: Option<Span>
@ -580,7 +590,7 @@ struct TypeNsDef {
// Records a possibly-private value definition. // Records a possibly-private value definition.
#[deriving(Clone, Show)] #[deriving(Clone, Show)]
struct ValueNsDef { struct ValueNsDef {
is_public: bool, // see note in ImportResolution about how to use this modifiers: DefModifiers, // see note in ImportResolution about how to use this
def: Def, def: Def,
value_span: Option<Span>, value_span: Option<Span>,
} }
@ -616,13 +626,14 @@ impl NameBindings {
is_public: bool, is_public: bool,
sp: Span) { sp: Span) {
// Merges the module with the existing type def or creates a new one. // Merges the module with the existing type def or creates a new one.
let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE;
let module_ = Rc::new(Module::new(parent_link, def_id, kind, external, let module_ = Rc::new(Module::new(parent_link, def_id, kind, external,
is_public)); is_public));
let type_def = self.type_def.borrow().clone(); let type_def = self.type_def.borrow().clone();
match type_def { match type_def {
None => { None => {
*self.type_def.borrow_mut() = Some(TypeNsDef { *self.type_def.borrow_mut() = Some(TypeNsDef {
is_public: is_public, modifiers: modifiers,
module_def: Some(module_), module_def: Some(module_),
type_def: None, type_def: None,
type_span: Some(sp) type_span: Some(sp)
@ -630,7 +641,7 @@ impl NameBindings {
} }
Some(type_def) => { Some(type_def) => {
*self.type_def.borrow_mut() = Some(TypeNsDef { *self.type_def.borrow_mut() = Some(TypeNsDef {
is_public: is_public, modifiers: modifiers,
module_def: Some(module_), module_def: Some(module_),
type_span: Some(sp), type_span: Some(sp),
type_def: type_def.type_def type_def: type_def.type_def
@ -647,13 +658,14 @@ impl NameBindings {
external: bool, external: bool,
is_public: bool, is_public: bool,
_sp: Span) { _sp: Span) {
let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE;
let type_def = self.type_def.borrow().clone(); let type_def = self.type_def.borrow().clone();
match type_def { match type_def {
None => { None => {
let module = Module::new(parent_link, def_id, kind, let module = Module::new(parent_link, def_id, kind,
external, is_public); external, is_public);
*self.type_def.borrow_mut() = Some(TypeNsDef { *self.type_def.borrow_mut() = Some(TypeNsDef {
is_public: is_public, modifiers: modifiers,
module_def: Some(Rc::new(module)), module_def: Some(Rc::new(module)),
type_def: None, type_def: None,
type_span: None, type_span: None,
@ -668,7 +680,7 @@ impl NameBindings {
external, external,
is_public); is_public);
*self.type_def.borrow_mut() = Some(TypeNsDef { *self.type_def.borrow_mut() = Some(TypeNsDef {
is_public: is_public, modifiers: modifiers,
module_def: Some(Rc::new(module)), module_def: Some(Rc::new(module)),
type_def: type_def.type_def, type_def: type_def.type_def,
type_span: None, type_span: None,
@ -681,7 +693,8 @@ impl NameBindings {
} }
/// Records a type definition. /// Records a type definition.
fn define_type(&self, def: Def, sp: Span, is_public: bool) { fn define_type(&self, def: Def, sp: Span, modifiers: DefModifiers) {
debug!("defining type for def {} with modifiers {}", def, modifiers);
// Merges the type with the existing type def or creates a new one. // Merges the type with the existing type def or creates a new one.
let type_def = self.type_def.borrow().clone(); let type_def = self.type_def.borrow().clone();
match type_def { match type_def {
@ -690,7 +703,7 @@ impl NameBindings {
module_def: None, module_def: None,
type_def: Some(def), type_def: Some(def),
type_span: Some(sp), type_span: Some(sp),
is_public: is_public, modifiers: modifiers,
}); });
} }
Some(type_def) => { Some(type_def) => {
@ -698,18 +711,19 @@ impl NameBindings {
type_def: Some(def), type_def: Some(def),
type_span: Some(sp), type_span: Some(sp),
module_def: type_def.module_def, module_def: type_def.module_def,
is_public: is_public, modifiers: modifiers,
}); });
} }
} }
} }
/// Records a value definition. /// Records a value definition.
fn define_value(&self, def: Def, sp: Span, is_public: bool) { fn define_value(&self, def: Def, sp: Span, modifiers: DefModifiers) {
debug!("defining value for def {} with modifiers {}", def, modifiers);
*self.value_def.borrow_mut() = Some(ValueNsDef { *self.value_def.borrow_mut() = Some(ValueNsDef {
def: def, def: def,
value_span: Some(sp), value_span: Some(sp),
is_public: is_public, modifiers: modifiers,
}); });
} }
@ -743,12 +757,16 @@ impl NameBindings {
} }
fn defined_in_public_namespace(&self, namespace: Namespace) -> bool { fn defined_in_public_namespace(&self, namespace: Namespace) -> bool {
self.defined_in_namespace_with(namespace, PUBLIC)
}
fn defined_in_namespace_with(&self, namespace: Namespace, modifiers: DefModifiers) -> bool {
match namespace { match namespace {
TypeNS => match *self.type_def.borrow() { TypeNS => match *self.type_def.borrow() {
Some(ref def) => def.is_public, None => false Some(ref def) => def.modifiers.contains(modifiers), None => false
}, },
ValueNS => match *self.value_def.borrow() { ValueNS => match *self.value_def.borrow() {
Some(ref def) => def.is_public, None => false Some(ref def) => def.modifiers.contains(modifiers), None => false
} }
} }
} }
@ -1214,6 +1232,7 @@ impl<'a> Resolver<'a> {
let name = item.ident.name; let name = item.ident.name;
let sp = item.span; let sp = item.span;
let is_public = item.vis == ast::Public; let is_public = item.vis == ast::Public;
let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE;
match item.node { match item.node {
ItemMod(..) => { ItemMod(..) => {
@ -1241,13 +1260,13 @@ impl<'a> Resolver<'a> {
let mutbl = m == ast::MutMutable; let mutbl = m == ast::MutMutable;
name_bindings.define_value name_bindings.define_value
(DefStatic(local_def(item.id), mutbl), sp, is_public); (DefStatic(local_def(item.id), mutbl), sp, modifiers);
parent parent
} }
ItemConst(_, _) => { ItemConst(_, _) => {
self.add_child(name, parent.clone(), ForbidDuplicateValues, sp) self.add_child(name, parent.clone(), ForbidDuplicateValues, sp)
.define_value(DefConst(local_def(item.id)), .define_value(DefConst(local_def(item.id)),
sp, is_public); sp, modifiers);
parent parent
} }
ItemFn(_, _, _, _, _) => { ItemFn(_, _, _, _, _) => {
@ -1255,7 +1274,7 @@ impl<'a> Resolver<'a> {
self.add_child(name, parent.clone(), ForbidDuplicateValues, sp); self.add_child(name, parent.clone(), ForbidDuplicateValues, sp);
let def = DefFn(local_def(item.id), false); let def = DefFn(local_def(item.id), false);
name_bindings.define_value(def, sp, is_public); name_bindings.define_value(def, sp, modifiers);
parent parent
} }
@ -1268,7 +1287,7 @@ impl<'a> Resolver<'a> {
sp); sp);
name_bindings.define_type name_bindings.define_type
(DefTy(local_def(item.id), false), sp, is_public); (DefTy(local_def(item.id), false), sp, modifiers);
parent parent
} }
@ -1280,14 +1299,32 @@ impl<'a> Resolver<'a> {
sp); sp);
name_bindings.define_type name_bindings.define_type
(DefTy(local_def(item.id), true), sp, is_public); (DefTy(local_def(item.id), true), sp, modifiers);
let parent_link = self.get_parent_link(parent.clone(), name);
// We want to make sure the module type is EnumModuleKind
// even if there's already an ImplModuleKind module defined,
// since that's how we prevent duplicate enum definitions
name_bindings.set_module_kind(parent_link,
Some(local_def(item.id)),
EnumModuleKind,
false,
is_public,
sp);
for variant in (*enum_definition).variants.iter() { for variant in (*enum_definition).variants.iter() {
self.build_reduced_graph_for_variant(
&**variant,
local_def(item.id),
ModuleReducedGraphParent(name_bindings.get_module()),
modifiers);
// Temporary staging hack
self.build_reduced_graph_for_variant( self.build_reduced_graph_for_variant(
&**variant, &**variant,
local_def(item.id), local_def(item.id),
parent.clone(), parent.clone(),
is_public); modifiers | ENUM_STAGING_HACK);
} }
parent parent
} }
@ -1303,14 +1340,14 @@ impl<'a> Resolver<'a> {
let name_bindings = self.add_child(name, parent.clone(), forbid, sp); let name_bindings = self.add_child(name, parent.clone(), forbid, sp);
// Define a name in the type namespace. // Define a name in the type namespace.
name_bindings.define_type(DefTy(local_def(item.id), false), sp, is_public); name_bindings.define_type(DefTy(local_def(item.id), false), sp, modifiers);
// If this is a newtype or unit-like struct, define a name // If this is a newtype or unit-like struct, define a name
// in the value namespace as well // in the value namespace as well
match ctor_id { match ctor_id {
Some(cid) => { Some(cid) => {
name_bindings.define_value(DefStruct(local_def(cid)), name_bindings.define_value(DefStruct(local_def(cid)),
sp, is_public); sp, modifiers);
} }
None => {} None => {}
} }
@ -1347,6 +1384,12 @@ impl<'a> Resolver<'a> {
ImplModuleKind => { ImplModuleKind => {
ModuleReducedGraphParent(child.get_module()) ModuleReducedGraphParent(child.get_module())
} }
Some(ref child) if child.get_module_if_available()
.is_some() &&
child.get_module().kind.get() ==
EnumModuleKind => {
ModuleReducedGraphParent(child.get_module())
}
// Create the module // Create the module
_ => { _ => {
let name_bindings = let name_bindings =
@ -1403,12 +1446,16 @@ impl<'a> Resolver<'a> {
} }
}; };
let is_public = // NB: not IMPORTABLE
method.pe_vis() == ast::Public; let modifiers = if method.pe_vis() == ast::Public {
PUBLIC
} else {
DefModifiers::empty()
};
method_name_bindings.define_value( method_name_bindings.define_value(
def, def,
method.span, method.span,
is_public); modifiers);
} }
TypeImplItem(ref typedef) => { TypeImplItem(ref typedef) => {
// Add the typedef to the module. // Add the typedef to the module.
@ -1421,12 +1468,16 @@ impl<'a> Resolver<'a> {
typedef.span); typedef.span);
let def = DefAssociatedTy(local_def( let def = DefAssociatedTy(local_def(
typedef.id)); typedef.id));
let is_public = typedef.vis == // NB: not IMPORTABLE
ast::Public; let modifiers = if typedef.vis == ast::Public {
PUBLIC
} else {
DefModifiers::empty()
};
typedef_name_bindings.define_type( typedef_name_bindings.define_type(
def, def,
typedef.span, typedef.span,
is_public); modifiers);
} }
} }
} }
@ -1499,9 +1550,10 @@ impl<'a> Resolver<'a> {
module_parent.clone(), module_parent.clone(),
ForbidDuplicateTypesAndValues, ForbidDuplicateTypesAndValues,
ty_m.span); ty_m.span);
// NB: not IMPORTABLE
method_name_bindings.define_value(def, method_name_bindings.define_value(def,
ty_m.span, ty_m.span,
true); PUBLIC);
(name, static_flag) (name, static_flag)
} }
@ -1514,9 +1566,10 @@ impl<'a> Resolver<'a> {
module_parent.clone(), module_parent.clone(),
ForbidDuplicateTypesAndValues, ForbidDuplicateTypesAndValues,
associated_type.span); associated_type.span);
// NB: not IMPORTABLE
name_bindings.define_type(def, name_bindings.define_type(def,
associated_type.span, associated_type.span,
true); PUBLIC);
(associated_type.ident.name, TypeTraitItemKind) (associated_type.ident.name, TypeTraitItemKind)
} }
@ -1525,7 +1578,7 @@ impl<'a> Resolver<'a> {
self.trait_item_map.insert((name, def_id), kind); self.trait_item_map.insert((name, def_id), kind);
} }
name_bindings.define_type(DefTrait(def_id), sp, is_public); name_bindings.define_type(DefTrait(def_id), sp, modifiers);
parent parent
} }
ItemMac(..) => parent ItemMac(..) => parent
@ -1538,7 +1591,7 @@ impl<'a> Resolver<'a> {
variant: &Variant, variant: &Variant,
item_id: DefId, item_id: DefId,
parent: ReducedGraphParent, parent: ReducedGraphParent,
is_public: bool) { modifiers: DefModifiers) {
let name = variant.node.name.name; let name = variant.node.name.name;
let is_exported = match variant.node.kind { let is_exported = match variant.node.kind {
TupleVariantKind(_) => false, TupleVariantKind(_) => false,
@ -1554,10 +1607,10 @@ impl<'a> Resolver<'a> {
variant.span); variant.span);
child.define_value(DefVariant(item_id, child.define_value(DefVariant(item_id,
local_def(variant.node.id), is_exported), local_def(variant.node.id), is_exported),
variant.span, is_public); variant.span, modifiers);
child.define_type(DefVariant(item_id, child.define_type(DefVariant(item_id,
local_def(variant.node.id), is_exported), local_def(variant.node.id), is_exported),
variant.span, is_public); variant.span, modifiers);
} }
/// Constructs the reduced graph for one 'view item'. View items consist /// Constructs the reduced graph for one 'view item'. View items consist
@ -1703,6 +1756,7 @@ impl<'a> Resolver<'a> {
f: |&mut Resolver|) { f: |&mut Resolver|) {
let name = foreign_item.ident.name; let name = foreign_item.ident.name;
let is_public = foreign_item.vis == ast::Public; let is_public = foreign_item.vis == ast::Public;
let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE;
let name_bindings = let name_bindings =
self.add_child(name, parent, ForbidDuplicateValues, self.add_child(name, parent, ForbidDuplicateValues,
foreign_item.span); foreign_item.span);
@ -1710,7 +1764,7 @@ impl<'a> Resolver<'a> {
match foreign_item.node { match foreign_item.node {
ForeignItemFn(_, ref generics) => { ForeignItemFn(_, ref generics) => {
let def = DefFn(local_def(foreign_item.id), false); let def = DefFn(local_def(foreign_item.id), false);
name_bindings.define_value(def, foreign_item.span, is_public); name_bindings.define_value(def, foreign_item.span, modifiers);
self.with_type_parameter_rib( self.with_type_parameter_rib(
HasTypeParameters(generics, HasTypeParameters(generics,
@ -1721,7 +1775,7 @@ impl<'a> Resolver<'a> {
} }
ForeignItemStatic(_, m) => { ForeignItemStatic(_, m) => {
let def = DefStatic(local_def(foreign_item.id), m); let def = DefStatic(local_def(foreign_item.id), m);
name_bindings.define_value(def, foreign_item.span, is_public); name_bindings.define_value(def, foreign_item.span, modifiers);
f(self) f(self)
} }
@ -1766,6 +1820,7 @@ impl<'a> Resolver<'a> {
external crate) building external def, priv {}", external crate) building external def, priv {}",
vis); vis);
let is_public = vis == ast::Public; let is_public = vis == ast::Public;
let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE;
let is_exported = is_public && match new_parent { let is_exported = is_public && match new_parent {
ModuleReducedGraphParent(ref module) => { ModuleReducedGraphParent(ref module) => {
match module.def_id.get() { match module.def_id.get() {
@ -1779,6 +1834,7 @@ impl<'a> Resolver<'a> {
} }
let kind = match def { let kind = match def {
DefTy(_, true) => EnumModuleKind,
DefStruct(..) | DefTy(..) => ImplModuleKind, DefStruct(..) | DefTy(..) => ImplModuleKind,
_ => NormalModuleKind _ => NormalModuleKind
}; };
@ -1813,6 +1869,7 @@ impl<'a> Resolver<'a> {
match def { match def {
DefMod(_) | DefForeignMod(_) => {} DefMod(_) | DefForeignMod(_) => {}
// Still here for staging
DefVariant(enum_did, variant_id, is_struct) => { DefVariant(enum_did, variant_id, is_struct) => {
debug!("(building reduced graph for external crate) building \ debug!("(building reduced graph for external crate) building \
variant {}", variant {}",
@ -1822,23 +1879,36 @@ impl<'a> Resolver<'a> {
// definition. // definition.
let is_exported = is_public || let is_exported = is_public ||
self.external_exports.contains(&enum_did); self.external_exports.contains(&enum_did);
let modifiers = IMPORTABLE | ENUM_STAGING_HACK | if is_exported {
PUBLIC
} else {
DefModifiers::empty()
};
if is_struct { if is_struct {
child_name_bindings.define_type(def, DUMMY_SP, is_exported); child_name_bindings.define_type(def, DUMMY_SP, modifiers);
// Not adding fields for variants as they are not accessed with a self receiver // Not adding fields for variants as they are not accessed with a self receiver
self.structs.insert(variant_id, Vec::new()); self.structs.insert(variant_id, Vec::new());
} else { } else {
child_name_bindings.define_value(def, DUMMY_SP, is_exported); child_name_bindings.define_value(def, DUMMY_SP, modifiers);
} }
} }
DefFn(ctor_id, true) => { DefFn(ctor_id, true) => {
child_name_bindings.define_value( child_name_bindings.define_value(
csearch::get_tuple_struct_definition_if_ctor(&self.session.cstore, ctor_id) csearch::get_tuple_struct_definition_if_ctor(&self.session.cstore, ctor_id)
.map_or(def, |_| DefStruct(ctor_id)), DUMMY_SP, is_public); .map_or(def, |_| DefStruct(ctor_id)), DUMMY_SP, modifiers);
} }
DefFn(..) | DefStaticMethod(..) | DefStatic(..) | DefConst(..) | DefMethod(..) => { DefFn(..) | DefStaticMethod(..) | DefStatic(..) | DefConst(..) | DefMethod(..) => {
debug!("(building reduced graph for external \ debug!("(building reduced graph for external \
crate) building value (fn/static) {}", final_ident); crate) building value (fn/static) {}", final_ident);
child_name_bindings.define_value(def, DUMMY_SP, is_public); // impl methods have already been defined with the correct importability modifier
let mut modifiers = match *child_name_bindings.value_def.borrow() {
Some(ref def) => (modifiers & !IMPORTABLE) | (def.modifiers & IMPORTABLE),
None => modifiers
};
if new_parent.module().kind.get() != NormalModuleKind {
modifiers = modifiers & !IMPORTABLE;
}
child_name_bindings.define_value(def, DUMMY_SP, modifiers);
} }
DefTrait(def_id) => { DefTrait(def_id) => {
debug!("(building reduced graph for external \ debug!("(building reduced graph for external \
@ -1867,7 +1937,7 @@ impl<'a> Resolver<'a> {
} }
} }
child_name_bindings.define_type(def, DUMMY_SP, is_public); child_name_bindings.define_type(def, DUMMY_SP, modifiers);
// Define a module if necessary. // Define a module if necessary.
let parent_link = self.get_parent_link(new_parent, name); let parent_link = self.get_parent_link(new_parent, name);
@ -1878,23 +1948,57 @@ impl<'a> Resolver<'a> {
is_public, is_public,
DUMMY_SP) DUMMY_SP)
} }
DefTy(def_id, true) => { // enums
debug!("(building reduced graph for external crate) building enum {}", final_ident);
child_name_bindings.define_type(def, DUMMY_SP, modifiers);
let enum_module = ModuleReducedGraphParent(child_name_bindings.get_module());
let variants = csearch::get_enum_variant_defs(&self.session.cstore, def_id);
for &(v_def, name, vis) in variants.iter() {
let (variant_id, is_struct) = match v_def {
DefVariant(_, variant_id, is_struct) => (variant_id, is_struct),
_ => unreachable!()
};
let child = self.add_child(name, enum_module.clone(),
OverwriteDuplicates,
DUMMY_SP);
// If this variant is public, then it was publicly reexported,
// otherwise we need to inherit the visibility of the enum
// definition.
let variant_exported = vis == ast::Public || is_exported;
let modifiers = IMPORTABLE | if variant_exported {
PUBLIC
} else {
DefModifiers::empty()
};
if is_struct {
child.define_type(v_def, DUMMY_SP, modifiers);
// Not adding fields for variants as they are not accessed with a self
// receiver
self.structs.insert(variant_id, Vec::new());
} else {
child.define_value(v_def, DUMMY_SP, modifiers);
}
}
}
DefTy(..) | DefAssociatedTy(..) => { DefTy(..) | DefAssociatedTy(..) => {
debug!("(building reduced graph for external \ debug!("(building reduced graph for external \
crate) building type {}", final_ident); crate) building type {}", final_ident);
child_name_bindings.define_type(def, DUMMY_SP, is_public); child_name_bindings.define_type(def, DUMMY_SP, modifiers);
} }
DefStruct(def_id) => { DefStruct(def_id) => {
debug!("(building reduced graph for external \ debug!("(building reduced graph for external \
crate) building type and value for {}", crate) building type and value for {}",
final_ident); final_ident);
child_name_bindings.define_type(def, DUMMY_SP, is_public); child_name_bindings.define_type(def, DUMMY_SP, modifiers);
let fields = csearch::get_struct_fields(&self.session.cstore, def_id).iter().map(|f| { let fields = csearch::get_struct_fields(&self.session.cstore, def_id).iter().map(|f| {
f.name f.name
}).collect::<Vec<_>>(); }).collect::<Vec<_>>();
if fields.len() == 0 { if fields.len() == 0 {
child_name_bindings.define_value(def, DUMMY_SP, is_public); child_name_bindings.define_value(def, DUMMY_SP, modifiers);
} }
// Record the def ID and fields of this struct. // Record the def ID and fields of this struct.
@ -2021,9 +2125,14 @@ impl<'a> Resolver<'a> {
DUMMY_SP); DUMMY_SP);
let def = DefFn(method_info.def_id, false); let def = DefFn(method_info.def_id, false);
// NB: not IMPORTABLE
let modifiers = if visibility == ast::Public {
PUBLIC
} else {
DefModifiers::empty()
};
method_name_bindings.define_value( method_name_bindings.define_value(
def, DUMMY_SP, def, DUMMY_SP, modifiers);
visibility == ast::Public);
} }
} }
@ -2394,7 +2503,7 @@ impl<'a> Resolver<'a> {
fn create_name_bindings_from_module(module: Rc<Module>) -> NameBindings { fn create_name_bindings_from_module(module: Rc<Module>) -> NameBindings {
NameBindings { NameBindings {
type_def: RefCell::new(Some(TypeNsDef { type_def: RefCell::new(Some(TypeNsDef {
is_public: false, modifiers: IMPORTABLE,
module_def: Some(module), module_def: Some(module),
type_def: None, type_def: None,
type_span: None type_span: None
@ -2596,6 +2705,12 @@ impl<'a> Resolver<'a> {
target, target,
ValueNS); ValueNS);
self.check_that_import_is_importable(
&**name_bindings,
directive.span,
target,
ValueNS);
import_resolution.value_target = import_resolution.value_target =
Some(Target::new(target_module.clone(), Some(Target::new(target_module.clone(),
name_bindings.clone(), name_bindings.clone(),
@ -2619,6 +2734,12 @@ impl<'a> Resolver<'a> {
target, target,
TypeNS); TypeNS);
self.check_that_import_is_importable(
&**name_bindings,
directive.span,
target,
TypeNS);
import_resolution.type_target = import_resolution.type_target =
Some(Target::new(target_module.clone(), Some(Target::new(target_module.clone(),
name_bindings.clone(), name_bindings.clone(),
@ -2829,7 +2950,7 @@ impl<'a> Resolver<'a> {
self.module_to_string(module_)); self.module_to_string(module_));
// Merge the child item into the import resolution. // Merge the child item into the import resolution.
if name_bindings.defined_in_public_namespace(ValueNS) { if name_bindings.defined_in_namespace_with(ValueNS, IMPORTABLE | PUBLIC) {
debug!("(resolving glob import) ... for value target"); debug!("(resolving glob import) ... for value target");
dest_import_resolution.value_target = dest_import_resolution.value_target =
Some(Target::new(containing_module.clone(), Some(Target::new(containing_module.clone(),
@ -2837,7 +2958,7 @@ impl<'a> Resolver<'a> {
import_directive.shadowable)); import_directive.shadowable));
dest_import_resolution.value_id = id; dest_import_resolution.value_id = id;
} }
if name_bindings.defined_in_public_namespace(TypeNS) { if name_bindings.defined_in_namespace_with(TypeNS, IMPORTABLE | PUBLIC) {
debug!("(resolving glob import) ... for type target"); debug!("(resolving glob import) ... for type target");
dest_import_resolution.type_target = dest_import_resolution.type_target =
Some(Target::new(containing_module, Some(Target::new(containing_module,
@ -2879,6 +3000,19 @@ impl<'a> Resolver<'a> {
} }
} }
/// Checks that an import is actually importable
fn check_that_import_is_importable(&mut self,
name_bindings: &NameBindings,
import_span: Span,
name: Name,
namespace: Namespace) {
if !name_bindings.defined_in_namespace_with(namespace, IMPORTABLE) {
let msg = format!("`{}` is not directly importable",
token::get_name(name));
self.session.span_err(import_span, msg.as_slice());
}
}
/// Checks that imported names and items don't have the same name. /// Checks that imported names and items don't have the same name.
fn check_for_conflicts_between_imports_and_items(&mut self, fn check_for_conflicts_between_imports_and_items(&mut self,
module: &Module, module: &Module,
@ -2918,8 +3052,8 @@ impl<'a> Resolver<'a> {
match import_resolution.value_target { match import_resolution.value_target {
Some(ref target) if !target.shadowable => { Some(ref target) if !target.shadowable => {
match *name_bindings.value_def.borrow() { match *name_bindings.value_def.borrow() {
None => {} // We want to allow the "flat" def of enum variants to be shadowed
Some(ref value) => { Some(ref value) if !value.modifiers.contains(ENUM_STAGING_HACK) => {
let msg = format!("import `{}` conflicts with value \ let msg = format!("import `{}` conflicts with value \
in this module", in this module",
token::get_name(name).get()); token::get_name(name).get());
@ -2933,6 +3067,7 @@ impl<'a> Resolver<'a> {
} }
} }
} }
_ => {}
} }
} }
Some(_) | None => {} Some(_) | None => {}
@ -2941,8 +3076,8 @@ impl<'a> Resolver<'a> {
match import_resolution.type_target { match import_resolution.type_target {
Some(ref target) if !target.shadowable => { Some(ref target) if !target.shadowable => {
match *name_bindings.type_def.borrow() { match *name_bindings.type_def.borrow() {
None => {} // We want to allow the "flat" def of enum variants to be shadowed
Some(ref ty) => { Some(ref ty) if !ty.modifiers.contains(ENUM_STAGING_HACK) => {
match ty.module_def { match ty.module_def {
None => { None => {
let msg = format!("import `{}` conflicts with type in \ let msg = format!("import `{}` conflicts with type in \
@ -2993,6 +3128,7 @@ impl<'a> Resolver<'a> {
} }
} }
} }
_ => {}
} }
} }
Some(_) | None => {} Some(_) | None => {}
@ -3131,43 +3267,28 @@ impl<'a> Resolver<'a> {
return Failed(Some((span, msg))); return Failed(Some((span, msg)));
} }
Some(ref module_def) => { Some(ref module_def) => {
// If we're doing the search for an search_module = module_def.clone();
// import, do not allow traits and impls
// to be selected. // track extern crates for unused_extern_crate lint
match (name_search_type, match module_def.def_id.get() {
module_def.kind.get()) { Some(did) => {
(ImportSearch, TraitModuleKind) | self.used_crates.insert(did.krate);
(ImportSearch, ImplModuleKind) => {
let msg =
"Cannot import from a trait or \
type implementation".to_string();
return Failed(Some((span, msg)));
} }
(_, _) => { _ => {}
search_module = module_def.clone(); }
// track extern crates for unused_extern_crates lint // Keep track of the closest
match module_def.def_id.get() { // private module used when
Some(did) => { // resolving this import chain.
self.used_crates.insert(did.krate); if !used_proxy &&
} !search_module.is_public {
_ => {} match search_module.def_id
} .get() {
Some(did) => {
// Keep track of the closest closest_private =
// private module used when LastMod(DependsOn(did));
// resolving this import chain.
if !used_proxy &&
!search_module.is_public {
match search_module.def_id
.get() {
Some(did) => {
closest_private =
LastMod(DependsOn(did));
}
None => {}
}
} }
None => {}
} }
} }
} }
@ -3388,6 +3509,7 @@ impl<'a> Resolver<'a> {
} }
TraitModuleKind | TraitModuleKind |
ImplModuleKind | ImplModuleKind |
EnumModuleKind |
AnonymousModuleKind => { AnonymousModuleKind => {
search_module = parent_module_node.upgrade().unwrap(); search_module = parent_module_node.upgrade().unwrap();
} }
@ -3485,6 +3607,7 @@ impl<'a> Resolver<'a> {
NormalModuleKind => return Some(new_module), NormalModuleKind => return Some(new_module),
TraitModuleKind | TraitModuleKind |
ImplModuleKind | ImplModuleKind |
EnumModuleKind |
AnonymousModuleKind => module_ = new_module, AnonymousModuleKind => module_ = new_module,
} }
} }
@ -3500,6 +3623,7 @@ impl<'a> Resolver<'a> {
NormalModuleKind => return module_, NormalModuleKind => return module_,
TraitModuleKind | TraitModuleKind |
ImplModuleKind | ImplModuleKind |
EnumModuleKind |
AnonymousModuleKind => { AnonymousModuleKind => {
match self.get_nearest_normal_module_parent(module_.clone()) { match self.get_nearest_normal_module_parent(module_.clone()) {
None => module_, None => module_,

View file

@ -0,0 +1,38 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(globs, struct_variant)]
pub use Foo::*;
pub enum Foo {
A,
B(int),
C { a: int },
}
impl Foo {
pub fn foo() {}
}
pub mod nest {
pub use self::Bar::*;
pub enum Bar {
D,
E(int),
F { a: int },
}
impl Bar {
pub fn foo() {}
}
}

View file

@ -0,0 +1,22 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(struct_variant)]
pub enum Foo {
A,
B(int),
C { a: int },
}
impl Foo {
pub fn foo() {}
pub fn bar(&self) {}
}

View file

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
pub use self::sub::Bar; pub use self::sub::{Bar, Baz};
pub trait Trait { pub trait Trait {
fn foo(); fn foo();
@ -26,4 +26,10 @@ mod sub {
impl Bar { impl Bar {
pub fn new() {} pub fn new() {}
} }
pub enum Baz {}
impl Baz {
pub fn new() {}
}
} }

View file

@ -13,7 +13,7 @@ mod Foo {
} }
enum Foo { //~ ERROR duplicate definition of type or module `Foo` enum Foo { //~ ERROR duplicate definition of type or module `Foo`
X X //~ ERROR duplicate definition of value `X`
} }
fn main() {} fn main() {}

View file

@ -0,0 +1,28 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// aux-build:namespaced_enums.rs
#![feature(struct_variant, globs)]
extern crate namespaced_enums;
mod m {
pub use namespaced_enums::Foo::*;
}
pub fn main() {
use namespaced_enums::Foo::*;
foo(); //~ ERROR unresolved name `foo`
m::foo(); //~ ERROR unresolved name `m::foo`
bar(); //~ ERROR unresolved name `bar`
m::bar(); //~ ERROR unresolved name `m::bar`
}

View file

@ -0,0 +1,36 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(struct_variant, globs)]
mod m2 {
pub enum Foo {
A,
B(int),
C { a: int },
}
impl Foo {
pub fn foo() {}
pub fn bar(&self) {}
}
}
mod m {
pub use m2::Foo::*;
}
pub fn main() {
use m2::Foo::*;
foo(); //~ ERROR unresolved name `foo`
m::foo(); //~ ERROR unresolved name `m::foo`
bar(); //~ ERROR unresolved name `bar`
m::bar(); //~ ERROR unresolved name `m::bar`
}

View file

@ -13,12 +13,15 @@
extern crate use_from_trait_xc; extern crate use_from_trait_xc;
use use_from_trait_xc::Trait::foo; use use_from_trait_xc::Trait::foo;
//~^ ERROR unresolved import `use_from_trait_xc::Trait::foo`. Cannot import from a trait or type imp //~^ ERROR `foo` is not directly importable
use use_from_trait_xc::Foo::new; use use_from_trait_xc::Foo::new;
//~^ ERROR unresolved import `use_from_trait_xc::Foo::new`. Cannot import from a trait or type imple //~^ ERROR `new` is not directly importable
use use_from_trait_xc::Bar::new; use use_from_trait_xc::Bar::new as bnew;
//~^ ERROR unresolved import `use_from_trait_xc::Bar::new`. Cannot import from a trait or type //~^ ERROR `bnew` is not directly importable
use use_from_trait_xc::Baz::new as baznew;
//~^ ERROR `baznew` is not directly importable
fn main() {} fn main() {}

View file

@ -9,9 +9,9 @@
// except according to those terms. // except according to those terms.
use Trait::foo; use Trait::foo;
//~^ ERROR unresolved import `Trait::foo`. Cannot import from a trait or type implementation //~^ ERROR `foo` is not directly importable
use Foo::new; use Foo::new;
//~^ ERROR unresolved import `Foo::new`. Cannot import from a trait or type implementation //~^ ERROR `new` is not directly importable
pub trait Trait { pub trait Trait {
fn foo(); fn foo();

View file

@ -0,0 +1,32 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// aux-build:namespaced_enum_emulate_flat.rs
#![feature(struct_variant)]
extern crate namespaced_enum_emulate_flat;
use namespaced_enum_emulate_flat::{Foo, A, B, C};
use namespaced_enum_emulate_flat::nest::{Bar, D, E, F};
fn _f(f: Foo) {
match f {
A | B(_) | C { .. } => {}
}
}
fn _f2(f: Bar) {
match f {
D | E(_) | F { .. } => {}
}
}
pub fn main() {}

View file

@ -0,0 +1,51 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(globs, struct_variant)]
pub use Foo::*;
use nest::{Bar, D, E, F};
pub enum Foo {
A,
B(int),
C { a: int },
}
impl Foo {
pub fn foo() {}
}
fn _f(f: Foo) {
match f {
A | B(_) | C { .. } => {}
}
}
mod nest {
pub use self::Bar::*;
pub enum Bar {
D,
E(int),
F { a: int },
}
impl Bar {
pub fn foo() {}
}
}
fn _f2(f: Bar) {
match f {
D | E(_) | F { .. } => {}
}
}
fn main() {}

View file

@ -0,0 +1,34 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// aux-build:namespaced_enums.rs
#![feature(globs, struct_variant)]
extern crate namespaced_enums;
fn _f(f: namespaced_enums::Foo) {
use namespaced_enums::Foo::*;
match f {
A | B(_) | C { .. } => {}
}
}
mod m {
pub use namespaced_enums::Foo::*;
}
fn _f2(f: namespaced_enums::Foo) {
match f {
m::A | m::B(_) | m::C { .. } => {}
}
}
pub fn main() {}

View file

@ -0,0 +1,42 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(globs, struct_variant)]
mod m2 {
pub enum Foo {
A,
B(int),
C { a: int },
}
impl Foo {
pub fn foo() {}
}
}
mod m {
pub use m2::Foo::*;
}
fn _f(f: m2::Foo) {
use m2::Foo::*;
match f {
A | B(_) | C { .. } => {}
}
}
fn _f2(f: m2::Foo) {
match f {
m::A | m::B(_) | m::C { .. } => {}
}
}
pub fn main() {}

View file

@ -0,0 +1,25 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// aux-build:namespaced_enums.rs
#![feature(struct_variant)]
extern crate namespaced_enums;
use namespaced_enums::Foo;
fn _foo (f: Foo) {
match f {
Foo::A | Foo::B(_) | Foo::C { .. } => {}
}
}
pub fn main() {}

View file

@ -0,0 +1,24 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(struct_variant)]
enum Foo {
A,
B(int),
C { a: int },
}
fn _foo (f: Foo) {
match f {
Foo::A | Foo::B(_) | Foo::C { .. } => {}
}
}
pub fn main() {}