mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-05 03:38:29 +00:00
resolve: Create dummy bindings for all unresolved imports
This commit is contained in:
parent
18f32b73bd
commit
09195d3822
@ -583,18 +583,23 @@ impl<'a> Resolver<'a> {
|
|||||||
t
|
t
|
||||||
}
|
}
|
||||||
|
|
||||||
// Define a "dummy" resolution containing a Res::Err as a placeholder for a
|
// Define a dummy resolution containing a `Res::Err` as a placeholder for a failed resolution,
|
||||||
// failed resolution
|
// also mark such failed imports as used to avoid duplicate diagnostics.
|
||||||
fn import_dummy_binding(&mut self, import: &'a Import<'a>) {
|
fn import_dummy_binding(&mut self, import: &'a Import<'a>) {
|
||||||
if let ImportKind::Single { target, .. } = import.kind {
|
if let ImportKind::Single { target, ref target_bindings, .. } = import.kind {
|
||||||
|
if target_bindings.iter().any(|binding| binding.get().is_some()) {
|
||||||
|
return; // Has resolution, do not create the dummy binding
|
||||||
|
}
|
||||||
let dummy_binding = self.dummy_binding;
|
let dummy_binding = self.dummy_binding;
|
||||||
let dummy_binding = self.import(dummy_binding, import);
|
let dummy_binding = self.import(dummy_binding, import);
|
||||||
self.per_ns(|this, ns| {
|
self.per_ns(|this, ns| {
|
||||||
let key = this.new_key(target, ns);
|
let key = this.new_key(target, ns);
|
||||||
let _ = this.try_define(import.parent_scope.module, key, dummy_binding);
|
let _ = this.try_define(import.parent_scope.module, key, dummy_binding);
|
||||||
});
|
});
|
||||||
// Consider erroneous imports used to avoid duplicate diagnostics.
|
|
||||||
self.record_use(target, dummy_binding, false);
|
self.record_use(target, dummy_binding, false);
|
||||||
|
} else if import.imported_module.get().is_none() {
|
||||||
|
import.used.set(true);
|
||||||
|
self.used_imports.insert(import.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -659,7 +664,13 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
|
|||||||
.map(|i| (false, i))
|
.map(|i| (false, i))
|
||||||
.chain(indeterminate_imports.into_iter().map(|i| (true, i)))
|
.chain(indeterminate_imports.into_iter().map(|i| (true, i)))
|
||||||
{
|
{
|
||||||
if let Some(err) = self.finalize_import(import) {
|
let unresolved_import_error = self.finalize_import(import);
|
||||||
|
|
||||||
|
// If this import is unresolved then create a dummy import
|
||||||
|
// resolution for it so that later resolve stages won't complain.
|
||||||
|
self.r.import_dummy_binding(import);
|
||||||
|
|
||||||
|
if let Some(err) = unresolved_import_error {
|
||||||
if let ImportKind::Single { source, ref source_bindings, .. } = import.kind {
|
if let ImportKind::Single { source, ref source_bindings, .. } = import.kind {
|
||||||
if source.name == kw::SelfLower {
|
if source.name == kw::SelfLower {
|
||||||
// Silence `unresolved import` error if E0429 is already emitted
|
// Silence `unresolved import` error if E0429 is already emitted
|
||||||
@ -669,9 +680,6 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the error is a single failed import then create a "fake" import
|
|
||||||
// resolution for it so that later resolve stages won't complain.
|
|
||||||
self.r.import_dummy_binding(import);
|
|
||||||
if prev_root_id.as_u32() != 0
|
if prev_root_id.as_u32() != 0
|
||||||
&& prev_root_id.as_u32() != import.root_id.as_u32()
|
&& prev_root_id.as_u32() != import.root_id.as_u32()
|
||||||
&& !errors.is_empty()
|
&& !errors.is_empty()
|
||||||
@ -691,8 +699,6 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
|
|||||||
prev_root_id = import.root_id;
|
prev_root_id = import.root_id;
|
||||||
}
|
}
|
||||||
} else if is_indeterminate {
|
} else if is_indeterminate {
|
||||||
// Consider erroneous imports used to avoid duplicate diagnostics.
|
|
||||||
self.r.used_imports.insert(import.id);
|
|
||||||
let path = import_path_to_string(
|
let path = import_path_to_string(
|
||||||
&import.module_path.iter().map(|seg| seg.ident).collect::<Vec<_>>(),
|
&import.module_path.iter().map(|seg| seg.ident).collect::<Vec<_>>(),
|
||||||
&import.kind,
|
&import.kind,
|
||||||
@ -824,26 +830,23 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
|
|||||||
Err(Undetermined) => indeterminate = true,
|
Err(Undetermined) => indeterminate = true,
|
||||||
// Don't update the resolution, because it was never added.
|
// Don't update the resolution, because it was never added.
|
||||||
Err(Determined) if target.name == kw::Underscore => {}
|
Err(Determined) if target.name == kw::Underscore => {}
|
||||||
Err(Determined) => {
|
Ok(binding) if binding.is_importable() => {
|
||||||
|
let imported_binding = this.import(binding, import);
|
||||||
|
target_bindings[ns].set(Some(imported_binding));
|
||||||
|
this.define(parent, target, ns, imported_binding);
|
||||||
|
}
|
||||||
|
source_binding @ (Ok(..) | Err(Determined)) => {
|
||||||
|
if source_binding.is_ok() {
|
||||||
|
let msg = format!("`{}` is not directly importable", target);
|
||||||
|
struct_span_err!(this.session, import.span, E0253, "{}", &msg)
|
||||||
|
.span_label(import.span, "cannot be imported directly")
|
||||||
|
.emit();
|
||||||
|
}
|
||||||
let key = this.new_key(target, ns);
|
let key = this.new_key(target, ns);
|
||||||
this.update_resolution(parent, key, |_, resolution| {
|
this.update_resolution(parent, key, |_, resolution| {
|
||||||
resolution.single_imports.remove(&Interned::new_unchecked(import));
|
resolution.single_imports.remove(&Interned::new_unchecked(import));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Ok(binding) if !binding.is_importable() => {
|
|
||||||
let msg = format!("`{}` is not directly importable", target);
|
|
||||||
struct_span_err!(this.session, import.span, E0253, "{}", &msg)
|
|
||||||
.span_label(import.span, "cannot be imported directly")
|
|
||||||
.emit();
|
|
||||||
// Do not import this illegal binding. Import a dummy binding and pretend
|
|
||||||
// everything is fine
|
|
||||||
this.import_dummy_binding(import);
|
|
||||||
}
|
|
||||||
Ok(binding) => {
|
|
||||||
let imported_binding = this.import(binding, import);
|
|
||||||
target_bindings[ns].set(Some(imported_binding));
|
|
||||||
this.define(parent, target, ns, imported_binding);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -876,10 +879,6 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
|
|||||||
self.r.unusable_binding = orig_unusable_binding;
|
self.r.unusable_binding = orig_unusable_binding;
|
||||||
}
|
}
|
||||||
import.vis.set(orig_vis);
|
import.vis.set(orig_vis);
|
||||||
if let PathResult::Failed { .. } | PathResult::NonModule(..) = path_res {
|
|
||||||
// Consider erroneous imports used to avoid duplicate diagnostics.
|
|
||||||
self.r.used_imports.insert(import.id);
|
|
||||||
}
|
|
||||||
let module = match path_res {
|
let module = match path_res {
|
||||||
PathResult::Module(module) => {
|
PathResult::Module(module) => {
|
||||||
// Consistency checks, analogous to `finalize_macro_resolutions`.
|
// Consistency checks, analogous to `finalize_macro_resolutions`.
|
||||||
@ -1144,7 +1143,6 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
|
|||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
// `resolve_ident_in_module` reported a privacy error.
|
// `resolve_ident_in_module` reported a privacy error.
|
||||||
self.r.import_dummy_binding(import);
|
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
// Regression test for issue #95879.
|
||||||
|
|
||||||
|
use unresolved_crate::module::Name; //~ ERROR failed to resolve
|
||||||
|
|
||||||
|
/// [Name]
|
||||||
|
pub struct S;
|
@ -0,0 +1,11 @@
|
|||||||
|
error[E0433]: failed to resolve: maybe a missing crate `unresolved_crate`?
|
||||||
|
--> $DIR/unresolved-import-recovery.rs:3:5
|
||||||
|
|
|
||||||
|
LL | use unresolved_crate::module::Name;
|
||||||
|
| ^^^^^^^^^^^^^^^^ maybe a missing crate `unresolved_crate`?
|
||||||
|
|
||||||
|
error: Compilation failed, aborting rustdoc
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0433`.
|
@ -9,7 +9,7 @@ mod foo {
|
|||||||
|
|
||||||
pub fn g() {
|
pub fn g() {
|
||||||
use ::super::main; //~ ERROR global paths cannot start with `super`
|
use ::super::main; //~ ERROR global paths cannot start with `super`
|
||||||
main(); //~ ERROR cannot find function `main` in this scope
|
main();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,18 +16,6 @@ error[E0433]: failed to resolve: global paths cannot start with `super`
|
|||||||
LL | use ::super::main;
|
LL | use ::super::main;
|
||||||
| ^^^^^ global paths cannot start with `super`
|
| ^^^^^ global paths cannot start with `super`
|
||||||
|
|
||||||
error[E0425]: cannot find function `main` in this scope
|
error: aborting due to 3 previous errors
|
||||||
--> $DIR/use-super-global-path.rs:12:9
|
|
||||||
|
|
|
||||||
LL | main();
|
|
||||||
| ^^^^ not found in this scope
|
|
||||||
|
|
|
||||||
help: consider importing this function
|
|
||||||
|
|
|
||||||
LL | use main;
|
|
||||||
|
|
|
||||||
|
|
||||||
error: aborting due to 4 previous errors
|
For more information about this error, try `rustc --explain E0433`.
|
||||||
|
|
||||||
Some errors have detailed explanations: E0425, E0433.
|
|
||||||
For more information about an error, try `rustc --explain E0425`.
|
|
||||||
|
Loading…
Reference in New Issue
Block a user