@@ -45,8 +45,8 @@ use crate::{
45
45
AmbiguityError , AmbiguityErrorMisc , AmbiguityKind , BindingError , BindingKey , Finalize ,
46
46
ForwardGenericParamBanReason , HasGenericParams , LexicalScopeBinding , MacroRulesScope , Module ,
47
47
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,
50
50
} ;
51
51
52
52
type Res = def:: Res < ast:: NodeId > ;
@@ -465,61 +465,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
465
465
err. subdiagnostic ( errors:: RemoveUnnecessaryImport { span } ) ;
466
466
}
467
467
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
-
523
468
pub ( crate ) fn add_module_candidates (
524
469
& self ,
525
470
module : Module < ' ra > ,
@@ -1046,15 +991,17 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
1046
991
if filter_fn ( res) {
1047
992
for derive in parent_scope. derives {
1048
993
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 {
1058
1005
continue ;
1059
1006
} ;
1060
1007
suggestions. extend (
@@ -1589,15 +1536,17 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
1589
1536
} ) ;
1590
1537
}
1591
1538
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 {
1601
1550
continue ;
1602
1551
} ;
1603
1552
@@ -2269,21 +2218,22 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
2269
2218
if ns == TypeNS || ns == ValueNS {
2270
2219
let ns_to_try = if ns == TypeNS { ValueNS } else { TypeNS } ;
2271
2220
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 ( )
2282
2232
} else if let Some ( ribs) = ribs
2283
2233
&& let Some ( TypeNS | ValueNS ) = opt_ns
2284
2234
{
2285
2235
assert ! ( ignore_import. is_none( ) ) ;
2286
- match self . resolve_ident_in_lexical_scope (
2236
+ match SmartResolver :: Speculative ( self ) . resolve_ident_in_lexical_scope (
2287
2237
ident,
2288
2238
ns_to_try,
2289
2239
parent_scope,
@@ -2296,16 +2246,17 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
2296
2246
_ => None ,
2297
2247
}
2298
2248
} 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 ( )
2309
2260
} ;
2310
2261
if let Some ( binding) = binding {
2311
2262
msg = format ! (
@@ -2332,7 +2283,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
2332
2283
// Check whether the name refers to an item in the value namespace.
2333
2284
let binding = if let Some ( ribs) = ribs {
2334
2285
assert ! ( ignore_import. is_none( ) ) ;
2335
- self . resolve_ident_in_lexical_scope (
2286
+ SmartResolver :: Speculative ( self ) . resolve_ident_in_lexical_scope (
2336
2287
ident,
2337
2288
ValueNS ,
2338
2289
parent_scope,
@@ -2399,15 +2350,17 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
2399
2350
} ,
2400
2351
)
2401
2352
} ) ;
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
+ {
2411
2364
let descr = binding. res ( ) . descr ( ) ;
2412
2365
( format ! ( "{descr} `{ident}` is not a crate or module" ) , suggestion)
2413
2366
} else {
@@ -3297,6 +3250,63 @@ fn show_candidates(
3297
3250
showed
3298
3251
}
3299
3252
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
+
3300
3310
#[ derive( Debug ) ]
3301
3311
struct UsePlacementFinder {
3302
3312
target_module : NodeId ,
0 commit comments