Skip to content

Commit fbc3229

Browse files
committed
Refactor out finalize_import() from resolve_import().
1 parent 165b0b6 commit fbc3229

File tree

2 files changed

+125
-101
lines changed

2 files changed

+125
-101
lines changed

src/librustc_resolve/lib.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -957,7 +957,10 @@ pub struct Resolver<'a> {
957957

958958
structs: FnvHashMap<DefId, Vec<Name>>,
959959

960-
// All indeterminate imports (i.e. imports not known to succeed or fail).
960+
// All imports known to succeed or fail.
961+
determined_imports: Vec<&'a ImportDirective<'a>>,
962+
963+
// All non-determined imports.
961964
indeterminate_imports: Vec<&'a ImportDirective<'a>>,
962965

963966
// The module that represents the current item scope.
@@ -1149,6 +1152,7 @@ impl<'a> Resolver<'a> {
11491152
trait_item_map: FnvHashMap(),
11501153
structs: FnvHashMap(),
11511154

1155+
determined_imports: Vec::new(),
11521156
indeterminate_imports: Vec::new(),
11531157

11541158
current_module: graph_root,

src/librustc_resolve/resolve_imports.rs

Lines changed: 120 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ impl<'a> Resolver<'a> {
144144

145145
/// Attempts to resolve the supplied name in the given module for the given namespace.
146146
/// If successful, returns the binding corresponding to the name.
147+
/// Invariant: if `record_used` is `Some`, import resolution must be complete.
147148
pub fn resolve_name_in_module(&mut self,
148149
module: Module<'a>,
149150
name: Name,
@@ -159,32 +160,46 @@ impl<'a> Resolver<'a> {
159160
_ => return Failed(None), // This happens when there is a cycle of imports
160161
};
161162

162-
if let Some(result) = self.try_result(&resolution, ns, allow_private_imports) {
163-
// If the resolution doesn't depend on glob definability, check privacy and return.
164-
return result.and_then(|binding| {
165-
if !allow_private_imports && binding.is_import() && !binding.is_pseudo_public() {
163+
let is_disallowed_private_import = |binding: &NameBinding| {
164+
!allow_private_imports && !binding.is_pseudo_public() && binding.is_import()
165+
};
166+
167+
if let Some(span) = record_used {
168+
if let Some(binding) = resolution.binding {
169+
if is_disallowed_private_import(binding) {
166170
return Failed(None);
167171
}
168-
if let Some(span) = record_used {
169-
self.record_use(name, ns, binding);
170-
if !self.is_accessible(binding.vis) {
171-
self.privacy_errors.push(PrivacyError(span, name, binding));
172-
}
172+
self.record_use(name, ns, binding);
173+
if !self.is_accessible(binding.vis) {
174+
self.privacy_errors.push(PrivacyError(span, name, binding));
175+
}
176+
}
177+
178+
return resolution.binding.map(Success).unwrap_or(Failed(None));
179+
}
180+
181+
// If the resolution doesn't depend on glob definability, check privacy and return.
182+
if let Some(result) = self.try_result(&resolution, ns) {
183+
return result.and_then(|binding| {
184+
if self.is_accessible(binding.vis) && !is_disallowed_private_import(binding) {
185+
Success(binding)
186+
} else {
187+
Failed(None)
173188
}
174-
Success(binding)
175189
});
176190
}
177191

178192
// Check if the globs are determined
179193
for directive in module.globs.borrow().iter() {
180-
if !allow_private_imports && directive.vis != ty::Visibility::Public { continue }
181-
if let Some(target_module) = directive.target_module.get() {
182-
let result = self.resolve_name_in_module(target_module, name, ns, false, None);
183-
if let Indeterminate = result {
194+
if self.is_accessible(directive.vis) {
195+
if let Some(target_module) = directive.target_module.get() {
196+
let result = self.resolve_name_in_module(target_module, name, ns, true, None);
197+
if let Indeterminate = result {
198+
return Indeterminate;
199+
}
200+
} else {
184201
return Indeterminate;
185202
}
186-
} else {
187-
return Indeterminate;
188203
}
189204
}
190205

@@ -193,10 +208,7 @@ impl<'a> Resolver<'a> {
193208

194209
// Returns Some(the resolution of the name), or None if the resolution depends
195210
// on whether more globs can define the name.
196-
fn try_result(&mut self,
197-
resolution: &NameResolution<'a>,
198-
ns: Namespace,
199-
allow_private_imports: bool)
211+
fn try_result(&mut self, resolution: &NameResolution<'a>, ns: Namespace)
200212
-> Option<ResolveResult<&'a NameBinding<'a>>> {
201213
match resolution.binding {
202214
Some(binding) if !binding.is_glob_import() =>
@@ -206,17 +218,8 @@ impl<'a> Resolver<'a> {
206218

207219
// Check if a single import can still define the name.
208220
match resolution.single_imports {
209-
SingleImports::None => {},
210221
SingleImports::AtLeastOne => return Some(Indeterminate),
211-
SingleImports::MaybeOne(directive) => {
212-
// If (1) we don't allow private imports, (2) no public single import can define
213-
// the name, and (3) no public glob has defined the name, the resolution depends
214-
// on whether more globs can define the name.
215-
if !allow_private_imports && directive.vis != ty::Visibility::Public &&
216-
!resolution.binding.map(NameBinding::is_pseudo_public).unwrap_or(false) {
217-
return None;
218-
}
219-
222+
SingleImports::MaybeOne(directive) if self.is_accessible(directive.vis) => {
220223
let target_module = match directive.target_module.get() {
221224
Some(target_module) => target_module,
222225
None => return Some(Indeterminate),
@@ -225,11 +228,12 @@ impl<'a> Resolver<'a> {
225228
SingleImport { source, .. } => source,
226229
GlobImport { .. } => unreachable!(),
227230
};
228-
match self.resolve_name_in_module(target_module, name, ns, false, None) {
231+
match self.resolve_name_in_module(target_module, name, ns, true, None) {
229232
Failed(_) => {}
230233
_ => return Some(Indeterminate),
231234
}
232235
}
236+
SingleImports::MaybeOne(_) | SingleImports::None => {},
233237
}
234238

235239
resolution.binding.map(Success)
@@ -389,7 +393,6 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
389393
fn resolve_imports(&mut self) {
390394
let mut i = 0;
391395
let mut prev_num_indeterminates = self.indeterminate_imports.len() + 1;
392-
let mut errors = Vec::new();
393396

394397
while self.indeterminate_imports.len() < prev_num_indeterminates {
395398
prev_num_indeterminates = self.indeterminate_imports.len();
@@ -400,19 +403,9 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
400403

401404
for import in imports {
402405
match self.resolve_import(&import) {
403-
Failed(err) => {
404-
let (span, help) = match err {
405-
Some((span, msg)) => (span, format!(". {}", msg)),
406-
None => (import.span, String::new()),
407-
};
408-
errors.push(ImportResolvingError {
409-
import_directive: import,
410-
span: span,
411-
help: help,
412-
});
413-
}
406+
Failed(_) => self.determined_imports.push(import),
414407
Indeterminate => self.indeterminate_imports.push(import),
415-
Success(()) => {}
408+
Success(()) => self.determined_imports.push(import),
416409
}
417410
}
418411

@@ -423,6 +416,22 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
423416
self.finalize_resolutions_in(module);
424417
}
425418

419+
let mut errors = Vec::new();
420+
for i in 0 .. self.determined_imports.len() {
421+
let import = self.determined_imports[i];
422+
if let Failed(err) = self.finalize_import(import) {
423+
let (span, help) = match err {
424+
Some((span, msg)) => (span, format!(". {}", msg)),
425+
None => (import.span, String::new()),
426+
};
427+
errors.push(ImportResolvingError {
428+
import_directive: import,
429+
span: span,
430+
help: help,
431+
});
432+
}
433+
}
434+
426435
// Report unresolved imports only if no hard error was already reported
427436
// to avoid generating multiple errors on the same import.
428437
if errors.len() == 0 {
@@ -481,9 +490,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
481490

482491
let target_module = match directive.target_module.get() {
483492
Some(module) => module,
484-
_ => match self.resolve_module_path(&directive.module_path,
485-
DontUseLexicalScope,
486-
Some(directive.span)) {
493+
_ => match self.resolve_module_path(&directive.module_path, DontUseLexicalScope, None) {
487494
Success(module) => module,
488495
Indeterminate => return Indeterminate,
489496
Failed(err) => return Failed(err),
@@ -494,27 +501,29 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
494501
let (source, target, value_result, type_result) = match directive.subclass {
495502
SingleImport { source, target, ref value_result, ref type_result } =>
496503
(source, target, value_result, type_result),
497-
GlobImport { .. } => return self.resolve_glob_import(target_module, directive),
504+
GlobImport { .. } => {
505+
self.resolve_glob_import(directive);
506+
return Success(());
507+
}
498508
};
499509

500-
let mut privacy_error = true;
510+
let mut indeterminate = false;
501511
for &(ns, result) in &[(ValueNS, value_result), (TypeNS, type_result)] {
502-
let was_determined = if let Err(false) = result.get() {
512+
if let Err(false) = result.get() {
503513
result.set({
504-
let span = Some(directive.span);
505-
match self.resolve_name_in_module(target_module, source, ns, false, span) {
514+
match self.resolve_name_in_module(target_module, source, ns, false, None) {
506515
Success(binding) => Ok(binding),
507516
Indeterminate => Err(false),
508517
Failed(_) => Err(true),
509518
}
510519
});
511-
false
512520
} else {
513-
true
521+
continue
514522
};
515523

516524
match result.get() {
517-
Err(true) if !was_determined => {
525+
Err(false) => indeterminate = true,
526+
Err(true) => {
518527
self.update_resolution(module, target, ns, |_, resolution| {
519528
resolution.single_imports.directive_failed()
520529
});
@@ -529,26 +538,55 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
529538
self.import_dummy_binding(directive);
530539
return Success(());
531540
}
532-
Ok(binding) if !self.is_accessible(binding.vis) => {}
533-
Ok(binding) if !was_determined => {
541+
Ok(binding) => {
534542
let imported_binding = self.import(binding, directive);
535543
let conflict = self.try_define(module, target, ns, imported_binding);
536544
if let Err(old_binding) = conflict {
537545
let binding = &self.import(binding, directive);
538546
self.report_conflict(module, target, ns, binding, old_binding);
539547
}
540-
privacy_error = false;
541548
}
542-
Ok(_) => privacy_error = false,
543-
_ => {}
544549
}
545550
}
546551

547-
let (value_result, type_result) = (value_result.get(), type_result.get());
548-
match (value_result, type_result) {
549-
(Err(false), _) | (_, Err(false)) => return Indeterminate,
550-
(Err(true), Err(true)) => {
551-
let resolutions = target_module.resolutions.borrow();
552+
if indeterminate { Indeterminate } else { Success(()) }
553+
}
554+
555+
fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> ResolveResult<()> {
556+
self.set_current_module(directive.parent);
557+
558+
let ImportDirective { ref module_path, span, .. } = *directive;
559+
let module_result = self.resolve_module_path(&module_path, DontUseLexicalScope, Some(span));
560+
let module = match module_result {
561+
Success(module) => module,
562+
Indeterminate => return Indeterminate,
563+
Failed(err) => return Failed(err),
564+
};
565+
566+
let (source, value_result, type_result) = match directive.subclass {
567+
SingleImport { source, ref value_result, ref type_result, .. } =>
568+
(source, value_result.get(), type_result.get()),
569+
GlobImport { .. } if module.def_id() == directive.parent.def_id() => {
570+
// Importing a module into itself is not allowed.
571+
let msg = "Cannot glob-import a module into itself.".into();
572+
return Failed(Some((directive.span, msg)));
573+
}
574+
GlobImport { .. } => return Success(()),
575+
};
576+
577+
for &(ns, result) in &[(ValueNS, value_result), (TypeNS, type_result)] {
578+
if let Ok(binding) = result {
579+
self.record_use(source, ns, binding);
580+
}
581+
}
582+
583+
if value_result.is_err() && type_result.is_err() {
584+
let (value_result, type_result);
585+
value_result = self.resolve_name_in_module(module, source, ValueNS, false, Some(span));
586+
type_result = self.resolve_name_in_module(module, source, TypeNS, false, Some(span));
587+
588+
return if let (Failed(_), Failed(_)) = (value_result, type_result) {
589+
let resolutions = module.resolutions.borrow();
552590
let names = resolutions.iter().filter_map(|(&(ref name, _), resolution)| {
553591
if *name == source { return None; } // Never suggest the same name
554592
match *resolution.borrow() {
@@ -561,29 +599,22 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
561599
Some(name) => format!(". Did you mean to use `{}`?", name),
562600
None => "".to_owned(),
563601
};
564-
let module_str = module_to_string(target_module);
602+
let module_str = module_to_string(module);
565603
let msg = if &module_str == "???" {
566604
format!("There is no `{}` in the crate root{}", source, lev_suggestion)
567605
} else {
568606
format!("There is no `{}` in `{}`{}", source, module_str, lev_suggestion)
569607
};
570-
return Failed(Some((directive.span, msg)));
571-
}
572-
_ => (),
573-
}
574-
575-
if privacy_error {
576-
for &(ns, result) in &[(ValueNS, value_result), (TypeNS, type_result)] {
577-
let binding = match result { Ok(binding) => binding, _ => continue };
578-
self.privacy_errors.push(PrivacyError(directive.span, source, binding));
579-
let imported_binding = self.import(binding, directive);
580-
let _ = self.try_define(module, target, ns, imported_binding);
608+
Failed(Some((directive.span, msg)))
609+
} else {
610+
// `resolve_name_in_module` reported a privacy error.
611+
self.import_dummy_binding(directive);
612+
Success(())
581613
}
582614
}
583615

584616
match (value_result, type_result) {
585-
(Ok(binding), _) if !binding.pseudo_vis().is_at_least(directive.vis, self) &&
586-
self.is_accessible(binding.vis) => {
617+
(Ok(binding), _) if !binding.pseudo_vis().is_at_least(directive.vis, self) => {
587618
let msg = format!("`{}` is private, and cannot be reexported", source);
588619
let note_msg = format!("consider marking `{}` as `pub` in the imported module",
589620
source);
@@ -592,8 +623,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
592623
.emit();
593624
}
594625

595-
(_, Ok(binding)) if !binding.pseudo_vis().is_at_least(directive.vis, self) &&
596-
self.is_accessible(binding.vis) => {
626+
(_, Ok(binding)) if !binding.pseudo_vis().is_at_least(directive.vis, self) => {
597627
if binding.is_extern_crate() {
598628
let msg = format!("extern crate `{}` is private, and cannot be reexported \
599629
(error E0364), consider declaring with `pub`",
@@ -626,27 +656,20 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
626656
return Success(());
627657
}
628658

629-
// Resolves a glob import. Note that this function cannot fail; it either
630-
// succeeds or bails out (as importing * from an empty module or a module
631-
// that exports nothing is valid). target_module is the module we are
632-
// actually importing, i.e., `foo` in `use foo::*`.
633-
fn resolve_glob_import(&mut self, target_module: Module<'b>, directive: &'b ImportDirective<'b>)
634-
-> ResolveResult<()> {
659+
fn resolve_glob_import(&mut self, directive: &'b ImportDirective<'b>) {
660+
let target_module = directive.target_module.get().unwrap();
661+
self.populate_module_if_necessary(target_module);
662+
635663
if let Some(Def::Trait(_)) = target_module.def {
636664
self.session.span_err(directive.span, "items in traits are not importable.");
637665
}
638666

639-
let module = self.current_module;
640-
if module.def_id() == target_module.def_id() {
641-
// This means we are trying to glob import a module into itself, and it is a no-go
642-
let msg = "Cannot glob-import a module into itself.".into();
643-
return Failed(Some((directive.span, msg)));
644-
}
645-
self.populate_module_if_necessary(target_module);
646-
647-
if let GlobImport { is_prelude: true } = directive.subclass {
667+
let module = directive.parent;
668+
if target_module.def_id() == module.def_id() {
669+
return;
670+
} else if let GlobImport { is_prelude: true } = directive.subclass {
648671
self.prelude = Some(target_module);
649-
return Success(());
672+
return;
650673
}
651674

652675
// Add to target_module's glob_importers
@@ -669,9 +692,6 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
669692
let resolution = PathResolution::new(Def::Mod(did));
670693
self.def_map.insert(directive.id, resolution);
671694
}
672-
673-
debug!("(resolving glob import) successfully resolved import");
674-
return Success(());
675695
}
676696

677697
// Miscellaneous post-processing, including recording reexports, reporting conflicts,

0 commit comments

Comments
 (0)