Skip to content

Commit 96041cc

Browse files
committed
More perseverant about indeterminate imports.
Most errors generated by resolve might be caused by not-yet-resolved glob imports. This changes the behavior of the resolve imports algorithms to not fail prematurally on first error, but instead buffer intermediate errors and report them only when stuck. Fixes #18083
1 parent 88c2914 commit 96041cc

File tree

2 files changed

+63
-31
lines changed

2 files changed

+63
-31
lines changed

src/librustc_resolve/lib.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
html_root_url = "http://doc.rust-lang.org/nightly/")]
2121

2222
#![feature(associated_consts)]
23+
#![feature(borrow_state)]
2324
#![feature(rc_weak)]
2425
#![feature(rustc_diagnostic_macros)]
2526
#![feature(rustc_private)]
@@ -538,8 +539,8 @@ enum ResolveResult<T> {
538539
}
539540

540541
impl<T> ResolveResult<T> {
541-
fn indeterminate(&self) -> bool {
542-
match *self { Indeterminate => true, _ => false }
542+
fn success(&self) -> bool {
543+
match *self { Success(_) => true, _ => false }
543544
}
544545
}
545546

@@ -731,7 +732,12 @@ impl Module {
731732
}
732733

733734
fn all_imports_resolved(&self) -> bool {
734-
self.imports.borrow().len() == self.resolved_import_count.get()
735+
if self.imports.borrow_state() == ::std::cell::BorrowState::Writing {
736+
// it is currently being resolved ! so nope
737+
false
738+
} else {
739+
self.imports.borrow().len() == self.resolved_import_count.get()
740+
}
735741
}
736742
}
737743

src/librustc_resolve/resolve_imports.rs

Lines changed: 54 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -208,15 +208,28 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
208208
i, self.resolver.unresolved_imports);
209209

210210
let module_root = self.resolver.graph_root.get_module();
211-
self.resolve_imports_for_module_subtree(module_root.clone());
211+
let errors = self.resolve_imports_for_module_subtree(module_root.clone());
212212

213213
if self.resolver.unresolved_imports == 0 {
214214
debug!("(resolving imports) success");
215215
break;
216216
}
217217

218218
if self.resolver.unresolved_imports == prev_unresolved_imports {
219-
self.resolver.report_unresolved_imports(module_root);
219+
// resolving failed
220+
if errors.len() > 0 {
221+
for (span, path, help) in errors {
222+
resolve_error(self.resolver,
223+
span,
224+
ResolutionError::UnresolvedImport(Some((&*path, &*help))));
225+
}
226+
} else {
227+
// report unresolved imports only if no hard error was already reported
228+
// to avoid generating multiple errors on the same import
229+
// imports that are still undeterminate at this point are actually blocked
230+
// by errored imports, so there is no point reporting them
231+
self.resolver.report_unresolved_imports(module_root);
232+
}
220233
break;
221234
}
222235

@@ -227,11 +240,13 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
227240

228241
/// Attempts to resolve imports for the given module and all of its
229242
/// submodules.
230-
fn resolve_imports_for_module_subtree(&mut self, module_: Rc<Module>) {
243+
fn resolve_imports_for_module_subtree(&mut self, module_: Rc<Module>)
244+
-> Vec<(Span, String, String)> {
245+
let mut errors = Vec::new();
231246
debug!("(resolving imports for module subtree) resolving {}",
232247
module_to_string(&*module_));
233248
let orig_module = replace(&mut self.resolver.current_module, module_.clone());
234-
self.resolve_imports_for_module(module_.clone());
249+
errors.extend(self.resolve_imports_for_module(module_.clone()));
235250
self.resolver.current_module = orig_module;
236251

237252
build_reduced_graph::populate_module_if_necessary(self.resolver, &module_);
@@ -241,53 +256,65 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
241256
// Nothing to do.
242257
}
243258
Some(child_module) => {
244-
self.resolve_imports_for_module_subtree(child_module);
259+
errors.extend(self.resolve_imports_for_module_subtree(child_module));
245260
}
246261
}
247262
}
248263

249264
for (_, child_module) in module_.anonymous_children.borrow().iter() {
250-
self.resolve_imports_for_module_subtree(child_module.clone());
265+
errors.extend(self.resolve_imports_for_module_subtree(child_module.clone()));
251266
}
267+
268+
errors
252269
}
253270

254271
/// Attempts to resolve imports for the given module only.
255-
fn resolve_imports_for_module(&mut self, module: Rc<Module>) {
272+
fn resolve_imports_for_module(&mut self, module: Rc<Module>) -> Vec<(Span, String, String)> {
273+
let mut errors = Vec::new();
274+
256275
if module.all_imports_resolved() {
257276
debug!("(resolving imports for module) all imports resolved for \
258277
{}",
259278
module_to_string(&*module));
260-
return;
279+
return errors;
261280
}
262281

263-
let imports = module.imports.borrow();
282+
let mut imports = module.imports.borrow_mut();
264283
let import_count = imports.len();
265-
while module.resolved_import_count.get() < import_count {
284+
let mut indeterminate_imports = Vec::new();
285+
while module.resolved_import_count.get() + indeterminate_imports.len() < import_count {
266286
let import_index = module.resolved_import_count.get();
267-
let import_directive = &(*imports)[import_index];
268287
match self.resolve_import_for_module(module.clone(),
269-
import_directive) {
288+
&imports[import_index]) {
270289
ResolveResult::Failed(err) => {
290+
let import_directive = &imports[import_index];
271291
let (span, help) = match err {
272292
Some((span, msg)) => (span, format!(". {}", msg)),
273293
None => (import_directive.span, String::new())
274294
};
275-
resolve_error(self.resolver,
276-
span,
277-
ResolutionError::UnresolvedImport(
278-
Some((&*import_path_to_string(
279-
&import_directive.module_path,
280-
import_directive.subclass),
281-
&*help)))
282-
);
295+
errors.push((span,
296+
import_path_to_string(
297+
&import_directive.module_path,
298+
import_directive.subclass
299+
),
300+
help))
301+
}
302+
ResolveResult::Indeterminate => {}
303+
ResolveResult::Success(()) => {
304+
// count success
305+
module.resolved_import_count
306+
.set(module.resolved_import_count.get() + 1);
307+
continue;
283308
}
284-
ResolveResult::Indeterminate => break, // Bail out. We'll come around next time.
285-
ResolveResult::Success(()) => () // Good. Continue.
286309
}
310+
// This resolution was not successful, keep it for later
311+
indeterminate_imports.push(imports.swap_remove(import_index));
287312

288-
module.resolved_import_count
289-
.set(module.resolved_import_count.get() + 1);
290313
}
314+
315+
imports.extend(indeterminate_imports);
316+
317+
errors
291318
}
292319

293320
/// Attempts to resolve the given import. The return value indicates
@@ -367,11 +394,10 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
367394
}
368395

369396
// Decrement the count of unresolved globs if necessary. But only if
370-
// the resolution result is indeterminate -- otherwise we'll stop
371-
// processing imports here. (See the loop in
372-
// resolve_imports_for_module).
397+
// the resolution result is a success -- other cases will
398+
// be handled by the main loop.
373399

374-
if !resolution_result.indeterminate() {
400+
if resolution_result.success() {
375401
match import_directive.subclass {
376402
GlobImport => {
377403
assert!(module_.glob_count.get() >= 1);

0 commit comments

Comments
 (0)