Skip to content

librustc: Disallow use from reaching into impls or traits. #6462

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
194 changes: 136 additions & 58 deletions src/librustc/middle/resolve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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.
Expand All @@ -440,6 +455,7 @@ pub enum ModuleKind {
NormalModuleKind,
ExternModuleKind,
TraitModuleKind,
ImplModuleKind,
AnonymousModuleKind,
}

Expand Down Expand Up @@ -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<node_id,@mut Module>,

// The status of resolving each import in this module.
Expand Down Expand Up @@ -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<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.
Expand Down Expand Up @@ -1228,7 +1275,7 @@ pub impl Resolver {
name_bindings.define_module(Public,
parent_link,
Some(def_id),
TraitModuleKind,
ImplModuleKind,
sp);

let new_parent = ModuleReducedGraphParent(
Expand Down Expand Up @@ -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) =
Expand All @@ -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 \
Expand Down Expand Up @@ -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 =
Expand All @@ -1780,7 +1839,7 @@ pub impl Resolver {
Public,
parent_link,
Some(def),
NormalModuleKind,
ImplModuleKind,
dummy_sp());
type_module =
child_name_bindings.
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;

Expand All @@ -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 => {
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand All @@ -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 \
Expand Down Expand Up @@ -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,
}
}
}
}
Expand All @@ -2552,31 +2627,27 @@ 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);
}

/// 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);

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -2740,6 +2811,7 @@ pub impl Resolver {
}
ExternModuleKind |
TraitModuleKind |
ImplModuleKind |
AnonymousModuleKind => {
search_module = parent_module_node;
}
Expand All @@ -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.
}
Expand Down Expand Up @@ -2840,6 +2912,7 @@ pub impl Resolver {
NormalModuleKind => return Some(new_module),
ExternModuleKind |
TraitModuleKind |
ImplModuleKind |
AnonymousModuleKind => module_ = new_module,
}
}
Expand All @@ -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
Expand Down Expand Up @@ -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);
}

Expand All @@ -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");
Expand Down Expand Up @@ -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`",
Expand Down Expand Up @@ -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`",
Expand Down
Loading