@@ -8,12 +8,13 @@ use rustc_errors::{
88} ;
99use rustc_feature:: BUILTIN_ATTRIBUTES ;
1010use rustc_hir:: def:: Namespace :: { self , * } ;
11- use rustc_hir:: def:: { self , CtorKind , CtorOf , DefKind , NonMacroAttrKind } ;
11+ use rustc_hir:: def:: { self , CtorKind , CtorOf , DefKind , NonMacroAttrKind , PerNS } ;
1212use rustc_hir:: def_id:: { DefId , CRATE_DEF_INDEX , LOCAL_CRATE } ;
1313use rustc_hir:: PrimTy ;
1414use rustc_middle:: bug;
1515use rustc_middle:: ty:: DefIdTree ;
1616use rustc_session:: Session ;
17+ use rustc_span:: edition:: Edition ;
1718use rustc_span:: hygiene:: MacroKind ;
1819use rustc_span:: lev_distance:: find_best_match_for_name;
1920use rustc_span:: source_map:: SourceMap ;
@@ -22,10 +23,11 @@ use rustc_span::{BytePos, Span};
2223use tracing:: debug;
2324
2425use crate :: imports:: { Import , ImportKind , ImportResolver } ;
26+ use crate :: late:: Rib ;
2527use crate :: path_names_to_string;
26- use crate :: { AmbiguityError , AmbiguityErrorMisc , AmbiguityKind } ;
28+ use crate :: { AmbiguityError , AmbiguityErrorMisc , AmbiguityKind , Finalize } ;
2729use crate :: { BindingError , HasGenericParams , MacroRulesScope , Module , ModuleOrUniformRoot } ;
28- use crate :: { NameBinding , NameBindingKind , PrivacyError , VisResolutionError } ;
30+ use crate :: { LexicalScopeBinding , NameBinding , NameBindingKind , PrivacyError , VisResolutionError } ;
2931use crate :: { ParentScope , PathResult , ResolutionError , Resolver , Scope , ScopeSet , Segment } ;
3032
3133type Res = def:: Res < ast:: NodeId > ;
@@ -1377,6 +1379,196 @@ impl<'a> Resolver<'a> {
13771379 sugg => sugg,
13781380 }
13791381 }
1382+
1383+ crate fn report_path_resolution_error (
1384+ & mut self ,
1385+ path : & [ Segment ] ,
1386+ opt_ns : Option < Namespace > , // `None` indicates a module path in import
1387+ parent_scope : & ParentScope < ' a > ,
1388+ finalize_full : Finalize ,
1389+ ribs : Option < & PerNS < Vec < Rib < ' a > > > > ,
1390+ unusable_binding : Option < & ' a NameBinding < ' a > > ,
1391+ module : Option < ModuleOrUniformRoot < ' a > > ,
1392+ i : usize ,
1393+ ident : Ident ,
1394+ ) -> ( String , Option < Suggestion > ) {
1395+ let finalize = finalize_full. path_span ( ) ;
1396+ let is_last = i == path. len ( ) - 1 ;
1397+ let ns = if is_last { opt_ns. unwrap_or ( TypeNS ) } else { TypeNS } ;
1398+ let module_res = match module {
1399+ Some ( ModuleOrUniformRoot :: Module ( module) ) => module. res ( ) ,
1400+ _ => None ,
1401+ } ;
1402+ if module_res == self . graph_root . res ( ) {
1403+ let is_mod = |res| matches ! ( res, Res :: Def ( DefKind :: Mod , _) ) ;
1404+ let mut candidates = self . lookup_import_candidates ( ident, TypeNS , parent_scope, is_mod) ;
1405+ candidates
1406+ . sort_by_cached_key ( |c| ( c. path . segments . len ( ) , pprust:: path_to_string ( & c. path ) ) ) ;
1407+ if let Some ( candidate) = candidates. get ( 0 ) {
1408+ (
1409+ String :: from ( "unresolved import" ) ,
1410+ Some ( (
1411+ vec ! [ ( ident. span, pprust:: path_to_string( & candidate. path) ) ] ,
1412+ String :: from ( "a similar path exists" ) ,
1413+ Applicability :: MaybeIncorrect ,
1414+ ) ) ,
1415+ )
1416+ } else if self . session . edition ( ) == Edition :: Edition2015 {
1417+ ( format ! ( "maybe a missing crate `{}`?" , ident) , None )
1418+ } else {
1419+ ( format ! ( "could not find `{}` in the crate root" , ident) , None )
1420+ }
1421+ } else if i == 0 {
1422+ if ident. name . as_str ( ) . chars ( ) . next ( ) . map_or ( false , |c| c. is_ascii_uppercase ( ) ) {
1423+ // Check whether the name refers to an item in the value namespace.
1424+ let suggestion = if ribs. is_some ( ) {
1425+ let match_span = match self . resolve_ident_in_lexical_scope (
1426+ ident,
1427+ ValueNS ,
1428+ parent_scope,
1429+ Finalize :: No ,
1430+ & ribs. unwrap ( ) [ ValueNS ] ,
1431+ unusable_binding,
1432+ ) {
1433+ // Name matches a local variable. For example:
1434+ // ```
1435+ // fn f() {
1436+ // let Foo: &str = "";
1437+ // println!("{}", Foo::Bar); // Name refers to local
1438+ // // variable `Foo`.
1439+ // }
1440+ // ```
1441+ Some ( LexicalScopeBinding :: Res ( Res :: Local ( id) ) ) => {
1442+ Some ( * self . pat_span_map . get ( & id) . unwrap ( ) )
1443+ }
1444+
1445+ // Name matches item from a local name binding
1446+ // created by `use` declaration. For example:
1447+ // ```
1448+ // pub Foo: &str = "";
1449+ //
1450+ // mod submod {
1451+ // use super::Foo;
1452+ // println!("{}", Foo::Bar); // Name refers to local
1453+ // // binding `Foo`.
1454+ // }
1455+ // ```
1456+ Some ( LexicalScopeBinding :: Item ( name_binding) ) => Some ( name_binding. span ) ,
1457+ _ => None ,
1458+ } ;
1459+
1460+ if let Some ( span) = match_span {
1461+ Some ( (
1462+ vec ! [ ( span, String :: from( "" ) ) ] ,
1463+ format ! ( "`{}` is defined here, but is not a type" , ident) ,
1464+ Applicability :: MaybeIncorrect ,
1465+ ) )
1466+ } else {
1467+ None
1468+ }
1469+ } else {
1470+ None
1471+ } ;
1472+
1473+ ( format ! ( "use of undeclared type `{}`" , ident) , suggestion)
1474+ } else {
1475+ (
1476+ format ! ( "use of undeclared crate or module `{}`" , ident) ,
1477+ if ident. name == sym:: alloc {
1478+ Some ( (
1479+ vec ! [ ] ,
1480+ String :: from ( "add `extern crate alloc` to use the `alloc` crate" ) ,
1481+ Applicability :: MaybeIncorrect ,
1482+ ) )
1483+ } else {
1484+ self . find_similarly_named_module_or_crate ( ident. name , & parent_scope. module )
1485+ . map ( |sugg| {
1486+ (
1487+ vec ! [ ( ident. span, sugg. to_string( ) ) ] ,
1488+ String :: from ( "there is a crate or module with a similar name" ) ,
1489+ Applicability :: MaybeIncorrect ,
1490+ )
1491+ } )
1492+ } ,
1493+ )
1494+ }
1495+ } else {
1496+ let parent = path[ i - 1 ] . ident . name ;
1497+ let parent = match parent {
1498+ // ::foo is mounted at the crate root for 2015, and is the extern
1499+ // prelude for 2018+
1500+ kw:: PathRoot if self . session . edition ( ) > Edition :: Edition2015 => {
1501+ "the list of imported crates" . to_owned ( )
1502+ }
1503+ kw:: PathRoot | kw:: Crate => "the crate root" . to_owned ( ) ,
1504+ _ => {
1505+ format ! ( "`{}`" , parent)
1506+ }
1507+ } ;
1508+
1509+ let mut msg = format ! ( "could not find `{}` in {}" , ident, parent) ;
1510+ if ns == TypeNS || ns == ValueNS {
1511+ let ns_to_try = if ns == TypeNS { ValueNS } else { TypeNS } ;
1512+ let binding = if let Some ( module) = module {
1513+ self . resolve_ident_in_module (
1514+ module,
1515+ ident,
1516+ ns_to_try,
1517+ parent_scope,
1518+ finalize,
1519+ false ,
1520+ unusable_binding,
1521+ ) . ok ( )
1522+ } else if let Some ( ribs) = ribs
1523+ && let Some ( TypeNS | ValueNS ) = opt_ns
1524+ {
1525+ match self . resolve_ident_in_lexical_scope (
1526+ ident,
1527+ ns_to_try,
1528+ parent_scope,
1529+ finalize_full,
1530+ & ribs[ ns_to_try] ,
1531+ unusable_binding,
1532+ ) {
1533+ // we found a locally-imported or available item/module
1534+ Some ( LexicalScopeBinding :: Item ( binding) ) => Some ( binding) ,
1535+ _ => None ,
1536+ }
1537+ } else {
1538+ let scopes = ScopeSet :: All ( ns_to_try, opt_ns. is_none ( ) ) ;
1539+ self . early_resolve_ident_in_lexical_scope (
1540+ ident,
1541+ scopes,
1542+ parent_scope,
1543+ finalize,
1544+ finalize. is_some ( ) ,
1545+ false ,
1546+ unusable_binding,
1547+ ) . ok ( )
1548+ } ;
1549+ if let Some ( binding) = binding {
1550+ let mut found = |what| {
1551+ msg = format ! (
1552+ "expected {}, found {} `{}` in {}" ,
1553+ ns. descr( ) ,
1554+ what,
1555+ ident,
1556+ parent
1557+ )
1558+ } ;
1559+ if binding. module ( ) . is_some ( ) {
1560+ found ( "module" )
1561+ } else {
1562+ match binding. res ( ) {
1563+ Res :: Def ( kind, id) => found ( kind. descr ( id) ) ,
1564+ _ => found ( ns_to_try. descr ( ) ) ,
1565+ }
1566+ }
1567+ } ;
1568+ }
1569+ ( msg, None )
1570+ }
1571+ }
13801572}
13811573
13821574impl < ' a , ' b > ImportResolver < ' a , ' b > {
0 commit comments