Fixed diagnostic and added test for issue 81508
This commit is contained in:
parent
926ec1cb8b
commit
e433f55852
4 changed files with 100 additions and 14 deletions
|
@ -1031,7 +1031,6 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||
}
|
||||
|
||||
ItemKind::Static(ref ty, _, ref expr) | ItemKind::Const(_, ref ty, ref expr) => {
|
||||
debug!("resolve_item ItemKind::Const");
|
||||
self.with_item_rib(HasGenericParams::No, |this| {
|
||||
this.visit_ty(ty);
|
||||
if let Some(expr) = expr {
|
||||
|
@ -1597,6 +1596,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|
|||
.try_resolve_as_non_binding(pat_src, pat, bmode, ident, has_sub)
|
||||
.unwrap_or_else(|| self.fresh_binding(ident, pat.id, pat_src, bindings));
|
||||
self.r.record_partial_res(pat.id, PartialRes::new(res));
|
||||
self.r.record_local_span(pat.id, pat.span);
|
||||
}
|
||||
PatKind::TupleStruct(ref path, ref sub_patterns) => {
|
||||
self.smart_resolve_path(
|
||||
|
|
|
@ -884,6 +884,10 @@ pub struct Resolver<'a> {
|
|||
/// "self-confirming" import resolutions during import validation.
|
||||
unusable_binding: Option<&'a NameBinding<'a>>,
|
||||
|
||||
// Spans for local variables found during resolution
|
||||
// Used for suggestions during error reporting
|
||||
local_span_map: NodeMap<Span>,
|
||||
|
||||
/// Resolutions for nodes that have a single resolution.
|
||||
partial_res_map: NodeMap<PartialRes>,
|
||||
/// Resolutions for import nodes, which have multiple resolutions in different namespaces.
|
||||
|
@ -1262,6 +1266,7 @@ impl<'a> Resolver<'a> {
|
|||
last_import_segment: false,
|
||||
unusable_binding: None,
|
||||
|
||||
local_span_map: Default::default(),
|
||||
partial_res_map: Default::default(),
|
||||
import_res_map: Default::default(),
|
||||
label_res_map: Default::default(),
|
||||
|
@ -1879,7 +1884,6 @@ impl<'a> Resolver<'a> {
|
|||
ribs,
|
||||
)));
|
||||
}
|
||||
|
||||
module = match ribs[i].kind {
|
||||
ModuleRibKind(module) => module,
|
||||
MacroDefinition(def) if def == self.macro_def(ident.span.ctxt()) => {
|
||||
|
@ -1890,7 +1894,6 @@ impl<'a> Resolver<'a> {
|
|||
}
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
match module.kind {
|
||||
ModuleKind::Block(..) => {} // We can see through blocks
|
||||
_ => break,
|
||||
|
@ -1909,8 +1912,8 @@ impl<'a> Resolver<'a> {
|
|||
return Some(LexicalScopeBinding::Item(binding));
|
||||
}
|
||||
}
|
||||
|
||||
self.early_resolve_ident_in_lexical_scope(
|
||||
let returned_item = self
|
||||
.early_resolve_ident_in_lexical_scope(
|
||||
orig_ident,
|
||||
ScopeSet::Late(ns, module, record_used_id),
|
||||
parent_scope,
|
||||
|
@ -1919,7 +1922,9 @@ impl<'a> Resolver<'a> {
|
|||
path_span,
|
||||
)
|
||||
.ok()
|
||||
.map(LexicalScopeBinding::Item)
|
||||
.map(LexicalScopeBinding::Item);
|
||||
|
||||
returned_item
|
||||
}
|
||||
|
||||
fn hygienic_lexical_parent(
|
||||
|
@ -2386,7 +2391,40 @@ impl<'a> Resolver<'a> {
|
|||
.next()
|
||||
.map_or(false, |c| c.is_ascii_uppercase())
|
||||
{
|
||||
(format!("use of undeclared type `{}`", ident), None)
|
||||
// Add check case for similarly named item in alternative namespace
|
||||
let mut suggestion = None;
|
||||
|
||||
if ribs.is_some() {
|
||||
if let Some(res) = self.resolve_ident_in_lexical_scope(
|
||||
ident,
|
||||
ValueNS,
|
||||
parent_scope,
|
||||
None,
|
||||
path_span,
|
||||
&ribs.unwrap()[ValueNS],
|
||||
) {
|
||||
let mut match_span: Option<Span> = None;
|
||||
match res {
|
||||
LexicalScopeBinding::Res(Res::Local(id)) => {
|
||||
match_span =
|
||||
Some(*self.local_span_map.get(&id).unwrap());
|
||||
}
|
||||
LexicalScopeBinding::Item(name_binding) => {
|
||||
match_span = Some(name_binding.span);
|
||||
}
|
||||
_ => (),
|
||||
};
|
||||
if let Some(span) = match_span {
|
||||
suggestion = Some((
|
||||
vec![(span, String::from(""))],
|
||||
format!("{} is defined here, but is not a type", ident),
|
||||
Applicability::MaybeIncorrect,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(format!("use of undeclared type `{}`", ident), suggestion)
|
||||
} else {
|
||||
(format!("use of undeclared crate or module `{}`", ident), None)
|
||||
}
|
||||
|
@ -2797,6 +2835,11 @@ impl<'a> Resolver<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn record_local_span(&mut self, node: NodeId, span: Span) {
|
||||
debug!("(recording local) recording {:?} for {:?}", node, span);
|
||||
self.local_span_map.insert(node, span);
|
||||
}
|
||||
|
||||
fn is_accessible_from(&self, vis: ty::Visibility, module: Module<'a>) -> bool {
|
||||
vis.is_accessible_from(module.nearest_parent_mod, self)
|
||||
}
|
||||
|
|
22
src/test/ui/resolve/issue-81508.rs
Normal file
22
src/test/ui/resolve/issue-81508.rs
Normal file
|
@ -0,0 +1,22 @@
|
|||
// Confusing diagnostic when using variable as a type:
|
||||
//
|
||||
// Previous warnings indicate Foo is not used, when in fact it is
|
||||
// used improperly as a variable or constant. New warning points
|
||||
// out user may be trying to use variable as a type. Test demonstrates
|
||||
// cases for both local variable and const.
|
||||
|
||||
fn main() {
|
||||
let Baz: &str = "";
|
||||
|
||||
println!("{}", Baz::Bar); //~ ERROR: failed to resolve: use of undeclared type `Baz`
|
||||
}
|
||||
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const Foo: &str = "";
|
||||
|
||||
mod submod {
|
||||
use super::Foo;
|
||||
fn function() {
|
||||
println!("{}", Foo::Bar); //~ ERROR: failed to resolve: use of undeclared type `Foo`
|
||||
}
|
||||
}
|
21
src/test/ui/resolve/issue-81508.stderr
Normal file
21
src/test/ui/resolve/issue-81508.stderr
Normal file
|
@ -0,0 +1,21 @@
|
|||
error[E0433]: failed to resolve: use of undeclared type `Baz`
|
||||
--> $DIR/issue-81508.rs:11:20
|
||||
|
|
||||
LL | let Baz: &str = "";
|
||||
| --- help: Baz is defined here, but is not a type
|
||||
LL |
|
||||
LL | println!("{}", Baz::Bar);
|
||||
| ^^^ use of undeclared type `Baz`
|
||||
|
||||
error[E0433]: failed to resolve: use of undeclared type `Foo`
|
||||
--> $DIR/issue-81508.rs:20:24
|
||||
|
|
||||
LL | use super::Foo;
|
||||
| ---------- help: Foo is defined here, but is not a type
|
||||
LL | fn function() {
|
||||
LL | println!("{}", Foo::Bar);
|
||||
| ^^^ use of undeclared type `Foo`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0433`.
|
Loading…
Add table
Add a link
Reference in a new issue