Skip to content

Commit be0501f

Browse files
committed
suggest similarly named type when use of undeclared crate or module
1 parent 8c1cc82 commit be0501f

File tree

6 files changed

+118
-13
lines changed

6 files changed

+118
-13
lines changed

compiler/rustc_resolve/src/diagnostics.rs

Lines changed: 85 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use rustc_span::{BytePos, Span};
2828
use tracing::debug;
2929

3030
use crate::imports::{Import, ImportKind, ImportResolver};
31-
use crate::late::{PatternSource, Rib};
31+
use crate::late::{PatternSource, Rib, RibKind};
3232
use crate::path_names_to_string;
3333
use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, BindingError, Finalize};
3434
use crate::{HasGenericParams, MacroRulesScope, Module, ModuleKind, ModuleOrUniformRoot};
@@ -1825,6 +1825,75 @@ impl<'a> Resolver<'a> {
18251825
}
18261826
}
18271827

1828+
fn find_similarly_named_type(
1829+
&mut self,
1830+
ident: Symbol,
1831+
ribs: Option<&PerNS<Vec<Rib<'a>>>>,
1832+
) -> Option<Symbol> {
1833+
fn is_type_candidate(res: Res) -> bool {
1834+
matches!(
1835+
res,
1836+
Res::Def(
1837+
DefKind::Struct
1838+
| DefKind::Union
1839+
| DefKind::Enum
1840+
| DefKind::Trait
1841+
| DefKind::TraitAlias
1842+
| DefKind::TyAlias
1843+
| DefKind::AssocTy
1844+
| DefKind::TyParam
1845+
| DefKind::OpaqueTy
1846+
| DefKind::ForeignTy,
1847+
_
1848+
) | Res::PrimTy(..)
1849+
| Res::SelfTy { .. }
1850+
)
1851+
}
1852+
1853+
let mut names = Vec::new();
1854+
if let Some(ribs) = ribs {
1855+
// Search in lexical scope.
1856+
// Walk backwards up the ribs in scope and collect candidates.
1857+
for rib in ribs[TypeNS].iter().rev() {
1858+
for (ident, res) in &rib.bindings {
1859+
if is_type_candidate(*res) {
1860+
names.push(TypoSuggestion::typo_from_res(ident.name, *res));
1861+
}
1862+
}
1863+
// Items in scope
1864+
if let RibKind::ModuleRibKind(module) = rib.kind {
1865+
// Items from this module
1866+
self.add_module_candidates(module, &mut names, &is_type_candidate);
1867+
1868+
if let ModuleKind::Block(..) = module.kind {
1869+
// We can through blocks
1870+
} else {
1871+
// Items from the prelude
1872+
if !module.no_implicit_prelude {
1873+
if let Some(prelude) = self.prelude {
1874+
self.add_module_candidates(prelude, &mut names, &is_type_candidate);
1875+
}
1876+
}
1877+
break;
1878+
}
1879+
}
1880+
}
1881+
// Add primitive types
1882+
names.extend(PrimTy::ALL.iter().map(|prim_ty| {
1883+
TypoSuggestion::typo_from_res(prim_ty.name(), Res::PrimTy(*prim_ty))
1884+
}))
1885+
}
1886+
1887+
let mut names = names.iter().map(|sugg| sugg.candidate).collect::<Vec<Symbol>>();
1888+
names.sort();
1889+
names.dedup();
1890+
1891+
match find_best_match_for_name(&names, ident, None) {
1892+
Some(sugg) if sugg == ident => None,
1893+
sugg => sugg,
1894+
}
1895+
}
1896+
18281897
pub(crate) fn report_path_resolution_error(
18291898
&mut self,
18301899
path: &[Segment],
@@ -2001,16 +2070,22 @@ impl<'a> Resolver<'a> {
20012070
String::from("add `extern crate alloc` to use the `alloc` crate"),
20022071
Applicability::MaybeIncorrect,
20032072
))
2073+
} else if let Some(sugg) =
2074+
self.find_similarly_named_module_or_crate(ident.name, &parent_scope.module)
2075+
{
2076+
Some((
2077+
vec![(ident.span, sugg.to_string())],
2078+
String::from("there is a crate or module with a similar name"),
2079+
Applicability::MaybeIncorrect,
2080+
))
20042081
} else {
2005-
self.find_similarly_named_module_or_crate(ident.name, &parent_scope.module).map(
2006-
|sugg| {
2007-
(
2008-
vec![(ident.span, sugg.to_string())],
2009-
String::from("there is a crate or module with a similar name"),
2010-
Applicability::MaybeIncorrect,
2011-
)
2012-
},
2013-
)
2082+
self.find_similarly_named_type(ident.name, ribs).map(|sugg| {
2083+
(
2084+
vec![(ident.span, sugg.to_string())],
2085+
String::from("there is a type with a similar name"),
2086+
Applicability::MaybeIncorrect,
2087+
)
2088+
})
20142089
};
20152090
(format!("use of undeclared crate or module `{}`", ident), suggestion)
20162091
}

src/test/ui/macros/builtin-prelude-no-accidents.stderr

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@ error[E0433]: failed to resolve: use of undeclared crate or module `vec`
1414
--> $DIR/builtin-prelude-no-accidents.rs:7:14
1515
|
1616
LL | type B = vec::Vec<u8>;
17-
| ^^^ use of undeclared crate or module `vec`
17+
| ^^^
18+
| |
19+
| use of undeclared crate or module `vec`
20+
| help: there is a type with a similar name (notice the capitalization): `Vec`
1821

1922
error: aborting due to 3 previous errors
2023

src/test/ui/macros/macro_path_as_generic_bound.stderr

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ error[E0433]: failed to resolve: use of undeclared crate or module `m`
22
--> $DIR/macro_path_as_generic_bound.rs:7:6
33
|
44
LL | foo!(m::m2::A);
5-
| ^ use of undeclared crate or module `m`
5+
| ^
6+
| |
7+
| use of undeclared crate or module `m`
8+
| help: there is a type with a similar name: `T`
69

710
error: aborting due to previous error
811

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Beginners often write an incorrect type name whose initial letter is
2+
// a lowercase while the correct one is an uppercase.
3+
// (e.g. `string` instead of `String`)
4+
// This tests that we suggest the latter when we encounter the former.
5+
6+
fn main() {
7+
let _ = string::new();
8+
//~^ ERROR failed to resolve: use of undeclared crate or module `string`
9+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0433]: failed to resolve: use of undeclared crate or module `string`
2+
--> $DIR/suggest-type-to-lowercase-path.rs:7:13
3+
|
4+
LL | let _ = string::new();
5+
| ^^^^^^
6+
| |
7+
| use of undeclared crate or module `string`
8+
| help: there is a type with a similar name (notice the capitalization): `String`
9+
10+
error: aborting due to previous error
11+
12+
For more information about this error, try `rustc --explain E0433`.

src/test/ui/suggestions/type-ascription-instead-of-path.stderr

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ error[E0433]: failed to resolve: use of undeclared crate or module `io`
22
--> $DIR/type-ascription-instead-of-path.rs:2:9
33
|
44
LL | std:io::stdin();
5-
| ^^ use of undeclared crate or module `io`
5+
| ^^
6+
| |
7+
| use of undeclared crate or module `io`
8+
| help: there is a type with a similar name: `i8`
69

710
error[E0423]: expected value, found crate `std`
811
--> $DIR/type-ascription-instead-of-path.rs:2:5

0 commit comments

Comments
 (0)