Skip to content

Commit e433f55

Browse files
committed
Fixed diagnostic and added test for issue 81508
1 parent 926ec1c commit e433f55

File tree

4 files changed

+100
-14
lines changed

4 files changed

+100
-14
lines changed

compiler/rustc_resolve/src/late.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1031,7 +1031,6 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
10311031
}
10321032

10331033
ItemKind::Static(ref ty, _, ref expr) | ItemKind::Const(_, ref ty, ref expr) => {
1034-
debug!("resolve_item ItemKind::Const");
10351034
self.with_item_rib(HasGenericParams::No, |this| {
10361035
this.visit_ty(ty);
10371036
if let Some(expr) = expr {
@@ -1597,6 +1596,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
15971596
.try_resolve_as_non_binding(pat_src, pat, bmode, ident, has_sub)
15981597
.unwrap_or_else(|| self.fresh_binding(ident, pat.id, pat_src, bindings));
15991598
self.r.record_partial_res(pat.id, PartialRes::new(res));
1599+
self.r.record_local_span(pat.id, pat.span);
16001600
}
16011601
PatKind::TupleStruct(ref path, ref sub_patterns) => {
16021602
self.smart_resolve_path(

compiler/rustc_resolve/src/lib.rs

+56-13
Original file line numberDiff line numberDiff line change
@@ -884,6 +884,10 @@ pub struct Resolver<'a> {
884884
/// "self-confirming" import resolutions during import validation.
885885
unusable_binding: Option<&'a NameBinding<'a>>,
886886

887+
// Spans for local variables found during resolution
888+
// Used for suggestions during error reporting
889+
local_span_map: NodeMap<Span>,
890+
887891
/// Resolutions for nodes that have a single resolution.
888892
partial_res_map: NodeMap<PartialRes>,
889893
/// Resolutions for import nodes, which have multiple resolutions in different namespaces.
@@ -1262,6 +1266,7 @@ impl<'a> Resolver<'a> {
12621266
last_import_segment: false,
12631267
unusable_binding: None,
12641268

1269+
local_span_map: Default::default(),
12651270
partial_res_map: Default::default(),
12661271
import_res_map: Default::default(),
12671272
label_res_map: Default::default(),
@@ -1879,7 +1884,6 @@ impl<'a> Resolver<'a> {
18791884
ribs,
18801885
)));
18811886
}
1882-
18831887
module = match ribs[i].kind {
18841888
ModuleRibKind(module) => module,
18851889
MacroDefinition(def) if def == self.macro_def(ident.span.ctxt()) => {
@@ -1890,7 +1894,6 @@ impl<'a> Resolver<'a> {
18901894
}
18911895
_ => continue,
18921896
};
1893-
18941897
match module.kind {
18951898
ModuleKind::Block(..) => {} // We can see through blocks
18961899
_ => break,
@@ -1909,17 +1912,19 @@ impl<'a> Resolver<'a> {
19091912
return Some(LexicalScopeBinding::Item(binding));
19101913
}
19111914
}
1915+
let returned_item = self
1916+
.early_resolve_ident_in_lexical_scope(
1917+
orig_ident,
1918+
ScopeSet::Late(ns, module, record_used_id),
1919+
parent_scope,
1920+
record_used,
1921+
record_used,
1922+
path_span,
1923+
)
1924+
.ok()
1925+
.map(LexicalScopeBinding::Item);
19121926

1913-
self.early_resolve_ident_in_lexical_scope(
1914-
orig_ident,
1915-
ScopeSet::Late(ns, module, record_used_id),
1916-
parent_scope,
1917-
record_used,
1918-
record_used,
1919-
path_span,
1920-
)
1921-
.ok()
1922-
.map(LexicalScopeBinding::Item)
1927+
returned_item
19231928
}
19241929

19251930
fn hygienic_lexical_parent(
@@ -2386,7 +2391,40 @@ impl<'a> Resolver<'a> {
23862391
.next()
23872392
.map_or(false, |c| c.is_ascii_uppercase())
23882393
{
2389-
(format!("use of undeclared type `{}`", ident), None)
2394+
// Add check case for similarly named item in alternative namespace
2395+
let mut suggestion = None;
2396+
2397+
if ribs.is_some() {
2398+
if let Some(res) = self.resolve_ident_in_lexical_scope(
2399+
ident,
2400+
ValueNS,
2401+
parent_scope,
2402+
None,
2403+
path_span,
2404+
&ribs.unwrap()[ValueNS],
2405+
) {
2406+
let mut match_span: Option<Span> = None;
2407+
match res {
2408+
LexicalScopeBinding::Res(Res::Local(id)) => {
2409+
match_span =
2410+
Some(*self.local_span_map.get(&id).unwrap());
2411+
}
2412+
LexicalScopeBinding::Item(name_binding) => {
2413+
match_span = Some(name_binding.span);
2414+
}
2415+
_ => (),
2416+
};
2417+
if let Some(span) = match_span {
2418+
suggestion = Some((
2419+
vec![(span, String::from(""))],
2420+
format!("{} is defined here, but is not a type", ident),
2421+
Applicability::MaybeIncorrect,
2422+
));
2423+
}
2424+
}
2425+
}
2426+
2427+
(format!("use of undeclared type `{}`", ident), suggestion)
23902428
} else {
23912429
(format!("use of undeclared crate or module `{}`", ident), None)
23922430
}
@@ -2797,6 +2835,11 @@ impl<'a> Resolver<'a> {
27972835
}
27982836
}
27992837

2838+
fn record_local_span(&mut self, node: NodeId, span: Span) {
2839+
debug!("(recording local) recording {:?} for {:?}", node, span);
2840+
self.local_span_map.insert(node, span);
2841+
}
2842+
28002843
fn is_accessible_from(&self, vis: ty::Visibility, module: Module<'a>) -> bool {
28012844
vis.is_accessible_from(module.nearest_parent_mod, self)
28022845
}

src/test/ui/resolve/issue-81508.rs

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Confusing diagnostic when using variable as a type:
2+
//
3+
// Previous warnings indicate Foo is not used, when in fact it is
4+
// used improperly as a variable or constant. New warning points
5+
// out user may be trying to use variable as a type. Test demonstrates
6+
// cases for both local variable and const.
7+
8+
fn main() {
9+
let Baz: &str = "";
10+
11+
println!("{}", Baz::Bar); //~ ERROR: failed to resolve: use of undeclared type `Baz`
12+
}
13+
14+
#[allow(non_upper_case_globals)]
15+
pub const Foo: &str = "";
16+
17+
mod submod {
18+
use super::Foo;
19+
fn function() {
20+
println!("{}", Foo::Bar); //~ ERROR: failed to resolve: use of undeclared type `Foo`
21+
}
22+
}
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
error[E0433]: failed to resolve: use of undeclared type `Baz`
2+
--> $DIR/issue-81508.rs:11:20
3+
|
4+
LL | let Baz: &str = "";
5+
| --- help: Baz is defined here, but is not a type
6+
LL |
7+
LL | println!("{}", Baz::Bar);
8+
| ^^^ use of undeclared type `Baz`
9+
10+
error[E0433]: failed to resolve: use of undeclared type `Foo`
11+
--> $DIR/issue-81508.rs:20:24
12+
|
13+
LL | use super::Foo;
14+
| ---------- help: Foo is defined here, but is not a type
15+
LL | fn function() {
16+
LL | println!("{}", Foo::Bar);
17+
| ^^^ use of undeclared type `Foo`
18+
19+
error: aborting due to 2 previous errors
20+
21+
For more information about this error, try `rustc --explain E0433`.

0 commit comments

Comments
 (0)