@@ -45,8 +45,8 @@ use crate::{
4545 AmbiguityError , AmbiguityErrorMisc , AmbiguityKind , BindingError , BindingKey , Finalize ,
4646 ForwardGenericParamBanReason , HasGenericParams , LexicalScopeBinding , MacroRulesScope , Module ,
4747 ModuleKind , ModuleOrUniformRoot , NameBinding , NameBindingKind , ParentScope , PathResult ,
48- PrivacyError , ResolutionError , Resolver , Scope , ScopeSet , Segment , UseError , Used ,
49- VisResolutionError , errors as errs, path_names_to_string,
48+ PrivacyError , ResolutionError , Resolver , Scope , ScopeSet , Segment , SmartResolver , UseError ,
49+ Used , VisResolutionError , errors as errs, path_names_to_string,
5050} ;
5151
5252type Res = def:: Res < ast:: NodeId > ;
@@ -465,61 +465,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
465465 err. subdiagnostic ( errors:: RemoveUnnecessaryImport { span } ) ;
466466 }
467467
468- pub ( crate ) fn lint_if_path_starts_with_module (
469- & mut self ,
470- finalize : Option < Finalize > ,
471- path : & [ Segment ] ,
472- second_binding : Option < NameBinding < ' _ > > ,
473- ) {
474- let Some ( Finalize { node_id, root_span, .. } ) = finalize else {
475- return ;
476- } ;
477-
478- let first_name = match path. get ( 0 ) {
479- // In the 2018 edition this lint is a hard error, so nothing to do
480- Some ( seg) if seg. ident . span . is_rust_2015 ( ) && self . tcx . sess . is_rust_2015 ( ) => {
481- seg. ident . name
482- }
483- _ => return ,
484- } ;
485-
486- // We're only interested in `use` paths which should start with
487- // `{{root}}` currently.
488- if first_name != kw:: PathRoot {
489- return ;
490- }
491-
492- match path. get ( 1 ) {
493- // If this import looks like `crate::...` it's already good
494- Some ( Segment { ident, .. } ) if ident. name == kw:: Crate => return ,
495- // Otherwise go below to see if it's an extern crate
496- Some ( _) => { }
497- // If the path has length one (and it's `PathRoot` most likely)
498- // then we don't know whether we're gonna be importing a crate or an
499- // item in our crate. Defer this lint to elsewhere
500- None => return ,
501- }
502-
503- // If the first element of our path was actually resolved to an
504- // `ExternCrate` (also used for `crate::...`) then no need to issue a
505- // warning, this looks all good!
506- if let Some ( binding) = second_binding
507- && let NameBindingKind :: Import { import, .. } = binding. kind
508- // Careful: we still want to rewrite paths from renamed extern crates.
509- && let ImportKind :: ExternCrate { source : None , .. } = import. kind
510- {
511- return ;
512- }
513-
514- let diag = BuiltinLintDiag :: AbsPathWithModule ( root_span) ;
515- self . lint_buffer . buffer_lint (
516- ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE ,
517- node_id,
518- root_span,
519- diag,
520- ) ;
521- }
522-
523468 pub ( crate ) fn add_module_candidates (
524469 & self ,
525470 module : Module < ' ra > ,
@@ -1046,15 +991,17 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
1046991 if filter_fn ( res) {
1047992 for derive in parent_scope. derives {
1048993 let parent_scope = & ParentScope { derives : & [ ] , ..* parent_scope } ;
1049- let Ok ( ( Some ( ext) , _) ) = this. resolve_macro_path (
1050- derive,
1051- Some ( MacroKind :: Derive ) ,
1052- parent_scope,
1053- false ,
1054- false ,
1055- None ,
1056- None ,
1057- ) else {
994+ let Ok ( ( Some ( ext) , _) ) = SmartResolver :: Finalize ( this)
995+ . resolve_macro_path (
996+ derive,
997+ Some ( MacroKind :: Derive ) ,
998+ parent_scope,
999+ false ,
1000+ false ,
1001+ None ,
1002+ None ,
1003+ )
1004+ else {
10581005 continue ;
10591006 } ;
10601007 suggestions. extend (
@@ -1589,15 +1536,17 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
15891536 } ) ;
15901537 }
15911538 for ns in [ Namespace :: MacroNS , Namespace :: TypeNS , Namespace :: ValueNS ] {
1592- let Ok ( binding) = self . early_resolve_ident_in_lexical_scope (
1593- ident,
1594- ScopeSet :: All ( ns) ,
1595- parent_scope,
1596- None ,
1597- false ,
1598- None ,
1599- None ,
1600- ) else {
1539+ let Ok ( binding) = SmartResolver :: Speculative ( self )
1540+ . early_resolve_ident_in_lexical_scope (
1541+ ident,
1542+ ScopeSet :: All ( ns) ,
1543+ parent_scope,
1544+ None ,
1545+ false ,
1546+ None ,
1547+ None ,
1548+ )
1549+ else {
16011550 continue ;
16021551 } ;
16031552
@@ -2269,21 +2218,22 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
22692218 if ns == TypeNS || ns == ValueNS {
22702219 let ns_to_try = if ns == TypeNS { ValueNS } else { TypeNS } ;
22712220 let binding = if let Some ( module) = module {
2272- self . resolve_ident_in_module (
2273- module,
2274- ident,
2275- ns_to_try,
2276- parent_scope,
2277- None ,
2278- ignore_binding,
2279- ignore_import,
2280- )
2281- . ok ( )
2221+ SmartResolver :: Speculative ( self )
2222+ . resolve_ident_in_module (
2223+ module,
2224+ ident,
2225+ ns_to_try,
2226+ parent_scope,
2227+ None ,
2228+ ignore_binding,
2229+ ignore_import,
2230+ )
2231+ . ok ( )
22822232 } else if let Some ( ribs) = ribs
22832233 && let Some ( TypeNS | ValueNS ) = opt_ns
22842234 {
22852235 assert ! ( ignore_import. is_none( ) ) ;
2286- match self . resolve_ident_in_lexical_scope (
2236+ match SmartResolver :: Speculative ( self ) . resolve_ident_in_lexical_scope (
22872237 ident,
22882238 ns_to_try,
22892239 parent_scope,
@@ -2296,16 +2246,17 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
22962246 _ => None ,
22972247 }
22982248 } else {
2299- self . early_resolve_ident_in_lexical_scope (
2300- ident,
2301- ScopeSet :: All ( ns_to_try) ,
2302- parent_scope,
2303- None ,
2304- false ,
2305- ignore_binding,
2306- ignore_import,
2307- )
2308- . ok ( )
2249+ SmartResolver :: Speculative ( self )
2250+ . early_resolve_ident_in_lexical_scope (
2251+ ident,
2252+ ScopeSet :: All ( ns_to_try) ,
2253+ parent_scope,
2254+ None ,
2255+ false ,
2256+ ignore_binding,
2257+ ignore_import,
2258+ )
2259+ . ok ( )
23092260 } ;
23102261 if let Some ( binding) = binding {
23112262 msg = format ! (
@@ -2332,7 +2283,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
23322283 // Check whether the name refers to an item in the value namespace.
23332284 let binding = if let Some ( ribs) = ribs {
23342285 assert ! ( ignore_import. is_none( ) ) ;
2335- self . resolve_ident_in_lexical_scope (
2286+ SmartResolver :: Speculative ( self ) . resolve_ident_in_lexical_scope (
23362287 ident,
23372288 ValueNS ,
23382289 parent_scope,
@@ -2399,15 +2350,17 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
23992350 } ,
24002351 )
24012352 } ) ;
2402- if let Ok ( binding) = self . early_resolve_ident_in_lexical_scope (
2403- ident,
2404- ScopeSet :: All ( ValueNS ) ,
2405- parent_scope,
2406- None ,
2407- false ,
2408- ignore_binding,
2409- ignore_import,
2410- ) {
2353+ if let Ok ( binding) = SmartResolver :: Speculative ( self )
2354+ . early_resolve_ident_in_lexical_scope (
2355+ ident,
2356+ ScopeSet :: All ( ValueNS ) ,
2357+ parent_scope,
2358+ None ,
2359+ false ,
2360+ ignore_binding,
2361+ ignore_import,
2362+ )
2363+ {
24112364 let descr = binding. res ( ) . descr ( ) ;
24122365 ( format ! ( "{descr} `{ident}` is not a crate or module" ) , suggestion)
24132366 } else {
@@ -3297,6 +3250,63 @@ fn show_candidates(
32973250 showed
32983251}
32993252
3253+ impl < ' r , ' ra , ' tcx > SmartResolver < ' r , ' ra , ' tcx > {
3254+ pub ( crate ) fn lint_if_path_starts_with_module (
3255+ mut self ,
3256+ finalize : Option < Finalize > ,
3257+ path : & [ Segment ] ,
3258+ second_binding : Option < NameBinding < ' _ > > ,
3259+ ) {
3260+ let Some ( Finalize { node_id, root_span, .. } ) = finalize else {
3261+ return ;
3262+ } ;
3263+
3264+ let first_name = match path. get ( 0 ) {
3265+ // In the 2018 edition this lint is a hard error, so nothing to do
3266+ Some ( seg) if seg. ident . span . is_rust_2015 ( ) && self . tcx . sess . is_rust_2015 ( ) => {
3267+ seg. ident . name
3268+ }
3269+ _ => return ,
3270+ } ;
3271+
3272+ // We're only interested in `use` paths which should start with
3273+ // `{{root}}` currently.
3274+ if first_name != kw:: PathRoot {
3275+ return ;
3276+ }
3277+
3278+ match path. get ( 1 ) {
3279+ // If this import looks like `crate::...` it's already good
3280+ Some ( Segment { ident, .. } ) if ident. name == kw:: Crate => return ,
3281+ // Otherwise go below to see if it's an extern crate
3282+ Some ( _) => { }
3283+ // If the path has length one (and it's `PathRoot` most likely)
3284+ // then we don't know whether we're gonna be importing a crate or an
3285+ // item in our crate. Defer this lint to elsewhere
3286+ None => return ,
3287+ }
3288+
3289+ // If the first element of our path was actually resolved to an
3290+ // `ExternCrate` (also used for `crate::...`) then no need to issue a
3291+ // warning, this looks all good!
3292+ if let Some ( binding) = second_binding
3293+ && let NameBindingKind :: Import { import, .. } = binding. kind
3294+ // Careful: we still want to rewrite paths from renamed extern crates.
3295+ && let ImportKind :: ExternCrate { source : None , .. } = import. kind
3296+ {
3297+ return ;
3298+ }
3299+
3300+ let diag = BuiltinLintDiag :: AbsPathWithModule ( root_span) ;
3301+ self . res_mut ( ) . lint_buffer . buffer_lint (
3302+ ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE ,
3303+ node_id,
3304+ root_span,
3305+ diag,
3306+ ) ;
3307+ }
3308+ }
3309+
33003310#[ derive( Debug ) ]
33013311struct UsePlacementFinder {
33023312 target_module : NodeId ,
0 commit comments