Auto merge of #32328 - jseyfried:coherence, r=nikomatsakis

resolve: Improve import failure detection and lay groundwork for RFC 1422

This PR improves import failure detection and lays some groundwork for RFC 1422.
More specifically, it
 - Avoids recomputing the resolution of an import directive's module path.
 - Refactors code in `resolve_imports` that does not scale to the arbitrarily many levels of visibility that will be required by RFC 1422.
  - Replaces `ModuleS`'s fields `public_glob_count`, `private_glob_count`, and `resolved_globs` with a list of glob import directives `globs`.
  - Replaces `NameResolution`'s fields `pub_outstanding_references` and `outstanding_references` with a field `single_imports` of a newly defined type `SingleImports`.
 - Improves import failure detection by detecting cycles that include single imports (currently, only cycles of globs are detected). This fixes #32119.

r? @nikomatsakis
This commit is contained in:
bors 2016-04-04 21:50:05 -07:00
commit 7fd331e166
4 changed files with 207 additions and 207 deletions

View file

@ -14,8 +14,7 @@
//! any imports resolved.
use DefModifiers;
use resolve_imports::ImportDirective;
use resolve_imports::ImportDirectiveSubclass::{self, SingleImport, GlobImport};
use resolve_imports::ImportDirectiveSubclass::{self, GlobImport};
use Module;
use Namespace::{self, TypeNS, ValueNS};
use {NameBinding, NameBindingKind};
@ -28,7 +27,7 @@ use rustc::middle::def::*;
use rustc::middle::def_id::{CRATE_DEF_INDEX, DefId};
use rustc::ty::VariantKind;
use syntax::ast::{Name, NodeId};
use syntax::ast::Name;
use syntax::attr::AttrMetaMethods;
use syntax::parse::token::special_idents;
use syntax::codemap::{Span, DUMMY_SP};
@ -152,8 +151,8 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
}
let subclass = ImportDirectiveSubclass::single(binding, source_name);
self.build_import_directive(parent,
module_path,
self.unresolved_imports += 1;
parent.add_import_directive(module_path,
subclass,
view_path.span,
item.id,
@ -203,8 +202,8 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
}
};
let subclass = ImportDirectiveSubclass::single(rename, name);
self.build_import_directive(parent,
module_path,
self.unresolved_imports += 1;
parent.add_import_directive(module_path,
subclass,
source_item.span,
source_item.node.id(),
@ -213,8 +212,8 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
}
}
ViewPathGlob(_) => {
self.build_import_directive(parent,
module_path,
self.unresolved_imports += 1;
parent.add_import_directive(module_path,
GlobImport,
view_path.span,
item.id,
@ -521,39 +520,6 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
}
}
/// Creates and adds an import directive to the given module.
fn build_import_directive(&mut self,
module_: Module<'b>,
module_path: Vec<Name>,
subclass: ImportDirectiveSubclass,
span: Span,
id: NodeId,
is_public: bool,
is_prelude: bool) {
// Bump the reference count on the name. Or, if this is a glob, set
// the appropriate flag.
match subclass {
SingleImport { target, .. } => {
module_.increment_outstanding_references_for(target, ValueNS, is_public);
module_.increment_outstanding_references_for(target, TypeNS, is_public);
}
GlobImport if !is_prelude => {
// Set the glob flag. This tells us that we don't know the
// module's exports ahead of time.
module_.inc_glob_count(is_public)
}
// Prelude imports are not included in the glob counts since they do not get added to
// `resolved_globs` -- they are handled separately in `resolve_imports`.
GlobImport => {}
}
let directive =
ImportDirective::new(module_path, subclass, span, id, is_public, is_prelude);
module_.add_import_directive(directive);
self.unresolved_imports += 1;
}
/// Ensures that the reduced graph rooted at the given external module
/// is built, building it if it is not.
pub fn populate_module_if_necessary(&mut self, module: Module<'b>) {

View file

@ -828,8 +828,8 @@ pub struct ModuleS<'a> {
// is the NodeId of the local `extern crate` item (otherwise, `extern_crate_id` is None).
extern_crate_id: Option<NodeId>,
resolutions: RefCell<HashMap<(Name, Namespace), NameResolution<'a>>>,
unresolved_imports: RefCell<Vec<&'a ImportDirective>>,
resolutions: RefCell<HashMap<(Name, Namespace), &'a RefCell<NameResolution<'a>>>>,
unresolved_imports: RefCell<Vec<&'a ImportDirective<'a>>>,
// The module children of this node, including normal modules and anonymous modules.
// Anonymous children are pseudo-modules that are implicitly created around items
@ -849,14 +849,8 @@ pub struct ModuleS<'a> {
prelude: RefCell<Option<Module<'a>>>,
glob_importers: RefCell<Vec<(Module<'a>, &'a ImportDirective)>>,
resolved_globs: RefCell<(Vec<Module<'a>> /* public */, Vec<Module<'a>> /* private */)>,
// The number of public glob imports in this module.
public_glob_count: Cell<usize>,
// The number of private glob imports in this module.
private_glob_count: Cell<usize>,
glob_importers: RefCell<Vec<(Module<'a>, &'a ImportDirective<'a>)>>,
globs: RefCell<Vec<&'a ImportDirective<'a>>>,
// Whether this module is populated. If not populated, any attempt to
// access the children must be preceded with a
@ -884,22 +878,15 @@ impl<'a> ModuleS<'a> {
module_children: RefCell::new(NodeMap()),
prelude: RefCell::new(None),
glob_importers: RefCell::new(Vec::new()),
resolved_globs: RefCell::new((Vec::new(), Vec::new())),
public_glob_count: Cell::new(0),
private_glob_count: Cell::new(0),
globs: RefCell::new((Vec::new())),
populated: Cell::new(!external),
arenas: arenas
}
}
fn add_import_directive(&self, import_directive: ImportDirective) {
let import_directive = self.arenas.alloc_import_directive(import_directive);
self.unresolved_imports.borrow_mut().push(import_directive);
}
fn for_each_child<F: FnMut(Name, Namespace, &'a NameBinding<'a>)>(&self, mut f: F) {
for (&(name, ns), name_resolution) in self.resolutions.borrow().iter() {
name_resolution.binding.map(|binding| f(name, ns, binding));
name_resolution.borrow().binding.map(|binding| f(name, ns, binding));
}
}
@ -929,11 +916,6 @@ impl<'a> ModuleS<'a> {
_ => false,
}
}
fn inc_glob_count(&self, is_public: bool) {
let glob_count = if is_public { &self.public_glob_count } else { &self.private_glob_count };
glob_count.set(glob_count.get() + 1);
}
}
impl<'a> fmt::Debug for ModuleS<'a> {
@ -1135,7 +1117,8 @@ pub struct Resolver<'a, 'tcx: 'a> {
struct ResolverArenas<'a> {
modules: arena::TypedArena<ModuleS<'a>>,
name_bindings: arena::TypedArena<NameBinding<'a>>,
import_directives: arena::TypedArena<ImportDirective>,
import_directives: arena::TypedArena<ImportDirective<'a>>,
name_resolutions: arena::TypedArena<RefCell<NameResolution<'a>>>,
}
impl<'a> ResolverArenas<'a> {
@ -1145,9 +1128,13 @@ impl<'a> ResolverArenas<'a> {
fn alloc_name_binding(&'a self, name_binding: NameBinding<'a>) -> &'a NameBinding<'a> {
self.name_bindings.alloc(name_binding)
}
fn alloc_import_directive(&'a self, import_directive: ImportDirective) -> &'a ImportDirective {
fn alloc_import_directive(&'a self, import_directive: ImportDirective<'a>)
-> &'a ImportDirective {
self.import_directives.alloc(import_directive)
}
fn alloc_name_resolution(&'a self) -> &'a RefCell<NameResolution<'a>> {
self.name_resolutions.alloc(Default::default())
}
}
#[derive(PartialEq)]
@ -1216,6 +1203,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
modules: arena::TypedArena::new(),
name_bindings: arena::TypedArena::new(),
import_directives: arena::TypedArena::new(),
name_resolutions: arena::TypedArena::new(),
}
}

View file

@ -30,7 +30,7 @@ use syntax::codemap::Span;
use syntax::util::lev_distance::find_best_match_for_name;
use std::mem::replace;
use std::cell::Cell;
use std::cell::{Cell, RefCell};
/// Contains data for specific types of import directives.
#[derive(Clone, Debug)]
@ -57,8 +57,9 @@ impl ImportDirectiveSubclass {
/// One import directive.
#[derive(Debug,Clone)]
pub struct ImportDirective {
pub struct ImportDirective<'a> {
module_path: Vec<Name>,
target_module: Cell<Option<Module<'a>>>, // the resolution of `module_path`
subclass: ImportDirectiveSubclass,
span: Span,
id: NodeId,
@ -66,29 +67,11 @@ pub struct ImportDirective {
is_prelude: bool,
}
impl ImportDirective {
pub fn new(module_path: Vec<Name>,
subclass: ImportDirectiveSubclass,
span: Span,
id: NodeId,
is_public: bool,
is_prelude: bool)
-> ImportDirective {
ImportDirective {
module_path: module_path,
subclass: subclass,
span: span,
id: id,
is_public: is_public,
is_prelude: is_prelude,
}
}
impl<'a> ImportDirective<'a> {
// Given the binding to which this directive resolves in a particular namespace,
// this returns the binding for the name this directive defines in that namespace.
fn import<'a>(&self,
binding: &'a NameBinding<'a>,
privacy_error: Option<Box<PrivacyError<'a>>>) -> NameBinding<'a> {
fn import(&self, binding: &'a NameBinding<'a>, privacy_error: Option<Box<PrivacyError<'a>>>)
-> NameBinding<'a> {
let mut modifiers = match self.is_public {
true => DefModifiers::PUBLIC | DefModifiers::IMPORTABLE,
false => DefModifiers::empty(),
@ -110,17 +93,52 @@ impl ImportDirective {
}
#[derive(Clone, Default)]
/// Records information about the resolution of a name in a module.
/// Records information about the resolution of a name in a namespace of a module.
pub struct NameResolution<'a> {
/// The number of unresolved single imports of any visibility that could define the name.
outstanding_references: u32,
/// The number of unresolved `pub` single imports that could define the name.
pub_outstanding_references: u32,
/// The single imports that define the name in the namespace.
single_imports: SingleImports<'a>,
/// The least shadowable known binding for this name, or None if there are no known bindings.
pub binding: Option<&'a NameBinding<'a>>,
duplicate_globs: Vec<&'a NameBinding<'a>>,
}
#[derive(Clone, Debug)]
enum SingleImports<'a> {
/// No single imports can define the name in the namespace.
None,
/// Only the given single import can define the name in the namespace.
MaybeOne(&'a ImportDirective<'a>),
/// At least one single import will define the name in the namespace.
AtLeastOne,
}
impl<'a> Default for SingleImports<'a> {
fn default() -> Self {
SingleImports::None
}
}
impl<'a> SingleImports<'a> {
fn add_directive(&mut self, directive: &'a ImportDirective<'a>) {
match *self {
SingleImports::None => *self = SingleImports::MaybeOne(directive),
// If two single imports can define the name in the namespace, we can assume that at
// least one of them will define it since otherwise both would have to define only one
// namespace, leading to a duplicate error.
SingleImports::MaybeOne(_) => *self = SingleImports::AtLeastOne,
SingleImports::AtLeastOne => {}
};
}
fn directive_failed(&mut self) {
match *self {
SingleImports::None => unreachable!(),
SingleImports::MaybeOne(_) => *self = SingleImports::None,
SingleImports::AtLeastOne => {}
}
}
}
impl<'a> NameResolution<'a> {
fn try_define(&mut self, binding: &'a NameBinding<'a>) -> Result<(), &'a NameBinding<'a>> {
if let Some(old_binding) = self.binding {
@ -139,40 +157,54 @@ impl<'a> NameResolution<'a> {
Ok(())
}
// Returns the binding for the name if it is known or None if it not known.
fn binding(&self) -> Option<&'a NameBinding<'a>> {
self.binding.and_then(|binding| match self.single_imports {
SingleImports::None => Some(binding),
_ if !binding.defined_with(DefModifiers::GLOB_IMPORTED) => Some(binding),
_ => None, // The binding could be shadowed by a single import, so it is not known.
})
}
// Returns Some(the resolution of the name), or None if the resolution depends
// on whether more globs can define the name.
fn try_result(&self, allow_private_imports: bool)
fn try_result(&self, ns: Namespace, allow_private_imports: bool)
-> Option<ResolveResult<&'a NameBinding<'a>>> {
match self.binding {
Some(binding) if !binding.defined_with(DefModifiers::GLOB_IMPORTED) =>
Some(Success(binding)),
// If (1) we don't allow private imports, (2) no public single import can define the
// name, and (3) no public glob has defined the name, the resolution depends on globs.
_ if !allow_private_imports && self.pub_outstanding_references == 0 &&
!self.binding.map(NameBinding::is_public).unwrap_or(false) => None,
_ if self.outstanding_references > 0 => Some(Indeterminate),
Some(binding) => Some(Success(binding)),
None => None,
}
}
fn increment_outstanding_references(&mut self, is_public: bool) {
self.outstanding_references += 1;
if is_public {
self.pub_outstanding_references += 1;
}
}
fn decrement_outstanding_references(&mut self, is_public: bool) {
let decrement_references = |count: &mut _| {
assert!(*count > 0);
*count -= 1;
return Some(Success(binding)),
_ => {} // Items and single imports are not shadowable
};
decrement_references(&mut self.outstanding_references);
if is_public {
decrement_references(&mut self.pub_outstanding_references);
// Check if a single import can still define the name.
match self.single_imports {
SingleImports::None => {},
SingleImports::AtLeastOne => return Some(Indeterminate),
SingleImports::MaybeOne(directive) => {
// If (1) we don't allow private imports, (2) no public single import can define
// the name, and (3) no public glob has defined the name, the resolution depends
// on whether more globs can define the name.
if !allow_private_imports && !directive.is_public &&
!self.binding.map(NameBinding::is_public).unwrap_or(false) {
return None;
}
let target_module = match directive.target_module.get() {
Some(target_module) => target_module,
None => return Some(Indeterminate),
};
let name = match directive.subclass {
SingleImport { source, .. } => source,
GlobImport => unreachable!(),
};
match target_module.resolve_name(name, ns, false) {
Failed(_) => {}
_ => return Some(Indeterminate),
}
}
}
self.binding.map(Success)
}
fn report_conflicts<F: FnMut(&NameBinding, &NameBinding)>(&self, mut report: F) {
@ -195,15 +227,20 @@ impl<'a> NameResolution<'a> {
}
impl<'a> ::ModuleS<'a> {
fn resolution(&self, name: Name, ns: Namespace) -> &'a RefCell<NameResolution<'a>> {
*self.resolutions.borrow_mut().entry((name, ns))
.or_insert_with(|| self.arenas.alloc_name_resolution())
}
pub fn resolve_name(&self, name: Name, ns: Namespace, allow_private_imports: bool)
-> ResolveResult<&'a NameBinding<'a>> {
let resolutions = match self.resolutions.borrow_state() {
::std::cell::BorrowState::Unused => self.resolutions.borrow(),
_ => return Failed(None), // This happens when there is a cycle of glob imports
let resolution = self.resolution(name, ns);
let resolution = match resolution.borrow_state() {
::std::cell::BorrowState::Unused => resolution.borrow_mut(),
_ => return Failed(None), // This happens when there is a cycle of imports
};
let resolution = resolutions.get(&(name, ns)).cloned().unwrap_or_default();
if let Some(result) = resolution.try_result(allow_private_imports) {
if let Some(result) = resolution.try_result(ns, allow_private_imports) {
// If the resolution doesn't depend on glob definability, check privacy and return.
return result.and_then(|binding| {
let allowed = allow_private_imports || !binding.is_import() || binding.is_public();
@ -211,29 +248,15 @@ impl<'a> ::ModuleS<'a> {
});
}
let (ref mut public_globs, ref mut private_globs) = *self.resolved_globs.borrow_mut();
// Check if the public globs are determined
if public_globs.len() < self.public_glob_count.get() {
return Indeterminate;
}
for module in public_globs.iter() {
if let Indeterminate = module.resolve_name(name, ns, false) {
return Indeterminate;
}
}
if !allow_private_imports {
return Failed(None);
}
// Check if the private globs are determined
if private_globs.len() < self.private_glob_count.get() {
return Indeterminate;
}
for module in private_globs.iter() {
if let Indeterminate = module.resolve_name(name, ns, false) {
return Indeterminate;
// Check if the globs are determined
for directive in self.globs.borrow().iter() {
if !allow_private_imports && !directive.is_public { continue }
match directive.target_module.get() {
None => return Indeterminate,
Some(target_module) => match target_module.resolve_name(name, ns, false) {
Indeterminate => return Indeterminate,
_ => {}
}
}
}
@ -243,7 +266,7 @@ impl<'a> ::ModuleS<'a> {
// Invariant: this may not be called until import resolution is complete.
pub fn resolve_name_in_lexical_scope(&self, name: Name, ns: Namespace)
-> Option<&'a NameBinding<'a>> {
self.resolutions.borrow().get(&(name, ns)).and_then(|resolution| resolution.binding)
self.resolution(name, ns).borrow().binding
.or_else(|| self.prelude.borrow().and_then(|prelude| {
prelude.resolve_name(name, ns, false).success()
}))
@ -258,9 +281,36 @@ impl<'a> ::ModuleS<'a> {
})
}
pub fn increment_outstanding_references_for(&self, name: Name, ns: Namespace, is_public: bool) {
self.resolutions.borrow_mut().entry((name, ns)).or_insert_with(Default::default)
.increment_outstanding_references(is_public);
pub fn add_import_directive(&self,
module_path: Vec<Name>,
subclass: ImportDirectiveSubclass,
span: Span,
id: NodeId,
is_public: bool,
is_prelude: bool) {
let directive = self.arenas.alloc_import_directive(ImportDirective {
module_path: module_path,
target_module: Cell::new(None),
subclass: subclass,
span: span,
id: id,
is_public: is_public,
is_prelude: is_prelude,
});
self.unresolved_imports.borrow_mut().push(directive);
match directive.subclass {
SingleImport { target, .. } => {
for &ns in &[ValueNS, TypeNS] {
self.resolution(target, ns).borrow_mut().single_imports
.add_directive(directive);
}
}
// We don't add prelude imports to the globs since they only affect lexical scopes,
// which are not relevant to import resolution.
GlobImport if directive.is_prelude => {}
GlobImport => self.globs.borrow_mut().push(directive),
}
}
// Use `update` to mutate the resolution for the name.
@ -268,13 +318,12 @@ impl<'a> ::ModuleS<'a> {
fn update_resolution<T, F>(&self, name: Name, ns: Namespace, update: F) -> T
where F: FnOnce(&mut NameResolution<'a>) -> T
{
let mut resolutions = self.resolutions.borrow_mut();
let resolution = resolutions.entry((name, ns)).or_insert_with(Default::default);
let was_success = resolution.try_result(false).and_then(ResolveResult::success).is_some();
let mut resolution = &mut *self.resolution(name, ns).borrow_mut();
let was_known = resolution.binding().is_some();
let t = update(resolution);
if !was_success {
if let Some(Success(binding)) = resolution.try_result(false) {
if !was_known {
if let Some(binding) = resolution.binding() {
self.define_in_glob_importers(name, ns, binding);
}
}
@ -292,7 +341,7 @@ impl<'a> ::ModuleS<'a> {
struct ImportResolvingError<'a> {
/// Module where the error happened
source_module: Module<'a>,
import_directive: &'a ImportDirective,
import_directive: &'a ImportDirective<'a>,
span: Span,
help: String,
}
@ -424,19 +473,23 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
/// 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(&mut self, directive: &'b ImportDirective) -> ResolveResult<()> {
fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> ResolveResult<()> {
debug!("(resolving import for module) resolving import `{}::...` in `{}`",
names_to_string(&directive.module_path),
module_to_string(self.resolver.current_module));
let target_module = match self.resolver.resolve_module_path(&directive.module_path,
DontUseLexicalScope,
directive.span) {
Success(module) => module,
Indeterminate => return Indeterminate,
Failed(err) => return Failed(err),
let target_module = match directive.target_module.get() {
Some(module) => module,
_ => match self.resolver.resolve_module_path(&directive.module_path,
DontUseLexicalScope,
directive.span) {
Success(module) => module,
Indeterminate => return Indeterminate,
Failed(err) => return Failed(err),
},
};
directive.target_module.set(Some(target_module));
let (source, target, value_determined, type_determined) = match directive.subclass {
SingleImport { source, target, ref value_determined, ref type_determined } =>
(source, target, value_determined, type_determined),
@ -444,26 +497,12 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
};
// We need to resolve both namespaces for this to succeed.
let module_ = self.resolver.current_module;
let (value_result, type_result) = {
let mut resolve_in_ns = |ns, determined: bool| {
// Temporarily count the directive as determined so that the resolution fails
// (as opposed to being indeterminate) when it can only be defined by the directive.
if !determined {
module_.resolutions.borrow_mut().get_mut(&(target, ns)).unwrap()
.decrement_outstanding_references(directive.is_public);
}
let result =
self.resolver.resolve_name_in_module(target_module, source, ns, false, true);
if !determined {
module_.increment_outstanding_references_for(target, ns, directive.is_public)
}
result
};
(resolve_in_ns(ValueNS, value_determined.get()),
resolve_in_ns(TypeNS, type_determined.get()))
};
let value_result =
self.resolver.resolve_name_in_module(target_module, source, ValueNS, false, true);
let type_result =
self.resolver.resolve_name_in_module(target_module, source, TypeNS, false, true);
let module_ = self.resolver.current_module;
for &(ns, result, determined) in &[(ValueNS, &value_result, value_determined),
(TypeNS, &type_result, type_determined)] {
if determined.get() { continue }
@ -488,18 +527,24 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
let binding = &directive.import(binding, None);
self.resolver.report_conflict(module_, target, ns, binding, old_binding);
}
} else {
module_.update_resolution(target, ns, |resolution| {
resolution.single_imports.directive_failed();
});
}
module_.update_resolution(target, ns, |resolution| {
resolution.decrement_outstanding_references(directive.is_public);
})
}
match (&value_result, &type_result) {
(&Indeterminate, _) | (_, &Indeterminate) => return Indeterminate,
(&Failed(_), &Failed(_)) => {
let children = target_module.resolutions.borrow();
let names = children.keys().map(|&(ref name, _)| name);
let resolutions = target_module.resolutions.borrow();
let names = resolutions.iter().filter_map(|(&(ref name, _), resolution)| {
match *resolution.borrow() {
NameResolution { binding: Some(_), .. } => Some(name),
NameResolution { single_imports: SingleImports::None, .. } => None,
_ => Some(name),
}
});
let lev_suggestion = match find_best_match_for_name(names, &source.as_str(), None) {
Some(name) => format!(". Did you mean to use `{}`?", name),
None => "".to_owned(),
@ -579,7 +624,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
// succeeds or bails out (as importing * from an empty module or a module
// that exports nothing is valid). target_module is the module we are
// actually importing, i.e., `foo` in `use foo::*`.
fn resolve_glob_import(&mut self, target_module: Module<'b>, directive: &'b ImportDirective)
fn resolve_glob_import(&mut self, target_module: Module<'b>, directive: &'b ImportDirective<'b>)
-> ResolveResult<()> {
if let Some(Def::Trait(_)) = target_module.def {
self.resolver.session.span_err(directive.span, "items in traits are not importable.");
@ -598,15 +643,11 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
return Success(());
}
// Add to target_module's glob_importers and module_'s resolved_globs
// Add to target_module's glob_importers
target_module.glob_importers.borrow_mut().push((module_, directive));
match *module_.resolved_globs.borrow_mut() {
(ref mut public_globs, _) if directive.is_public => public_globs.push(target_module),
(_, ref mut private_globs) => private_globs.push(target_module),
}
for (&(name, ns), resolution) in target_module.resolutions.borrow().iter() {
if let Some(Success(binding)) = resolution.try_result(false) {
if let Some(binding) = resolution.borrow().binding() {
if binding.defined_with(DefModifiers::IMPORTABLE | DefModifiers::PUBLIC) {
let _ = module_.try_define_child(name, ns, directive.import(binding, None));
}
@ -630,11 +671,11 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
// reporting conflicts, reporting the PRIVATE_IN_PUBLIC lint, and reporting unresolved imports.
fn finalize_resolutions(&mut self, module: Module<'b>, report_unresolved_imports: bool) {
// Since import resolution is finished, globs will not define any more names.
module.public_glob_count.set(0); module.private_glob_count.set(0);
*module.resolved_globs.borrow_mut() = (Vec::new(), Vec::new());
*module.globs.borrow_mut() = Vec::new();
let mut reexports = Vec::new();
for (&(name, ns), resolution) in module.resolutions.borrow().iter() {
let resolution = resolution.borrow();
resolution.report_conflicts(|b1, b2| {
self.resolver.report_conflict(module, name, ns, b1, b2)
});

View file

@ -9,15 +9,20 @@
// except according to those terms.
#![feature(rustc_attrs)]
#![allow(unused_imports)]
pub type Type = i32;
pub type T = ();
mod foo { pub use super::T; }
mod bar { pub use super::T; }
mod one { use super::Type; }
pub use self::one::*;
pub use foo::*;
pub use bar::*;
mod two { use super::Type; }
pub use self::two::*;
mod baz {
pub type T = ();
mod foo { pub use super::T as S; }
mod bar { pub use super::foo::S as T; }
pub use self::bar::*;
}
#[rustc_error]
fn main() {} //~ ERROR compilation successful