diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs index d92623636f4..e6a0363fcbf 100644 --- a/src/librustc/metadata/csearch.rs +++ b/src/librustc/metadata/csearch.rs @@ -15,6 +15,7 @@ use metadata::common::*; use metadata::cstore; use metadata::decoder; +use middle::def; use middle::lang_items; use middle::resolve; 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) } +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) -> Vec> { let cstore = &tcx.sess.cstore; diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 213f32a1d18..0df98bfb0b1 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -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, cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt) -> Vec> { let data = cdata.data(); diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 3d102892277..c297bdc6ca2 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -492,6 +492,7 @@ enum ModuleKind { NormalModuleKind, TraitModuleKind, ImplModuleKind, + EnumModuleKind, 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. #[deriving(Clone)] 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>, type_def: Option, type_span: Option @@ -580,7 +590,7 @@ struct TypeNsDef { // Records a possibly-private value definition. #[deriving(Clone, Show)] 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, value_span: Option, } @@ -616,13 +626,14 @@ impl NameBindings { is_public: bool, sp: Span) { // 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, is_public)); let type_def = self.type_def.borrow().clone(); match type_def { None => { *self.type_def.borrow_mut() = Some(TypeNsDef { - is_public: is_public, + modifiers: modifiers, module_def: Some(module_), type_def: None, type_span: Some(sp) @@ -630,7 +641,7 @@ impl NameBindings { } Some(type_def) => { *self.type_def.borrow_mut() = Some(TypeNsDef { - is_public: is_public, + modifiers: modifiers, module_def: Some(module_), type_span: Some(sp), type_def: type_def.type_def @@ -647,13 +658,14 @@ impl NameBindings { external: bool, is_public: bool, _sp: Span) { + let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE; let type_def = self.type_def.borrow().clone(); match type_def { None => { let module = Module::new(parent_link, def_id, kind, external, is_public); *self.type_def.borrow_mut() = Some(TypeNsDef { - is_public: is_public, + modifiers: modifiers, module_def: Some(Rc::new(module)), type_def: None, type_span: None, @@ -668,7 +680,7 @@ impl NameBindings { external, is_public); *self.type_def.borrow_mut() = Some(TypeNsDef { - is_public: is_public, + modifiers: modifiers, module_def: Some(Rc::new(module)), type_def: type_def.type_def, type_span: None, @@ -681,7 +693,8 @@ impl NameBindings { } /// 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. let type_def = self.type_def.borrow().clone(); match type_def { @@ -690,7 +703,7 @@ impl NameBindings { module_def: None, type_def: Some(def), type_span: Some(sp), - is_public: is_public, + modifiers: modifiers, }); } Some(type_def) => { @@ -698,18 +711,19 @@ impl NameBindings { type_def: Some(def), type_span: Some(sp), module_def: type_def.module_def, - is_public: is_public, + modifiers: modifiers, }); } } } /// 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 { def: def, 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 { + self.defined_in_namespace_with(namespace, PUBLIC) + } + + fn defined_in_namespace_with(&self, namespace: Namespace, modifiers: DefModifiers) -> bool { match namespace { 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() { - 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 sp = item.span; let is_public = item.vis == ast::Public; + let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE; match item.node { ItemMod(..) => { @@ -1241,13 +1260,13 @@ impl<'a> Resolver<'a> { let mutbl = m == ast::MutMutable; name_bindings.define_value - (DefStatic(local_def(item.id), mutbl), sp, is_public); + (DefStatic(local_def(item.id), mutbl), sp, modifiers); parent } ItemConst(_, _) => { self.add_child(name, parent.clone(), ForbidDuplicateValues, sp) .define_value(DefConst(local_def(item.id)), - sp, is_public); + sp, modifiers); parent } ItemFn(_, _, _, _, _) => { @@ -1255,7 +1274,7 @@ impl<'a> Resolver<'a> { self.add_child(name, parent.clone(), ForbidDuplicateValues, sp); let def = DefFn(local_def(item.id), false); - name_bindings.define_value(def, sp, is_public); + name_bindings.define_value(def, sp, modifiers); parent } @@ -1268,7 +1287,7 @@ impl<'a> Resolver<'a> { sp); name_bindings.define_type - (DefTy(local_def(item.id), false), sp, is_public); + (DefTy(local_def(item.id), false), sp, modifiers); parent } @@ -1280,14 +1299,32 @@ impl<'a> Resolver<'a> { sp); 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() { + 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( &**variant, local_def(item.id), parent.clone(), - is_public); + modifiers | ENUM_STAGING_HACK); } parent } @@ -1303,14 +1340,14 @@ impl<'a> Resolver<'a> { let name_bindings = self.add_child(name, parent.clone(), forbid, sp); // 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 // in the value namespace as well match ctor_id { Some(cid) => { name_bindings.define_value(DefStruct(local_def(cid)), - sp, is_public); + sp, modifiers); } None => {} } @@ -1347,6 +1384,12 @@ impl<'a> Resolver<'a> { ImplModuleKind => { 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 _ => { let name_bindings = @@ -1403,12 +1446,16 @@ impl<'a> Resolver<'a> { } }; - let is_public = - method.pe_vis() == ast::Public; + // NB: not IMPORTABLE + let modifiers = if method.pe_vis() == ast::Public { + PUBLIC + } else { + DefModifiers::empty() + }; method_name_bindings.define_value( def, method.span, - is_public); + modifiers); } TypeImplItem(ref typedef) => { // Add the typedef to the module. @@ -1421,12 +1468,16 @@ impl<'a> Resolver<'a> { typedef.span); let def = DefAssociatedTy(local_def( typedef.id)); - let is_public = typedef.vis == - ast::Public; + // NB: not IMPORTABLE + let modifiers = if typedef.vis == ast::Public { + PUBLIC + } else { + DefModifiers::empty() + }; typedef_name_bindings.define_type( def, typedef.span, - is_public); + modifiers); } } } @@ -1499,9 +1550,10 @@ impl<'a> Resolver<'a> { module_parent.clone(), ForbidDuplicateTypesAndValues, ty_m.span); + // NB: not IMPORTABLE method_name_bindings.define_value(def, ty_m.span, - true); + PUBLIC); (name, static_flag) } @@ -1514,9 +1566,10 @@ impl<'a> Resolver<'a> { module_parent.clone(), ForbidDuplicateTypesAndValues, associated_type.span); + // NB: not IMPORTABLE name_bindings.define_type(def, associated_type.span, - true); + PUBLIC); (associated_type.ident.name, TypeTraitItemKind) } @@ -1525,7 +1578,7 @@ impl<'a> Resolver<'a> { 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 } ItemMac(..) => parent @@ -1538,7 +1591,7 @@ impl<'a> Resolver<'a> { variant: &Variant, item_id: DefId, parent: ReducedGraphParent, - is_public: bool) { + modifiers: DefModifiers) { let name = variant.node.name.name; let is_exported = match variant.node.kind { TupleVariantKind(_) => false, @@ -1554,10 +1607,10 @@ impl<'a> Resolver<'a> { variant.span); child.define_value(DefVariant(item_id, local_def(variant.node.id), is_exported), - variant.span, is_public); + variant.span, modifiers); child.define_type(DefVariant(item_id, 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 @@ -1703,6 +1756,7 @@ impl<'a> Resolver<'a> { f: |&mut Resolver|) { let name = foreign_item.ident.name; let is_public = foreign_item.vis == ast::Public; + let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE; let name_bindings = self.add_child(name, parent, ForbidDuplicateValues, foreign_item.span); @@ -1710,7 +1764,7 @@ impl<'a> Resolver<'a> { match foreign_item.node { ForeignItemFn(_, ref generics) => { 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( HasTypeParameters(generics, @@ -1721,7 +1775,7 @@ impl<'a> Resolver<'a> { } ForeignItemStatic(_, 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) } @@ -1766,6 +1820,7 @@ impl<'a> Resolver<'a> { external crate) building external def, priv {}", vis); let is_public = vis == ast::Public; + let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE; let is_exported = is_public && match new_parent { ModuleReducedGraphParent(ref module) => { match module.def_id.get() { @@ -1779,6 +1834,7 @@ impl<'a> Resolver<'a> { } let kind = match def { + DefTy(_, true) => EnumModuleKind, DefStruct(..) | DefTy(..) => ImplModuleKind, _ => NormalModuleKind }; @@ -1813,6 +1869,7 @@ impl<'a> Resolver<'a> { match def { DefMod(_) | DefForeignMod(_) => {} + // Still here for staging DefVariant(enum_did, variant_id, is_struct) => { debug!("(building reduced graph for external crate) building \ variant {}", @@ -1822,23 +1879,36 @@ impl<'a> Resolver<'a> { // definition. let is_exported = is_public || self.external_exports.contains(&enum_did); + let modifiers = IMPORTABLE | ENUM_STAGING_HACK | if is_exported { + PUBLIC + } else { + DefModifiers::empty() + }; 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 self.structs.insert(variant_id, Vec::new()); } else { - child_name_bindings.define_value(def, DUMMY_SP, is_exported); + child_name_bindings.define_value(def, DUMMY_SP, modifiers); } } DefFn(ctor_id, true) => { child_name_bindings.define_value( 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(..) => { debug!("(building reduced graph for external \ 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) => { 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. let parent_link = self.get_parent_link(new_parent, name); @@ -1878,23 +1948,57 @@ impl<'a> Resolver<'a> { is_public, 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(..) => { debug!("(building reduced graph for external \ 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) => { debug!("(building reduced graph for external \ crate) building type and value for {}", 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| { f.name }).collect::>(); 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. @@ -2021,9 +2125,14 @@ impl<'a> Resolver<'a> { DUMMY_SP); 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( - def, DUMMY_SP, - visibility == ast::Public); + def, DUMMY_SP, modifiers); } } @@ -2394,7 +2503,7 @@ impl<'a> Resolver<'a> { fn create_name_bindings_from_module(module: Rc) -> NameBindings { NameBindings { type_def: RefCell::new(Some(TypeNsDef { - is_public: false, + modifiers: IMPORTABLE, module_def: Some(module), type_def: None, type_span: None @@ -2596,6 +2705,12 @@ impl<'a> Resolver<'a> { target, ValueNS); + self.check_that_import_is_importable( + &**name_bindings, + directive.span, + target, + ValueNS); + import_resolution.value_target = Some(Target::new(target_module.clone(), name_bindings.clone(), @@ -2619,6 +2734,12 @@ impl<'a> Resolver<'a> { target, TypeNS); + self.check_that_import_is_importable( + &**name_bindings, + directive.span, + target, + TypeNS); + import_resolution.type_target = Some(Target::new(target_module.clone(), name_bindings.clone(), @@ -2829,7 +2950,7 @@ impl<'a> Resolver<'a> { self.module_to_string(module_)); // 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"); dest_import_resolution.value_target = Some(Target::new(containing_module.clone(), @@ -2837,7 +2958,7 @@ impl<'a> Resolver<'a> { import_directive.shadowable)); 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"); dest_import_resolution.type_target = 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. fn check_for_conflicts_between_imports_and_items(&mut self, module: &Module, @@ -2918,8 +3052,8 @@ impl<'a> Resolver<'a> { match import_resolution.value_target { Some(ref target) if !target.shadowable => { match *name_bindings.value_def.borrow() { - None => {} - Some(ref value) => { + // We want to allow the "flat" def of enum variants to be shadowed + Some(ref value) if !value.modifiers.contains(ENUM_STAGING_HACK) => { let msg = format!("import `{}` conflicts with value \ in this module", token::get_name(name).get()); @@ -2933,6 +3067,7 @@ impl<'a> Resolver<'a> { } } } + _ => {} } } Some(_) | None => {} @@ -2941,8 +3076,8 @@ impl<'a> Resolver<'a> { match import_resolution.type_target { Some(ref target) if !target.shadowable => { match *name_bindings.type_def.borrow() { - None => {} - Some(ref ty) => { + // We want to allow the "flat" def of enum variants to be shadowed + Some(ref ty) if !ty.modifiers.contains(ENUM_STAGING_HACK) => { match ty.module_def { None => { let msg = format!("import `{}` conflicts with type in \ @@ -2993,6 +3128,7 @@ impl<'a> Resolver<'a> { } } } + _ => {} } } Some(_) | None => {} @@ -3131,43 +3267,28 @@ impl<'a> Resolver<'a> { return Failed(Some((span, msg))); } Some(ref module_def) => { - // If we're doing the search for an - // import, do not allow traits and impls - // to be selected. - match (name_search_type, - module_def.kind.get()) { - (ImportSearch, TraitModuleKind) | - (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_crate lint + match module_def.def_id.get() { + Some(did) => { + self.used_crates.insert(did.krate); } - (_, _) => { - search_module = module_def.clone(); + _ => {} + } - // track extern crates for unused_extern_crates lint - match module_def.def_id.get() { - Some(did) => { - self.used_crates.insert(did.krate); - } - _ => {} - } - - // Keep track of the closest - // private module used when - // 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 => {} - } + // Keep track of the closest + // private module used when + // 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 => {} } } } @@ -3388,6 +3509,7 @@ impl<'a> Resolver<'a> { } TraitModuleKind | ImplModuleKind | + EnumModuleKind | AnonymousModuleKind => { search_module = parent_module_node.upgrade().unwrap(); } @@ -3485,6 +3607,7 @@ impl<'a> Resolver<'a> { NormalModuleKind => return Some(new_module), TraitModuleKind | ImplModuleKind | + EnumModuleKind | AnonymousModuleKind => module_ = new_module, } } @@ -3500,6 +3623,7 @@ impl<'a> Resolver<'a> { NormalModuleKind => return module_, TraitModuleKind | ImplModuleKind | + EnumModuleKind | AnonymousModuleKind => { match self.get_nearest_normal_module_parent(module_.clone()) { None => module_, diff --git a/src/test/auxiliary/namespaced_enum_emulate_flat.rs b/src/test/auxiliary/namespaced_enum_emulate_flat.rs new file mode 100644 index 00000000000..3a11f30049c --- /dev/null +++ b/src/test/auxiliary/namespaced_enum_emulate_flat.rs @@ -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 or the MIT license +// , 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() {} + } +} + + diff --git a/src/test/auxiliary/namespaced_enums.rs b/src/test/auxiliary/namespaced_enums.rs new file mode 100644 index 00000000000..a6e6f9b0191 --- /dev/null +++ b/src/test/auxiliary/namespaced_enums.rs @@ -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 or the MIT license +// , 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) {} +} + diff --git a/src/test/auxiliary/use_from_trait_xc.rs b/src/test/auxiliary/use_from_trait_xc.rs index 8c547c28002..22e0d3168ca 100644 --- a/src/test/auxiliary/use_from_trait_xc.rs +++ b/src/test/auxiliary/use_from_trait_xc.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub use self::sub::Bar; +pub use self::sub::{Bar, Baz}; pub trait Trait { fn foo(); @@ -26,4 +26,10 @@ mod sub { impl Bar { pub fn new() {} } + + pub enum Baz {} + + impl Baz { + pub fn new() {} + } } diff --git a/src/test/compile-fail/enum-and-module-in-same-scope.rs b/src/test/compile-fail/enum-and-module-in-same-scope.rs index 7464764666c..7526c6753e6 100644 --- a/src/test/compile-fail/enum-and-module-in-same-scope.rs +++ b/src/test/compile-fail/enum-and-module-in-same-scope.rs @@ -13,7 +13,7 @@ mod Foo { } enum Foo { //~ ERROR duplicate definition of type or module `Foo` - X + X //~ ERROR duplicate definition of value `X` } fn main() {} diff --git a/src/test/compile-fail/namespaced-enum-glob-import-no-impls-xcrate.rs b/src/test/compile-fail/namespaced-enum-glob-import-no-impls-xcrate.rs new file mode 100644 index 00000000000..09916a11f72 --- /dev/null +++ b/src/test/compile-fail/namespaced-enum-glob-import-no-impls-xcrate.rs @@ -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 or the MIT license +// , 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` +} + diff --git a/src/test/compile-fail/namespaced-enum-glob-import-no-impls.rs b/src/test/compile-fail/namespaced-enum-glob-import-no-impls.rs new file mode 100644 index 00000000000..1554d410070 --- /dev/null +++ b/src/test/compile-fail/namespaced-enum-glob-import-no-impls.rs @@ -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 or the MIT license +// , 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` +} diff --git a/src/test/compile-fail/use-from-trait-xc.rs b/src/test/compile-fail/use-from-trait-xc.rs index cea85955d37..ff282413580 100644 --- a/src/test/compile-fail/use-from-trait-xc.rs +++ b/src/test/compile-fail/use-from-trait-xc.rs @@ -13,12 +13,15 @@ extern crate use_from_trait_xc; 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; -//~^ 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; -//~^ ERROR unresolved import `use_from_trait_xc::Bar::new`. Cannot import from a trait or type +use use_from_trait_xc::Bar::new as bnew; +//~^ ERROR `bnew` is not directly importable + +use use_from_trait_xc::Baz::new as baznew; +//~^ ERROR `baznew` is not directly importable fn main() {} diff --git a/src/test/compile-fail/use-from-trait.rs b/src/test/compile-fail/use-from-trait.rs index c9eea3c5df2..2a97155dd2e 100644 --- a/src/test/compile-fail/use-from-trait.rs +++ b/src/test/compile-fail/use-from-trait.rs @@ -9,9 +9,9 @@ // except according to those terms. 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; -//~^ ERROR unresolved import `Foo::new`. Cannot import from a trait or type implementation +//~^ ERROR `new` is not directly importable pub trait Trait { fn foo(); diff --git a/src/test/run-pass/namespaced-enum-emulate-flat-xc.rs b/src/test/run-pass/namespaced-enum-emulate-flat-xc.rs new file mode 100644 index 00000000000..540a0acb123 --- /dev/null +++ b/src/test/run-pass/namespaced-enum-emulate-flat-xc.rs @@ -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 or the MIT license +// , 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() {} + diff --git a/src/test/run-pass/namespaced-enum-emulate-flat.rs b/src/test/run-pass/namespaced-enum-emulate-flat.rs new file mode 100644 index 00000000000..2aad9bcff56 --- /dev/null +++ b/src/test/run-pass/namespaced-enum-emulate-flat.rs @@ -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 or the MIT license +// , 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() {} diff --git a/src/test/run-pass/namespaced-enum-glob-import-xcrate.rs b/src/test/run-pass/namespaced-enum-glob-import-xcrate.rs new file mode 100644 index 00000000000..35fb6676954 --- /dev/null +++ b/src/test/run-pass/namespaced-enum-glob-import-xcrate.rs @@ -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 or the MIT license +// , 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() {} diff --git a/src/test/run-pass/namespaced-enum-glob-import.rs b/src/test/run-pass/namespaced-enum-glob-import.rs new file mode 100644 index 00000000000..fe6f3427383 --- /dev/null +++ b/src/test/run-pass/namespaced-enum-glob-import.rs @@ -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 or the MIT license +// , 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() {} diff --git a/src/test/run-pass/namespaced-enums-xcrate.rs b/src/test/run-pass/namespaced-enums-xcrate.rs new file mode 100644 index 00000000000..c5f80eaea5a --- /dev/null +++ b/src/test/run-pass/namespaced-enums-xcrate.rs @@ -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 or the MIT license +// , 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() {} + diff --git a/src/test/run-pass/namespaced-enums.rs b/src/test/run-pass/namespaced-enums.rs new file mode 100644 index 00000000000..afa39c326b6 --- /dev/null +++ b/src/test/run-pass/namespaced-enums.rs @@ -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 or the MIT license +// , 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() {}