diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index d2c8320d8baf5..7eed50855c436 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -290,8 +290,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 { @@ -425,7 +437,10 @@ pub struct ImportState { } pub fn ImportState() -> ImportState { - ImportState{ used: false, warned: false } + ImportState { + used: false, + warned: false, + } } /// The link from a module up to its nearest parent node. @@ -440,6 +455,7 @@ pub enum ModuleKind { NormalModuleKind, ExternModuleKind, TraitModuleKind, + ImplModuleKind, AnonymousModuleKind, } @@ -470,7 +486,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, // The status of resolving each import in this module. @@ -562,6 +577,38 @@ pub impl NameBindings { self.type_span = Some(sp); } + /// 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, + 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. @@ -1228,7 +1275,7 @@ pub impl Resolver { name_bindings.define_module(Public, parent_link, Some(def_id), - TraitModuleKind, + ImplModuleKind, sp); let new_parent = ModuleReducedGraphParent( @@ -1608,8 +1655,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, self_ty) = @@ -1629,6 +1676,14 @@ pub impl Resolver { self.trait_info.insert(def_id, interned_method_names); 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 \ @@ -1771,6 +1826,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 = @@ -1780,7 +1839,7 @@ pub impl Resolver { Public, parent_link, Some(def), - NormalModuleKind, + ImplModuleKind, dummy_sp()); type_module = child_name_bindings. @@ -1891,10 +1950,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; @@ -2016,9 +2073,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; @@ -2032,10 +2090,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 => { @@ -2122,7 +2181,7 @@ pub impl Resolver { containing_module: @mut Module, target: ident, source: ident) - -> ResolveResult<()> { + -> ResolveResult<()> { debug!("(resolving single import) resolving `%s` = `%s::%s` from \ `%s`", *self.session.str_of(target), @@ -2159,9 +2218,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 @@ -2489,7 +2546,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, @@ -2499,12 +2555,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 \ @@ -2533,8 +2594,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, + } } } } @@ -2552,18 +2627,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); @@ -2571,12 +2641,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); @@ -2648,7 +2719,7 @@ pub impl Resolver { module_path, start_index, span, - SearchItemsAndPublicImports) + name_search_type) } /// Invariant: This must only be called during main resolution, not during @@ -2740,6 +2811,7 @@ pub impl Resolver { } ExternModuleKind | TraitModuleKind | + ImplModuleKind | AnonymousModuleKind => { search_module = parent_module_node; } @@ -2759,7 +2831,7 @@ pub impl Resolver { match self.resolve_name_in_module(search_module, name, namespace, - SearchItemsAndAllImports) { + PathPublicOrPrivateSearch) { Failed => { // Continue up the search chain. } @@ -2840,6 +2912,7 @@ pub impl Resolver { NormalModuleKind => return Some(new_module), ExternModuleKind | TraitModuleKind | + ImplModuleKind | AnonymousModuleKind => module_ = new_module, } } @@ -2856,7 +2929,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 @@ -2940,7 +3016,8 @@ pub impl Resolver { // If this is a search of all imports, we should be done with glob // resolution at this point. - if name_search_type == SearchItemsAndAllImports { + if name_search_type == PathPublicOrPrivateSearch || + name_search_type == PathPublicOnlySearch { assert!(module_.glob_count == 0); } @@ -2962,7 +3039,7 @@ pub impl Resolver { } Some(target) if name_search_type == - SearchItemsAndAllImports || + PathPublicOrPrivateSearch || import_resolution.privacy == Public => { debug!("(resolving name in module) resolved to \ import"); @@ -4488,10 +4565,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`", @@ -4540,7 +4618,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 502f34a4d9e47..95fba0fa227a4 100644 --- a/src/librustpkg/rustpkg.rc +++ b/src/librustpkg/rustpkg.rc @@ -712,7 +712,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(); @@ -720,14 +719,18 @@ impl PkgSrc { debug!("Matching against %?", self.id.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 0000000000000..2ab95c271aec7 --- /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 0000000000000..56805f58ad29a --- /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 0000000000000..10a30f0a266b3 --- /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() {} +