Skip to content

Commit a1e29da

Browse files
committed
Auto merge of #32167 - jseyfried:refactor_prelude, r=nikomatsakis
resolve: Refactor how the prelude is handled This PR refactors how the prelude is handled in `resolve`. Instead of importing names from the prelude into each module's `resolutions`, this PR adds a new field `prelude: RefCell<Option<Module>>` to `ModuleS` that is set during import resolution but used only when resolving in a lexical scope (i.e. the scope of an initial segment of a relative path). r? @nikomatsakis
2 parents cf9274b + 54cd4d1 commit a1e29da

File tree

3 files changed

+70
-90
lines changed

3 files changed

+70
-90
lines changed

src/librustc_resolve/build_reduced_graph.rs

+10-13
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ use {NameBinding, NameBindingKind};
2222
use module_to_string;
2323
use ParentLink::{ModuleParentLink, BlockParentLink};
2424
use Resolver;
25-
use resolve_imports::Shadowable;
2625
use {resolve_error, resolve_struct_error, ResolutionError};
2726

2827
use rustc::middle::cstore::{CrateStore, ChildItem, DlDef, DlField, DlImpl};
@@ -161,14 +160,9 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
161160
};
162161

163162
// Build up the import directives.
164-
let shadowable = item.attrs.iter().any(|attr| {
163+
let is_prelude = item.attrs.iter().any(|attr| {
165164
attr.name() == special_idents::prelude_import.name.as_str()
166165
});
167-
let shadowable = if shadowable {
168-
Shadowable::Always
169-
} else {
170-
Shadowable::Never
171-
};
172166

173167
match view_path.node {
174168
ViewPathSimple(binding, ref full_path) => {
@@ -186,7 +180,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
186180
view_path.span,
187181
item.id,
188182
is_public,
189-
shadowable);
183+
is_prelude);
190184
}
191185
ViewPathList(_, ref source_items) => {
192186
// Make sure there's at most one `mod` import in the list.
@@ -237,7 +231,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
237231
source_item.span,
238232
source_item.node.id(),
239233
is_public,
240-
shadowable);
234+
is_prelude);
241235
}
242236
}
243237
ViewPathGlob(_) => {
@@ -247,7 +241,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
247241
view_path.span,
248242
item.id,
249243
is_public,
250-
shadowable);
244+
is_prelude);
251245
}
252246
}
253247
parent
@@ -631,7 +625,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
631625
span: Span,
632626
id: NodeId,
633627
is_public: bool,
634-
shadowable: Shadowable) {
628+
is_prelude: bool) {
635629
// Bump the reference count on the name. Or, if this is a glob, set
636630
// the appropriate flag.
637631

@@ -640,15 +634,18 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
640634
module_.increment_outstanding_references_for(target, ValueNS, is_public);
641635
module_.increment_outstanding_references_for(target, TypeNS, is_public);
642636
}
643-
GlobImport => {
637+
GlobImport if !is_prelude => {
644638
// Set the glob flag. This tells us that we don't know the
645639
// module's exports ahead of time.
646640
module_.inc_glob_count(is_public)
647641
}
642+
// Prelude imports are not included in the glob counts since they do not get added to
643+
// `resolved_globs` -- they are handled separately in `resolve_imports`.
644+
GlobImport => {}
648645
}
649646

650647
let directive =
651-
ImportDirective::new(module_path, subclass, span, id, is_public, shadowable);
648+
ImportDirective::new(module_path, subclass, span, id, is_public, is_prelude);
652649
module_.add_import_directive(directive);
653650
self.unresolved_imports += 1;
654651
}

src/librustc_resolve/lib.rs

+21-25
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,8 @@ fn resolve_struct_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>,
349349
if let Some(sp) = resolver.ast_map.span_if_local(did) {
350350
err.span_note(sp, "constant defined here");
351351
}
352-
if let Success(binding) = resolver.current_module.resolve_name(name, ValueNS, true) {
352+
if let Some(binding) = resolver.current_module
353+
.resolve_name_in_lexical_scope(name, ValueNS) {
353354
if binding.is_import() {
354355
err.span_note(binding.span.unwrap(), "constant imported here");
355356
}
@@ -820,7 +821,7 @@ pub struct ModuleS<'a> {
820821
// entry block for `f`.
821822
module_children: RefCell<NodeMap<Module<'a>>>,
822823

823-
shadowed_traits: RefCell<Vec<&'a NameBinding<'a>>>,
824+
prelude: RefCell<Option<Module<'a>>>,
824825

825826
glob_importers: RefCell<Vec<(Module<'a>, &'a ImportDirective)>>,
826827
resolved_globs: RefCell<(Vec<Module<'a>> /* public */, Vec<Module<'a>> /* private */)>,
@@ -855,7 +856,7 @@ impl<'a> ModuleS<'a> {
855856
resolutions: RefCell::new(HashMap::new()),
856857
unresolved_imports: RefCell::new(Vec::new()),
857858
module_children: RefCell::new(NodeMap()),
858-
shadowed_traits: RefCell::new(Vec::new()),
859+
prelude: RefCell::new(None),
859860
glob_importers: RefCell::new(Vec::new()),
860861
resolved_globs: RefCell::new((Vec::new(), Vec::new())),
861862
public_glob_count: Cell::new(0),
@@ -932,8 +933,7 @@ bitflags! {
932933
// Variants are considered `PUBLIC`, but some of them live in private enums.
933934
// We need to track them to prohibit reexports like `pub use PrivEnum::Variant`.
934935
const PRIVATE_VARIANT = 1 << 2,
935-
const PRELUDE = 1 << 3,
936-
const GLOB_IMPORTED = 1 << 4,
936+
const GLOB_IMPORTED = 1 << 3,
937937
}
938938
}
939939

@@ -1537,13 +1537,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
15371537
module: Module<'a>,
15381538
name: Name,
15391539
namespace: Namespace,
1540-
allow_private_imports: bool,
1540+
use_lexical_scope: bool,
15411541
record_used: bool)
15421542
-> ResolveResult<&'a NameBinding<'a>> {
15431543
debug!("(resolving name in module) resolving `{}` in `{}`", name, module_to_string(module));
15441544

15451545
build_reduced_graph::populate_module_if_necessary(self, module);
1546-
module.resolve_name(name, namespace, allow_private_imports).and_then(|binding| {
1546+
match use_lexical_scope {
1547+
true => module.resolve_name_in_lexical_scope(name, namespace)
1548+
.map(Success).unwrap_or(Failed(None)),
1549+
false => module.resolve_name(name, namespace, false),
1550+
}.and_then(|binding| {
15471551
if record_used {
15481552
self.record_use(name, namespace, binding);
15491553
}
@@ -2962,7 +2966,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
29622966
if name_path.len() == 1 {
29632967
match this.primitive_type_table.primitive_types.get(last_name) {
29642968
Some(_) => None,
2965-
None => this.current_module.resolve_name(*last_name, TypeNS, true).success()
2969+
None => this.current_module.resolve_name_in_lexical_scope(*last_name, TypeNS)
29662970
.and_then(NameBinding::module)
29672971
}
29682972
} else {
@@ -3019,7 +3023,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
30193023

30203024
// Look for a method in the current self type's impl module.
30213025
if let Some(module) = get_module(self, path.span, &name_path) {
3022-
if let Success(binding) = module.resolve_name(name, ValueNS, true) {
3026+
if let Some(binding) = module.resolve_name_in_lexical_scope(name, ValueNS) {
30233027
if let Some(Def::Method(did)) = binding.def() {
30243028
if is_static_method(self, did) {
30253029
return StaticMethod(path_names_to_string(&path, 0));
@@ -3336,33 +3340,25 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
33363340
}
33373341

33383342
// Look for trait children.
3339-
build_reduced_graph::populate_module_if_necessary(self, &search_module);
3340-
3341-
search_module.for_each_child(|_, ns, name_binding| {
3343+
let mut search_in_module = |module: Module<'a>| module.for_each_child(|_, ns, binding| {
33423344
if ns != TypeNS { return }
3343-
let trait_def_id = match name_binding.def() {
3345+
let trait_def_id = match binding.def() {
33443346
Some(Def::Trait(trait_def_id)) => trait_def_id,
33453347
Some(..) | None => return,
33463348
};
33473349
if self.trait_item_map.contains_key(&(name, trait_def_id)) {
33483350
add_trait_info(&mut found_traits, trait_def_id, name);
33493351
let trait_name = self.get_trait_name(trait_def_id);
3350-
self.record_use(trait_name, TypeNS, name_binding);
3351-
}
3352-
});
3353-
3354-
// Look for shadowed traits.
3355-
for binding in search_module.shadowed_traits.borrow().iter() {
3356-
let did = binding.def().unwrap().def_id();
3357-
if self.trait_item_map.contains_key(&(name, did)) {
3358-
add_trait_info(&mut found_traits, did, name);
3359-
let trait_name = self.get_trait_name(did);
33603352
self.record_use(trait_name, TypeNS, binding);
33613353
}
3362-
}
3354+
});
3355+
search_in_module(search_module);
33633356

33643357
match search_module.parent_link {
3365-
NoParentLink | ModuleParentLink(..) => break,
3358+
NoParentLink | ModuleParentLink(..) => {
3359+
search_module.prelude.borrow().map(search_in_module);
3360+
break;
3361+
}
33663362
BlockParentLink(parent_module, _) => {
33673363
search_module = parent_module;
33683364
}

src/librustc_resolve/resolve_imports.rs

+39-52
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,6 @@ impl ImportDirectiveSubclass {
5757
}
5858
}
5959

60-
/// Whether an import can be shadowed by another import.
61-
#[derive(Debug,PartialEq,Clone,Copy)]
62-
pub enum Shadowable {
63-
Always,
64-
Never,
65-
}
66-
6760
/// One import directive.
6861
#[derive(Debug,Clone)]
6962
pub struct ImportDirective {
@@ -72,7 +65,7 @@ pub struct ImportDirective {
7265
pub span: Span,
7366
pub id: NodeId,
7467
pub is_public: bool, // see note in ImportResolutionPerNamespace about how to use this
75-
pub shadowable: Shadowable,
68+
pub is_prelude: bool,
7669
}
7770

7871
impl ImportDirective {
@@ -81,15 +74,15 @@ impl ImportDirective {
8174
span: Span,
8275
id: NodeId,
8376
is_public: bool,
84-
shadowable: Shadowable)
77+
is_prelude: bool)
8578
-> ImportDirective {
8679
ImportDirective {
8780
module_path: module_path,
8881
subclass: subclass,
8982
span: span,
9083
id: id,
9184
is_public: is_public,
92-
shadowable: shadowable,
85+
is_prelude: is_prelude,
9386
}
9487
}
9588

@@ -105,9 +98,6 @@ impl ImportDirective {
10598
if let GlobImport = self.subclass {
10699
modifiers = modifiers | DefModifiers::GLOB_IMPORTED;
107100
}
108-
if self.shadowable == Shadowable::Always {
109-
modifiers = modifiers | DefModifiers::PRELUDE;
110-
}
111101

112102
NameBinding {
113103
kind: NameBindingKind::Import {
@@ -135,44 +125,36 @@ pub struct NameResolution<'a> {
135125

136126
impl<'a> NameResolution<'a> {
137127
fn try_define(&mut self, binding: &'a NameBinding<'a>) -> Result<(), &'a NameBinding<'a>> {
138-
match self.binding {
139-
Some(old_binding) if !old_binding.defined_with(DefModifiers::PRELUDE) => {
140-
if binding.defined_with(DefModifiers::GLOB_IMPORTED) {
141-
self.duplicate_globs.push(binding);
142-
} else if old_binding.defined_with(DefModifiers::GLOB_IMPORTED) {
143-
self.duplicate_globs.push(old_binding);
144-
self.binding = Some(binding);
145-
} else {
146-
return Err(old_binding);
147-
}
128+
if let Some(old_binding) = self.binding {
129+
if binding.defined_with(DefModifiers::GLOB_IMPORTED) {
130+
self.duplicate_globs.push(binding);
131+
} else if old_binding.defined_with(DefModifiers::GLOB_IMPORTED) {
132+
self.duplicate_globs.push(old_binding);
133+
self.binding = Some(binding);
134+
} else {
135+
return Err(old_binding);
148136
}
149-
_ => self.binding = Some(binding),
137+
} else {
138+
self.binding = Some(binding);
150139
}
151140

152141
Ok(())
153142
}
154143

155-
// Returns the resolution of the name assuming no more globs will define it.
156-
fn result(&self, allow_private_imports: bool) -> ResolveResult<&'a NameBinding<'a>> {
157-
match self.binding {
158-
Some(binding) if !binding.defined_with(DefModifiers::GLOB_IMPORTED) => Success(binding),
159-
// If we don't allow private imports and no public imports can define the name, fail.
160-
_ if !allow_private_imports && self.pub_outstanding_references == 0 &&
161-
!self.binding.map(NameBinding::is_public).unwrap_or(false) => Failed(None),
162-
_ if self.outstanding_references > 0 => Indeterminate,
163-
Some(binding) => Success(binding),
164-
None => Failed(None),
165-
}
166-
}
167-
168144
// Returns Some(the resolution of the name), or None if the resolution depends
169145
// on whether more globs can define the name.
170146
fn try_result(&self, allow_private_imports: bool)
171147
-> Option<ResolveResult<&'a NameBinding<'a>>> {
172-
match self.result(allow_private_imports) {
173-
Success(binding) if binding.defined_with(DefModifiers::PRELUDE) => None,
174-
Failed(_) => None,
175-
result @ _ => Some(result),
148+
match self.binding {
149+
Some(binding) if !binding.defined_with(DefModifiers::GLOB_IMPORTED) =>
150+
Some(Success(binding)),
151+
// If (1) we don't allow private imports, (2) no public single import can define the
152+
// name, and (3) no public glob has defined the name, the resolution depends on globs.
153+
_ if !allow_private_imports && self.pub_outstanding_references == 0 &&
154+
!self.binding.map(NameBinding::is_public).unwrap_or(false) => None,
155+
_ if self.outstanding_references > 0 => Some(Indeterminate),
156+
Some(binding) => Some(Success(binding)),
157+
None => None,
176158
}
177159
}
178160

@@ -202,8 +184,6 @@ impl<'a> NameResolution<'a> {
202184
};
203185

204186
for duplicate_glob in self.duplicate_globs.iter() {
205-
if duplicate_glob.defined_with(DefModifiers::PRELUDE) { continue }
206-
207187
// FIXME #31337: We currently allow items to shadow glob-imported re-exports.
208188
if !binding.is_import() {
209189
if let NameBindingKind::Import { binding, .. } = duplicate_glob.kind {
@@ -259,7 +239,16 @@ impl<'a> ::ModuleS<'a> {
259239
}
260240
}
261241

262-
resolution.result(true)
242+
Failed(None)
243+
}
244+
245+
// Invariant: this may not be called until import resolution is complete.
246+
pub fn resolve_name_in_lexical_scope(&self, name: Name, ns: Namespace)
247+
-> Option<&'a NameBinding<'a>> {
248+
self.resolutions.borrow().get(&(name, ns)).and_then(|resolution| resolution.binding)
249+
.or_else(|| self.prelude.borrow().and_then(|prelude| {
250+
prelude.resolve_name(name, ns, false).success()
251+
}))
263252
}
264253

265254
// Define the name or return the existing binding if there is a collision.
@@ -369,7 +358,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
369358
// resolution for it so that later resolve stages won't complain.
370359
if let SingleImport { target, .. } = e.import_directive.subclass {
371360
let dummy_binding = self.resolver.arenas.alloc_name_binding(NameBinding {
372-
modifiers: DefModifiers::PRELUDE,
361+
modifiers: DefModifiers::GLOB_IMPORTED,
373362
kind: NameBindingKind::Def(Def::Err),
374363
span: None,
375364
});
@@ -623,6 +612,11 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
623612
}
624613
build_reduced_graph::populate_module_if_necessary(self.resolver, target_module);
625614

615+
if directive.is_prelude {
616+
*module_.prelude.borrow_mut() = Some(target_module);
617+
return Success(());
618+
}
619+
626620
// Add to target_module's glob_importers and module_'s resolved_globs
627621
target_module.glob_importers.borrow_mut().push((module_, directive));
628622
match *module_.resolved_globs.borrow_mut() {
@@ -685,13 +679,6 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
685679
self.resolver.session.add_lint(lint, id, binding.span.unwrap(), msg);
686680
}
687681
}
688-
689-
// We can always use methods from the prelude traits
690-
for glob_binding in resolution.duplicate_globs.iter() {
691-
if glob_binding.defined_with(DefModifiers::PRELUDE) {
692-
module.shadowed_traits.borrow_mut().push(glob_binding);
693-
}
694-
}
695682
}
696683

697684
if reexports.len() > 0 {

0 commit comments

Comments
 (0)