Skip to content

Commit 3d9db59

Browse files
committed
Detect cycles that include renamed imports
1 parent 26e38d2 commit 3d9db59

File tree

3 files changed

+32
-16
lines changed

3 files changed

+32
-16
lines changed

src/librustc_resolve/lib.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -827,7 +827,7 @@ pub struct ModuleS<'a> {
827827
// is the NodeId of the local `extern crate` item (otherwise, `extern_crate_id` is None).
828828
extern_crate_id: Option<NodeId>,
829829

830-
resolutions: RefCell<HashMap<(Name, Namespace), NameResolution<'a>>>,
830+
resolutions: RefCell<HashMap<(Name, Namespace), &'a RefCell<NameResolution<'a>>>>,
831831
unresolved_imports: RefCell<Vec<&'a ImportDirective<'a>>>,
832832

833833
// The module children of this node, including normal modules and anonymous modules.
@@ -885,7 +885,7 @@ impl<'a> ModuleS<'a> {
885885

886886
fn for_each_child<F: FnMut(Name, Namespace, &'a NameBinding<'a>)>(&self, mut f: F) {
887887
for (&(name, ns), name_resolution) in self.resolutions.borrow().iter() {
888-
name_resolution.binding.map(|binding| f(name, ns, binding));
888+
name_resolution.borrow().binding.map(|binding| f(name, ns, binding));
889889
}
890890
}
891891

@@ -1117,6 +1117,7 @@ struct ResolverArenas<'a> {
11171117
modules: arena::TypedArena<ModuleS<'a>>,
11181118
name_bindings: arena::TypedArena<NameBinding<'a>>,
11191119
import_directives: arena::TypedArena<ImportDirective<'a>>,
1120+
name_resolutions: arena::TypedArena<RefCell<NameResolution<'a>>>,
11201121
}
11211122

11221123
impl<'a> ResolverArenas<'a> {
@@ -1130,6 +1131,9 @@ impl<'a> ResolverArenas<'a> {
11301131
-> &'a ImportDirective {
11311132
self.import_directives.alloc(import_directive)
11321133
}
1134+
fn alloc_name_resolution(&'a self) -> &'a RefCell<NameResolution<'a>> {
1135+
self.name_resolutions.alloc(Default::default())
1136+
}
11331137
}
11341138

11351139
#[derive(PartialEq)]
@@ -1198,6 +1202,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
11981202
modules: arena::TypedArena::new(),
11991203
name_bindings: arena::TypedArena::new(),
12001204
import_directives: arena::TypedArena::new(),
1205+
name_resolutions: arena::TypedArena::new(),
12011206
}
12021207
}
12031208

src/librustc_resolve/resolve_imports.rs

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ use syntax::codemap::Span;
3030
use syntax::util::lev_distance::find_best_match_for_name;
3131

3232
use std::mem::replace;
33-
use std::cell::Cell;
33+
use std::cell::{Cell, RefCell};
3434

3535
/// Contains data for specific types of import directives.
3636
#[derive(Clone, Debug)]
@@ -194,8 +194,8 @@ impl<'a> NameResolution<'a> {
194194
None => return Some(Indeterminate),
195195
};
196196
let name = match directive.subclass {
197-
SingleImport { source, target, .. } if source == target => target,
198-
_ => return Some(Indeterminate),
197+
SingleImport { source, .. } => source,
198+
GlobImport => unreachable!(),
199199
};
200200
match target_module.resolve_name(name, ns, false) {
201201
Failed(_) => {}
@@ -227,14 +227,19 @@ impl<'a> NameResolution<'a> {
227227
}
228228

229229
impl<'a> ::ModuleS<'a> {
230+
fn resolution(&self, name: Name, ns: Namespace) -> &'a RefCell<NameResolution<'a>> {
231+
*self.resolutions.borrow_mut().entry((name, ns))
232+
.or_insert_with(|| self.arenas.alloc_name_resolution())
233+
}
234+
230235
pub fn resolve_name(&self, name: Name, ns: Namespace, allow_private_imports: bool)
231236
-> ResolveResult<&'a NameBinding<'a>> {
232-
let resolutions = match self.resolutions.borrow_state() {
233-
::std::cell::BorrowState::Unused => self.resolutions.borrow(),
234-
_ => return Failed(None), // This happens when there is a cycle of glob imports
237+
let resolution = self.resolution(name, ns);
238+
let resolution = match resolution.borrow_state() {
239+
::std::cell::BorrowState::Unused => resolution.borrow_mut(),
240+
_ => return Failed(None), // This happens when there is a cycle of imports
235241
};
236242

237-
let resolution = resolutions.get(&(name, ns)).cloned().unwrap_or_default();
238243
if let Some(result) = resolution.try_result(ns, allow_private_imports) {
239244
// If the resolution doesn't depend on glob definability, check privacy and return.
240245
return result.and_then(|binding| {
@@ -261,7 +266,7 @@ impl<'a> ::ModuleS<'a> {
261266
// Invariant: this may not be called until import resolution is complete.
262267
pub fn resolve_name_in_lexical_scope(&self, name: Name, ns: Namespace)
263268
-> Option<&'a NameBinding<'a>> {
264-
self.resolutions.borrow().get(&(name, ns)).and_then(|resolution| resolution.binding)
269+
self.resolution(name, ns).borrow().binding
265270
.or_else(|| self.prelude.borrow().and_then(|prelude| {
266271
prelude.resolve_name(name, ns, false).success()
267272
}))
@@ -296,10 +301,9 @@ impl<'a> ::ModuleS<'a> {
296301
self.unresolved_imports.borrow_mut().push(directive);
297302
match directive.subclass {
298303
SingleImport { target, .. } => {
299-
let mut resolutions = self.resolutions.borrow_mut();
300304
for &ns in &[ValueNS, TypeNS] {
301-
resolutions.entry((target, ns)).or_insert_with(Default::default)
302-
.single_imports.add_directive(directive);
305+
self.resolution(target, ns).borrow_mut().single_imports
306+
.add_directive(directive);
303307
}
304308
}
305309
// We don't add prelude imports to the globs since they only affect lexical scopes,
@@ -314,8 +318,7 @@ impl<'a> ::ModuleS<'a> {
314318
fn update_resolution<T, F>(&self, name: Name, ns: Namespace, update: F) -> T
315319
where F: FnOnce(&mut NameResolution<'a>) -> T
316320
{
317-
let mut resolutions = self.resolutions.borrow_mut();
318-
let resolution = resolutions.entry((name, ns)).or_insert_with(Default::default);
321+
let mut resolution = &mut *self.resolution(name, ns).borrow_mut();
319322
let was_known = resolution.binding().is_some();
320323

321324
let t = update(resolution);
@@ -638,7 +641,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
638641
target_module.glob_importers.borrow_mut().push((module_, directive));
639642

640643
for (&(name, ns), resolution) in target_module.resolutions.borrow().iter() {
641-
if let Some(binding) = resolution.binding() {
644+
if let Some(binding) = resolution.borrow().binding() {
642645
if binding.defined_with(DefModifiers::IMPORTABLE | DefModifiers::PUBLIC) {
643646
let _ = module_.try_define_child(name, ns, directive.import(binding, None));
644647
}
@@ -666,6 +669,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
666669

667670
let mut reexports = Vec::new();
668671
for (&(name, ns), resolution) in module.resolutions.borrow().iter() {
672+
let resolution = resolution.borrow();
669673
resolution.report_conflicts(|b1, b2| {
670674
self.resolver.report_conflict(module, name, ns, b1, b2)
671675
});

src/test/compile-fail/issue-32119.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,12 @@ mod bar { pub use super::T; }
1717
pub use foo::*;
1818
pub use bar::*;
1919

20+
mod baz {
21+
pub type T = ();
22+
mod foo { pub use super::T as S; }
23+
mod bar { pub use super::foo::S as T; }
24+
pub use self::bar::*;
25+
}
26+
2027
#[rustc_error]
2128
fn main() {} //~ ERROR compilation successful

0 commit comments

Comments
 (0)