librustc: Disallow `use` from reaching into impls or traits.
This can perhaps be restored in the future. For now this is a precursor to making typedefs work as expected.
This commit is contained in:
parent
291518712f
commit
ca9bb2d9ac
|
@ -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:
|
||||
// After the first element of the path, allow searching only
|
||||
// through public identifiers.
|
||||
//
|
||||
// pub mod core {
|
||||
// pub use vec;
|
||||
// }
|
||||
//
|
||||
// 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`",
|
||||
|
|
|
@ -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),
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
pub trait Trait {
|
||||
fn foo();
|
||||
}
|
||||
|
||||
struct Foo;
|
||||
|
||||
impl Foo {
|
||||
pub fn new() {}
|
||||
}
|
||||
|
|
@ -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() {
|
||||
}
|
||||
|
|
@ -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() {}
|
||||
|
Loading…
Reference in New Issue