about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSteven Fackler <sfackler@gmail.com>2014-10-18 23:46:08 -0700
committerSteven Fackler <sfackler@gmail.com>2014-10-31 20:43:35 -0700
commitd7ff7da65a1e8e45cbbec7cd487773ee468e12ed (patch)
treef151ea585ee27632b583cc051f4c993767a4eae8
parent88b6e93d35c34e143ba060a617e71c8af10fa15e (diff)
downloadrust-d7ff7da65a1e8e45cbbec7cd487773ee468e12ed.tar.gz
rust-d7ff7da65a1e8e45cbbec7cd487773ee468e12ed.zip
First stage of enum namespacing changes
-rw-r--r--src/librustc/metadata/csearch.rs7
-rw-r--r--src/librustc/metadata/decoder.rs18
-rw-r--r--src/librustc/middle/resolve.rs296
-rw-r--r--src/test/auxiliary/namespaced_enum_emulate_flat.rs38
-rw-r--r--src/test/auxiliary/namespaced_enums.rs22
-rw-r--r--src/test/auxiliary/use_from_trait_xc.rs8
-rw-r--r--src/test/compile-fail/enum-and-module-in-same-scope.rs2
-rw-r--r--src/test/compile-fail/namespaced-enum-glob-import-no-impls-xcrate.rs28
-rw-r--r--src/test/compile-fail/namespaced-enum-glob-import-no-impls.rs36
-rw-r--r--src/test/compile-fail/use-from-trait-xc.rs11
-rw-r--r--src/test/compile-fail/use-from-trait.rs4
-rw-r--r--src/test/run-pass/namespaced-enum-emulate-flat-xc.rs32
-rw-r--r--src/test/run-pass/namespaced-enum-emulate-flat.rs51
-rw-r--r--src/test/run-pass/namespaced-enum-glob-import-xcrate.rs34
-rw-r--r--src/test/run-pass/namespaced-enum-glob-import.rs42
-rw-r--r--src/test/run-pass/namespaced-enums-xcrate.rs25
-rw-r--r--src/test/run-pass/namespaced-enums.rs24
17 files changed, 584 insertions, 94 deletions
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<Rc<ty::VariantInfo>> {
     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<IdentInterner>, cdata: Cmd, id: ast::NodeId,
                      tcx: &ty::ctxt) -> Vec<Rc<ty::VariantInfo>> {
     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<Rc<Module>>,
     type_def: Option<Def>,
     type_span: Option<Span>
@@ -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<Span>,
 }
@@ -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::<Vec<_>>();
 
             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<Module>) -> 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 <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() {}
+    }
+}
+
+
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 <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) {}
+}
+
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 <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`
+}
+
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 <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`
+}
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 <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() {}
+
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 <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() {}
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 <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() {}
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 <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() {}
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 <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() {}
+
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 <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() {}