Skip to content

Commit c2533b6

Browse files
committed
resolve: Remove SingleImports in favor of a simple set
1 parent 2214349 commit c2533b6

File tree

1 file changed

+26
-99
lines changed

1 file changed

+26
-99
lines changed

src/librustc_resolve/resolve_imports.rs

Lines changed: 26 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ use syntax::util::lev_distance::find_best_match_for_name;
3333
use syntax_pos::Span;
3434

3535
use std::cell::{Cell, RefCell};
36-
use std::{mem, ptr};
36+
use std::mem;
3737

3838
/// Contains data for specific types of import directives.
3939
#[derive(Clone, Debug)]
@@ -104,67 +104,20 @@ impl<'a> ImportDirective<'a> {
104104
#[derive(Clone, Default, Debug)]
105105
/// Records information about the resolution of a name in a namespace of a module.
106106
pub struct NameResolution<'a> {
107-
/// The single imports that define the name in the namespace.
108-
single_imports: SingleImports<'a>,
107+
/// Single imports that may define the name in the namespace.
108+
/// Import directives are arena-allocated, so it's ok to use pointers as keys, they are stable.
109+
single_imports: FxHashSet<*const ImportDirective<'a>>,
109110
/// The least shadowable known binding for this name, or None if there are no known bindings.
110111
pub binding: Option<&'a NameBinding<'a>>,
111112
shadowed_glob: Option<&'a NameBinding<'a>>,
112113
}
113114

114-
#[derive(Clone, Debug)]
115-
enum SingleImports<'a> {
116-
/// No single imports can define the name in the namespace.
117-
None,
118-
/// Only the given single import can define the name in the namespace.
119-
MaybeOne(&'a ImportDirective<'a>),
120-
/// Only one of these two single imports can define the name in the namespace.
121-
MaybeTwo(&'a ImportDirective<'a>, &'a ImportDirective<'a>),
122-
/// At least one single import will define the name in the namespace.
123-
AtLeastOne,
124-
}
125-
126-
impl<'a> Default for SingleImports<'a> {
127-
/// Creates a `SingleImports<'a>` of None type.
128-
fn default() -> Self {
129-
SingleImports::None
130-
}
131-
}
132-
133-
impl<'a> SingleImports<'a> {
134-
fn add_directive(&mut self, directive: &'a ImportDirective<'a>, use_extern_macros: bool) {
135-
match *self {
136-
SingleImports::None => *self = SingleImports::MaybeOne(directive),
137-
SingleImports::MaybeOne(directive_one) => *self = if use_extern_macros {
138-
SingleImports::MaybeTwo(directive_one, directive)
139-
} else {
140-
SingleImports::AtLeastOne
141-
},
142-
// If three single imports can define the name in the namespace, we can assume that at
143-
// least one of them will define it since otherwise we'd get duplicate errors in one of
144-
// other namespaces.
145-
SingleImports::MaybeTwo(..) => *self = SingleImports::AtLeastOne,
146-
SingleImports::AtLeastOne => {}
147-
};
148-
}
149-
150-
fn directive_failed(&mut self, dir: &'a ImportDirective<'a>) {
151-
match *self {
152-
SingleImports::None => unreachable!(),
153-
SingleImports::MaybeOne(_) => *self = SingleImports::None,
154-
SingleImports::MaybeTwo(dir1, dir2) =>
155-
*self = SingleImports::MaybeOne(if ptr::eq(dir1, dir) { dir1 } else { dir2 }),
156-
SingleImports::AtLeastOne => {}
157-
}
158-
}
159-
}
160-
161115
impl<'a> NameResolution<'a> {
162116
// Returns the binding for the name if it is known or None if it not known.
163117
fn binding(&self) -> Option<&'a NameBinding<'a>> {
164-
self.binding.and_then(|binding| match self.single_imports {
165-
SingleImports::None => Some(binding),
166-
_ if !binding.is_glob_import() => Some(binding),
167-
_ => None, // The binding could be shadowed by a single import, so it is not known.
118+
self.binding.and_then(|binding| {
119+
if !binding.is_glob_import() ||
120+
self.single_imports.is_empty() { Some(binding) } else { None }
168121
})
169122
}
170123
}
@@ -227,58 +180,31 @@ impl<'a> Resolver<'a> {
227180
if usable { Ok(binding) } else { Err(Determined) }
228181
};
229182

230-
// Items and single imports are not shadowable.
183+
// Items and single imports are not shadowable, if we have one, then it's determined.
231184
if let Some(binding) = resolution.binding {
232185
if !binding.is_glob_import() {
233186
return check_usable(self, binding);
234187
}
235188
}
236189

237-
// Check if a single import can still define the name.
238-
let resolve_single_import = |this: &mut Self, directive: &'a ImportDirective<'a>| {
239-
let module = match directive.imported_module.get() {
240-
Some(module) => module,
241-
None => return false,
242-
};
243-
let ident = match directive.subclass {
190+
// From now on we either have a glob resolution or no resolution.
191+
192+
// Check if one of single imports can still define the name,
193+
// if it can then our result is not determined and can be invalidated.
194+
for single_import in &resolution.single_imports {
195+
let single_import = unsafe { &**single_import };
196+
if !self.is_accessible(single_import.vis.get()) {
197+
continue;
198+
}
199+
let module = unwrap_or!(single_import.imported_module.get(), return Err(Undetermined));
200+
let ident = match single_import.subclass {
244201
SingleImport { source, .. } => source,
245202
_ => unreachable!(),
246203
};
247-
match this.resolve_ident_in_module(module, ident, ns, false, path_span) {
248-
Err(Determined) => {}
249-
_ => return false,
250-
}
251-
true
252-
};
253-
match resolution.single_imports {
254-
SingleImports::AtLeastOne => return Err(Undetermined),
255-
SingleImports::MaybeOne(directive) => {
256-
let accessible = self.is_accessible(directive.vis.get());
257-
if accessible {
258-
if !resolve_single_import(self, directive) {
259-
return Err(Undetermined)
260-
}
261-
}
262-
}
263-
SingleImports::MaybeTwo(directive1, directive2) => {
264-
let accessible1 = self.is_accessible(directive1.vis.get());
265-
let accessible2 = self.is_accessible(directive2.vis.get());
266-
if accessible1 && accessible2 {
267-
if !resolve_single_import(self, directive1) &&
268-
!resolve_single_import(self, directive2) {
269-
return Err(Undetermined)
270-
}
271-
} else if accessible1 {
272-
if !resolve_single_import(self, directive1) {
273-
return Err(Undetermined)
274-
}
275-
} else {
276-
if !resolve_single_import(self, directive2) {
277-
return Err(Undetermined)
278-
}
279-
}
204+
match self.resolve_ident_in_module(module, ident, ns, false, path_span) {
205+
Err(Determined) => continue,
206+
Ok(_) | Err(Undetermined) => return Err(Undetermined),
280207
}
281-
SingleImports::None => {},
282208
}
283209

284210
let no_unresolved_invocations =
@@ -348,7 +274,7 @@ impl<'a> Resolver<'a> {
348274
SingleImport { target, type_ns_only, .. } => {
349275
self.per_ns(|this, ns| if !type_ns_only || ns == TypeNS {
350276
let mut resolution = this.resolution(current_module, target, ns).borrow_mut();
351-
resolution.single_imports.add_directive(directive, this.use_extern_macros);
277+
resolution.single_imports.insert(directive);
352278
});
353279
}
354280
// We don't add prelude imports to the globs since they only affect lexical scopes,
@@ -640,7 +566,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
640566
Err(Undetermined) => indeterminate = true,
641567
Err(Determined) => {
642568
this.update_resolution(parent, target, ns, |_, resolution| {
643-
resolution.single_imports.directive_failed(directive)
569+
resolution.single_imports.remove(&(directive as *const _));
644570
});
645571
}
646572
Ok(binding) if !binding.is_importable() => {
@@ -826,7 +752,8 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
826752
_ => Some(&i.name),
827753
}
828754
},
829-
NameResolution { single_imports: SingleImports::None, .. } => None,
755+
NameResolution { ref single_imports, .. }
756+
if single_imports.is_empty() => None,
830757
_ => Some(&i.name),
831758
}
832759
});

0 commit comments

Comments
 (0)