@@ -4,6 +4,7 @@ use crate::late::{LifetimeBinderKind, LifetimeRes, LifetimeRibKind, LifetimeUseS
4
4
use crate :: { errors, path_names_to_string} ;
5
5
use crate :: { Module , ModuleKind , ModuleOrUniformRoot } ;
6
6
use crate :: { PathResult , PathSource , Segment } ;
7
+ use rustc_hir:: def:: Namespace :: { self , * } ;
7
8
8
9
use rustc_ast:: visit:: { FnCtxt , FnKind , LifetimeCtxt } ;
9
10
use rustc_ast:: {
@@ -17,7 +18,6 @@ use rustc_errors::{
17
18
MultiSpan ,
18
19
} ;
19
20
use rustc_hir as hir;
20
- use rustc_hir:: def:: Namespace :: { self , * } ;
21
21
use rustc_hir:: def:: { self , CtorKind , CtorOf , DefKind } ;
22
22
use rustc_hir:: def_id:: { DefId , CRATE_DEF_ID } ;
23
23
use rustc_hir:: PrimTy ;
@@ -221,10 +221,14 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
221
221
let suggestion = if self . current_trait_ref . is_none ( )
222
222
&& let Some ( ( fn_kind, _) ) = self . diagnostic_metadata . current_function
223
223
&& let Some ( FnCtxt :: Assoc ( _) ) = fn_kind. ctxt ( )
224
+ && let FnKind :: Fn ( _, _, sig, ..) = fn_kind
224
225
&& let Some ( items) = self . diagnostic_metadata . current_impl_items
225
226
&& let Some ( item) = items. iter ( ) . find ( |i| {
226
227
if let AssocItemKind :: Fn ( ..) | AssocItemKind :: Const ( ..) = & i. kind
227
228
&& i. ident . name == item_str. name
229
+ // don't suggest if the item is in Fn signature arguments
230
+ // issue #112590
231
+ && !sig. span . contains ( item_span)
228
232
{
229
233
debug ! ( ?item_str. name) ;
230
234
return true
@@ -318,11 +322,56 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
318
322
}
319
323
}
320
324
325
+ /// Try to suggest for a module path that cannot be resolved.
326
+ /// Such as `fmt::Debug` where `fmt` is not resolved without importing,
327
+ /// here we search with `lookup_import_candidates` for a module named `fmt`
328
+ /// with `TypeNS` as namespace.
329
+ ///
330
+ /// We need a separate function here because we won't suggest for a path with single segment
331
+ /// and we won't change `SourcePath` api `is_expected` to match `Type` with `DefKind::Mod`
332
+ pub ( crate ) fn smart_resolve_partial_mod_path_errors (
333
+ & mut self ,
334
+ prefix_path : & [ Segment ] ,
335
+ path : & [ Segment ] ,
336
+ ) -> Vec < ImportSuggestion > {
337
+ let next_seg = if path. len ( ) >= prefix_path. len ( ) + 1 && prefix_path. len ( ) == 1 {
338
+ path. get ( prefix_path. len ( ) )
339
+ } else {
340
+ None
341
+ } ;
342
+ if let Some ( segment) = prefix_path. last ( ) &&
343
+ let Some ( next_seg) = next_seg {
344
+ let candidates = self . r . lookup_import_candidates (
345
+ segment. ident ,
346
+ Namespace :: TypeNS ,
347
+ & self . parent_scope ,
348
+ & |res : Res | matches ! ( res, Res :: Def ( DefKind :: Mod , _) ) ,
349
+ ) ;
350
+ // double check next seg is valid
351
+ candidates
352
+ . into_iter ( )
353
+ . filter ( |candidate| {
354
+ if let Some ( def_id) = candidate. did &&
355
+ let Some ( module) = self . r . get_module ( def_id) {
356
+ self . r . resolutions ( module) . borrow ( ) . iter ( ) . any ( |( key, _r) | {
357
+ key. ident . name == next_seg. ident . name
358
+ } )
359
+ } else {
360
+ false
361
+ }
362
+ } )
363
+ . collect :: < Vec < _ > > ( )
364
+ } else {
365
+ Vec :: new ( )
366
+ }
367
+ }
368
+
321
369
/// Handles error reporting for `smart_resolve_path_fragment` function.
322
370
/// Creates base error and amends it with one short label and possibly some longer helps/notes.
323
371
pub ( crate ) fn smart_resolve_report_errors (
324
372
& mut self ,
325
373
path : & [ Segment ] ,
374
+ full_path : & [ Segment ] ,
326
375
span : Span ,
327
376
source : PathSource < ' _ > ,
328
377
res : Option < Res > ,
@@ -364,7 +413,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
364
413
}
365
414
366
415
let ( found, candidates) =
367
- self . try_lookup_name_relaxed ( & mut err, source, path, span, res, & base_error) ;
416
+ self . try_lookup_name_relaxed ( & mut err, source, path, full_path , span, res, & base_error) ;
368
417
if found {
369
418
return ( err, candidates) ;
370
419
}
@@ -470,6 +519,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
470
519
err : & mut Diagnostic ,
471
520
source : PathSource < ' _ > ,
472
521
path : & [ Segment ] ,
522
+ full_path : & [ Segment ] ,
473
523
span : Span ,
474
524
res : Option < Res > ,
475
525
base_error : & BaseError ,
@@ -639,6 +689,10 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
639
689
}
640
690
}
641
691
692
+ if candidates. is_empty ( ) {
693
+ candidates = self . smart_resolve_partial_mod_path_errors ( path, full_path) ;
694
+ }
695
+
642
696
return ( false , candidates) ;
643
697
}
644
698
0 commit comments