about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/middle/resolve.rs192
-rw-r--r--src/librustpkg/rustpkg.rc21
-rw-r--r--src/test/auxiliary/use_from_trait_xc.rs10
-rw-r--r--src/test/compile-fail/use-from-trait-xc.rs12
-rw-r--r--src/test/compile-fail/use-from-trait.rs17
5 files changed, 187 insertions, 65 deletions
diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs
index 057b85730a0..bfa4862e054 100644
--- a/src/librustc/middle/resolve.rs
+++ b/src/librustc/middle/resolve.rs
@@ -255,8 +255,20 @@ pub enum AllowCapturingSelfFlag {
 
 #[deriving(Eq)]
 enum NameSearchType {
-    SearchItemsAndPublicImports,    //< Search items and public imports.
-    SearchItemsAndAllImports,       //< Search items and all imports.
+    /// We're doing a name search in order to resolve a `use` directive.
+    ImportSearch,
+
+    /// We're doing a name search in order to resolve a path type, a path
+    /// expression, or a path pattern. We can select public or private
+    /// names.
+    ///
+    /// XXX: This should be ripped out of resolve and handled later, in
+    /// the privacy checking phase.
+    PathPublicOrPrivateSearch,
+
+    /// We're doing a name search in order to resolve a path type, a path
+    /// expression, or a path pattern. Allow only public names to be selected.
+    PathPublicOnlySearch,
 }
 
 pub enum BareIdentifierPatternResolution {
@@ -394,6 +406,7 @@ pub enum ModuleKind {
     NormalModuleKind,
     ExternModuleKind,
     TraitModuleKind,
+    ImplModuleKind,
     AnonymousModuleKind,
 }
 
@@ -424,7 +437,6 @@ pub struct Module {
     //
     // There will be an anonymous module created around `g` with the ID of the
     // entry block for `f`.
-
     anonymous_children: @mut HashMap<node_id,@mut Module>,
 
     // The status of resolving each import in this module.
@@ -514,6 +526,38 @@ pub impl NameBindings {
         }
     }
 
+    /// Sets the kind of the module, creating a new one if necessary.
+    fn set_module_kind(@mut self,
+                       privacy: Privacy,
+                       parent_link: ParentLink,
+                       def_id: Option<def_id>,
+                       kind: ModuleKind,
+                       sp: span) {
+        match self.type_def {
+            None => {
+                let module = @mut Module(parent_link, def_id, kind);
+                self.type_def = Some(TypeNsDef {
+                    privacy: privacy,
+                    module_def: Some(module),
+                    type_def: None
+                })
+            }
+            Some(type_def) => {
+                match type_def.module_def {
+                    None => {
+                        let module = @mut Module(parent_link, def_id, kind);
+                        self.type_def = Some(TypeNsDef {
+                            privacy: privacy,
+                            module_def: Some(module),
+                            type_def: type_def.type_def
+                        })
+                    }
+                    Some(module_def) => module_def.kind = kind,
+                }
+            }
+        }
+    }
+
     /// Records a type definition.
     fn define_type(@mut self, privacy: Privacy, def: def, sp: span) {
         // Merges the type with the existing type def or creates a new one.
@@ -1191,7 +1235,7 @@ pub impl Resolver {
                         name_bindings.define_module(Public,
                                                     parent_link,
                                                     Some(def_id),
-                                                    TraitModuleKind,
+                                                    ImplModuleKind,
                                                     sp);
 
                         let new_parent = ModuleReducedGraphParent(
@@ -1579,8 +1623,8 @@ pub impl Resolver {
               // If this is a trait, add all the method names
               // to the trait info.
 
-              let method_def_ids = get_trait_method_def_ids(self.session.cstore,
-                                                            def_id);
+              let method_def_ids =
+                get_trait_method_def_ids(self.session.cstore, def_id);
               let mut interned_method_names = HashSet::new();
               for method_def_ids.each |&method_def_id| {
                   let (method_name, explicit_self) =
@@ -1608,6 +1652,14 @@ pub impl Resolver {
               }
 
               child_name_bindings.define_type(Public, def, dummy_sp());
+
+              // Define a module if necessary.
+              let parent_link = self.get_parent_link(new_parent, ident);
+              child_name_bindings.set_module_kind(Public,
+                                                  parent_link,
+                                                  Some(def_id),
+                                                  TraitModuleKind,
+                                                  dummy_sp())
           }
           def_ty(_) => {
               debug!("(building reduced graph for external \
@@ -1750,6 +1802,10 @@ pub impl Resolver {
                                             // We already have a module. This
                                             // is OK.
                                             type_module = module_def;
+
+                                            // Mark it as an impl module if
+                                            // necessary.
+                                            type_module.kind = ImplModuleKind;
                                         }
                                         Some(_) | None => {
                                             let parent_link =
@@ -1759,7 +1815,7 @@ pub impl Resolver {
                                                 Public,
                                                 parent_link,
                                                 Some(def),
-                                                NormalModuleKind,
+                                                ImplModuleKind,
                                                 dummy_sp());
                                             type_module =
                                                 child_name_bindings.
@@ -1866,10 +1922,8 @@ pub impl Resolver {
     // remain or unsuccessfully when no forward progress in resolving imports
     // is made.
 
-    /**
-     * Resolves all imports for the crate. This method performs the fixed-
-     * point iteration.
-     */
+    /// Resolves all imports for the crate. This method performs the fixed-
+    /// point iteration.
     fn resolve_imports(@mut self) {
         let mut i = 0;
         let mut prev_unresolved_imports = 0;
@@ -1991,9 +2045,10 @@ pub impl Resolver {
     /// don't know whether the name exists at the moment due to other
     /// currently-unresolved imports, or success if we know the name exists.
     /// If successful, the resolved bindings are written into the module.
-    fn resolve_import_for_module(@mut self, module_: @mut Module,
+    fn resolve_import_for_module(@mut self,
+                                 module_: @mut Module,
                                  import_directive: @ImportDirective)
-                              -> ResolveResult<()> {
+                                 -> ResolveResult<()> {
         let mut resolution_result = Failed;
         let module_path = &import_directive.module_path;
 
@@ -2007,10 +2062,11 @@ pub impl Resolver {
             // Use the crate root.
             Some(self.graph_root.get_module())
         } else {
-            match self.resolve_module_path_for_import(module_,
-                                                      *module_path,
-                                                      DontUseLexicalScope,
-                                                      import_directive.span) {
+            match self.resolve_module_path(module_,
+                                           *module_path,
+                                           DontUseLexicalScope,
+                                           import_directive.span,
+                                           ImportSearch) {
 
                 Failed => None,
                 Indeterminate => {
@@ -2097,7 +2153,7 @@ pub impl Resolver {
                              target: ident,
                              source: ident,
                              span: span)
-                          -> ResolveResult<()> {
+                             -> ResolveResult<()> {
         debug!("(resolving single import) resolving `%s` = `%s::%s` from \
                 `%s`",
                *self.session.str_of(target),
@@ -2134,9 +2190,7 @@ pub impl Resolver {
         // Unless we managed to find a result in both namespaces (unlikely),
         // search imports as well.
         match (value_result, type_result) {
-            (BoundResult(*), BoundResult(*)) => {
-                // Continue.
-            }
+            (BoundResult(*), BoundResult(*)) => {} // Continue.
             _ => {
                 // If there is an unresolved glob at this point in the
                 // containing module, bail out. We don't know enough to be
@@ -2460,7 +2514,6 @@ pub impl Resolver {
         // Resolve the module part of the path. This does not involve looking
         // upward though scope chains; we simply resolve names directly in
         // modules as we go.
-
         while index < module_path_len {
             let name = module_path[index];
             match self.resolve_name_in_module(search_module,
@@ -2470,12 +2523,17 @@ pub impl Resolver {
                 Failed => {
                     let segment_name = self.session.str_of(name);
                     let module_name = self.module_to_str(search_module);
-                    if module_name == ~"???" {
-                        self.session.span_err(span {lo: span.lo, hi: span.lo +
-                                              BytePos(str::len(*segment_name)), expn_info:
-                                              span.expn_info}, fmt!("unresolved import. maybe \
-                                                                    a missing `extern mod %s`?",
-                                                                    *segment_name));
+                    if "???" == module_name {
+                        let span = span {
+                            lo: span.lo,
+                            hi: span.lo + BytePos(str::len(*segment_name)),
+                            expn_info: span.expn_info,
+                        };
+                        self.session.span_err(span,
+                                              fmt!("unresolved import. maybe \
+                                                    a missing `extern mod \
+                                                    %s`?",
+                                                    *segment_name));
                         return Failed;
                     }
                     self.session.span_err(span, fmt!("unresolved import: could not find `%s` in \
@@ -2504,8 +2562,22 @@ pub impl Resolver {
                                                                     name)));
                                     return Failed;
                                 }
-                                Some(copy module_def) => {
-                                    search_module = module_def;
+                                Some(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) {
+                                        (ImportSearch, TraitModuleKind) |
+                                        (ImportSearch, ImplModuleKind) => {
+                                            self.session.span_err(
+                                                span,
+                                                ~"cannot import from a trait \
+                                                  or type implementation");
+                                            return Failed;
+                                        }
+                                        (_, _) => search_module = module_def,
+                                    }
                                 }
                             }
                         }
@@ -2523,18 +2595,13 @@ pub impl Resolver {
 
             index += 1;
 
-            // After the first element of the path, allow searching through
-            // items and imports unconditionally. This allows things like:
-            //
-            // pub mod core {
-            //     pub use vec;
-            // }
+            // After the first element of the path, allow searching only
+            // through public identifiers.
             //
-            // pub mod something_else {
-            //     use core::vec;
-            // }
-
-            name_search_type = SearchItemsAndPublicImports;
+            // XXX: Rip this out and move it to the privacy checker.
+            if name_search_type == PathPublicOrPrivateSearch {
+                name_search_type = PathPublicOnlySearch
+            }
         }
 
         return Success(search_module);
@@ -2542,12 +2609,13 @@ pub impl Resolver {
 
     /// Attempts to resolve the module part of an import directive or path
     /// rooted at the given module.
-    fn resolve_module_path_for_import(@mut self,
-                                      module_: @mut Module,
-                                      module_path: &[ident],
-                                      use_lexical_scope: UseLexicalScopeFlag,
-                                      span: span)
-                                   -> ResolveResult<@mut Module> {
+    fn resolve_module_path(@mut self,
+                           module_: @mut Module,
+                           module_path: &[ident],
+                           use_lexical_scope: UseLexicalScopeFlag,
+                           span: span,
+                           name_search_type: NameSearchType)
+                           -> ResolveResult<@mut Module> {
         let module_path_len = module_path.len();
         assert!(module_path_len > 0);
 
@@ -2630,7 +2698,7 @@ pub impl Resolver {
                                            module_path,
                                            start_index,
                                            span,
-                                           SearchItemsAndPublicImports)
+                                           name_search_type)
     }
 
     /// Invariant: This must only be called during main resolution, not during
@@ -2722,6 +2790,7 @@ pub impl Resolver {
                                 }
                                 ExternModuleKind |
                                 TraitModuleKind |
+                                ImplModuleKind |
                                 AnonymousModuleKind => {
                                     search_module = parent_module_node;
                                 }
@@ -2741,7 +2810,7 @@ pub impl Resolver {
             match self.resolve_name_in_module(search_module,
                                               name,
                                               namespace,
-                                              SearchItemsAndAllImports) {
+                                              PathPublicOrPrivateSearch) {
                 Failed => {
                     // Continue up the search chain.
                 }
@@ -2822,6 +2891,7 @@ pub impl Resolver {
                         NormalModuleKind => return Some(new_module),
                         ExternModuleKind |
                         TraitModuleKind |
+                        ImplModuleKind |
                         AnonymousModuleKind => module_ = new_module,
                     }
                 }
@@ -2838,7 +2908,10 @@ pub impl Resolver {
                                              -> @mut Module {
         match module_.kind {
             NormalModuleKind => return module_,
-            ExternModuleKind | TraitModuleKind | AnonymousModuleKind => {
+            ExternModuleKind |
+            TraitModuleKind |
+            ImplModuleKind |
+            AnonymousModuleKind => {
                 match self.get_nearest_normal_module_parent(module_) {
                     None => module_,
                     Some(new_module) => new_module
@@ -2922,8 +2995,14 @@ pub impl Resolver {
 
         // If this is a search of all imports, we should be done with glob
         // resolution at this point.
+<<<<<<< HEAD
         if name_search_type == SearchItemsAndAllImports {
             assert_eq!(module_.glob_count, 0);
+=======
+        if name_search_type == PathPublicOrPrivateSearch ||
+                name_search_type == PathPublicOnlySearch {
+            assert!(module_.glob_count == 0);
+>>>>>>> librustc: Disallow `use` from reaching into impls or traits.
         }
 
         // Check the list of resolved imports.
@@ -2944,7 +3023,7 @@ pub impl Resolver {
                     }
                     Some(target)
                             if name_search_type ==
-                                SearchItemsAndAllImports ||
+                                PathPublicOrPrivateSearch ||
                             import_resolution.privacy == Public => {
                         debug!("(resolving name in module) resolved to \
                                 import");
@@ -4483,10 +4562,11 @@ pub impl Resolver {
         let module_path_idents = self.intern_module_part_of_path(path);
 
         let containing_module;
-        match self.resolve_module_path_for_import(self.current_module,
-                                                  module_path_idents,
-                                                  UseLexicalScope,
-                                                  path.span) {
+        match self.resolve_module_path(self.current_module,
+                                       module_path_idents,
+                                       UseLexicalScope,
+                                       path.span,
+                                       PathPublicOnlySearch) {
             Failed => {
                 self.session.span_err(path.span,
                                       fmt!("use of undeclared module `%s`",
@@ -4535,7 +4615,7 @@ pub impl Resolver {
                                                  module_path_idents,
                                                  0,
                                                  path.span,
-                                                 SearchItemsAndAllImports) {
+                                                 PathPublicOrPrivateSearch) {
             Failed => {
                 self.session.span_err(path.span,
                                       fmt!("use of undeclared module `::%s`",
diff --git a/src/librustpkg/rustpkg.rc b/src/librustpkg/rustpkg.rc
index 94fdcddfbb5..19dc973a4a1 100644
--- a/src/librustpkg/rustpkg.rc
+++ b/src/librustpkg/rustpkg.rc
@@ -602,7 +602,6 @@ impl PkgSrc {
     /// Infers crates to build. Called only in the case where there
     /// is no custom build logic
     fn find_crates(&mut self) {
-        use PkgSrc::push_crate;
         use conditions::missing_pkg_files::cond;
 
         let dir = self.check_dir();
@@ -610,14 +609,18 @@ impl PkgSrc {
         debug!("Matching against %?", self.id.local_path.filestem());
         for os::walk_dir(&dir) |pth| {
             match pth.filename() {
-                Some(~"lib.rs") => push_crate(&mut self.libs,
-                                              prefix, pth),
-                Some(~"main.rs") => push_crate(&mut self.mains,
-                                               prefix, pth),
-                Some(~"test.rs") => push_crate(&mut self.tests,
-                                               prefix, pth),
-                Some(~"bench.rs") => push_crate(&mut self.benchs,
-                                                prefix, pth),
+                Some(~"lib.rs") => PkgSrc::push_crate(&mut self.libs,
+                                                      prefix,
+                                                      pth),
+                Some(~"main.rs") => PkgSrc::push_crate(&mut self.mains,
+                                                       prefix,
+                                                       pth),
+                Some(~"test.rs") => PkgSrc::push_crate(&mut self.tests,
+                                                       prefix,
+                                                       pth),
+                Some(~"bench.rs") => PkgSrc::push_crate(&mut self.benchs,
+                                                        prefix,
+                                                        pth),
                 _ => ()
             }
         }
diff --git a/src/test/auxiliary/use_from_trait_xc.rs b/src/test/auxiliary/use_from_trait_xc.rs
new file mode 100644
index 00000000000..2ab95c271ae
--- /dev/null
+++ b/src/test/auxiliary/use_from_trait_xc.rs
@@ -0,0 +1,10 @@
+pub trait Trait {
+    fn foo();
+}
+
+struct Foo;
+
+impl Foo {
+    pub fn new() {}
+}
+
diff --git a/src/test/compile-fail/use-from-trait-xc.rs b/src/test/compile-fail/use-from-trait-xc.rs
new file mode 100644
index 00000000000..56805f58ad2
--- /dev/null
+++ b/src/test/compile-fail/use-from-trait-xc.rs
@@ -0,0 +1,12 @@
+// aux-build:use_from_trait_xc.rs
+
+extern mod use_from_trait_xc;
+
+use use_from_trait_xc::Trait::foo;  //~ ERROR cannot import from a trait or type implementation
+//~^ ERROR failed to resolve import
+use use_from_trait_xc::Foo::new;    //~ ERROR cannot import from a trait or type implementation
+//~^ ERROR failed to resolve import
+
+fn main() {
+}
+
diff --git a/src/test/compile-fail/use-from-trait.rs b/src/test/compile-fail/use-from-trait.rs
new file mode 100644
index 00000000000..10a30f0a266
--- /dev/null
+++ b/src/test/compile-fail/use-from-trait.rs
@@ -0,0 +1,17 @@
+use Trait::foo;  //~ ERROR cannot import from a trait or type implementation
+//~^ ERROR failed to resolve import
+use Foo::new;    //~ ERROR cannot import from a trait or type implementation
+//~^ ERROR failed to resolve import
+
+pub trait Trait {
+    fn foo();
+}
+
+struct Foo;
+
+impl Foo {
+    fn new() {}
+}
+
+fn main() {}
+