From 63f248b0c0cc5c99f0b063dd837e2240c01cf9c7 Mon Sep 17 00:00:00 2001 From: GTimothy <22472919+GTimothy@users.noreply.github.com> Date: Wed, 6 May 2026 12:08:35 +0200 Subject: [PATCH 01/16] stdlib test cases Co-authored-by: Chris Simpkins --- tests/ui/README.md | 3 + tests/ui/libstd-case-typo/libstd.rs | 439 ++++++++++++++++++++++++++++ 2 files changed, 442 insertions(+) create mode 100644 tests/ui/libstd-case-typo/libstd.rs diff --git a/tests/ui/README.md b/tests/ui/README.md index 2fe1657e7ecf2..1f18f6d2fbc96 100644 --- a/tests/ui/README.md +++ b/tests/ui/README.md @@ -810,6 +810,9 @@ Exercises let-else constructs. Exercises of the lexer. +## `tests/ui/libstd-case-typo/` +Tests for import suggestions with typo tolerance. + ## `tests/ui/lifetimes/` Broad directory on lifetimes, including proper specifiers, lifetimes not living long enough, or undeclared lifetime names. diff --git a/tests/ui/libstd-case-typo/libstd.rs b/tests/ui/libstd-case-typo/libstd.rs new file mode 100644 index 0000000000000..45463a5467cd9 --- /dev/null +++ b/tests/ui/libstd-case-typo/libstd.rs @@ -0,0 +1,439 @@ +// checks case typos with libstd::alloc structs + +fn test_layout(_x: LayOut){} +//~^ ERROR: cannot find type `LayOut` in this scope +fn test_system(_x: system){} +//~^ ERROR: cannot find type `system` in this scope + +// checks case typos with libstd::any structs + +fn test_typeid(_x: Typeid){} +//~^ ERROR: cannot find type `Typeid` in this scope + +// checks case typos with libstd::ascii structs + +fn test_escapedefault(_x: Escapedefault){} +//~^ ERROR: cannot find type `Escapedefault` in this scope + +// checks case typos with libstd::cell structs + +fn test_cell(_x: cell<()>){} +//~^ ERROR: cannot find type `cell` in this scope + +// checks case typos with libstd::char structs + +fn test_decodeutf16(_x: DecodeUTF16<()>){} +//~^ ERROR: cannot find type `DecodeUTF16` in this scope + +fn test_escapeunicode(_x: Escapeunicode){} +//~^ ERROR: cannot find type `Escapeunicode` in this scope + +fn test_tolowercase(_x: Tolowercase){} +//~^ ERROR: cannot find type `Tolowercase` in this scope + +fn test_touppercase(_x: Touppercase){} +//~^ ERROR: cannot find type `Touppercase` in this scope + +// checks case typos with libstd::cmp structs + +fn test_reverse(_x: reverse<()>){} +//~^ ERROR: cannot find type `reverse` in this scope + +// checks case typos with libstd::collections structs + +fn test_btreemap(_x: BtreeMap<(), ()>){} +//~^ ERROR: cannot find type `BtreeMap` in this scope +fn test_btreeset(_x: BtreeSet<()>){} +//~^ ERROR: cannot find type `BtreeSet` in this scope +fn test_binaryheap(_x: Binaryheap<()>){} +//~^ ERROR: cannot find type `Binaryheap` in this scope +fn test_hashmap(_x: Hashmap){} +//~^ ERROR: cannot find type `Hashmap` in this scope +fn test_hashset(_x: Hashset<()>){} +//~^ ERROR: cannot find type `Hashset` in this scope +fn test_linkedlist(_x: Linkedlist<()>){} +//~^ ERROR: cannot find type `Linkedlist` in this scope +fn test_vecdeque(_x: Vecdeque<()>){} +//~^ ERROR: cannot find type `Vecdeque` in this scope + +// checks case typos with libstd::env structs + +fn test_args(_x: args){} +//~^ ERROR: cannot find type `args` in this scope +fn test_argsos(_x: Argsos){} +//~^ ERROR: cannot find type `Argsos` in this scope +fn test_splitpaths(_x: Splitpaths<'_>){} +//~^ ERROR: cannot find type `Splitpaths` in this scope +fn test_vars(_x: vars){} +//~^ ERROR: cannot find type `vars` in this scope +fn test_varsos(_x: Varsos){} +//~^ ERROR: cannot find type `Varsos` in this scope + +// checks case typos with libstd::ffi structs + +fn test_cstr(_x: cStr){} +//~^ ERROR: cannot find type `cStr` in this scope +fn test_osstr(_x: Osstr){} +//~^ ERROR: cannot find type `Osstr` in this scope +fn test_osstring(_x: Osstring){} +//~^ ERROR: cannot find type `Osstring` in this scope + +// checks case typos with libstd::fmt structs + +fn test_debuglist(_x: Debuglist){} +//~^ ERROR: cannot find type `Debuglist` in this scope +fn test_debugmap(_x: Debugmap){} +//~^ ERROR: cannot find type `Debugmap` in this scope +fn test_debugset(_x: Debugset){} +//~^ ERROR: cannot find type `Debugset` in this scope +fn test_debugstruct(_x: Debugstruct){} +//~^ ERROR: cannot find type `Debugstruct` in this scope +fn test_debugtuple(_x: Debugtuple){} +//~^ ERROR: cannot find type `Debugtuple` in this scope +fn test_fmter(mut _x: formatter){} +//~^ ERROR: cannot find type `formatter` in this scope + +// checks case typos with libstd::fs structs + +fn test_dirbuilder(_x: Dirbuilder){} +//~^ ERROR: cannot find type `Dirbuilder` in this scope +fn test_direntry(_x: Direntry){} +//~^ ERROR: cannot find type `Direntry` in this scope +fn test_filetype(_x: Filetype){} +//~^ ERROR: cannot find type `Filetype` in this scope +fn test_metadata(_x: MetaData){} +//~^ ERROR: cannot find type `MetaData` in this scope +fn test_openoptions(_x: Openoptions){} +//~^ ERROR: cannot find type `Openoptions` in this scope +fn test_permissions(_x: permissions){} +//~^ ERROR: cannot find type `permissions` in this scope +fn test_readdir(_x: Readdir){} +//~^ ERROR: cannot find type `Readdir` in this scope + +// checks case typos with libstd::hash structs + +fn test_buildhasherdefault(_x: BuildhasherDefault){} +//~^ ERROR: cannot find type `BuildhasherDefault` in this scope + +// checks case typos with libstd::io structs + +fn test_bufreader(_x: Bufreader<()>){} +//~^ ERROR: cannot find type `Bufreader` in this scope +fn test_bufwriter(_x: Bufwriter<()>){} +//~^ ERROR: cannot find type `Bufwriter` in this scope +fn test_bytes(_x: bytes<()>){} +//~^ ERROR: cannot find type `bytes` in this scope +fn test_chain(_x: chain<(), ()>){} +//~^ ERROR: cannot find type `chain` in this scope +fn test_cursor(_x: cursor<()>){} +//~^ ERROR: cannot find type `cursor` in this scope +fn test_empty(_x: empty){} +//~^ ERROR: cannot find type `empty` in this scope +fn test_ioslice(_x: Ioslice){} +//~^ ERROR: cannot find type `Ioslice` in this scope +fn test_ioslicemut(_x: IosliceMut){} +//~^ ERROR: cannot find type `IosliceMut` in this scope +fn test_linewriter(_x: Linewriter<()>){} +//~^ ERROR: cannot find type `Linewriter` in this scope +fn test_lines(_x: lines<()>){} +//~^ ERROR: cannot find type `lines` in this scope +fn test_repeat(_x: repeat){} +//~^ ERROR: cannot find type `repeat` in this scope +fn test_sink(_x: sink){} +//~^ ERROR: cannot find type `sink` in this scope +fn test_split(_x: split<()>){} +//~^ ERROR: cannot find type `split` in this scope +fn test_stderr(_x: StdErr){} +//~^ ERROR: cannot find type `StdErr` in this scope +fn test_stderrlock(_x: StdErrLock){} +//~^ ERROR: cannot find type `StdErrLock` in this scope +fn test_stdin(_x: StdIn){} +//~^ ERROR: cannot find type `StdIn` in this scope +fn test_stdinlock(_x: StdInLock){} +//~^ ERROR: cannot find type `StdInLock` in this scope +fn test_stdout(_x: StdOut){} +//~^ ERROR: cannot find type `StdOut` in this scope +fn test_stdoutlock(_x: StdOutLock){} +//~^ ERROR: cannot find type `StdOutLock` in this scope +fn test_take(_x: take){} +//~^ ERROR: cannot find type `take` in this scope + +// checks case typos with libstd::iter structs + +fn test_cloned(_x: cloned<(), ()>){} +//~^ ERROR: cannot find type `cloned` in this scope +fn test_copied(_x: copied<(), ()>){} +//~^ ERROR: cannot find type `copied` in this scope +fn test_cycle(_x: cycle<(), ()>){} +//~^ ERROR: cannot find type `cycle` in this scope +fn test_enumerate(_x: enumerate<(), ()>){} +//~^ ERROR: cannot find type `enumerate` in this scope +fn test_filter(_x: filter<(), ()>){} +//~^ ERROR: cannot find type `filter` in this scope +fn test_filtermap(_x: Filtermap<(), ()>){} +//~^ ERROR: cannot find type `Filtermap` in this scope +fn test_flatten(_x: flatten<()>){} +//~^ ERROR: cannot find type `flatten` in this scope +fn test_fromfn(_x: Fromfn<()>){} +//~^ ERROR: cannot find type `Fromfn` in this scope +fn test_fuse(_x: fuse<()>){} +//~^ ERROR: cannot find type `fuse` in this scope +fn test_inspect(_x: inspect<(), ()>){} +//~^ ERROR: cannot find type `inspect` in this scope +fn test_map(_x: map<(), ()>){} +//~^ ERROR: cannot find type `map` in this scope +fn test_once(_x: once<()>){} +//~^ ERROR: cannot find type `once` in this scope +fn test_oncewith(_x: Oncewith<()>){} +//~^ ERROR: cannot find type `Oncewith` in this scope +fn test_peekable(_x: peekable<()>){} +//~^ ERROR: cannot find type `peekable` in this scope +fn test_repeatwith(_x: Repeatwith<()>){} +//~^ ERROR: cannot find type `Repeatwith` in this scope +fn test_rev(_x: rev<()>){} +//~^ ERROR: cannot find type `rev` in this scope +fn test_scan(_x: scan<(), (), ()>){} +//~^ ERROR: cannot find type `scan` in this scope +fn test_skip(_x: skip<()>){} +//~^ ERROR: cannot find type `skip` in this scope +fn test_skipwhile(_x: Skipwhile<(), ()>){} +//~^ ERROR: cannot find type `Skipwhile` in this scope +fn test_stepby(_x: Stepby<()>){} +//~^ ERROR: cannot find type `Stepby` in this scope +fn test_successors(_x: successors<()>){} +//~^ ERROR: cannot find type `successors` in this scope +fn test_takewhile(_x: Takewhile<(), ()>){} +//~^ ERROR: cannot find type `Takewhile` in this scope +fn test_zip(_x: zip<(), ()>){} +//~^ ERROR: cannot find type `zip` in this scope + +// checks case typos with libstd::marker structs + +fn test_phantomdata(_x: Phantomdata){} +//~^ ERROR: cannot find type `Phantomdata` in this scope +fn test_phantompinned(_x: Phantompinned){} +//~^ ERROR: cannot find type `Phantompinned` in this scope + +// checks case typos with libstd::mem structs + +fn test_discriminant(_x: discriminant<()>){} +//~^ ERROR: cannot find type `discriminant` in this scope +fn test_manuallydrop(_x: Manuallydrop<()>){} +//~^ ERROR: cannot find type `Manuallydrop` in this scope + +// checks case typos with libstd::net structs + +fn test_incoming(_x: incoming){} +//~^ ERROR: cannot find type `incoming` in this scope +fn test_ipv4addr(_x: IPv4Addr){} +//~^ ERROR: cannot find type `IPv4Addr` in this scope +fn test_ipv6addr(_x: IPv6Addr){} +//~^ ERROR: cannot find type `IPv6Addr` in this scope +fn test_socketaddrv4(_x: SocketAddrv4){} +//~^ ERROR: cannot find type `SocketAddrv4` in this scope +fn test_socketaddrv6(_x: SocketAddrv6){} +//~^ ERROR: cannot find type `SocketAddrv6` in this scope +fn test_tcplistener(_x: TCPListener){} +//~^ ERROR: cannot find type `TCPListener` in this scope +fn test_tcpstream(_x: TCPStream){} +//~^ ERROR: cannot find type `TCPStream` in this scope +fn test_udpsocket(_x: UDPSocket){} +//~^ ERROR: cannot find type `UDPSocket` in this scope + +// checks case typos with libstd::num structs + +fn test_nonzeroi8(_x: NonZeroi8){} +//~^ ERROR: cannot find type `NonZeroi8` in this scope +fn test_nonzeroi16(_x: NonZeroi16){} +//~^ ERROR: cannot find type `NonZeroi16` in this scope +fn test_nonzeroi32(_x: NonZeroi32){} +//~^ ERROR: cannot find type `NonZeroi32` in this scope +fn test_nonzeroi64(_x: NonZeroi64){} +//~^ ERROR: cannot find type `NonZeroi64` in this scope +fn test_nonzeroi128(_x: NonZeroi128){} +//~^ ERROR: cannot find type `NonZeroi128` in this scope +fn test_nonzerou8(_x: NonZerou8){} +//~^ ERROR: cannot find type `NonZerou8` in this scope +fn test_nonzerou16(_x: NonZerou16){} +//~^ ERROR: cannot find type `NonZerou16` in this scope +fn test_nonzerou32(_x: NonZerou32){} +//~^ ERROR: cannot find type `NonZerou32` in this scope +fn test_nonzerou64(_x: NonZerou64){} +//~^ ERROR: cannot find type `NonZerou64` in this scope +fn test_nonzerou128(_x: NonZerou128){} +//~^ ERROR: cannot find type `NonZerou128` in this scope +fn test_nonzerousize(_x: NonzeroUsize){} +//~^ ERROR: cannot find type `NonzeroUsize` in this scope +fn test_wrapping(_x: wrapping){} +//~^ ERROR: cannot find type `wrapping` in this scope + +// checks case typos with libstd::ops structs + +fn test_range(_x: range<()>){} +//~^ ERROR: cannot find type `range` in this scope +fn test_rangefrom(_x: Rangefrom<()>){} +//~^ ERROR: cannot find type `Rangefrom` in this scope +fn test_rangefull(_x: Rangefull<()>){} +//~^ ERROR: cannot find type `Rangefull` in this scope +fn test_rangeinclusive(_x: Rangeinclusive<()>){} +//~^ ERROR: cannot find type `Rangeinclusive` in this scope +fn test_rangeto(_x: Rangeto<()>){} +//~^ ERROR: cannot find type `Rangeto` in this scope +fn test_rangetoinclusive(_x: RangetoInclusive<()>){} +//~^ ERROR: cannot find type `RangetoInclusive` in this scope + +// checks case typos with libstd::panic structs + +fn test_assertunwindsafe(_x: AssertUnwindsafe<()>){} +//~^ ERROR: cannot find type `AssertUnwindsafe` in this scope +fn test_location(_x: location<()>){} +//~^ ERROR: cannot find type `location` in this scope +fn test_panicinfo(_x: Panicinfo<()>){} +//~^ ERROR: cannot find type `Panicinfo` in this scope + +// checks case typos with libstd::path structs + +fn test_ancestors(_x: ancestors){} +//~^ ERROR: cannot find type `ancestors` in this scope +fn test_components(_x: components){} +//~^ ERROR: cannot find type `components` in this scope +fn test_pathbuf(_x: Pathbuf){} +//~^ ERROR: cannot find type `Pathbuf` in this scope +fn test_prefixcomponent(_x: Prefixcomponent){} +//~^ ERROR: cannot find type `Prefixcomponent` in this scope + +// checks case typos with libstd::pin structs + +fn test_pin(_x: pin<()>){} +//~^ ERROR: cannot find type `pin` in this scope + +// checks case typos with libstd::process structs + +fn test_child(_x: child){} +//~^ ERROR: cannot find type `child` in this scope +fn test_childstderr(_x: ChildStdErr){} +//~^ ERROR: cannot find type `ChildStdErr` in this scope +fn test_childstdin(_x: ChildStdIn){} +//~^ ERROR: cannot find type `ChildStdIn` in this scope +fn test_childstdout(_x: ChildStdOut){} +//~^ ERROR: cannot find type `ChildStdOut` in this scope +fn test_command(_x: command){} +//~^ ERROR: cannot find type `command` in this scope +fn test_exitstatus(_x: Exitstatus){} +//~^ ERROR: cannot find type `Exitstatus` in this scope +fn test_output(_x: output){} +//~^ ERROR: cannot find type `output` in this scope +fn test_stdio(_x: StdIo){} +//~^ ERROR: cannot find type `StdIo` in this scope + +// checks case typos with libstd::ptr structs + +fn test_nonnull(_x: Nonnull<()>){} +//~^ ERROR: cannot find type `Nonnull` in this scope + +// checks case typos with libstd::rc structs + +fn test_rc(_x: rc<()>){} +//~^ ERROR: cannot find type `rc` in this scope +fn test_weak(_x: weak<()>){} +//~^ ERROR: cannot find type `weak` in this scope + +// checks case typos with libstd::string structs + +fn test_drain(_x: drain){} +//~^ ERROR: cannot find type `drain` in this scope + +// checks case typos with libstd::str structs + +fn test_charindices(_x: Charindices){} +//~^ ERROR: cannot find type `Charindices` in this scope +fn test_chars(_x: chars){} +//~^ ERROR: cannot find type `chars` in this scope +fn test_encodeutf16(_x: EncodeUTF16){} +//~^ ERROR: cannot find type `EncodeUTF16` in this scope +fn test_matchindices(_x: Matchindices){} +//~^ ERROR: cannot find type `Matchindices` in this scope +fn test_rmatchindices(_x: RmatchIndices){} +//~^ ERROR: cannot find type `RmatchIndices` in this scope +fn test_rmatches(_x: Rmatches){} +//~^ ERROR: cannot find type `Rmatches` in this scope +fn test_rsplit(_x: Rsplit){} +//~^ ERROR: cannot find type `Rsplit` in this scope +fn test_rsplitn(_x: RSplitn){} +//~^ ERROR: cannot find type `RSplitn` in this scope +fn test_rsplitterminator(_x: RsplitTerminator){} +//~^ ERROR: cannot find type `RsplitTerminator` in this scope +fn test_splitasciiwhitespace(_x: SplitASCIIWhitespace){} +//~^ ERROR: cannot find type `SplitASCIIWhitespace` in this scope +fn test_splitn(_x: Splitn){} +//~^ ERROR: cannot find type `Splitn` in this scope +fn test_splitterminator(_x: Splitterminator){} +//~^ ERROR: cannot find type `Splitterminator` in this scope +fn test_splitwhitespace(_x: Splitwhitespace){} +//~^ ERROR: cannot find type `Splitwhitespace` in this scope + +// checks case typos with libstd::sync structs + +fn test_arc(_x: arc<()>){} +//~^ ERROR: cannot find type `arc` in this scope +fn test_barrier(_x: barrier<()>){} +//~^ ERROR: cannot find type `barrier` in this scope +fn test_barrierwaitresult(_x: BarrierwaitResult<()>){} +//~^ ERROR: cannot find type `BarrierwaitResult` in this scope +fn test_condvar(_x: CondVar<()>){} +//~^ ERROR: cannot find type `CondVar` in this scope +fn test_mutex(_x: mutex<()>){} +//~^ ERROR: cannot find type `mutex` in this scope +fn test_mutexguard(_x: Mutexguard<()>){} +//~^ ERROR: cannot find type `Mutexguard` in this scope +fn test_rwlock(_x: RWlock<()>){} +//~^ ERROR: cannot find type `RWlock` in this scope +fn test_rwlockreadguard(_x: RWlockReadGuard<()>){} +//~^ ERROR: cannot find type `RWlockReadGuard` in this scope +fn test_rwlockwriteguard(_x: RWlockWriteGuard<()>){} +//~^ ERROR: cannot find type `RWlockWriteGuard` in this scope +fn test_waittimeoutresult(_x: WaittimeoutResult<()>){} +//~^ ERROR: cannot find type `WaittimeoutResult` in this scope + +// checks case typos with libstd::task structs + +fn test_context(_x: context){} +//~^ ERROR: cannot find type `context` in this scope +fn test_rawwaker(_x: Rawwaker){} +//~^ ERROR: cannot find type `Rawwaker` in this scope +fn test_rawwakervtable(_x: RawwakerVTable){} +//~^ ERROR: cannot find type `RawwakerVTable` in this scope +fn test_waker(_x: waker){} +//~^ ERROR: cannot find type `waker` in this scope + +// checks case typos with libstd::thread structs + +fn test_builder(_x: builder){} +//~^ ERROR: cannot find type `builder` in this scope +fn test_joinhandle(_x: Joinhandle<()>){} +//~^ ERROR: cannot find type `Joinhandle` in this scope +fn test_localkey(_x: Localkey<()>){} +//~^ ERROR: cannot find type `Localkey` in this scope +fn test_thread(_x: thread){} +//~^ ERROR: cannot find type `thread` in this scope +fn test_threadid(_x: ThreadID){} +//~^ ERROR: cannot find type `ThreadID` in this scope + +// checks case typos with libstd::time structs + +fn test_duration(_x: duration){} +//~^ ERROR: cannot find type `duration` in this scope +fn test_instant(_x: instant){} +//~^ ERROR: cannot find type `instant` in this scope +fn test_systemtime(_x: Systemtime){} +//~^ ERROR: cannot find type `Systemtime` in this scope + +fn test_systemtime2(_x: SystemTime){} +//~^ ERROR: cannot find type `SystemTime` in this scope + +struct SystemTome{} +mod st{ + struct SystemTame{} +} + +fn main(){} From 7b3401b31e3b3b4439a510131c93089b53de8bf4 Mon Sep 17 00:00:00 2001 From: GTimothy <22472919+GTimothy@users.noreply.github.com> Date: Wed, 6 May 2026 12:14:06 +0200 Subject: [PATCH 02/16] suggest imports with edit distance of 1 adds a is_exact_match field to ImportSuggestion that is unused for now. suggestions now include 1-edit variations as suggestions --- compiler/rustc_resolve/src/diagnostics.rs | 62 +++++++++++-------- .../rustc_resolve/src/late/diagnostics.rs | 4 +- 2 files changed, 39 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 7e1dd19167899..c4e2762a9fc4c 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -29,7 +29,7 @@ use rustc_session::lint::builtin::{ AMBIGUOUS_PANIC_IMPORTS, MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS, }; use rustc_session::utils::was_invoked_from_cargo; -use rustc_span::edit_distance::find_best_match_for_name; +use rustc_span::edit_distance::{edit_distance, find_best_match_for_name}; use rustc_span::edition::Edition; use rustc_span::hygiene::MacroKind; use rustc_span::source_map::SourceMap; @@ -118,6 +118,7 @@ pub(crate) struct ImportSuggestion { /// An extra note that should be issued if this item is suggested pub note: Option, pub is_stable: bool, + pub is_exact_match: bool, } /// Adjust the impl span so that just the `impl` keyword is taken by removing @@ -1440,7 +1441,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // collect results based on the filter function // avoid suggesting anything from the same module in which we are resolving // avoid suggesting anything with a hygienic name - if ident.name == lookup_ident.name + let is_exact_match = ident.name == lookup_ident.name; + if (is_exact_match + || Some(1) == edit_distance(ident.name.as_str(), lookup_ident.name.as_str(), 1)) && ns == namespace && in_module != parent_scope.module && ident.ctxt.is_root() @@ -1520,6 +1523,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { note, via_import, is_stable, + is_exact_match, }); } } @@ -3537,7 +3541,7 @@ pub(crate) fn import_candidates( ); } -type PathString<'a> = (String, &'a str, Option, &'a Option, bool); +type PathString<'a> = (String, &'a str, Option, &'a Option, bool, bool); /// When an entity with a given name is not available in scope, we search for /// entities with that name in all crates. This method allows outputting the @@ -3573,6 +3577,7 @@ fn show_candidates( c.did.and_then(|did| Some(tcx.source_span(did.as_local()?))), &c.note, c.via_import, + c.is_exact_match, )) } } else { @@ -3582,6 +3587,7 @@ fn show_candidates( c.did.and_then(|did| Some(tcx.source_span(did.as_local()?))), &c.note, c.via_import, + c.is_exact_match, )) } }); @@ -3612,27 +3618,29 @@ fn show_candidates( } if !accessible_path_strings.is_empty() { - let (determiner, kind, s, name, through) = - if let [(name, descr, _, _, via_import)] = &accessible_path_strings[..] { - ( - "this", - *descr, - "", - format!(" `{name}`"), - if *via_import { " through its public re-export" } else { "" }, - ) - } else { - // Get the unique item kinds and if there's only one, we use the right kind name - // instead of the more generic "items". - let kinds = accessible_path_strings - .iter() - .map(|(_, descr, _, _, _)| *descr) - .collect::>(); - let kind = if let Some(kind) = kinds.get_only() { kind } else { "item" }; - let s = if kind.ends_with('s') { "es" } else { "s" }; + let (determiner, kind, s, name, through) = if let [ + (name, descr, _, _, via_import, _is_exact_match), + ] = &accessible_path_strings[..] + { + ( + "this", + *descr, + "", + format!(" `{name}`"), + if *via_import { " through its public re-export" } else { "" }, + ) + } else { + // Get the unique item kinds and if there's only one, we use the right kind name + // instead of the more generic "items". + let kinds = accessible_path_strings + .iter() + .map(|(_, descr, _, _, _, _is_exact_match)| *descr) + .collect::>(); + let kind = if let Some(kind) = kinds.get_only() { kind } else { "item" }; + let s = if kind.ends_with('s') { "es" } else { "s" }; - ("one of these", kind, s, String::new(), "") - }; + ("one of these", kind, s, String::new(), "") + }; let instead = if let Instead::Yes = instead { " instead" } else { "" }; let mut msg = if let DiagMode::Pattern = mode { @@ -3725,7 +3733,9 @@ fn show_candidates( { let prefix = if let DiagMode::Pattern = mode { "you might have meant to match on " } else { "" }; - if let [(name, descr, source_span, note, _)] = &inaccessible_path_strings[..] { + if let [(name, descr, source_span, note, _, _is_exact_match)] = + &inaccessible_path_strings[..] + { let msg = format!( "{prefix}{descr} `{name}`{} exists but is inaccessible", if let DiagMode::Pattern = mode { ", which" } else { "" } @@ -3745,7 +3755,7 @@ fn show_candidates( } else { let descr = inaccessible_path_strings .iter() - .map(|&(_, descr, _, _, _)| descr) + .map(|&(_, descr, _, _, _, _is_exact_match)| descr) .all_equal_value() .unwrap_or("item"); let plural_descr = @@ -3755,7 +3765,7 @@ fn show_candidates( let mut has_colon = false; let mut spans = Vec::new(); - for (name, _, source_span, _, _) in &inaccessible_path_strings { + for (name, _, source_span, _, _, _is_exact_match) in &inaccessible_path_strings { if let Some(source_span) = source_span { let span = tcx.sess.source_map().guess_head_span(*source_span); spans.push((name, span)); diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 6f86759d46c5f..1ad5083fbfbe9 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -3038,7 +3038,8 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { path_segments.push(ast::PathSegment::from_ident(ident.orig(orig_ident_span))); let doc_visible = doc_visible && (module_def_id.is_local() || !r.tcx.is_doc_hidden(module_def_id)); - if module_def_id == def_id { + let is_exact_match = module_def_id == def_id; + if is_exact_match { let path = Path { span: name_binding.span, segments: path_segments, tokens: None }; result = Some(( @@ -3052,6 +3053,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { note: None, via_import: false, is_stable: true, + is_exact_match, }, )); } else { From a23f444f5fca1119814d44f661fec49d71b4f25b Mon Sep 17 00:00:00 2001 From: GTimothy <22472919+GTimothy@users.noreply.github.com> Date: Wed, 6 May 2026 13:08:17 +0200 Subject: [PATCH 03/16] bless stdlib test case --- tests/ui/libstd-case-typo/libstd.stderr | 1952 +++++++++++++++++++++++ 1 file changed, 1952 insertions(+) create mode 100644 tests/ui/libstd-case-typo/libstd.stderr diff --git a/tests/ui/libstd-case-typo/libstd.stderr b/tests/ui/libstd-case-typo/libstd.stderr new file mode 100644 index 0000000000000..6fa93103a322b --- /dev/null +++ b/tests/ui/libstd-case-typo/libstd.stderr @@ -0,0 +1,1952 @@ +error[E0425]: cannot find type `LayOut` in this scope + --> $DIR/libstd.rs:3:20 + | +LL | fn test_layout(_x: LayOut){} + | ^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::alloc::Layout; + | + +error[E0425]: cannot find type `system` in this scope + --> $DIR/libstd.rs:5:20 + | +LL | fn test_system(_x: system){} + | ^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::alloc::System; + | + +error[E0425]: cannot find type `Typeid` in this scope + --> $DIR/libstd.rs:10:20 + | +LL | fn test_typeid(_x: Typeid){} + | ^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::any::TypeId; + | + +error[E0425]: cannot find type `Escapedefault` in this scope + --> $DIR/libstd.rs:15:27 + | +LL | fn test_escapedefault(_x: Escapedefault){} + | ^^^^^^^^^^^^^ not found in this scope + | +help: consider importing one of these structs + | +LL + use std::ascii::EscapeDefault; + | +LL + use std::char::EscapeDefault; + | +LL + use std::str::EscapeDefault; + | + +error[E0425]: cannot find type `cell` in this scope + --> $DIR/libstd.rs:20:18 + | +LL | fn test_cell(_x: cell<()>){} + | ^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::cell::Cell; + | + +error[E0425]: cannot find type `DecodeUTF16` in this scope + --> $DIR/libstd.rs:25:25 + | +LL | fn test_decodeutf16(_x: DecodeUTF16<()>){} + | ^^^^^^^^^^^ not found in this scope + +error[E0425]: cannot find type `Escapeunicode` in this scope + --> $DIR/libstd.rs:28:27 + | +LL | fn test_escapeunicode(_x: Escapeunicode){} + | ^^^^^^^^^^^^^ not found in this scope + | +help: consider importing one of these structs + | +LL + use std::char::EscapeUnicode; + | +LL + use std::str::EscapeUnicode; + | + +error[E0425]: cannot find type `Tolowercase` in this scope + --> $DIR/libstd.rs:31:25 + | +LL | fn test_tolowercase(_x: Tolowercase){} + | ^^^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::char::ToLowercase; + | + +error[E0425]: cannot find type `Touppercase` in this scope + --> $DIR/libstd.rs:34:25 + | +LL | fn test_touppercase(_x: Touppercase){} + | ^^^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::char::ToUppercase; + | + +error[E0425]: cannot find type `reverse` in this scope + --> $DIR/libstd.rs:39:21 + | +LL | fn test_reverse(_x: reverse<()>){} + | ^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::cmp::Reverse; + | + +error[E0425]: cannot find type `BtreeMap` in this scope + --> $DIR/libstd.rs:44:22 + | +LL | fn test_btreemap(_x: BtreeMap<(), ()>){} + | ^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::collections::BTreeMap; + | + +error[E0425]: cannot find type `BtreeSet` in this scope + --> $DIR/libstd.rs:46:22 + | +LL | fn test_btreeset(_x: BtreeSet<()>){} + | ^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::collections::BTreeSet; + | + +error[E0425]: cannot find type `Binaryheap` in this scope + --> $DIR/libstd.rs:48:24 + | +LL | fn test_binaryheap(_x: Binaryheap<()>){} + | ^^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::collections::BinaryHeap; + | + +error[E0425]: cannot find type `Hashmap` in this scope + --> $DIR/libstd.rs:50:21 + | +LL | fn test_hashmap(_x: Hashmap){} + | ^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::collections::HashMap; + | + +error[E0425]: cannot find type `Hashset` in this scope + --> $DIR/libstd.rs:52:21 + | +LL | fn test_hashset(_x: Hashset<()>){} + | ^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::collections::HashSet; + | + +error[E0425]: cannot find type `Linkedlist` in this scope + --> $DIR/libstd.rs:54:24 + | +LL | fn test_linkedlist(_x: Linkedlist<()>){} + | ^^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::collections::LinkedList; + | + +error[E0425]: cannot find type `Vecdeque` in this scope + --> $DIR/libstd.rs:56:22 + | +LL | fn test_vecdeque(_x: Vecdeque<()>){} + | ^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::collections::VecDeque; + | + +error[E0425]: cannot find type `args` in this scope + --> $DIR/libstd.rs:61:18 + | +LL | fn test_args(_x: args){} + | ^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::env::Args; + | + +error[E0425]: cannot find type `Argsos` in this scope + --> $DIR/libstd.rs:63:20 + | +LL | fn test_argsos(_x: Argsos){} + | ^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::env::ArgsOs; + | + +error[E0425]: cannot find type `Splitpaths` in this scope + --> $DIR/libstd.rs:65:24 + | +LL | fn test_splitpaths(_x: Splitpaths<'_>){} + | ^^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::env::SplitPaths; + | + +error[E0425]: cannot find type `vars` in this scope + --> $DIR/libstd.rs:67:18 + | +LL | fn test_vars(_x: vars){} + | ^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::env::Vars; + | + +error[E0425]: cannot find type `Varsos` in this scope + --> $DIR/libstd.rs:69:20 + | +LL | fn test_varsos(_x: Varsos){} + | ^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::env::VarsOs; + | + +error[E0425]: cannot find type `cStr` in this scope + --> $DIR/libstd.rs:74:18 + | +LL | fn test_cstr(_x: cStr){} + | ^^^^ not found in this scope + | +help: consider importing one of these structs + | +LL + use std::ffi::CStr; + | +LL + use std::mem::type_info::Str; + | + +error[E0425]: cannot find type `Osstr` in this scope + --> $DIR/libstd.rs:76:19 + | +LL | fn test_osstr(_x: Osstr){} + | ^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::ffi::OsStr; + | + +error[E0425]: cannot find type `Osstring` in this scope + --> $DIR/libstd.rs:78:22 + | +LL | fn test_osstring(_x: Osstring){} + | ^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::ffi::OsString; + | + +error[E0425]: cannot find type `Debuglist` in this scope + --> $DIR/libstd.rs:83:23 + | +LL | fn test_debuglist(_x: Debuglist){} + | ^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::fmt::DebugList; + | + +error[E0425]: cannot find type `Debugmap` in this scope + --> $DIR/libstd.rs:85:22 + | +LL | fn test_debugmap(_x: Debugmap){} + | ^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::fmt::DebugMap; + | + +error[E0425]: cannot find type `Debugset` in this scope + --> $DIR/libstd.rs:87:22 + | +LL | fn test_debugset(_x: Debugset){} + | ^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::fmt::DebugSet; + | + +error[E0425]: cannot find type `Debugstruct` in this scope + --> $DIR/libstd.rs:89:25 + | +LL | fn test_debugstruct(_x: Debugstruct){} + | ^^^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::fmt::DebugStruct; + | + +error[E0425]: cannot find type `Debugtuple` in this scope + --> $DIR/libstd.rs:91:24 + | +LL | fn test_debugtuple(_x: Debugtuple){} + | ^^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::fmt::DebugTuple; + | + +error[E0425]: cannot find type `formatter` in this scope + --> $DIR/libstd.rs:93:23 + | +LL | fn test_fmter(mut _x: formatter){} + | ^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::fmt::Formatter; + | + +error[E0425]: cannot find type `Dirbuilder` in this scope + --> $DIR/libstd.rs:98:24 + | +LL | fn test_dirbuilder(_x: Dirbuilder){} + | ^^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::fs::DirBuilder; + | + +error[E0425]: cannot find type `Direntry` in this scope + --> $DIR/libstd.rs:100:22 + | +LL | fn test_direntry(_x: Direntry){} + | ^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::fs::DirEntry; + | + +error[E0425]: cannot find type `Filetype` in this scope + --> $DIR/libstd.rs:102:22 + | +LL | fn test_filetype(_x: Filetype){} + | ^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::fs::FileType; + | + +error[E0425]: cannot find type `MetaData` in this scope + --> $DIR/libstd.rs:104:22 + | +LL | fn test_metadata(_x: MetaData){} + | ^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::fs::Metadata; + | + +error[E0425]: cannot find type `Openoptions` in this scope + --> $DIR/libstd.rs:106:25 + | +LL | fn test_openoptions(_x: Openoptions){} + | ^^^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::fs::OpenOptions; + | + +error[E0425]: cannot find type `permissions` in this scope + --> $DIR/libstd.rs:108:25 + | +LL | fn test_permissions(_x: permissions){} + | ^^^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::fs::Permissions; + | + +error[E0425]: cannot find type `Readdir` in this scope + --> $DIR/libstd.rs:110:21 + | +LL | fn test_readdir(_x: Readdir){} + | ^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::fs::ReadDir; + | + +error[E0425]: cannot find type `BuildhasherDefault` in this scope + --> $DIR/libstd.rs:115:32 + | +LL | fn test_buildhasherdefault(_x: BuildhasherDefault){} + | ^^^^^^^^^^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::hash::BuildHasherDefault; + | + +error[E0425]: cannot find type `Bufreader` in this scope + --> $DIR/libstd.rs:120:23 + | +LL | fn test_bufreader(_x: Bufreader<()>){} + | ^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::io::BufReader; + | + +error[E0425]: cannot find type `Bufwriter` in this scope + --> $DIR/libstd.rs:122:23 + | +LL | fn test_bufwriter(_x: Bufwriter<()>){} + | ^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::io::BufWriter; + | + +error[E0425]: cannot find type `bytes` in this scope + --> $DIR/libstd.rs:124:19 + | +LL | fn test_bytes(_x: bytes<()>){} + | ^^^^^ not found in this scope + | +help: consider importing one of these structs + | +LL + use std::io::Bytes; + | +LL + use std::str::Bytes; + | + +error[E0425]: cannot find type `chain` in this scope + --> $DIR/libstd.rs:126:19 + | +LL | fn test_chain(_x: chain<(), ()>){} + | ^^^^^ not found in this scope + | +help: consider importing one of these structs + | +LL + use std::io::Chain; + | +LL + use std::iter::Chain; + | + +error[E0425]: cannot find type `cursor` in this scope + --> $DIR/libstd.rs:128:20 + | +LL | fn test_cursor(_x: cursor<()>){} + | ^^^^^^ not found in this scope + | +help: consider importing one of these structs + | +LL + use std::collections::btree_map::Cursor; + | +LL + use std::collections::btree_set::Cursor; + | +LL + use std::collections::linked_list::Cursor; + | +LL + use std::io::Cursor; + | + +error[E0425]: cannot find type `empty` in this scope + --> $DIR/libstd.rs:130:19 + | +LL | fn test_empty(_x: empty){} + | ^^^^^ not found in this scope + | +help: consider importing one of these structs + | +LL + use std::io::Empty; + | +LL + use std::iter::Empty; + | + +error[E0425]: cannot find type `Ioslice` in this scope + --> $DIR/libstd.rs:132:21 + | +LL | fn test_ioslice(_x: Ioslice){} + | ^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::io::IoSlice; + | + +error[E0425]: cannot find type `IosliceMut` in this scope + --> $DIR/libstd.rs:134:24 + | +LL | fn test_ioslicemut(_x: IosliceMut){} + | ^^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::io::IoSliceMut; + | + +error[E0425]: cannot find type `Linewriter` in this scope + --> $DIR/libstd.rs:136:24 + | +LL | fn test_linewriter(_x: Linewriter<()>){} + | ^^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::io::LineWriter; + | + +error[E0425]: cannot find type `lines` in this scope + --> $DIR/libstd.rs:138:19 + | +LL | fn test_lines(_x: lines<()>){} + | ^^^^^ not found in this scope + | +help: consider importing one of these structs + | +LL + use std::io::Lines; + | +LL + use std::str::Lines; + | + +error[E0425]: cannot find type `repeat` in this scope + --> $DIR/libstd.rs:140:20 + | +LL | fn test_repeat(_x: repeat){} + | ^^^^^^ not found in this scope + | +help: consider importing one of these structs + | +LL + use std::io::Repeat; + | +LL + use std::iter::Repeat; + | + +error[E0425]: cannot find type `sink` in this scope + --> $DIR/libstd.rs:142:18 + | +LL | fn test_sink(_x: sink){} + | ^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::io::Sink; + | + +error[E0425]: cannot find type `split` in this scope + --> $DIR/libstd.rs:144:19 + | +LL | fn test_split(_x: split<()>){} + | ^^^^^ not found in this scope + | +help: consider importing one of these structs + | +LL + use std::io::Split; + | +LL + use std::slice::Split; + | +LL + use std::str::Split; + | + +error[E0425]: cannot find type `StdErr` in this scope + --> $DIR/libstd.rs:146:20 + | +LL | fn test_stderr(_x: StdErr){} + | ^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::io::Stderr; + | + +error[E0425]: cannot find type `StdErrLock` in this scope + --> $DIR/libstd.rs:148:24 + | +LL | fn test_stderrlock(_x: StdErrLock){} + | ^^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::io::StderrLock; + | + +error[E0425]: cannot find type `StdIn` in this scope + --> $DIR/libstd.rs:150:19 + | +LL | fn test_stdin(_x: StdIn){} + | ^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::io::Stdin; + | + +error[E0425]: cannot find type `StdInLock` in this scope + --> $DIR/libstd.rs:152:23 + | +LL | fn test_stdinlock(_x: StdInLock){} + | ^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::io::StdinLock; + | + +error[E0425]: cannot find type `StdOut` in this scope + --> $DIR/libstd.rs:154:20 + | +LL | fn test_stdout(_x: StdOut){} + | ^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::io::Stdout; + | + +error[E0425]: cannot find type `StdOutLock` in this scope + --> $DIR/libstd.rs:156:24 + | +LL | fn test_stdoutlock(_x: StdOutLock){} + | ^^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::io::StdoutLock; + | + +error[E0425]: cannot find type `take` in this scope + --> $DIR/libstd.rs:158:18 + | +LL | fn test_take(_x: take){} + | ^^^^ not found in this scope + | +help: consider importing one of these items + | +LL + use std::io::Take; + | +LL + use std::iter::Take; + | +LL + use std::task::Wake; + | + +error[E0425]: cannot find type `cloned` in this scope + --> $DIR/libstd.rs:163:20 + | +LL | fn test_cloned(_x: cloned<(), ()>){} + | ^^^^^^ + | + --> $SRC_DIR/core/src/clone.rs:LL:COL + | + = note: similarly named trait `Clone` defined here +help: a trait with a similar name exists + | +LL - fn test_cloned(_x: cloned<(), ()>){} +LL + fn test_cloned(_x: Clone<(), ()>){} + | +help: consider importing this struct + | +LL + use std::iter::Cloned; + | + +error[E0425]: cannot find type `copied` in this scope + --> $DIR/libstd.rs:165:20 + | +LL | fn test_copied(_x: copied<(), ()>){} + | ^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::iter::Copied; + | + +error[E0425]: cannot find type `cycle` in this scope + --> $DIR/libstd.rs:167:19 + | +LL | fn test_cycle(_x: cycle<(), ()>){} + | ^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::iter::Cycle; + | + +error[E0425]: cannot find type `enumerate` in this scope + --> $DIR/libstd.rs:169:23 + | +LL | fn test_enumerate(_x: enumerate<(), ()>){} + | ^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::iter::Enumerate; + | + +error[E0425]: cannot find type `filter` in this scope + --> $DIR/libstd.rs:171:20 + | +LL | fn test_filter(_x: filter<(), ()>){} + | ^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::iter::Filter; + | + +error[E0425]: cannot find type `Filtermap` in this scope + --> $DIR/libstd.rs:173:23 + | +LL | fn test_filtermap(_x: Filtermap<(), ()>){} + | ^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::iter::FilterMap; + | + +error[E0425]: cannot find type `flatten` in this scope + --> $DIR/libstd.rs:175:21 + | +LL | fn test_flatten(_x: flatten<()>){} + | ^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::iter::Flatten; + | + +error[E0425]: cannot find type `Fromfn` in this scope + --> $DIR/libstd.rs:177:20 + | +LL | fn test_fromfn(_x: Fromfn<()>){} + | ^^^^^^ + | + --> $SRC_DIR/core/src/convert/mod.rs:LL:COL + | + = note: similarly named trait `From` defined here +help: a trait with a similar name exists + | +LL - fn test_fromfn(_x: Fromfn<()>){} +LL + fn test_fromfn(_x: From<()>){} + | +help: consider importing one of these structs + | +LL + use std::fmt::FromFn; + | +LL + use std::iter::FromFn; + | + +error[E0425]: cannot find type `fuse` in this scope + --> $DIR/libstd.rs:179:18 + | +LL | fn test_fuse(_x: fuse<()>){} + | ^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::iter::Fuse; + | + +error[E0425]: cannot find type `inspect` in this scope + --> $DIR/libstd.rs:181:21 + | +LL | fn test_inspect(_x: inspect<(), ()>){} + | ^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::iter::Inspect; + | + +error[E0425]: cannot find type `map` in this scope + --> $DIR/libstd.rs:183:17 + | +LL | fn test_map(_x: map<(), ()>){} + | ^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::iter::Map; + | + +error[E0425]: cannot find type `once` in this scope + --> $DIR/libstd.rs:185:18 + | +LL | fn test_once(_x: once<()>){} + | ^^^^ not found in this scope + | +help: consider importing one of these structs + | +LL + use std::iter::Once; + | +LL + use std::sync::Once; + | + +error[E0425]: cannot find type `Oncewith` in this scope + --> $DIR/libstd.rs:187:22 + | +LL | fn test_oncewith(_x: Oncewith<()>){} + | ^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::iter::OnceWith; + | + +error[E0425]: cannot find type `peekable` in this scope + --> $DIR/libstd.rs:189:22 + | +LL | fn test_peekable(_x: peekable<()>){} + | ^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::iter::Peekable; + | + +error[E0425]: cannot find type `Repeatwith` in this scope + --> $DIR/libstd.rs:191:24 + | +LL | fn test_repeatwith(_x: Repeatwith<()>){} + | ^^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::iter::RepeatWith; + | + +error[E0425]: cannot find type `rev` in this scope + --> $DIR/libstd.rs:193:17 + | +LL | fn test_rev(_x: rev<()>){} + | ^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::iter::Rev; + | + +error[E0425]: cannot find type `scan` in this scope + --> $DIR/libstd.rs:195:18 + | +LL | fn test_scan(_x: scan<(), (), ()>){} + | ^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::iter::Scan; + | + +error[E0425]: cannot find type `skip` in this scope + --> $DIR/libstd.rs:197:18 + | +LL | fn test_skip(_x: skip<()>){} + | ^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::iter::Skip; + | + +error[E0425]: cannot find type `Skipwhile` in this scope + --> $DIR/libstd.rs:199:23 + | +LL | fn test_skipwhile(_x: Skipwhile<(), ()>){} + | ^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::iter::SkipWhile; + | + +error[E0425]: cannot find type `Stepby` in this scope + --> $DIR/libstd.rs:201:20 + | +LL | fn test_stepby(_x: Stepby<()>){} + | ^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::iter::StepBy; + | + +error[E0425]: cannot find type `successors` in this scope + --> $DIR/libstd.rs:203:24 + | +LL | fn test_successors(_x: successors<()>){} + | ^^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::iter::Successors; + | + +error[E0425]: cannot find type `Takewhile` in this scope + --> $DIR/libstd.rs:205:23 + | +LL | fn test_takewhile(_x: Takewhile<(), ()>){} + | ^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::iter::TakeWhile; + | + +error[E0425]: cannot find type `zip` in this scope + --> $DIR/libstd.rs:207:17 + | +LL | fn test_zip(_x: zip<(), ()>){} + | ^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::iter::Zip; + | + +error[E0425]: cannot find type `Phantomdata` in this scope + --> $DIR/libstd.rs:212:25 + | +LL | fn test_phantomdata(_x: Phantomdata){} + | ^^^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::marker::PhantomData; + | + +error[E0425]: cannot find type `Phantompinned` in this scope + --> $DIR/libstd.rs:214:27 + | +LL | fn test_phantompinned(_x: Phantompinned){} + | ^^^^^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::marker::PhantomPinned; + | + +error[E0425]: cannot find type `discriminant` in this scope + --> $DIR/libstd.rs:219:26 + | +LL | fn test_discriminant(_x: discriminant<()>){} + | ^^^^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::mem::Discriminant; + | + +error[E0425]: cannot find type `Manuallydrop` in this scope + --> $DIR/libstd.rs:221:26 + | +LL | fn test_manuallydrop(_x: Manuallydrop<()>){} + | ^^^^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::mem::ManuallyDrop; + | + +error[E0425]: cannot find type `incoming` in this scope + --> $DIR/libstd.rs:226:22 + | +LL | fn test_incoming(_x: incoming){} + | ^^^^^^^^ not found in this scope + | +help: consider importing one of these structs + | +LL + use std::net::Incoming; + | +LL + use std::os::unix::net::Incoming; + | + +error[E0425]: cannot find type `IPv4Addr` in this scope + --> $DIR/libstd.rs:228:22 + | +LL | fn test_ipv4addr(_x: IPv4Addr){} + | ^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::net::Ipv4Addr; + | + +error[E0425]: cannot find type `IPv6Addr` in this scope + --> $DIR/libstd.rs:230:22 + | +LL | fn test_ipv6addr(_x: IPv6Addr){} + | ^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::net::Ipv6Addr; + | + +error[E0425]: cannot find type `SocketAddrv4` in this scope + --> $DIR/libstd.rs:232:26 + | +LL | fn test_socketaddrv4(_x: SocketAddrv4){} + | ^^^^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::net::SocketAddrV4; + | + +error[E0425]: cannot find type `SocketAddrv6` in this scope + --> $DIR/libstd.rs:234:26 + | +LL | fn test_socketaddrv6(_x: SocketAddrv6){} + | ^^^^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::net::SocketAddrV6; + | + +error[E0425]: cannot find type `TCPListener` in this scope + --> $DIR/libstd.rs:236:25 + | +LL | fn test_tcplistener(_x: TCPListener){} + | ^^^^^^^^^^^ not found in this scope + +error[E0425]: cannot find type `TCPStream` in this scope + --> $DIR/libstd.rs:238:23 + | +LL | fn test_tcpstream(_x: TCPStream){} + | ^^^^^^^^^ not found in this scope + +error[E0425]: cannot find type `UDPSocket` in this scope + --> $DIR/libstd.rs:240:23 + | +LL | fn test_udpsocket(_x: UDPSocket){} + | ^^^^^^^^^ not found in this scope + +error[E0425]: cannot find type `NonZeroi8` in this scope + --> $DIR/libstd.rs:245:23 + | +LL | fn test_nonzeroi8(_x: NonZeroi8){} + | ^^^^^^^^^ not found in this scope + | +help: consider importing one of these type aliases + | +LL + use std::num::NonZeroI8; + | +LL + use std::num::NonZeroU8; + | + +error[E0425]: cannot find type `NonZeroi16` in this scope + --> $DIR/libstd.rs:247:24 + | +LL | fn test_nonzeroi16(_x: NonZeroi16){} + | ^^^^^^^^^^ not found in this scope + | +help: consider importing one of these type aliases + | +LL + use std::num::NonZeroI16; + | +LL + use std::num::NonZeroU16; + | + +error[E0425]: cannot find type `NonZeroi32` in this scope + --> $DIR/libstd.rs:249:24 + | +LL | fn test_nonzeroi32(_x: NonZeroi32){} + | ^^^^^^^^^^ not found in this scope + | +help: consider importing one of these type aliases + | +LL + use std::num::NonZeroI32; + | +LL + use std::num::NonZeroU32; + | + +error[E0425]: cannot find type `NonZeroi64` in this scope + --> $DIR/libstd.rs:251:24 + | +LL | fn test_nonzeroi64(_x: NonZeroi64){} + | ^^^^^^^^^^ not found in this scope + | +help: consider importing one of these type aliases + | +LL + use std::num::NonZeroI64; + | +LL + use std::num::NonZeroU64; + | + +error[E0425]: cannot find type `NonZeroi128` in this scope + --> $DIR/libstd.rs:253:25 + | +LL | fn test_nonzeroi128(_x: NonZeroi128){} + | ^^^^^^^^^^^ not found in this scope + | +help: consider importing one of these type aliases + | +LL + use std::num::NonZeroI128; + | +LL + use std::num::NonZeroU128; + | + +error[E0425]: cannot find type `NonZerou8` in this scope + --> $DIR/libstd.rs:255:23 + | +LL | fn test_nonzerou8(_x: NonZerou8){} + | ^^^^^^^^^ not found in this scope + | +help: consider importing one of these type aliases + | +LL + use std::num::NonZeroI8; + | +LL + use std::num::NonZeroU8; + | + +error[E0425]: cannot find type `NonZerou16` in this scope + --> $DIR/libstd.rs:257:24 + | +LL | fn test_nonzerou16(_x: NonZerou16){} + | ^^^^^^^^^^ not found in this scope + | +help: consider importing one of these type aliases + | +LL + use std::num::NonZeroI16; + | +LL + use std::num::NonZeroU16; + | + +error[E0425]: cannot find type `NonZerou32` in this scope + --> $DIR/libstd.rs:259:24 + | +LL | fn test_nonzerou32(_x: NonZerou32){} + | ^^^^^^^^^^ not found in this scope + | +help: consider importing one of these type aliases + | +LL + use std::num::NonZeroI32; + | +LL + use std::num::NonZeroU32; + | + +error[E0425]: cannot find type `NonZerou64` in this scope + --> $DIR/libstd.rs:261:24 + | +LL | fn test_nonzerou64(_x: NonZerou64){} + | ^^^^^^^^^^ not found in this scope + | +help: consider importing one of these type aliases + | +LL + use std::num::NonZeroI64; + | +LL + use std::num::NonZeroU64; + | + +error[E0425]: cannot find type `NonZerou128` in this scope + --> $DIR/libstd.rs:263:25 + | +LL | fn test_nonzerou128(_x: NonZerou128){} + | ^^^^^^^^^^^ not found in this scope + | +help: consider importing one of these type aliases + | +LL + use std::num::NonZeroI128; + | +LL + use std::num::NonZeroU128; + | + +error[E0425]: cannot find type `NonzeroUsize` in this scope + --> $DIR/libstd.rs:265:26 + | +LL | fn test_nonzerousize(_x: NonzeroUsize){} + | ^^^^^^^^^^^^ not found in this scope + | +help: consider importing this type alias + | +LL + use std::num::NonZeroUsize; + | + +error[E0425]: cannot find type `wrapping` in this scope + --> $DIR/libstd.rs:267:22 + | +LL | fn test_wrapping(_x: wrapping){} + | ^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::num::Wrapping; + | + +error[E0425]: cannot find type `range` in this scope + --> $DIR/libstd.rs:272:19 + | +LL | fn test_range(_x: range<()>){} + | ^^^^^ not found in this scope + | +help: consider importing one of these structs + | +LL + use std::collections::btree_map::Range; + | +LL + use std::collections::btree_set::Range; + | +LL + use std::ops::Range; + | +LL + use std::range::Range; + | + +error[E0425]: cannot find type `Rangefrom` in this scope + --> $DIR/libstd.rs:274:23 + | +LL | fn test_rangefrom(_x: Rangefrom<()>){} + | ^^^^^^^^^ not found in this scope + | +help: consider importing one of these structs + | +LL + use std::ops::RangeFrom; + | +LL + use std::range::RangeFrom; + | + +error[E0425]: cannot find type `Rangefull` in this scope + --> $DIR/libstd.rs:276:23 + | +LL | fn test_rangefull(_x: Rangefull<()>){} + | ^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::ops::RangeFull; + | + +error[E0425]: cannot find type `Rangeinclusive` in this scope + --> $DIR/libstd.rs:278:28 + | +LL | fn test_rangeinclusive(_x: Rangeinclusive<()>){} + | ^^^^^^^^^^^^^^ not found in this scope + | +help: consider importing one of these structs + | +LL + use std::ops::RangeInclusive; + | +LL + use std::range::RangeInclusive; + | + +error[E0425]: cannot find type `Rangeto` in this scope + --> $DIR/libstd.rs:280:21 + | +LL | fn test_rangeto(_x: Rangeto<()>){} + | ^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::ops::RangeTo; + | + +error[E0425]: cannot find type `RangetoInclusive` in this scope + --> $DIR/libstd.rs:282:30 + | +LL | fn test_rangetoinclusive(_x: RangetoInclusive<()>){} + | ^^^^^^^^^^^^^^^^ not found in this scope + | +help: consider importing one of these structs + | +LL + use std::ops::RangeToInclusive; + | +LL + use std::range::RangeToInclusive; + | + +error[E0425]: cannot find type `AssertUnwindsafe` in this scope + --> $DIR/libstd.rs:287:30 + | +LL | fn test_assertunwindsafe(_x: AssertUnwindsafe<()>){} + | ^^^^^^^^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::panic::AssertUnwindSafe; + | + +error[E0425]: cannot find type `location` in this scope + --> $DIR/libstd.rs:289:22 + | +LL | fn test_location(_x: location<()>){} + | ^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::panic::Location; + | + +error[E0425]: cannot find type `Panicinfo` in this scope + --> $DIR/libstd.rs:291:23 + | +LL | fn test_panicinfo(_x: Panicinfo<()>){} + | ^^^^^^^^^ not found in this scope + | +help: consider importing this type alias + | +LL + use std::panic::PanicInfo; + | + +error[E0425]: cannot find type `ancestors` in this scope + --> $DIR/libstd.rs:296:23 + | +LL | fn test_ancestors(_x: ancestors){} + | ^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::path::Ancestors; + | + +error[E0425]: cannot find type `components` in this scope + --> $DIR/libstd.rs:298:24 + | +LL | fn test_components(_x: components){} + | ^^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::path::Components; + | + +error[E0425]: cannot find type `Pathbuf` in this scope + --> $DIR/libstd.rs:300:21 + | +LL | fn test_pathbuf(_x: Pathbuf){} + | ^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::path::PathBuf; + | + +error[E0425]: cannot find type `Prefixcomponent` in this scope + --> $DIR/libstd.rs:302:29 + | +LL | fn test_prefixcomponent(_x: Prefixcomponent){} + | ^^^^^^^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::path::PrefixComponent; + | + +error[E0425]: cannot find type `pin` in this scope + --> $DIR/libstd.rs:307:17 + | +LL | fn test_pin(_x: pin<()>){} + | ^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::pin::Pin; + | + +error[E0425]: cannot find type `child` in this scope + --> $DIR/libstd.rs:312:19 + | +LL | fn test_child(_x: child){} + | ^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::process::Child; + | + +error[E0425]: cannot find type `ChildStdErr` in this scope + --> $DIR/libstd.rs:314:25 + | +LL | fn test_childstderr(_x: ChildStdErr){} + | ^^^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::process::ChildStderr; + | + +error[E0425]: cannot find type `ChildStdIn` in this scope + --> $DIR/libstd.rs:316:24 + | +LL | fn test_childstdin(_x: ChildStdIn){} + | ^^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::process::ChildStdin; + | + +error[E0425]: cannot find type `ChildStdOut` in this scope + --> $DIR/libstd.rs:318:25 + | +LL | fn test_childstdout(_x: ChildStdOut){} + | ^^^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::process::ChildStdout; + | + +error[E0425]: cannot find type `command` in this scope + --> $DIR/libstd.rs:320:21 + | +LL | fn test_command(_x: command){} + | ^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::process::Command; + | + +error[E0425]: cannot find type `Exitstatus` in this scope + --> $DIR/libstd.rs:322:24 + | +LL | fn test_exitstatus(_x: Exitstatus){} + | ^^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::process::ExitStatus; + | + +error[E0425]: cannot find type `output` in this scope + --> $DIR/libstd.rs:324:20 + | +LL | fn test_output(_x: output){} + | ^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::process::Output; + | + +error[E0425]: cannot find type `StdIo` in this scope + --> $DIR/libstd.rs:326:19 + | +LL | fn test_stdio(_x: StdIo){} + | ^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::process::Stdio; + | + +error[E0425]: cannot find type `Nonnull` in this scope + --> $DIR/libstd.rs:331:21 + | +LL | fn test_nonnull(_x: Nonnull<()>){} + | ^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::ptr::NonNull; + | + +error[E0425]: cannot find type `rc` in this scope + --> $DIR/libstd.rs:336:16 + | +LL | fn test_rc(_x: rc<()>){} + | ^^ not found in this scope + | +help: consider importing one of these structs + | +LL + use std::rc::Rc; + | +LL + use std::sync::Arc; + | + +error[E0425]: cannot find type `weak` in this scope + --> $DIR/libstd.rs:338:18 + | +LL | fn test_weak(_x: weak<()>){} + | ^^^^ not found in this scope + | +help: consider importing one of these structs + | +LL + use std::rc::Weak; + | +LL + use std::sync::Weak; + | + +error[E0425]: cannot find type `drain` in this scope + --> $DIR/libstd.rs:343:19 + | +LL | fn test_drain(_x: drain){} + | ^^^^^ not found in this scope + | +help: consider importing one of these structs + | +LL + use std::collections::binary_heap::Drain; + | +LL + use std::collections::hash_map::Drain; + | +LL + use std::collections::hash_set::Drain; + | +LL + use std::collections::vec_deque::Drain; + | + = and 2 other candidates + +error[E0425]: cannot find type `Charindices` in this scope + --> $DIR/libstd.rs:348:25 + | +LL | fn test_charindices(_x: Charindices){} + | ^^^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::str::CharIndices; + | + +error[E0425]: cannot find type `chars` in this scope + --> $DIR/libstd.rs:350:19 + | +LL | fn test_chars(_x: chars){} + | ^^^^^ + | +help: a builtin type with a similar name exists + | +LL - fn test_chars(_x: chars){} +LL + fn test_chars(_x: char){} + | +help: consider importing one of these items + | +LL + use std::primitive::char; + | +LL + use std::str::Chars; + | + +error[E0425]: cannot find type `EncodeUTF16` in this scope + --> $DIR/libstd.rs:352:25 + | +LL | fn test_encodeutf16(_x: EncodeUTF16){} + | ^^^^^^^^^^^ not found in this scope + +error[E0425]: cannot find type `Matchindices` in this scope + --> $DIR/libstd.rs:354:26 + | +LL | fn test_matchindices(_x: Matchindices){} + | ^^^^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::str::MatchIndices; + | + +error[E0425]: cannot find type `RmatchIndices` in this scope + --> $DIR/libstd.rs:356:27 + | +LL | fn test_rmatchindices(_x: RmatchIndices){} + | ^^^^^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::str::RMatchIndices; + | + +error[E0425]: cannot find type `Rmatches` in this scope + --> $DIR/libstd.rs:358:22 + | +LL | fn test_rmatches(_x: Rmatches){} + | ^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::str::RMatches; + | + +error[E0425]: cannot find type `Rsplit` in this scope + --> $DIR/libstd.rs:360:20 + | +LL | fn test_rsplit(_x: Rsplit){} + | ^^^^^^ not found in this scope + | +help: consider importing one of these structs + | +LL + use std::slice::RSplit; + | +LL + use std::str::RSplit; + | + +error[E0425]: cannot find type `RSplitn` in this scope + --> $DIR/libstd.rs:362:21 + | +LL | fn test_rsplitn(_x: RSplitn){} + | ^^^^^^^ not found in this scope + | +help: consider importing one of these structs + | +LL + use std::slice::RSplit; + | +LL + use std::slice::RSplitN; + | +LL + use std::str::RSplit; + | +LL + use std::str::RSplitN; + | + +error[E0425]: cannot find type `RsplitTerminator` in this scope + --> $DIR/libstd.rs:364:30 + | +LL | fn test_rsplitterminator(_x: RsplitTerminator){} + | ^^^^^^^^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::str::RSplitTerminator; + | + +error[E0425]: cannot find type `SplitASCIIWhitespace` in this scope + --> $DIR/libstd.rs:366:34 + | +LL | fn test_splitasciiwhitespace(_x: SplitASCIIWhitespace){} + | ^^^^^^^^^^^^^^^^^^^^ not found in this scope + +error[E0425]: cannot find type `Splitn` in this scope + --> $DIR/libstd.rs:368:20 + | +LL | fn test_splitn(_x: Splitn){} + | ^^^^^^ not found in this scope + | +help: consider importing one of these structs + | +LL + use std::io::Split; + | +LL + use std::slice::Split; + | +LL + use std::slice::SplitN; + | +LL + use std::str::Split; + | + = and 1 other candidate + +error[E0425]: cannot find type `Splitterminator` in this scope + --> $DIR/libstd.rs:370:29 + | +LL | fn test_splitterminator(_x: Splitterminator){} + | ^^^^^^^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::str::SplitTerminator; + | + +error[E0425]: cannot find type `Splitwhitespace` in this scope + --> $DIR/libstd.rs:372:29 + | +LL | fn test_splitwhitespace(_x: Splitwhitespace){} + | ^^^^^^^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::str::SplitWhitespace; + | + +error[E0425]: cannot find type `arc` in this scope + --> $DIR/libstd.rs:377:17 + | +LL | fn test_arc(_x: arc<()>){} + | ^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::sync::Arc; + | + +error[E0425]: cannot find type `barrier` in this scope + --> $DIR/libstd.rs:379:21 + | +LL | fn test_barrier(_x: barrier<()>){} + | ^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::sync::Barrier; + | + +error[E0425]: cannot find type `BarrierwaitResult` in this scope + --> $DIR/libstd.rs:381:31 + | +LL | fn test_barrierwaitresult(_x: BarrierwaitResult<()>){} + | ^^^^^^^^^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::sync::BarrierWaitResult; + | + +error[E0425]: cannot find type `CondVar` in this scope + --> $DIR/libstd.rs:383:21 + | +LL | fn test_condvar(_x: CondVar<()>){} + | ^^^^^^^ not found in this scope + | +help: consider importing one of these structs + | +LL + use std::sync::Condvar; + | +LL + use std::sync::nonpoison::Condvar; + | + +error[E0425]: cannot find type `mutex` in this scope + --> $DIR/libstd.rs:385:19 + | +LL | fn test_mutex(_x: mutex<()>){} + | ^^^^^ not found in this scope + | +help: consider importing one of these structs + | +LL + use std::sync::Mutex; + | +LL + use std::sync::nonpoison::Mutex; + | + +error[E0425]: cannot find type `Mutexguard` in this scope + --> $DIR/libstd.rs:387:24 + | +LL | fn test_mutexguard(_x: Mutexguard<()>){} + | ^^^^^^^^^^ not found in this scope + | +help: consider importing one of these structs + | +LL + use std::sync::MutexGuard; + | +LL + use std::sync::nonpoison::MutexGuard; + | + +error[E0425]: cannot find type `RWlock` in this scope + --> $DIR/libstd.rs:389:20 + | +LL | fn test_rwlock(_x: RWlock<()>){} + | ^^^^^^ not found in this scope + +error[E0425]: cannot find type `RWlockReadGuard` in this scope + --> $DIR/libstd.rs:391:29 + | +LL | fn test_rwlockreadguard(_x: RWlockReadGuard<()>){} + | ^^^^^^^^^^^^^^^ not found in this scope + +error[E0425]: cannot find type `RWlockWriteGuard` in this scope + --> $DIR/libstd.rs:393:30 + | +LL | fn test_rwlockwriteguard(_x: RWlockWriteGuard<()>){} + | ^^^^^^^^^^^^^^^^ not found in this scope + +error[E0425]: cannot find type `WaittimeoutResult` in this scope + --> $DIR/libstd.rs:395:31 + | +LL | fn test_waittimeoutresult(_x: WaittimeoutResult<()>){} + | ^^^^^^^^^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::sync::WaitTimeoutResult; + | + +error[E0425]: cannot find type `context` in this scope + --> $DIR/libstd.rs:400:21 + | +LL | fn test_context(_x: context){} + | ^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::task::Context; + | + +error[E0425]: cannot find type `Rawwaker` in this scope + --> $DIR/libstd.rs:402:22 + | +LL | fn test_rawwaker(_x: Rawwaker){} + | ^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::task::RawWaker; + | + +error[E0425]: cannot find type `RawwakerVTable` in this scope + --> $DIR/libstd.rs:404:28 + | +LL | fn test_rawwakervtable(_x: RawwakerVTable){} + | ^^^^^^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::task::RawWakerVTable; + | + +error[E0425]: cannot find type `waker` in this scope + --> $DIR/libstd.rs:406:19 + | +LL | fn test_waker(_x: waker){} + | ^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::task::Waker; + | + +error[E0425]: cannot find type `builder` in this scope + --> $DIR/libstd.rs:411:21 + | +LL | fn test_builder(_x: builder){} + | ^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::thread::Builder; + | + +error[E0425]: cannot find type `Joinhandle` in this scope + --> $DIR/libstd.rs:413:24 + | +LL | fn test_joinhandle(_x: Joinhandle<()>){} + | ^^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::thread::JoinHandle; + | + +error[E0425]: cannot find type `Localkey` in this scope + --> $DIR/libstd.rs:415:22 + | +LL | fn test_localkey(_x: Localkey<()>){} + | ^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::thread::LocalKey; + | + +error[E0425]: cannot find type `thread` in this scope + --> $DIR/libstd.rs:417:20 + | +LL | fn test_thread(_x: thread){} + | ^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::thread::Thread; + | + +error[E0425]: cannot find type `ThreadID` in this scope + --> $DIR/libstd.rs:419:22 + | +LL | fn test_threadid(_x: ThreadID){} + | ^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::thread::ThreadId; + | + +error[E0425]: cannot find type `duration` in this scope + --> $DIR/libstd.rs:424:22 + | +LL | fn test_duration(_x: duration){} + | ^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::time::Duration; + | + +error[E0425]: cannot find type `instant` in this scope + --> $DIR/libstd.rs:426:21 + | +LL | fn test_instant(_x: instant){} + | ^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::time::Instant; + | + +error[E0425]: cannot find type `Systemtime` in this scope + --> $DIR/libstd.rs:428:24 + | +LL | fn test_systemtime(_x: Systemtime){} + | ^^^^^^^^^^ +... +LL | struct SystemTome{} + | ----------------- similarly named struct `SystemTome` defined here + | +help: a struct with a similar name exists + | +LL - fn test_systemtime(_x: Systemtime){} +LL + fn test_systemtime(_x: SystemTome){} + | +help: consider importing this struct + | +LL + use std::time::SystemTime; + | + +error[E0425]: cannot find type `SystemTime` in this scope + --> $DIR/libstd.rs:431:25 + | +LL | fn test_systemtime2(_x: SystemTime){} + | ^^^^^^^^^^ +... +LL | struct SystemTome{} + | ----------------- similarly named struct `SystemTome` defined here + | +note: struct `st::SystemTame` exists but is inaccessible + --> $DIR/libstd.rs:436:5 + | +LL | struct SystemTame{} + | ^^^^^^^^^^^^^^^^^ not accessible +help: a struct with a similar name exists + | +LL - fn test_systemtime2(_x: SystemTime){} +LL + fn test_systemtime2(_x: SystemTome){} + | +help: consider importing this struct + | +LL + use std::time::SystemTime; + | + +error: aborting due to 168 previous errors + +For more information about this error, try `rustc --explain E0425`. From 1e2bdb4ab898ae295f1b3b951716896cd2786558 Mon Sep 17 00:00:00 2001 From: GTimothy <22472919+GTimothy@users.noreply.github.com> Date: Fri, 8 May 2026 13:11:56 +0200 Subject: [PATCH 04/16] suggest imports with different casing --- compiler/rustc_resolve/src/diagnostics.rs | 94 ++++++++++++++++++++--- 1 file changed, 83 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index c4e2762a9fc4c..5125b32cd5088 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -29,7 +29,7 @@ use rustc_session::lint::builtin::{ AMBIGUOUS_PANIC_IMPORTS, MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS, }; use rustc_session::utils::was_invoked_from_cargo; -use rustc_span::edit_distance::{edit_distance, find_best_match_for_name}; +use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::edition::Edition; use rustc_span::hygiene::MacroKind; use rustc_span::source_map::SourceMap; @@ -774,7 +774,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } if could_be_path { - let import_suggestions = self.lookup_import_candidates( + let mut import_suggestions = self.lookup_import_candidates( name, Namespace::ValueNS, &parent_scope, @@ -868,13 +868,39 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } if import_suggestions.is_empty() && !suggested_typo { - let help_msg = format!( - "if you meant to match on a unit struct, unit variant or a `const` \ - item, consider making the path in the pattern qualified: \ - `path::to::ModOrType::{name}`", + let typo_import_suggestions = self.lookup_import_candidates_impl( + name, + Namespace::ValueNS, + &parent_scope, + |ident, lookup_ident| { + ident.name.as_str().to_lowercase() + == lookup_ident.name.as_str().to_lowercase() + }, + &|res: Res| { + matches!( + res, + Res::Def( + DefKind::Ctor(CtorOf::Variant, CtorKind::Const) + | DefKind::Ctor(CtorOf::Struct, CtorKind::Const) + | DefKind::Const { .. } + | DefKind::AssocConst { .. }, + _, + ) + ) + }, ); - err.span_help(span, help_msg); + if !typo_import_suggestions.is_empty() { + import_suggestions = typo_import_suggestions; + } else { + let help_msg = format!( + "if you meant to match on a unit struct, unit variant or a `const` \ + item, consider making the path in the pattern qualified: \ + `path::to::ModOrType::{name}`", + ); + err.span_help(span, help_msg); + } } + show_candidates( self.tcx, &mut err, @@ -1371,6 +1397,30 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ) -> Vec where FilterFn: Fn(Res) -> bool, + { + self.lookup_import_candidates_from_module_impl( + lookup_ident, + namespace, + parent_scope, + start_module, + crate_path, + |ident, lookup_ident| ident.name == lookup_ident.name, + filter_fn, + ) + } + fn lookup_import_candidates_from_module_impl( + &self, + lookup_ident: Ident, + namespace: Namespace, + parent_scope: &ParentScope<'ra>, + start_module: Module<'ra>, + crate_path: ThinVec, + ident_filter_fn: IdentFilterFn, + filter_fn: FilterFn, + ) -> Vec + where + IdentFilterFn: Fn(Ident, Ident) -> bool, + FilterFn: Fn(Res) -> bool, { let mut candidates = Vec::new(); let mut seen_modules = FxHashSet::default(); @@ -1441,9 +1491,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // collect results based on the filter function // avoid suggesting anything from the same module in which we are resolving // avoid suggesting anything with a hygienic name - let is_exact_match = ident.name == lookup_ident.name; - if (is_exact_match - || Some(1) == edit_distance(ident.name.as_str(), lookup_ident.name.as_str(), 1)) + let is_exact_match = ident_filter_fn(ident.orig(orig_ident_span), lookup_ident); + if is_exact_match && ns == namespace && in_module != parent_scope.module && ident.ctxt.is_root() @@ -1600,6 +1649,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { /// /// N.B., the method does not look into imports, but this is not a problem, /// since we report the definitions (thus, the de-aliased imports). + /// + /// An _impl variant allows to apply a filter function on the ident themselves. pub(crate) fn lookup_import_candidates( &mut self, lookup_ident: Ident, @@ -1609,14 +1660,35 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ) -> Vec where FilterFn: Fn(Res) -> bool, + { + self.lookup_import_candidates_impl( + lookup_ident, + namespace, + parent_scope, + |ident: Ident, lookup_ident: Ident| ident.name == lookup_ident.name, + filter_fn, + ) + } + pub(crate) fn lookup_import_candidates_impl( + &mut self, + lookup_ident: Ident, + namespace: Namespace, + parent_scope: &ParentScope<'ra>, + ident_filter_fn: IdentFilterFn, + filter_fn: FilterFn, + ) -> Vec + where + IdentFilterFn: Fn(Ident, Ident) -> bool, + FilterFn: Fn(Res) -> bool, { let crate_path = thin_vec![ast::PathSegment::from_ident(Ident::with_dummy_span(kw::Crate))]; - let mut suggestions = self.lookup_import_candidates_from_module( + let mut suggestions = self.lookup_import_candidates_from_module_impl( lookup_ident, namespace, parent_scope, self.graph_root.to_module(), crate_path, + &ident_filter_fn, &filter_fn, ); From 462f181e2206b3a930e7b92b8135af3a8524a2d0 Mon Sep 17 00:00:00 2001 From: GTimothy <22472919+GTimothy@users.noreply.github.com> Date: Sat, 9 May 2026 18:51:37 +0200 Subject: [PATCH 05/16] rebless --- tests/ui/libstd-case-typo/libstd.stderr | 123 +++++++++++++----------- 1 file changed, 66 insertions(+), 57 deletions(-) diff --git a/tests/ui/libstd-case-typo/libstd.stderr b/tests/ui/libstd-case-typo/libstd.stderr index 6fa93103a322b..da1efdac7b2c5 100644 --- a/tests/ui/libstd-case-typo/libstd.stderr +++ b/tests/ui/libstd-case-typo/libstd.stderr @@ -62,6 +62,11 @@ error[E0425]: cannot find type `DecodeUTF16` in this scope | LL | fn test_decodeutf16(_x: DecodeUTF16<()>){} | ^^^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::char::DecodeUtf16; + | error[E0425]: cannot find type `Escapeunicode` in this scope --> $DIR/libstd.rs:28:27 @@ -247,12 +252,10 @@ error[E0425]: cannot find type `cStr` in this scope LL | fn test_cstr(_x: cStr){} | ^^^^ not found in this scope | -help: consider importing one of these structs +help: consider importing this struct | LL + use std::ffi::CStr; | -LL + use std::mem::type_info::Str; - | error[E0425]: cannot find type `Osstr` in this scope --> $DIR/libstd.rs:76:19 @@ -665,14 +668,12 @@ error[E0425]: cannot find type `take` in this scope LL | fn test_take(_x: take){} | ^^^^ not found in this scope | -help: consider importing one of these items +help: consider importing one of these structs | LL + use std::io::Take; | LL + use std::iter::Take; | -LL + use std::task::Wake; - | error[E0425]: cannot find type `cloned` in this scope --> $DIR/libstd.rs:163:20 @@ -1053,18 +1054,33 @@ error[E0425]: cannot find type `TCPListener` in this scope | LL | fn test_tcplistener(_x: TCPListener){} | ^^^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::net::TcpListener; + | error[E0425]: cannot find type `TCPStream` in this scope --> $DIR/libstd.rs:238:23 | LL | fn test_tcpstream(_x: TCPStream){} | ^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::net::TcpStream; + | error[E0425]: cannot find type `UDPSocket` in this scope --> $DIR/libstd.rs:240:23 | LL | fn test_udpsocket(_x: UDPSocket){} | ^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::net::UdpSocket; + | error[E0425]: cannot find type `NonZeroi8` in this scope --> $DIR/libstd.rs:245:23 @@ -1072,12 +1088,10 @@ error[E0425]: cannot find type `NonZeroi8` in this scope LL | fn test_nonzeroi8(_x: NonZeroi8){} | ^^^^^^^^^ not found in this scope | -help: consider importing one of these type aliases +help: consider importing this type alias | LL + use std::num::NonZeroI8; | -LL + use std::num::NonZeroU8; - | error[E0425]: cannot find type `NonZeroi16` in this scope --> $DIR/libstd.rs:247:24 @@ -1085,12 +1099,10 @@ error[E0425]: cannot find type `NonZeroi16` in this scope LL | fn test_nonzeroi16(_x: NonZeroi16){} | ^^^^^^^^^^ not found in this scope | -help: consider importing one of these type aliases +help: consider importing this type alias | LL + use std::num::NonZeroI16; | -LL + use std::num::NonZeroU16; - | error[E0425]: cannot find type `NonZeroi32` in this scope --> $DIR/libstd.rs:249:24 @@ -1098,12 +1110,10 @@ error[E0425]: cannot find type `NonZeroi32` in this scope LL | fn test_nonzeroi32(_x: NonZeroi32){} | ^^^^^^^^^^ not found in this scope | -help: consider importing one of these type aliases +help: consider importing this type alias | LL + use std::num::NonZeroI32; | -LL + use std::num::NonZeroU32; - | error[E0425]: cannot find type `NonZeroi64` in this scope --> $DIR/libstd.rs:251:24 @@ -1111,12 +1121,10 @@ error[E0425]: cannot find type `NonZeroi64` in this scope LL | fn test_nonzeroi64(_x: NonZeroi64){} | ^^^^^^^^^^ not found in this scope | -help: consider importing one of these type aliases +help: consider importing this type alias | LL + use std::num::NonZeroI64; | -LL + use std::num::NonZeroU64; - | error[E0425]: cannot find type `NonZeroi128` in this scope --> $DIR/libstd.rs:253:25 @@ -1124,12 +1132,10 @@ error[E0425]: cannot find type `NonZeroi128` in this scope LL | fn test_nonzeroi128(_x: NonZeroi128){} | ^^^^^^^^^^^ not found in this scope | -help: consider importing one of these type aliases +help: consider importing this type alias | LL + use std::num::NonZeroI128; | -LL + use std::num::NonZeroU128; - | error[E0425]: cannot find type `NonZerou8` in this scope --> $DIR/libstd.rs:255:23 @@ -1137,9 +1143,7 @@ error[E0425]: cannot find type `NonZerou8` in this scope LL | fn test_nonzerou8(_x: NonZerou8){} | ^^^^^^^^^ not found in this scope | -help: consider importing one of these type aliases - | -LL + use std::num::NonZeroI8; +help: consider importing this type alias | LL + use std::num::NonZeroU8; | @@ -1150,9 +1154,7 @@ error[E0425]: cannot find type `NonZerou16` in this scope LL | fn test_nonzerou16(_x: NonZerou16){} | ^^^^^^^^^^ not found in this scope | -help: consider importing one of these type aliases - | -LL + use std::num::NonZeroI16; +help: consider importing this type alias | LL + use std::num::NonZeroU16; | @@ -1163,9 +1165,7 @@ error[E0425]: cannot find type `NonZerou32` in this scope LL | fn test_nonzerou32(_x: NonZerou32){} | ^^^^^^^^^^ not found in this scope | -help: consider importing one of these type aliases - | -LL + use std::num::NonZeroI32; +help: consider importing this type alias | LL + use std::num::NonZeroU32; | @@ -1176,9 +1176,7 @@ error[E0425]: cannot find type `NonZerou64` in this scope LL | fn test_nonzerou64(_x: NonZerou64){} | ^^^^^^^^^^ not found in this scope | -help: consider importing one of these type aliases - | -LL + use std::num::NonZeroI64; +help: consider importing this type alias | LL + use std::num::NonZeroU64; | @@ -1189,9 +1187,7 @@ error[E0425]: cannot find type `NonZerou128` in this scope LL | fn test_nonzerou128(_x: NonZerou128){} | ^^^^^^^^^^^ not found in this scope | -help: consider importing one of these type aliases - | -LL + use std::num::NonZeroI128; +help: consider importing this type alias | LL + use std::num::NonZeroU128; | @@ -1489,12 +1485,10 @@ error[E0425]: cannot find type `rc` in this scope LL | fn test_rc(_x: rc<()>){} | ^^ not found in this scope | -help: consider importing one of these structs +help: consider importing this struct | LL + use std::rc::Rc; | -LL + use std::sync::Arc; - | error[E0425]: cannot find type `weak` in this scope --> $DIR/libstd.rs:338:18 @@ -1549,9 +1543,7 @@ help: a builtin type with a similar name exists LL - fn test_chars(_x: chars){} LL + fn test_chars(_x: char){} | -help: consider importing one of these items - | -LL + use std::primitive::char; +help: consider importing this struct | LL + use std::str::Chars; | @@ -1561,6 +1553,11 @@ error[E0425]: cannot find type `EncodeUTF16` in this scope | LL | fn test_encodeutf16(_x: EncodeUTF16){} | ^^^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::str::EncodeUtf16; + | error[E0425]: cannot find type `Matchindices` in this scope --> $DIR/libstd.rs:354:26 @@ -1616,12 +1613,8 @@ LL | fn test_rsplitn(_x: RSplitn){} | help: consider importing one of these structs | -LL + use std::slice::RSplit; - | LL + use std::slice::RSplitN; | -LL + use std::str::RSplit; - | LL + use std::str::RSplitN; | @@ -1641,6 +1634,11 @@ error[E0425]: cannot find type `SplitASCIIWhitespace` in this scope | LL | fn test_splitasciiwhitespace(_x: SplitASCIIWhitespace){} | ^^^^^^^^^^^^^^^^^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::str::SplitAsciiWhitespace; + | error[E0425]: cannot find type `Splitn` in this scope --> $DIR/libstd.rs:368:20 @@ -1650,15 +1648,10 @@ LL | fn test_splitn(_x: Splitn){} | help: consider importing one of these structs | -LL + use std::io::Split; - | -LL + use std::slice::Split; - | LL + use std::slice::SplitN; | -LL + use std::str::Split; +LL + use std::str::SplitN; | - = and 1 other candidate error[E0425]: cannot find type `Splitterminator` in this scope --> $DIR/libstd.rs:370:29 @@ -1759,18 +1752,39 @@ error[E0425]: cannot find type `RWlock` in this scope | LL | fn test_rwlock(_x: RWlock<()>){} | ^^^^^^ not found in this scope + | +help: consider importing one of these structs + | +LL + use std::sync::RwLock; + | +LL + use std::sync::nonpoison::RwLock; + | error[E0425]: cannot find type `RWlockReadGuard` in this scope --> $DIR/libstd.rs:391:29 | LL | fn test_rwlockreadguard(_x: RWlockReadGuard<()>){} | ^^^^^^^^^^^^^^^ not found in this scope + | +help: consider importing one of these structs + | +LL + use std::sync::RwLockReadGuard; + | +LL + use std::sync::nonpoison::RwLockReadGuard; + | error[E0425]: cannot find type `RWlockWriteGuard` in this scope --> $DIR/libstd.rs:393:30 | LL | fn test_rwlockwriteguard(_x: RWlockWriteGuard<()>){} | ^^^^^^^^^^^^^^^^ not found in this scope + | +help: consider importing one of these structs + | +LL + use std::sync::RwLockWriteGuard; + | +LL + use std::sync::nonpoison::RwLockWriteGuard; + | error[E0425]: cannot find type `WaittimeoutResult` in this scope --> $DIR/libstd.rs:395:31 @@ -1932,11 +1946,6 @@ LL | fn test_systemtime2(_x: SystemTime){} LL | struct SystemTome{} | ----------------- similarly named struct `SystemTome` defined here | -note: struct `st::SystemTame` exists but is inaccessible - --> $DIR/libstd.rs:436:5 - | -LL | struct SystemTame{} - | ^^^^^^^^^^^^^^^^^ not accessible help: a struct with a similar name exists | LL - fn test_systemtime2(_x: SystemTime){} From 6b309743d96e54a9ecd2251ee2551015fcff56ce Mon Sep 17 00:00:00 2001 From: GTimothy <22472919+GTimothy@users.noreply.github.com> Date: Sat, 9 May 2026 18:52:14 +0200 Subject: [PATCH 06/16] v3 move and update case insensitive import suggestion to the end of try_lookup_name_relaxed --- compiler/rustc_resolve/src/diagnostics.rs | 62 +++++++------- .../rustc_resolve/src/late/diagnostics.rs | 83 ++++++++++++++++++- 2 files changed, 111 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 5125b32cd5088..6fdcc019b7e63 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -774,7 +774,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } if could_be_path { - let mut import_suggestions = self.lookup_import_candidates( + // let mut import_suggestions = self.lookup_import_candidates( + let import_suggestions = self.lookup_import_candidates( name, Namespace::ValueNS, &parent_scope, @@ -868,37 +869,37 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } if import_suggestions.is_empty() && !suggested_typo { - let typo_import_suggestions = self.lookup_import_candidates_impl( - name, - Namespace::ValueNS, - &parent_scope, - |ident, lookup_ident| { - ident.name.as_str().to_lowercase() - == lookup_ident.name.as_str().to_lowercase() - }, - &|res: Res| { - matches!( - res, - Res::Def( - DefKind::Ctor(CtorOf::Variant, CtorKind::Const) - | DefKind::Ctor(CtorOf::Struct, CtorKind::Const) - | DefKind::Const { .. } - | DefKind::AssocConst { .. }, - _, - ) - ) - }, - ); - if !typo_import_suggestions.is_empty() { - import_suggestions = typo_import_suggestions; - } else { - let help_msg = format!( - "if you meant to match on a unit struct, unit variant or a `const` \ + // let typo_import_suggestions = self.lookup_import_candidates( + // name, + // Namespace::ValueNS, + // &parent_scope, + // // |ident, lookup_ident| { + // // ident.name.as_str().to_lowercase() + // // == lookup_ident.name.as_str().to_lowercase() + // // }, + // &|res: Res| { + // matches!( + // res, + // Res::Def( + // DefKind::Ctor(CtorOf::Variant, CtorKind::Const) + // | DefKind::Ctor(CtorOf::Struct, CtorKind::Const) + // | DefKind::Const { .. } + // | DefKind::AssocConst { .. }, + // _, + // ) + // ) + // }, + // ); + // if !typo_import_suggestions.is_empty() { + // import_suggestions = typo_import_suggestions; + // } else { + let help_msg = format!( + "if you meant to match on a unit struct, unit variant or a `const` \ item, consider making the path in the pattern qualified: \ `path::to::ModOrType::{name}`", - ); - err.span_help(span, help_msg); - } + ); + err.span_help(span, help_msg); + // } } show_candidates( @@ -1492,6 +1493,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // avoid suggesting anything from the same module in which we are resolving // avoid suggesting anything with a hygienic name let is_exact_match = ident_filter_fn(ident.orig(orig_ident_span), lookup_ident); + // let is_exact_match = ident.name == lookup_ident.name; if is_exact_match && ns == namespace && in_module != parent_scope.module diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 1ad5083fbfbe9..0a84a807b9522 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -722,6 +722,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { candidates.clear(); } + // eprintln!("{:?}", suggested_candidates.clone()); let mut fallback = self.suggest_trait_and_bounds(&mut err, source, res, span, &base_error); fallback |= self.suggest_typo( &mut err, @@ -730,13 +731,16 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { following_seg, span, &base_error, - suggested_candidates, + suggested_candidates.clone(), ); + // last ditch attempt, look for case insensitive match + if fallback { // Fallback label. - err.span_label(base_error.span, base_error.fallback_label); + err.span_label(base_error.span, base_error.fallback_label.clone()); } + self.err_code_special_cases(&mut err, source, path, span); let module = base_error.module.unwrap_or_else(|| CRATE_DEF_ID.to_def_id()); @@ -859,6 +863,8 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } } + /// An _impl also exists that allows to specify a ident filter function. + /// Here the ident filter function is equality of names fn try_lookup_name_relaxed( &mut self, err: &mut Diag<'_>, @@ -869,6 +875,33 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { res: Option, base_error: &BaseError, ) -> (bool, FxHashSet, Vec) { + let ident_filter = |ident: Ident, lookup_ident: Ident| ident.name == lookup_ident.name; + self.try_lookup_name_relaxed_impl( + err, + source, + path, + following_seg, + span, + res, + base_error, + ident_filter, + ) + } + + fn try_lookup_name_relaxed_impl( + &mut self, + err: &mut Diag<'_>, + source: PathSource<'_, '_, '_>, + path: &[Segment], + following_seg: Option<&Segment>, + span: Span, + res: Option, + base_error: &BaseError, + ident_filter: IdentFilterFn, + ) -> (bool, FxHashSet, Vec) + where + IdentFilterFn: Fn(Ident, Ident) -> bool, + { let span = match following_seg { Some(_) if path[0].ident.span.eq_ctxt(path[path.len() - 1].ident.span) => { // The path `span` that comes in includes any following segments, which we don't @@ -881,13 +914,14 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { // Try to lookup name in more relaxed fashion for better error reporting. let ident = path.last().unwrap().ident; let is_expected = &|res| source.is_expected(res); + // let ident_filter = &| ident:Ident, ident_lookup:Ident| ident.name == ident_lookup.name; let ns = source.namespace(); let is_enum_variant = &|res| matches!(res, Res::Def(DefKind::Variant, _)); let path_str = Segment::names_to_string(path); let ident_span = path.last().map_or(span, |ident| ident.ident.span); let mut candidates = self .r - .lookup_import_candidates(ident, ns, &self.parent_scope, is_expected) + .lookup_import_candidates_impl(ident, ns, &self.parent_scope, ident_filter, is_expected) .into_iter() .filter(|ImportSuggestion { did, .. }| { match (did, res.and_then(|res| res.opt_def_id())) { @@ -1098,10 +1132,51 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } } } - + // eprintln!("1:{:?}", candidates.clone()); + // eprintln!("1:{:?}", suggested_candidates.clone()); if candidates.is_empty() { candidates = self.smart_resolve_partial_mod_path_errors(path, following_seg); } + // eprintln!("2:{:?}", candidates.clone()); + if candidates.is_empty() && err.children.is_empty() { + // eprintln!("{err:?}"); + // eprintln!("{:?}", (suggested_candidates.clone(), candidates.clone())); + let case_insensitive_filter = |ident: Ident, lookup_ident: Ident| { + ident.as_str().to_lowercase() == lookup_ident.as_str().to_lowercase() + }; + let mut case_agnostic_candidates = self + .r + .lookup_import_candidates_impl( + ident, + ns, + &self.parent_scope, + case_insensitive_filter, + is_expected, + ) + .into_iter() + .filter(|ImportSuggestion { did, .. }| { + // eprintln!("{:?} vs {:?}", did, res.and_then(|res| res.opt_def_id())); + match (did, res.and_then(|res| res.opt_def_id())) { + (Some(suggestion_did), Some(actual_did)) => *suggestion_did != actual_did, + _ => true, + } + }) + .collect::>(); + // Try to filter out intrinsics candidates, as long as we have + // some other candidates to suggest. + let intrinsic_candidates: Vec<_> = case_agnostic_candidates + .extract_if(.., |sugg| { + let path = path_names_to_string(&sugg.path); + path.starts_with("core::intrinsics::") || path.starts_with("std::intrinsics::") + }) + .collect(); + if case_agnostic_candidates.is_empty() { + // Put them back if we have no more candidates to suggest... + case_agnostic_candidates = intrinsic_candidates; + } + + candidates.extend(case_agnostic_candidates); + } (false, suggested_candidates, candidates) } From daa4044ed72f9cf4ca0760b3e31444e0410728ce Mon Sep 17 00:00:00 2001 From: GTimothy <22472919+GTimothy@users.noreply.github.com> Date: Tue, 12 May 2026 10:31:23 +0200 Subject: [PATCH 07/16] v4 filter out nonmacroattr filter out import suggestions that are in prelude other updates --- .../rustc_resolve/src/late/diagnostics.rs | 135 ++++++++++++------ 1 file changed, 95 insertions(+), 40 deletions(-) diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 0a84a807b9522..88268f8f3094d 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -902,6 +902,11 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { where IdentFilterFn: Fn(Ident, Ident) -> bool, { + let debug = false; + let _ = debug && { + eprintln!("err A: {err:?}"); + true + }; let span = match following_seg { Some(_) if path[0].ident.span.eq_ctxt(path[path.len() - 1].ident.span) => { // The path `span` that comes in includes any following segments, which we don't @@ -924,6 +929,10 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { .lookup_import_candidates_impl(ident, ns, &self.parent_scope, ident_filter, is_expected) .into_iter() .filter(|ImportSuggestion { did, .. }| { + let _ = debug && { + eprintln!("initial:{did:?}"); + true + }; match (did, res.and_then(|res| res.opt_def_id())) { (Some(suggestion_did), Some(actual_did)) => *suggestion_did != actual_did, _ => true, @@ -1132,50 +1141,96 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } } } - // eprintln!("1:{:?}", candidates.clone()); - // eprintln!("1:{:?}", suggested_candidates.clone()); + // let _ = debug && {eprintln!("1:{:?}", candidates.clone()); true}; + // let _ = debug && {eprintln!("1:{:?}", suggested_candidates.clone()); true}; if candidates.is_empty() { candidates = self.smart_resolve_partial_mod_path_errors(path, following_seg); } - // eprintln!("2:{:?}", candidates.clone()); - if candidates.is_empty() && err.children.is_empty() { - // eprintln!("{err:?}"); - // eprintln!("{:?}", (suggested_candidates.clone(), candidates.clone())); - let case_insensitive_filter = |ident: Ident, lookup_ident: Ident| { - ident.as_str().to_lowercase() == lookup_ident.as_str().to_lowercase() - }; - let mut case_agnostic_candidates = self - .r - .lookup_import_candidates_impl( - ident, - ns, - &self.parent_scope, - case_insensitive_filter, - is_expected, - ) - .into_iter() - .filter(|ImportSuggestion { did, .. }| { - // eprintln!("{:?} vs {:?}", did, res.and_then(|res| res.opt_def_id())); - match (did, res.and_then(|res| res.opt_def_id())) { - (Some(suggestion_did), Some(actual_did)) => *suggestion_did != actual_did, - _ => true, - } - }) - .collect::>(); - // Try to filter out intrinsics candidates, as long as we have - // some other candidates to suggest. - let intrinsic_candidates: Vec<_> = case_agnostic_candidates - .extract_if(.., |sugg| { - let path = path_names_to_string(&sugg.path); - path.starts_with("core::intrinsics::") || path.starts_with("std::intrinsics::") - }) - .collect(); - if case_agnostic_candidates.is_empty() { - // Put them back if we have no more candidates to suggest... - case_agnostic_candidates = intrinsic_candidates; - } + //what if there is no candidate there but it was a mod path error ? i do not want to resolve it as a type when it is a path.... - candidates.extend(case_agnostic_candidates); + // let _ = debug && {eprintln!("2:{:?}", candidates.clone()); true }; + if let Some(Res::NonMacroAttr(_)) = res { + } else { + // we do not suggest alternative capitalizations if only one letter, too many constants can match and it become noisy. + if candidates.is_empty() && err.children.is_empty() && ident.as_str().len() > 1 { + // let _ = debug && {eprintln!("{:?}", (suggested_candidates.clone(), candidates.clone())); true}; + let case_insensitive_filter = |ident: Ident, lookup_ident: Ident| { + ident.as_str().to_lowercase() == lookup_ident.as_str().to_lowercase() + }; + let mut case_agnostic_candidates = self + .r + .lookup_import_candidates_impl( + ident, + ns, + &self.parent_scope, + case_insensitive_filter, + is_expected, + ) + .into_iter() + .filter(|ImportSuggestion { did, .. }| { + let _ = debug && { + eprintln!("final:{did:?}"); + true + }; + let _ = debug && { + eprintln!("{:?} vs {:?}", did, res.and_then(|res| res.opt_def_id())); + true + }; + + // Filter out items that are in the prelude + if let Some(prelude) = self.r.prelude { + if let Some(suggestion_did) = did { + let mut is_in_prelude = false; + prelude.for_each_child(self.r, |_, _, _, _, decl| { + if decl.res().opt_def_id() == Some(*suggestion_did) { + is_in_prelude = true; + } + }); + if is_in_prelude { + return false; + } + } + } + match (did, res.and_then(|res| res.opt_def_id())) { + (Some(suggestion_did), Some(actual_did)) => { + *suggestion_did != actual_did + } + _ => true, + } + }) + .collect::>(); + // Try to filter out intrinsics candidates, as long as we have + // some other candidates to suggest. + let intrinsic_candidates: Vec<_> = case_agnostic_candidates + .extract_if(.., |sugg| { + let path = path_names_to_string(&sugg.path); + path.starts_with("core::intrinsics::") + || path.starts_with("std::intrinsics::") + }) + .collect(); + if case_agnostic_candidates.is_empty() { + // Put them back if we have no more candidates to suggest... + case_agnostic_candidates = intrinsic_candidates; + } + if !case_agnostic_candidates.is_empty() { + let _ = debug && { + eprintln!("err B: {err:?}"); + true + }; + let _ = debug && { + eprintln!("sou({ident}: {source:?}"); + true + }; + let _ = debug && { + eprintln!("res({ident}): {res:?}"); + true + }; + } + suggested_candidates.extend( + case_agnostic_candidates.iter().map(|sug| path_names_to_string(&sug.path)), + ); + candidates.extend(case_agnostic_candidates); + } } (false, suggested_candidates, candidates) From 5709fc6bef89699c1ef3fbbb12e99399f282e26b Mon Sep 17 00:00:00 2001 From: GTimothy <22472919+GTimothy@users.noreply.github.com> Date: Tue, 12 May 2026 10:32:53 +0200 Subject: [PATCH 08/16] v5 -move case insensitive import suggestion to its own function -call it at after all the other suggestion-adding functions -track whether any of them actually added a suggestion by making them return bools -only call it if no other was made previously --- .../rustc_resolve/src/late/diagnostics.rs | 279 ++++++++++++++---- 1 file changed, 226 insertions(+), 53 deletions(-) diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 88268f8f3094d..81b5a90079e53 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -652,21 +652,37 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { err.span_label(within_macro_span, "due to this macro variable"); } - self.detect_missing_binding_available_from_pattern(&mut err, path, following_seg); - self.suggest_at_operator_in_slice_pat_with_range(&mut err, path); - self.suggest_range_struct_destructuring(&mut err, path, source); - self.suggest_swapping_misplaced_self_ty_and_trait(&mut err, source, res, base_error.span); + let _missing_binding_available = + self.detect_missing_binding_available_from_pattern(&mut err, path, following_seg); + let _op_in_slice = self.suggest_at_operator_in_slice_pat_with_range(&mut err, path); + let range_destruct = self.suggest_range_struct_destructuring(&mut err, path, source); + let swapping = self.suggest_swapping_misplaced_self_ty_and_trait( + &mut err, + source, + res, + base_error.span, + ); if let Some((span, label)) = base_error.span_label { err.span_label(span, label); } - if let Some(ref sugg) = base_error.suggestion { + let base_suggestion = if let Some(ref sugg) = base_error.suggestion { err.span_suggestion_verbose(sugg.0, sugg.1, &sugg.2, Applicability::MaybeIncorrect); - } + true + } else { + false + }; - self.suggest_changing_type_to_const_param(&mut err, res, source, path, following_seg, span); - self.explain_functions_in_pattern(&mut err, res, source); + let changing_ty_const = self.suggest_changing_type_to_const_param( + &mut err, + res, + source, + path, + following_seg, + span, + ); + let funcall = self.explain_functions_in_pattern(&mut err, res, source); if self.suggest_pattern_match_with_let(&mut err, source, span) { // Fallback label. @@ -674,9 +690,9 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { return (err, Vec::new()); } - self.suggest_self_or_self_ref(&mut err, path, span); - self.detect_assoc_type_constraint_meant_as_path(&mut err, &base_error); - self.detect_rtn_with_fully_qualified_path( + let suggest_self = self.suggest_self_or_self_ref(&mut err, path, span); + let assoc_type = self.detect_assoc_type_constraint_meant_as_path(&mut err, &base_error); + let rtn = self.detect_rtn_with_fully_qualified_path( &mut err, path, following_seg, @@ -716,13 +732,13 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { if found { return (err, candidates); } - - if self.suggest_shadowed(&mut err, source, path, following_seg, span) { + let shadowed = self.suggest_shadowed(&mut err, source, path, following_seg, span); + if shadowed { // if there is already a shadowed name, don'suggest candidates for importing candidates.clear(); } - // eprintln!("{:?}", suggested_candidates.clone()); + // let _ = debug && {eprintln!("{:?}", suggested_candidates.clone()); true}; let mut fallback = self.suggest_trait_and_bounds(&mut err, source, res, span, &base_error); fallback |= self.suggest_typo( &mut err, @@ -734,13 +750,36 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { suggested_candidates.clone(), ); - // last ditch attempt, look for case insensitive match - if fallback { // Fallback label. err.span_label(base_error.span, base_error.fallback_label.clone()); } + if !(range_destruct + | swapping + | base_suggestion + | changing_ty_const + | funcall + | suggest_self + | assoc_type + | rtn + | shadowed) + { + // eprintln!("try import.") + let (found, _suggested_candidates, candidates) = self.lookup_import_case_insensitive( + &mut err, + source, + path, + following_seg, + span, + res, + &base_error, + ); + if found { + return (err, candidates); + } + } + self.err_code_special_cases(&mut err, source, path, span); let module = base_error.module.unwrap_or_else(|| CRATE_DEF_ID.to_def_id()); @@ -758,7 +797,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { source: PathSource<'_, '_, '_>, res: Option, qself: Option<&QSelf>, - ) { + ) -> bool { if let Some(Res::Def(DefKind::AssocFn, _)) = res && let PathSource::TraitItem(TypeNS, _) = source && let None = following_seg @@ -773,19 +812,21 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { format!("{}::{}(..)", ty_path.segments[0].ident, path[path.len() - 1].ident), Applicability::MaybeIncorrect, ); + return true; } + return false; } fn detect_assoc_type_constraint_meant_as_path( &self, err: &mut Diag<'_>, base_error: &BaseError, - ) { + ) -> bool { let Some(ty) = self.diag_metadata.current_type_path else { - return; + return false; }; let TyKind::Path(_, path) = &ty.kind else { - return; + return false; }; for segment in &path.segments { let Some(params) = &segment.args else { @@ -814,17 +855,24 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { "::", Applicability::MachineApplicable, ); + return true; } } } } + return false; } - fn suggest_self_or_self_ref(&mut self, err: &mut Diag<'_>, path: &[Segment], span: Span) { + fn suggest_self_or_self_ref( + &mut self, + err: &mut Diag<'_>, + path: &[Segment], + span: Span, + ) -> bool { if !self.self_type_is_available() { - return; + return false; } - let Some(path_last_segment) = path.last() else { return }; + let Some(path_last_segment) = path.last() else { return false }; let item_str = path_last_segment.ident; // Emit help message for fake-self from other languages (e.g., `this` in JavaScript). if ["this", "my"].contains(&item_str.as_str()) { @@ -860,7 +908,9 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { ); } } + return true; } + return false; } /// An _impl also exists that allows to specify a ident filter function. @@ -1149,10 +1199,121 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { //what if there is no candidate there but it was a mod path error ? i do not want to resolve it as a type when it is a path.... // let _ = debug && {eprintln!("2:{:?}", candidates.clone()); true }; + // if let Some(Res::NonMacroAttr(_)) = res { + // } else { + // // we do not suggest alternative capitalizations if only one letter, too many constants can match and it become noisy. + // if candidates.is_empty() && err.children.is_empty() && ident.as_str().len() > 1 { + // // let _ = debug && {eprintln!("{:?}", (suggested_candidates.clone(), candidates.clone())); true}; + // let case_insensitive_filter = |ident: Ident, lookup_ident: Ident| { + // ident.as_str().to_lowercase() == lookup_ident.as_str().to_lowercase() + // }; + // let mut case_agnostic_candidates = self + // .r + // .lookup_import_candidates_impl( + // ident, + // ns, + // &self.parent_scope, + // case_insensitive_filter, + // is_expected, + // ) + // .into_iter() + // .filter(|ImportSuggestion { did, .. }| { + // let _ = debug && { + // eprintln!("final:{did:?}"); + // true + // }; + // let _ = debug && { + // eprintln!("{:?} vs {:?}", did, res.and_then(|res| res.opt_def_id())); + // true + // }; + // + // // Filter out items that are in the prelude + // if let Some(prelude) = self.r.prelude { + // if let Some(suggestion_did) = did { + // let mut is_in_prelude = false; + // prelude.for_each_child(self.r, |_, _, _, _, decl| { + // if decl.res().opt_def_id() == Some(*suggestion_did) { + // is_in_prelude = true; + // } + // }); + // if is_in_prelude { + // return false; + // } + // } + // } + // match (did, res.and_then(|res| res.opt_def_id())) { + // (Some(suggestion_did), Some(actual_did)) => { + // *suggestion_did != actual_did + // } + // _ => true, + // } + // }) + // .collect::>(); + // // Try to filter out intrinsics candidates, as long as we have + // // some other candidates to suggest. + // let intrinsic_candidates: Vec<_> = case_agnostic_candidates + // .extract_if(.., |sugg| { + // let path = path_names_to_string(&sugg.path); + // path.starts_with("core::intrinsics::") + // || path.starts_with("std::intrinsics::") + // }) + // .collect(); + // if case_agnostic_candidates.is_empty() { + // // Put them back if we have no more candidates to suggest... + // case_agnostic_candidates = intrinsic_candidates; + // } + // if !case_agnostic_candidates.is_empty() { + // let _ = debug && { + // eprintln!("err B: {err:?}"); + // true + // }; + // let _ = debug && { + // eprintln!("sou({ident}: {source:?}"); + // true + // }; + // let _ = debug && { + // eprintln!("res({ident}): {res:?}"); + // true + // }; + // } + // suggested_candidates.extend( + // case_agnostic_candidates.iter().map(|sug| path_names_to_string(&sug.path)), + // ); + // candidates.extend(case_agnostic_candidates); + // } + // } + + (false, suggested_candidates, candidates) + } + fn lookup_import_case_insensitive( + &mut self, + err: &mut Diag<'_>, + source: PathSource<'_, '_, '_>, + path: &[Segment], + following_seg: Option<&Segment>, + span: Span, + res: Option, + base_error: &BaseError, + ) -> (bool, FxHashSet, Vec) { + let _ = base_error; + let _ = span; + let _ = following_seg; + let debug = false; + + let mut suggested_candidates = FxHashSet::default(); + // Try to lookup name in more relaxed fashion for better error reporting. + let ident = path.last().unwrap().ident; + let is_expected = &|res| source.is_expected(res); + // let ident_filter = &| ident:Ident, ident_lookup:Ident| ident.name == ident_lookup.name; + let ns = source.namespace(); + // let is_enum_variant = &|res| matches!(res, Res::Def(DefKind::Variant, _)); + // let path_str = Segment::names_to_string(path); + // let ident_span = path.last().map_or(span, |ident| ident.ident.span); + if let Some(Res::NonMacroAttr(_)) = res { } else { // we do not suggest alternative capitalizations if only one letter, too many constants can match and it become noisy. - if candidates.is_empty() && err.children.is_empty() && ident.as_str().len() > 1 { + if ident.as_str().len() > 1 { // let _ = debug && {eprintln!("{:?}", (suggested_candidates.clone(), candidates.clone())); true}; let case_insensitive_filter = |ident: Ident, lookup_ident: Ident| { ident.as_str().to_lowercase() == lookup_ident.as_str().to_lowercase() @@ -1229,11 +1390,10 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { suggested_candidates.extend( case_agnostic_candidates.iter().map(|sug| path_names_to_string(&sug.path)), ); - candidates.extend(case_agnostic_candidates); + return (true, suggested_candidates, case_agnostic_candidates); } } - - (false, suggested_candidates, candidates) + return (false, suggested_candidates, Vec::new()); } fn lookup_doc_alias_name(&mut self, path: &[Segment], ns: Namespace) -> Option<(DefId, Ident)> { @@ -1663,9 +1823,9 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { err: &mut Diag<'_>, path: &[Segment], following_seg: Option<&Segment>, - ) { - let [segment] = path else { return }; - let None = following_seg else { return }; + ) -> bool { + let [segment] = path else { return false }; + let None = following_seg else { return false }; for rib in self.ribs[ValueNS].iter().rev() { let patterns_with_skipped_bindings = self.r.tcx.with_stable_hashing_context(|mut hcx| { @@ -1704,14 +1864,19 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } } } + true } - fn suggest_at_operator_in_slice_pat_with_range(&self, err: &mut Diag<'_>, path: &[Segment]) { - let Some(pat) = self.diag_metadata.current_pat else { return }; + fn suggest_at_operator_in_slice_pat_with_range( + &self, + err: &mut Diag<'_>, + path: &[Segment], + ) -> bool { + let Some(pat) = self.diag_metadata.current_pat else { return false }; let (bound, side, range) = match &pat.kind { ast::PatKind::Range(Some(bound), None, range) => (bound, Side::Start, range), ast::PatKind::Range(None, Some(bound), range) => (bound, Side::End, range), - _ => return, + _ => return false, }; if let ExprKind::Path(None, range_path) = &bound.kind && let [segment] = &range_path.segments[..] @@ -1730,12 +1895,14 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { ident: segment.ident, snippet, }); + return true; } enum Side { Start, End, } + false } fn suggest_range_struct_destructuring( @@ -1743,22 +1910,22 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { err: &mut Diag<'_>, path: &[Segment], source: PathSource<'_, '_, '_>, - ) { + ) -> bool { if !matches!(source, PathSource::Pat | PathSource::TupleStruct(..) | PathSource::Expr(..)) { - return; + return false; } - let Some(pat) = self.diag_metadata.current_pat else { return }; - let ast::PatKind::Range(start, end, end_kind) = &pat.kind else { return }; + let Some(pat) = self.diag_metadata.current_pat else { return false }; + let ast::PatKind::Range(start, end, end_kind) = &pat.kind else { return false }; - let [segment] = path else { return }; + let [segment] = path else { return false }; let failing_span = segment.ident.span; let in_start = start.as_ref().is_some_and(|e| e.span.contains(failing_span)); let in_end = end.as_ref().is_some_and(|e| e.span.contains(failing_span)); if !in_start && !in_end { - return; + return false; } let start_snippet = @@ -1800,7 +1967,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { resolve_short_name(sym::RangeToInclusive, "std::ops::RangeToInclusive"), vec![field("end", end)], ), - _ => return, + _ => return false, }; err.span_suggestion_verbose( @@ -1814,6 +1981,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { "range patterns match against the start and end of a range; \ to bind the components, use a struct pattern", ); + true } fn suggest_swapping_misplaced_self_ty_and_trait( @@ -1822,7 +1990,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { source: PathSource<'_, 'ast, 'ra>, res: Option, span: Span, - ) { + ) -> bool { if let Some((trait_ref, self_ty)) = self.diag_metadata.currently_processing_impl_trait.clone() && let TyKind::Path(_, self_ty_path) = &self_ty.kind @@ -1841,7 +2009,9 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { vec![(trait_ref.path.span, self_ty_str), (self_ty.span, trait_ref_str)], Applicability::MaybeIncorrect, ); + return true; } + false } fn explain_functions_in_pattern( @@ -1849,11 +2019,12 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { err: &mut Diag<'_>, res: Option, source: PathSource<'_, '_, '_>, - ) { - let PathSource::TupleStruct(_, _) = source else { return }; - let Some(Res::Def(DefKind::Fn, _)) = res else { return }; + ) -> bool { + let PathSource::TupleStruct(_, _) = source else { return false }; + let Some(Res::Def(DefKind::Fn, _)) = res else { return false }; err.primary_message("expected a pattern, found a function call"); err.note("function calls are not allowed in patterns: "); + true } fn suggest_changing_type_to_const_param( @@ -1864,7 +2035,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { path: &[Segment], following_seg: Option<&Segment>, span: Span, - ) { + ) -> bool { if let PathSource::Expr(None) = source && let Some(Res::Def(DefKind::TyParam, _)) = res && following_seg.is_none() @@ -1877,8 +2048,8 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { // } // } // where `N` is a type param but should likely have been a const param. - let Some(item) = self.diag_metadata.current_item else { return }; - let Some(generics) = item.kind.generics() else { return }; + let Some(item) = self.diag_metadata.current_item else { return false }; + let Some(generics) = item.kind.generics() else { return false }; let Some(span) = generics.params.iter().find_map(|param| { // Only consider type params with no bounds. if param.bounds.is_empty() && param.ident.name == segment.ident.name { @@ -1887,15 +2058,15 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { None } }) else { - return; + return false; }; err.subdiagnostic(errors::UnexpectedResChangeTyParamToConstParamSugg { before: span.shrink_to_lo(), after: span.shrink_to_hi(), }); - return; + return true; } - let PathSource::Trait(_) = source else { return }; + let PathSource::Trait(_) = source else { return false }; // We don't include `DefKind::Str` and `DefKind::AssocTy` as they can't be reached here anyway. let applicability = match res { @@ -1911,11 +2082,11 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { { Applicability::MaybeIncorrect } - _ => return, + _ => return false, }; - let Some(item) = self.diag_metadata.current_item else { return }; - let Some(generics) = item.kind.generics() else { return }; + let Some(item) = self.diag_metadata.current_item else { return false }; + let Some(generics) = item.kind.generics() else { return false }; let param = generics.params.iter().find_map(|param| { // Only consider type params with exactly one trait bound. @@ -1936,7 +2107,9 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { span: param.shrink_to_lo(), applicability, }); + return true; } + false } fn suggest_pattern_match_with_let( From b2440d1f6c20980dca7514f3d442e31f7922c008 Mon Sep 17 00:00:00 2001 From: GTimothy <22472919+GTimothy@users.noreply.github.com> Date: Tue, 12 May 2026 10:33:17 +0200 Subject: [PATCH 09/16] v5 blessed --- tests/ui/cast/cast-errors-issue-43825.stderr | 7 +++++ .../unevaluated-const-ice-119731.stderr | 19 ++++++++---- tests/ui/coroutine/layout-error.stderr | 5 ++++ tests/ui/delegation/bad-resolve.stderr | 30 ++++++++++++++----- tests/ui/lint/recommend-literal.stderr | 21 ++++++++----- ...-param-decl-on-type-instead-of-impl.stderr | 19 ++++++++---- .../ui/parser/raw/raw-literal-keywords.stderr | 10 +++++++ ...n-with-missing-fields-resolve-error.stderr | 5 ++++ tests/ui/resolve/levenshtein.stderr | 18 +++++++++++ .../resolve/resolve-assoc-suggestions.stderr | 7 +++++ .../resolve-speculative-adjustment.stderr | 5 ++++ ...-to-add-suggestions-with-no-changes.stderr | 8 +++++ 12 files changed, 129 insertions(+), 25 deletions(-) diff --git a/tests/ui/cast/cast-errors-issue-43825.stderr b/tests/ui/cast/cast-errors-issue-43825.stderr index 658d5ddbb611c..27de24bde2405 100644 --- a/tests/ui/cast/cast-errors-issue-43825.stderr +++ b/tests/ui/cast/cast-errors-issue-43825.stderr @@ -3,6 +3,13 @@ error[E0425]: cannot find value `error` in this scope | LL | let error = error; | ^^^^^ not found in this scope + | +help: consider importing one of these items + | +LL + use std::fmt::Error; + | +LL + use std::fs::TryLockError::Error; + | error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr index 022074181cecd..6ea9359e5250f 100644 --- a/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr +++ b/tests/ui/const-generics/generic_const_exprs/unevaluated-const-ice-119731.stderr @@ -10,6 +10,19 @@ LL - pub use v20::{v13, v17}; LL + pub use v20::{v11, v17}; | +error[E0425]: cannot find function `v6` in this scope + --> $DIR/unevaluated-const-ice-119731.rs:13:35 + | +LL | const v0: [[usize; v4]; v4] = v6(v8); + | ^^ not found in this scope + | +help: consider importing one of these tuple variants + | +LL + use std::net::IpAddr::V6; + | +LL + use std::net::SocketAddr::V6; + | + error[E0425]: cannot find value `v8` in this scope --> $DIR/unevaluated-const-ice-119731.rs:13:38 | @@ -87,12 +100,6 @@ help: add `#![feature(min_adt_const_params)]` to the crate attributes to enable LL + #![feature(min_adt_const_params)] | -error[E0425]: cannot find function `v6` in this scope - --> $DIR/unevaluated-const-ice-119731.rs:13:35 - | -LL | const v0: [[usize; v4]; v4] = v6(v8); - | ^^ not found in this scope - error: maximum number of nodes exceeded in constant v20::v17::::{constant#0} --> $DIR/unevaluated-const-ice-119731.rs:28:37 | diff --git a/tests/ui/coroutine/layout-error.stderr b/tests/ui/coroutine/layout-error.stderr index f3b3843de898c..ad3bc541f4302 100644 --- a/tests/ui/coroutine/layout-error.stderr +++ b/tests/ui/coroutine/layout-error.stderr @@ -3,6 +3,11 @@ error[E0425]: cannot find value `Foo` in this scope | LL | let a = Foo; | ^^^ not found in this scope + | +help: consider importing this function + | +LL + use crate::foo; + | error: aborting due to 1 previous error diff --git a/tests/ui/delegation/bad-resolve.stderr b/tests/ui/delegation/bad-resolve.stderr index d1b3974e77081..24d03b229b98d 100644 --- a/tests/ui/delegation/bad-resolve.stderr +++ b/tests/ui/delegation/bad-resolve.stderr @@ -88,6 +88,28 @@ error[E0423]: expected function, found module `prefix::self` LL | reuse prefix::{self, super, crate}; | ^^^^^^ not a function +error[E0433]: `super` in paths can only be used in start position + --> $DIR/bad-resolve.rs:43:22 + | +LL | reuse prefix::{self, super, crate}; + | ^^^^^ can only be used in path start position + | +help: consider importing this enum + | +LL + use std::path::Prefix; + | + +error[E0433]: `crate` in paths can only be used in start position + --> $DIR/bad-resolve.rs:43:29 + | +LL | reuse prefix::{self, super, crate}; + | ^^^^^ can only be used in path start position + | +help: consider importing this enum + | +LL + use std::path::Prefix; + | + error[E0046]: not all trait items implemented, missing: `Type` --> $DIR/bad-resolve.rs:21:1 | @@ -105,13 +127,7 @@ LL | reuse unresolved_prefix::{a, b, c}; | = help: you might be missing a crate named `unresolved_prefix` -error[E0433]: `crate` in paths can only be used in start position - --> $DIR/bad-resolve.rs:43:29 - | -LL | reuse prefix::{self, super, crate}; - | ^^^^^ can only be used in path start position - -error: aborting due to 13 previous errors +error: aborting due to 14 previous errors Some errors have detailed explanations: E0046, E0324, E0407, E0423, E0425, E0433, E0575, E0576. For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/lint/recommend-literal.stderr b/tests/ui/lint/recommend-literal.stderr index 01e993df17a98..4504442110848 100644 --- a/tests/ui/lint/recommend-literal.stderr +++ b/tests/ui/lint/recommend-literal.stderr @@ -68,10 +68,17 @@ error[E0425]: cannot find type `float` in this scope --> $DIR/recommend-literal.rs:33:12 | LL | width: float, - | ^^^^^ - | | - | not found in this scope - | help: perhaps you intended to use this type: `f32` + | ^^^^^ not found in this scope + | +help: perhaps you intended to use this type + | +LL - width: float, +LL + width: f32, + | +help: consider importing this struct + | +LL + use std::mem::type_info::Float; + | error[E0425]: cannot find type `int` in this scope --> $DIR/recommend-literal.rs:36:19 @@ -84,10 +91,10 @@ help: perhaps you intended to use this type LL - depth: Option, LL + depth: Option, | -help: you might be missing a type parameter +help: consider importing this struct + | +LL + use std::mem::type_info::Int; | -LL | struct Data { - | +++++ error[E0425]: cannot find type `short` in this scope --> $DIR/recommend-literal.rs:42:16 diff --git a/tests/ui/parser/const-param-decl-on-type-instead-of-impl.stderr b/tests/ui/parser/const-param-decl-on-type-instead-of-impl.stderr index 7aba69a0cf5a0..26e13b39fcc87 100644 --- a/tests/ui/parser/const-param-decl-on-type-instead-of-impl.stderr +++ b/tests/ui/parser/const-param-decl-on-type-instead-of-impl.stderr @@ -22,6 +22,12 @@ error: unexpected `const` parameter declaration LL | path::path::Struct::() | ^^^^^^^^^^^^^^ expected a `const` expression, not a parameter declaration +error[E0425]: cannot find type `T` in this scope + --> $DIR/const-param-decl-on-type-instead-of-impl.rs:8:15 + | +LL | fn banana(a: >::BAR) {} + | ^ not found in this scope + error[E0433]: cannot find module or crate `path` in this scope --> $DIR/const-param-decl-on-type-instead-of-impl.rs:12:5 | @@ -29,12 +35,15 @@ LL | path::path::Struct::() | ^^^^ use of unresolved module or unlinked crate `path` | = help: you might be missing a crate named `path` - -error[E0425]: cannot find type `T` in this scope - --> $DIR/const-param-decl-on-type-instead-of-impl.rs:8:15 +help: consider importing this struct + | +LL + use std::path::Path; + | +help: if you import `path`, refer to it directly + | +LL - path::path::Struct::() +LL + path::Struct::() | -LL | fn banana(a: >::BAR) {} - | ^ not found in this scope error[E0308]: mismatched types --> $DIR/const-param-decl-on-type-instead-of-impl.rs:5:17 diff --git a/tests/ui/parser/raw/raw-literal-keywords.stderr b/tests/ui/parser/raw/raw-literal-keywords.stderr index f7b6c894a90fe..60ec16176b066 100644 --- a/tests/ui/parser/raw/raw-literal-keywords.stderr +++ b/tests/ui/parser/raw/raw-literal-keywords.stderr @@ -27,12 +27,22 @@ error[E0425]: cannot find value `r#struct` in this scope | LL | let _ = r#struct; | ^^^^^^^^ not found in this scope + | +help: consider importing this tuple variant + | +LL + use std::mem::type_info::TypeKind::Struct; + | error[E0425]: cannot find value `union` in this scope --> $DIR/raw-literal-keywords.rs:22:13 | LL | let _ = r#union; | ^^^^^^^ not found in this scope + | +help: consider importing this tuple variant + | +LL + use std::mem::type_info::TypeKind::Union; + | error: aborting due to 6 previous errors diff --git a/tests/ui/pattern/struct-pattern-with-missing-fields-resolve-error.stderr b/tests/ui/pattern/struct-pattern-with-missing-fields-resolve-error.stderr index b8c6f1d867a19..d61db9f3d50fd 100644 --- a/tests/ui/pattern/struct-pattern-with-missing-fields-resolve-error.stderr +++ b/tests/ui/pattern/struct-pattern-with-missing-fields-resolve-error.stderr @@ -13,6 +13,11 @@ LL | if let Website { url, .. } = website { | ------------------- this pattern doesn't include `title`, which is available in `Website` LL | println!("[{}]({})", title, url); | ^^^^^ not found in this scope + | +help: consider importing this unit variant + | +LL + use std::char::CharCase::Title; + | error[E0425]: cannot find value `a` in this scope --> $DIR/struct-pattern-with-missing-fields-resolve-error.rs:28:20 diff --git a/tests/ui/resolve/levenshtein.stderr b/tests/ui/resolve/levenshtein.stderr index 48515b9e6bd51..67328b9339745 100644 --- a/tests/ui/resolve/levenshtein.stderr +++ b/tests/ui/resolve/levenshtein.stderr @@ -74,6 +74,15 @@ help: a struct with a similar name exists (notice the capitalization) LL - let b: m::first = m::second; // Misspelled item in module. LL + let b: m::First = m::second; // Misspelled item in module. | +help: consider importing this struct + | +LL + use m::First; + | +help: if you import `first`, refer to it directly + | +LL - let b: m::first = m::second; // Misspelled item in module. +LL + let b: first = m::second; // Misspelled item in module. + | error[E0425]: cannot find value `second` in module `m` --> $DIR/levenshtein.rs:28:26 @@ -89,6 +98,15 @@ help: a unit struct with a similar name exists (notice the capitalization) LL - let b: m::first = m::second; // Misspelled item in module. LL + let b: m::first = m::Second; // Misspelled item in module. | +help: consider importing this unit struct + | +LL + use m::Second; + | +help: if you import `second`, refer to it directly + | +LL - let b: m::first = m::second; // Misspelled item in module. +LL + let b: m::first = second; // Misspelled item in module. + | error[E0425]: cannot find function `foobar` in this scope --> $DIR/levenshtein.rs:26:5 diff --git a/tests/ui/resolve/resolve-assoc-suggestions.stderr b/tests/ui/resolve/resolve-assoc-suggestions.stderr index e6311962884f1..2d0aa09251f47 100644 --- a/tests/ui/resolve/resolve-assoc-suggestions.stderr +++ b/tests/ui/resolve/resolve-assoc-suggestions.stderr @@ -3,6 +3,13 @@ error[E0425]: cannot find type `field` in this scope | LL | let _: field; | ^^^^^ not found in this scope + | +help: consider importing one of these items + | +LL + use std::field::Field; + | +LL + use std::mem::type_info::Field; + | error[E0531]: cannot find tuple struct or tuple variant `field` in this scope --> $DIR/resolve-assoc-suggestions.rs:18:13 diff --git a/tests/ui/resolve/resolve-speculative-adjustment.stderr b/tests/ui/resolve/resolve-speculative-adjustment.stderr index fb15472bdae8d..98fdb5fa5ba47 100644 --- a/tests/ui/resolve/resolve-speculative-adjustment.stderr +++ b/tests/ui/resolve/resolve-speculative-adjustment.stderr @@ -3,6 +3,11 @@ error[E0425]: cannot find value `field` in this scope | LL | field; | ^^^^^ not found in this scope + | +help: consider importing this function + | +LL + use std::intrinsics::mir::Field; + | error[E0425]: cannot find value `field` in this scope --> $DIR/resolve-speculative-adjustment.rs:23:9 diff --git a/tests/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.stderr b/tests/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.stderr index e54e5acffe8f8..db61dd03f550d 100644 --- a/tests/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.stderr +++ b/tests/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.stderr @@ -12,6 +12,14 @@ help: an enum with a similar name exists LL - impl result { LL + impl Result { | +help: consider importing one of these type aliases instead + | +LL + use std::fmt::Result; + | +LL + use std::io::Result; + | +LL + use std::thread::Result; + | error[E0573]: expected type, found variant `Err` --> $DIR/do-not-attempt-to-add-suggestions-with-no-changes.rs:4:25 From 9d657539a63a925deed4b1ef7110156cf922dfef Mon Sep 17 00:00:00 2001 From: GTimothy <22472919+GTimothy@users.noreply.github.com> Date: Tue, 12 May 2026 18:21:33 +0200 Subject: [PATCH 10/16] v6 -fix: actually call it after all other suggestion adding functions -only suggest modules when next_segment is Some -fix return value when case insensitive suggestions are made -add missing booleans to err_code_special_case and suggest_ident_hidden_by_hygiene --- .../rustc_resolve/src/late/diagnostics.rs | 62 ++++++++++++------- 1 file changed, 40 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 81b5a90079e53..64511d165b91e 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -755,15 +755,20 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { err.span_label(base_error.span, base_error.fallback_label.clone()); } - if !(range_destruct - | swapping - | base_suggestion - | changing_ty_const - | funcall - | suggest_self - | assoc_type - | rtn - | shadowed) + let special_case = self.err_code_special_cases(&mut err, source, path, span); + + if let Some(errcode) = err.code + && errcode.index() == 425 + && !(range_destruct + | swapping + | base_suggestion + | changing_ty_const + | funcall + | suggest_self + | assoc_type + | rtn + | shadowed + | special_case) { // eprintln!("try import.") let (found, _suggested_candidates, candidates) = self.lookup_import_case_insensitive( @@ -780,8 +785,6 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } } - self.err_code_special_cases(&mut err, source, path, span); - let module = base_error.module.unwrap_or_else(|| CRATE_DEF_ID.to_def_id()); self.r.find_cfg_stripped(&mut err, &path.last().unwrap().ident.name, module); @@ -1318,6 +1321,11 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { let case_insensitive_filter = |ident: Ident, lookup_ident: Ident| { ident.as_str().to_lowercase() == lookup_ident.as_str().to_lowercase() }; + let filter_function = |res:Res| if following_seg.is_none() { + is_expected(res) + } else { + matches!(res, Res::Def(DefKind::Mod, _)) + }; let mut case_agnostic_candidates = self .r .lookup_import_candidates_impl( @@ -1325,7 +1333,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { ns, &self.parent_scope, case_insensitive_filter, - is_expected, + filter_function, ) .into_iter() .filter(|ImportSuggestion { did, .. }| { @@ -1386,11 +1394,11 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { eprintln!("res({ident}): {res:?}"); true }; + suggested_candidates.extend( + case_agnostic_candidates.iter().map(|sug| path_names_to_string(&sug.path)), + ); + return (true, suggested_candidates, case_agnostic_candidates); } - suggested_candidates.extend( - case_agnostic_candidates.iter().map(|sug| path_names_to_string(&sug.path)), - ); - return (true, suggested_candidates, case_agnostic_candidates); } } return (false, suggested_candidates, Vec::new()); @@ -1625,7 +1633,8 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { source: PathSource<'_, '_, '_>, path: &[Segment], span: Span, - ) { + ) -> bool { + let mut special_case = false; if let Some(err_code) = err.code { if err_code == E0425 { for label_rib in &self.label_ribs { @@ -1646,12 +1655,13 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { ); // Do not lint against unused label when we suggest them. self.diag_metadata.unused_labels.swap_remove(node_id); + special_case = true } } } } - self.suggest_ident_hidden_by_hygiene(err, path, span); + special_case |= self.suggest_ident_hidden_by_hygiene(err, path, span); // cannot find type in this scope if let Some(correct) = Self::likely_rust_type(path) { err.span_suggestion( @@ -1660,13 +1670,20 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { correct, Applicability::MaybeIncorrect, ); + special_case = true; } } } + special_case } - fn suggest_ident_hidden_by_hygiene(&self, err: &mut Diag<'_>, path: &[Segment], span: Span) { - let [segment] = path else { return }; + fn suggest_ident_hidden_by_hygiene( + &self, + err: &mut Diag<'_>, + path: &[Segment], + span: Span, + ) -> bool { + let [segment] = path else { return false }; let ident = segment.ident; let callsite_span = span.source_callsite(); @@ -1682,7 +1699,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { binding_ident.span, "an identifier with the same name exists, but is not accessible due to macro hygiene", ); - return; + return true; } // Case 2: the identifier is defined in a macro call in the same scope @@ -1695,10 +1712,11 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { binding_ident.span, "an identifier with the same name is defined here, but is not accessible due to macro hygiene", ); - return; + return true; } } } + false } /// Emit special messages for unresolved `Self` and `self`. From 883ade30d25ad3a074b640ab0e9942f41f700949 Mon Sep 17 00:00:00 2001 From: GTimothy <22472919+GTimothy@users.noreply.github.com> Date: Tue, 12 May 2026 18:34:47 +0200 Subject: [PATCH 11/16] v6 blessed --- tests/ui/delegation/bad-resolve.stderr | 30 +++++-------------- tests/ui/lint/recommend-literal.stderr | 21 +++++-------- ...-param-decl-on-type-instead-of-impl.stderr | 4 +-- tests/ui/resolve/112590-2.fixed | 2 +- tests/ui/resolve/112590-2.stderr | 30 +++++++++++-------- ...-to-add-suggestions-with-no-changes.stderr | 8 ----- 6 files changed, 34 insertions(+), 61 deletions(-) diff --git a/tests/ui/delegation/bad-resolve.stderr b/tests/ui/delegation/bad-resolve.stderr index 24d03b229b98d..d1b3974e77081 100644 --- a/tests/ui/delegation/bad-resolve.stderr +++ b/tests/ui/delegation/bad-resolve.stderr @@ -88,28 +88,6 @@ error[E0423]: expected function, found module `prefix::self` LL | reuse prefix::{self, super, crate}; | ^^^^^^ not a function -error[E0433]: `super` in paths can only be used in start position - --> $DIR/bad-resolve.rs:43:22 - | -LL | reuse prefix::{self, super, crate}; - | ^^^^^ can only be used in path start position - | -help: consider importing this enum - | -LL + use std::path::Prefix; - | - -error[E0433]: `crate` in paths can only be used in start position - --> $DIR/bad-resolve.rs:43:29 - | -LL | reuse prefix::{self, super, crate}; - | ^^^^^ can only be used in path start position - | -help: consider importing this enum - | -LL + use std::path::Prefix; - | - error[E0046]: not all trait items implemented, missing: `Type` --> $DIR/bad-resolve.rs:21:1 | @@ -127,7 +105,13 @@ LL | reuse unresolved_prefix::{a, b, c}; | = help: you might be missing a crate named `unresolved_prefix` -error: aborting due to 14 previous errors +error[E0433]: `crate` in paths can only be used in start position + --> $DIR/bad-resolve.rs:43:29 + | +LL | reuse prefix::{self, super, crate}; + | ^^^^^ can only be used in path start position + +error: aborting due to 13 previous errors Some errors have detailed explanations: E0046, E0324, E0407, E0423, E0425, E0433, E0575, E0576. For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/lint/recommend-literal.stderr b/tests/ui/lint/recommend-literal.stderr index 4504442110848..01e993df17a98 100644 --- a/tests/ui/lint/recommend-literal.stderr +++ b/tests/ui/lint/recommend-literal.stderr @@ -68,17 +68,10 @@ error[E0425]: cannot find type `float` in this scope --> $DIR/recommend-literal.rs:33:12 | LL | width: float, - | ^^^^^ not found in this scope - | -help: perhaps you intended to use this type - | -LL - width: float, -LL + width: f32, - | -help: consider importing this struct - | -LL + use std::mem::type_info::Float; - | + | ^^^^^ + | | + | not found in this scope + | help: perhaps you intended to use this type: `f32` error[E0425]: cannot find type `int` in this scope --> $DIR/recommend-literal.rs:36:19 @@ -91,10 +84,10 @@ help: perhaps you intended to use this type LL - depth: Option, LL + depth: Option, | -help: consider importing this struct - | -LL + use std::mem::type_info::Int; +help: you might be missing a type parameter | +LL | struct Data { + | +++++ error[E0425]: cannot find type `short` in this scope --> $DIR/recommend-literal.rs:42:16 diff --git a/tests/ui/parser/const-param-decl-on-type-instead-of-impl.stderr b/tests/ui/parser/const-param-decl-on-type-instead-of-impl.stderr index 26e13b39fcc87..14527ec2ce007 100644 --- a/tests/ui/parser/const-param-decl-on-type-instead-of-impl.stderr +++ b/tests/ui/parser/const-param-decl-on-type-instead-of-impl.stderr @@ -35,9 +35,9 @@ LL | path::path::Struct::() | ^^^^ use of unresolved module or unlinked crate `path` | = help: you might be missing a crate named `path` -help: consider importing this struct +help: consider importing this module | -LL + use std::path::Path; +LL + use std::path; | help: if you import `path`, refer to it directly | diff --git a/tests/ui/resolve/112590-2.fixed b/tests/ui/resolve/112590-2.fixed index 2bda2197d6d47..3e9f5584767ee 100644 --- a/tests/ui/resolve/112590-2.fixed +++ b/tests/ui/resolve/112590-2.fixed @@ -29,7 +29,7 @@ fn _b() { } fn main() { - let _t: Vec = Vec::new(); //~ ERROR cannot find + let _t: Vec = vec::new(); //~ ERROR cannot find type _B = vec::Vec::; //~ ERROR cannot find let _t = AtomicBool::new(true); //~ ERROR cannot find } diff --git a/tests/ui/resolve/112590-2.stderr b/tests/ui/resolve/112590-2.stderr index 75e7961cb35f4..b96dea594f848 100644 --- a/tests/ui/resolve/112590-2.stderr +++ b/tests/ui/resolve/112590-2.stderr @@ -31,6 +31,23 @@ LL - let _: Vec = fox::bar::baz::MyVec::new(); LL + let _: Vec = MyVec::new(); | +error[E0433]: cannot find module or crate `vec` in this scope + --> $DIR/112590-2.rs:24:24 + | +LL | let _t: Vec = vec::new(); + | ^^^ use of unresolved module or unlinked crate `vec` + | + = help: you might be missing a crate named `vec` +help: a struct with a similar name exists (notice the capitalization) + | +LL - let _t: Vec = vec::new(); +LL + let _t: Vec = Vec::new(); + | +help: consider importing this module + | +LL + use std::vec; + | + error[E0433]: cannot find module or crate `vec` in this scope --> $DIR/112590-2.rs:25:15 | @@ -59,19 +76,6 @@ LL - let _t = std::sync_error::atomic::AtomicBool::new(true); LL + let _t = AtomicBool::new(true); | -error[E0433]: cannot find module or crate `vec` in this scope - --> $DIR/112590-2.rs:24:24 - | -LL | let _t: Vec = vec::new(); - | ^^^ use of unresolved module or unlinked crate `vec` - | - = help: you might be missing a crate named `vec` -help: a struct with a similar name exists (notice the capitalization) - | -LL - let _t: Vec = vec::new(); -LL + let _t: Vec = Vec::new(); - | - error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.stderr b/tests/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.stderr index db61dd03f550d..e54e5acffe8f8 100644 --- a/tests/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.stderr +++ b/tests/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.stderr @@ -12,14 +12,6 @@ help: an enum with a similar name exists LL - impl result { LL + impl Result { | -help: consider importing one of these type aliases instead - | -LL + use std::fmt::Result; - | -LL + use std::io::Result; - | -LL + use std::thread::Result; - | error[E0573]: expected type, found variant `Err` --> $DIR/do-not-attempt-to-add-suggestions-with-no-changes.rs:4:25 From befa669e3a4e4474f435bb0c6ccea6cf88916e49 Mon Sep 17 00:00:00 2001 From: GTimothy <22472919+GTimothy@users.noreply.github.com> Date: Wed, 13 May 2026 20:27:24 +0200 Subject: [PATCH 12/16] v7 fix trait_and_bounds return values by separating into two booleans add missing boolean outputs to detect_missing_bindings other small changes some code cleanup --- .../rustc_resolve/src/late/diagnostics.rs | 184 +++++++----------- 1 file changed, 68 insertions(+), 116 deletions(-) diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 64511d165b91e..0bc6fcdc27fa8 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -652,9 +652,9 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { err.span_label(within_macro_span, "due to this macro variable"); } - let _missing_binding_available = + let missing_binding_available = self.detect_missing_binding_available_from_pattern(&mut err, path, following_seg); - let _op_in_slice = self.suggest_at_operator_in_slice_pat_with_range(&mut err, path); + let op_in_slice = self.suggest_at_operator_in_slice_pat_with_range(&mut err, path); let range_destruct = self.suggest_range_struct_destructuring(&mut err, path, source); let swapping = self.suggest_swapping_misplaced_self_ty_and_trait( &mut err, @@ -739,8 +739,9 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } // let _ = debug && {eprintln!("{:?}", suggested_candidates.clone()); true}; - let mut fallback = self.suggest_trait_and_bounds(&mut err, source, res, span, &base_error); - fallback |= self.suggest_typo( + let traits_and_bounds = + self.suggest_trait_and_bounds(&mut err, source, res, span, &base_error); + let (typo, typo_fallback) = self.suggest_typo( &mut err, source, path, @@ -749,17 +750,40 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { &base_error, suggested_candidates.clone(), ); - - if fallback { + // eprintln!("{:?}", err); + // eprintln!("{:?}", (typo_fallback, traits_and_bounds)); + if traits_and_bounds | typo_fallback { // Fallback label. + // eprintln!("fallbackw"); + // eprintln!("{:?}", base_error.fallback_label.clone()); err.span_label(base_error.span, base_error.fallback_label.clone()); } let special_case = self.err_code_special_cases(&mut err, source, path, span); + // eprintln!( + // "{:?}", + // ( + // missing_binding_available, + // op_in_slice, + // range_destruct, + // swapping, + // base_suggestion, + // changing_ty_const, + // funcall, + // suggest_self, + // assoc_type + // ) + // ); + // eprintln!( + // "{:?}", + // (err.clone(), rtn, shadowed, special_case, found, traits_and_bounds, typo) + // ); if let Some(errcode) = err.code && errcode.index() == 425 - && !(range_destruct + && !(missing_binding_available + | op_in_slice + | range_destruct | swapping | base_suggestion | changing_ty_const @@ -768,10 +792,13 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { | assoc_type | rtn | shadowed - | special_case) + | special_case + | found + | traits_and_bounds + | typo) + && candidates.is_empty() { - // eprintln!("try import.") - let (found, _suggested_candidates, candidates) = self.lookup_import_case_insensitive( + (_, _, candidates) = self.lookup_import_case_insensitive( &mut err, source, path, @@ -780,9 +807,9 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { res, &base_error, ); - if found { - return (err, candidates); - } + // if found { + // return (err, candidates); + // } } let module = base_error.module.unwrap_or_else(|| CRATE_DEF_ID.to_def_id()); @@ -1199,92 +1226,6 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { if candidates.is_empty() { candidates = self.smart_resolve_partial_mod_path_errors(path, following_seg); } - //what if there is no candidate there but it was a mod path error ? i do not want to resolve it as a type when it is a path.... - - // let _ = debug && {eprintln!("2:{:?}", candidates.clone()); true }; - // if let Some(Res::NonMacroAttr(_)) = res { - // } else { - // // we do not suggest alternative capitalizations if only one letter, too many constants can match and it become noisy. - // if candidates.is_empty() && err.children.is_empty() && ident.as_str().len() > 1 { - // // let _ = debug && {eprintln!("{:?}", (suggested_candidates.clone(), candidates.clone())); true}; - // let case_insensitive_filter = |ident: Ident, lookup_ident: Ident| { - // ident.as_str().to_lowercase() == lookup_ident.as_str().to_lowercase() - // }; - // let mut case_agnostic_candidates = self - // .r - // .lookup_import_candidates_impl( - // ident, - // ns, - // &self.parent_scope, - // case_insensitive_filter, - // is_expected, - // ) - // .into_iter() - // .filter(|ImportSuggestion { did, .. }| { - // let _ = debug && { - // eprintln!("final:{did:?}"); - // true - // }; - // let _ = debug && { - // eprintln!("{:?} vs {:?}", did, res.and_then(|res| res.opt_def_id())); - // true - // }; - // - // // Filter out items that are in the prelude - // if let Some(prelude) = self.r.prelude { - // if let Some(suggestion_did) = did { - // let mut is_in_prelude = false; - // prelude.for_each_child(self.r, |_, _, _, _, decl| { - // if decl.res().opt_def_id() == Some(*suggestion_did) { - // is_in_prelude = true; - // } - // }); - // if is_in_prelude { - // return false; - // } - // } - // } - // match (did, res.and_then(|res| res.opt_def_id())) { - // (Some(suggestion_did), Some(actual_did)) => { - // *suggestion_did != actual_did - // } - // _ => true, - // } - // }) - // .collect::>(); - // // Try to filter out intrinsics candidates, as long as we have - // // some other candidates to suggest. - // let intrinsic_candidates: Vec<_> = case_agnostic_candidates - // .extract_if(.., |sugg| { - // let path = path_names_to_string(&sugg.path); - // path.starts_with("core::intrinsics::") - // || path.starts_with("std::intrinsics::") - // }) - // .collect(); - // if case_agnostic_candidates.is_empty() { - // // Put them back if we have no more candidates to suggest... - // case_agnostic_candidates = intrinsic_candidates; - // } - // if !case_agnostic_candidates.is_empty() { - // let _ = debug && { - // eprintln!("err B: {err:?}"); - // true - // }; - // let _ = debug && { - // eprintln!("sou({ident}: {source:?}"); - // true - // }; - // let _ = debug && { - // eprintln!("res({ident}): {res:?}"); - // true - // }; - // } - // suggested_candidates.extend( - // case_agnostic_candidates.iter().map(|sug| path_names_to_string(&sug.path)), - // ); - // candidates.extend(case_agnostic_candidates); - // } - // } (false, suggested_candidates, candidates) } @@ -1321,10 +1262,12 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { let case_insensitive_filter = |ident: Ident, lookup_ident: Ident| { ident.as_str().to_lowercase() == lookup_ident.as_str().to_lowercase() }; - let filter_function = |res:Res| if following_seg.is_none() { - is_expected(res) - } else { - matches!(res, Res::Def(DefKind::Mod, _)) + let filter_function = |res: Res| { + if following_seg.is_none() { + is_expected(res) + } else { + matches!(res, Res::Def(DefKind::Mod, _)) + } }; let mut case_agnostic_candidates = self .r @@ -1397,7 +1340,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { suggested_candidates.extend( case_agnostic_candidates.iter().map(|sug| path_names_to_string(&sug.path)), ); - return (true, suggested_candidates, case_agnostic_candidates); + return (false, suggested_candidates, case_agnostic_candidates); } } } @@ -1475,7 +1418,8 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { ) -> bool { let is_macro = base_error.span.from_expansion() && base_error.span.desugaring_kind().is_none(); - let mut fallback = false; + + let mut trait_and_bounds = false; if let ( PathSource::Trait(AliasPossibility::Maybe), @@ -1485,7 +1429,6 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { && let Some(bounds @ [first_bound, .., last_bound]) = self.diag_metadata.current_trait_object { - fallback = true; let spans: Vec = bounds .iter() .map(|bound| bound.span()) @@ -1534,12 +1477,15 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { Applicability::MaybeIncorrect, ); } + + trait_and_bounds = true; } - fallback |= self.restrict_assoc_type_in_where_clause(span, err); - fallback + trait_and_bounds |= self.restrict_assoc_type_in_where_clause(span, err); + trait_and_bounds } + // return a (suggested, display_fallback) boolean pair to indicate if suggestions were made and if fallback_label of err should be used or not. fn suggest_typo( &mut self, err: &mut Diag<'_>, @@ -1549,20 +1495,20 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { span: Span, base_error: &BaseError, suggested_candidates: FxHashSet, - ) -> bool { + ) -> (bool, bool) { let is_expected = &|res| source.is_expected(res); let ident_span = path.last().map_or(span, |ident| ident.ident.span); - // Prefer suggestions based on associated types from in-scope bounds (e.g. `T::Item`) // over purely edit-distance-based identifier suggestions. // Otherwise suggestions could be verbose. if self.suggest_assoc_type_from_bounds(err, source, path, ident_span) { - return false; + return (true, false); // disabling the use of display_fallback is existing behaviour } + let mut suggested = false; + let mut fallback = false; let typo_sugg = self.lookup_typo_candidate(path, following_seg, source.namespace(), is_expected); - let mut fallback = false; let typo_sugg = typo_sugg .to_opt_suggestion() .filter(|sugg| !suggested_candidates.contains(sugg.candidate.as_str())); @@ -1578,20 +1524,22 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { " = ", Applicability::MaybeIncorrect, ); + + suggested = true; } _ => {} } // If the trait has a single item (which wasn't matched by the algorithm), suggest it let suggestion = self.get_single_associated_item(path, &source, is_expected); - self.r.add_typo_suggestion(err, suggestion, ident_span); + suggested |= self.r.add_typo_suggestion(err, suggestion, ident_span); } if self.let_binding_suggestion(err, ident_span) { + suggested = true; fallback = false; } - - fallback + (suggested, fallback) } fn suggest_shadowed( @@ -1842,6 +1790,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { path: &[Segment], following_seg: Option<&Segment>, ) -> bool { + let mut missing_bindings = false; let [segment] = path else { return false }; let None = following_seg else { return false }; for rib in self.ribs[ValueNS].iter().rev() { @@ -1855,6 +1804,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { { for field in fields { if field.name == segment.ident.name { + missing_bindings = true; if spans.iter().all(|(_, had_error)| had_error.is_err()) { // This resolution error will likely be fixed by fixing a // syntax error in a pattern, so it is irrelevant to the user. @@ -1866,6 +1816,8 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { the expected fields", ); err.downgrade_to_delayed_bug(); + + missing_bindings = false; } let ty = self.r.tcx.item_name(*def_id); for (span, _) in spans { @@ -1882,7 +1834,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } } } - true + missing_bindings } fn suggest_at_operator_in_slice_pat_with_range( From f853b997f730cbca6c8e3536f7637bf7065c4ed5 Mon Sep 17 00:00:00 2001 From: GTimothy <22472919+GTimothy@users.noreply.github.com> Date: Wed, 13 May 2026 20:27:59 +0200 Subject: [PATCH 13/16] v7 blessed --- ...ern-with-missing-fields-resolve-error.stderr | 5 ----- .../resolve/export-fully-qualified-2018.stderr | 4 ++++ tests/ui/resolve/export-fully-qualified.stderr | 4 ++++ .../ui/suggestions/crate-or-module-typo.stderr | 17 +++++++++++------ 4 files changed, 19 insertions(+), 11 deletions(-) diff --git a/tests/ui/pattern/struct-pattern-with-missing-fields-resolve-error.stderr b/tests/ui/pattern/struct-pattern-with-missing-fields-resolve-error.stderr index d61db9f3d50fd..b8c6f1d867a19 100644 --- a/tests/ui/pattern/struct-pattern-with-missing-fields-resolve-error.stderr +++ b/tests/ui/pattern/struct-pattern-with-missing-fields-resolve-error.stderr @@ -13,11 +13,6 @@ LL | if let Website { url, .. } = website { | ------------------- this pattern doesn't include `title`, which is available in `Website` LL | println!("[{}]({})", title, url); | ^^^^^ not found in this scope - | -help: consider importing this unit variant - | -LL + use std::char::CharCase::Title; - | error[E0425]: cannot find value `a` in this scope --> $DIR/struct-pattern-with-missing-fields-resolve-error.rs:28:20 diff --git a/tests/ui/resolve/export-fully-qualified-2018.stderr b/tests/ui/resolve/export-fully-qualified-2018.stderr index 25c9e6fbdab96..1246d51a7fca1 100644 --- a/tests/ui/resolve/export-fully-qualified-2018.stderr +++ b/tests/ui/resolve/export-fully-qualified-2018.stderr @@ -5,6 +5,10 @@ LL | pub fn bar() { foo::baz(); } | ^^^ use of unresolved module or unlinked crate `foo` | = help: you might be missing a crate named `foo` +help: consider importing this module + | +LL + use crate::foo; + | error: aborting due to 1 previous error diff --git a/tests/ui/resolve/export-fully-qualified.stderr b/tests/ui/resolve/export-fully-qualified.stderr index f8433dcfb8924..c9514d34b8d0f 100644 --- a/tests/ui/resolve/export-fully-qualified.stderr +++ b/tests/ui/resolve/export-fully-qualified.stderr @@ -5,6 +5,10 @@ LL | pub fn bar() { foo::baz(); } | ^^^ use of unresolved module or unlinked crate `foo` | = help: you might be missing a crate named `foo` +help: consider importing this module + | +LL + use foo; + | error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/crate-or-module-typo.stderr b/tests/ui/suggestions/crate-or-module-typo.stderr index 49ac1c89ab52a..59d6c64b1b934 100644 --- a/tests/ui/suggestions/crate-or-module-typo.stderr +++ b/tests/ui/suggestions/crate-or-module-typo.stderr @@ -21,6 +21,17 @@ LL - use bas::bar; LL + use bar::bar; | +error[E0433]: cannot find module or crate `bar` in this scope + --> $DIR/crate-or-module-typo.rs:6:20 + | +LL | pub fn bar() { bar::baz(); } + | ^^^ function `bar` is not a crate or module + | +help: consider importing this module + | +LL + use crate::bar; + | + error[E0433]: cannot find module or crate `st` in this scope --> $DIR/crate-or-module-typo.rs:14:10 | @@ -41,12 +52,6 @@ LL - bar: st::cell::Cell LL + bar: cell::Cell | -error[E0433]: cannot find module or crate `bar` in this scope - --> $DIR/crate-or-module-typo.rs:6:20 - | -LL | pub fn bar() { bar::baz(); } - | ^^^ function `bar` is not a crate or module - error: aborting due to 4 previous errors Some errors have detailed explanations: E0432, E0433. From 810cc78a494f93aec9d589d0a75c394b8a5240c4 Mon Sep 17 00:00:00 2001 From: GTimothy <22472919+GTimothy@users.noreply.github.com> Date: Fri, 15 May 2026 20:15:47 +0200 Subject: [PATCH 14/16] v8 -in typo import suggestion, filter suggestions with the wrong number of parameters -add a missing true case in suggest_typo -code cleanup --- compiler/rustc_resolve/src/diagnostics.rs | 25 ------------------- compiler/rustc_resolve/src/late.rs | 12 +++++++++ .../rustc_resolve/src/late/diagnostics.rs | 18 +++++++++---- compiler/rustc_resolve/src/lib.rs | 13 ++++++++++ 4 files changed, 38 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 6fdcc019b7e63..12e8e2daa66b5 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -869,37 +869,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } if import_suggestions.is_empty() && !suggested_typo { - // let typo_import_suggestions = self.lookup_import_candidates( - // name, - // Namespace::ValueNS, - // &parent_scope, - // // |ident, lookup_ident| { - // // ident.name.as_str().to_lowercase() - // // == lookup_ident.name.as_str().to_lowercase() - // // }, - // &|res: Res| { - // matches!( - // res, - // Res::Def( - // DefKind::Ctor(CtorOf::Variant, CtorKind::Const) - // | DefKind::Ctor(CtorOf::Struct, CtorKind::Const) - // | DefKind::Const { .. } - // | DefKind::AssocConst { .. }, - // _, - // ) - // ) - // }, - // ); - // if !typo_import_suggestions.is_empty() { - // import_suggestions = typo_import_suggestions; - // } else { let help_msg = format!( "if you meant to match on a unit struct, unit variant or a `const` \ item, consider making the path in the pattern qualified: \ `path::to::ModOrType::{name}`", ); err.span_help(span, help_msg); - // } } show_candidates( diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 014a472c2c1bb..98ca09ec1cdc2 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -5596,6 +5596,18 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> { .filter(|param| matches!(param.kind, ast::GenericParamKind::Lifetime { .. })) .count(); self.r.item_generics_num_lifetimes.insert(def_id, count); + let type_or_const_count = generics + .params + .iter() + .filter(|param| { + matches!( + param.kind, + ast::GenericParamKind::Type { .. } + | ast::GenericParamKind::Const { .. } + ) + }) + .count(); + self.r.item_generics_num_type_or_const_params.insert(def_id, type_or_const_count); } ItemKind::ForeignMod(ForeignMod { items, .. }) => { diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 0bc6fcdc27fa8..aeafcc2a356a4 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -750,12 +750,8 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { &base_error, suggested_candidates.clone(), ); - // eprintln!("{:?}", err); - // eprintln!("{:?}", (typo_fallback, traits_and_bounds)); if traits_and_bounds | typo_fallback { // Fallback label. - // eprintln!("fallbackw"); - // eprintln!("{:?}", base_error.fallback_label.clone()); err.span_label(base_error.span, base_error.fallback_label.clone()); } @@ -1511,7 +1507,17 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { self.lookup_typo_candidate(path, following_seg, source.namespace(), is_expected); let typo_sugg = typo_sugg .to_opt_suggestion() - .filter(|sugg| !suggested_candidates.contains(sugg.candidate.as_str())); + .filter(|sugg| !suggested_candidates.contains(sugg.candidate.as_str())) + // this filters out suggestions that require parameters when no parameter is present + .filter(|sugg| { + if !path.last().is_some_and(|s| s.has_generic_args) { + return true; + } + let Some(def_id) = sugg.res.opt_def_id() else { + return true; + }; + self.r.item_generics_num_type_or_const_params(def_id) > 0 + }); if !self.r.add_typo_suggestion(err, typo_sugg, ident_span) { fallback = true; match self.diag_metadata.current_let_binding { @@ -1533,6 +1539,8 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { // If the trait has a single item (which wasn't matched by the algorithm), suggest it let suggestion = self.get_single_associated_item(path, &source, is_expected); suggested |= self.r.add_typo_suggestion(err, suggestion, ident_span); + } else { + suggested = true; } if self.let_binding_suggestion(err, ident_span) { diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index b15e4b1b72774..625388afe95da 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1456,6 +1456,8 @@ pub struct Resolver<'ra, 'tcx> { /// Amount of lifetime parameters for each item in the crate. item_generics_num_lifetimes: FxHashMap = default::fx_hash_map(), + /// Amount of type or const parameters for each item in the crate. + item_generics_num_type_or_const_params: FxHashMap = default::fx_hash_map(), /// Generic args to suggest for required params (e.g. `<'_>`, `<_, _>`), if any. item_required_generic_args_suggestions: FxHashMap = default::fx_hash_map(), delegation_fn_sigs: LocalDefIdMap = Default::default(), @@ -1676,6 +1678,17 @@ impl<'tcx> Resolver<'_, 'tcx> { self.tcx.generics_of(def_id).own_counts().lifetimes } } + // Get count of expected parameters + fn item_generics_num_type_or_const_params(&self, def_id: DefId) -> usize { + if let Some(def_id) = def_id.as_local() { + self.item_generics_num_type_or_const_params.get(&def_id).copied().unwrap_or(0) + } else { + // External crate metadata is already loaded — no cycle risk here. + let generics = self.tcx.generics_of(def_id); + let counts = generics.own_counts(); + counts.types.saturating_sub(generics.has_self as usize) + counts.consts + } +} fn item_required_generic_args_suggestion(&self, def_id: DefId) -> String { if let Some(def_id) = def_id.as_local() { From b7023086a0a5f658d355c386fb744e090a2c6af3 Mon Sep 17 00:00:00 2001 From: GTimothy <22472919+GTimothy@users.noreply.github.com> Date: Fri, 15 May 2026 20:52:02 +0200 Subject: [PATCH 15/16] v8 blessed --- .../mgca/unused_speculative_def_id.stderr | 11 +------ tests/ui/libstd-case-typo/libstd.stderr | 24 +-------------- tests/ui/resolve/112590-2.fixed | 2 +- tests/ui/resolve/112590-2.stderr | 30 ++++++++----------- tests/ui/resolve/levenshtein.stderr | 18 ----------- 5 files changed, 16 insertions(+), 69 deletions(-) diff --git a/tests/ui/const-generics/mgca/unused_speculative_def_id.stderr b/tests/ui/const-generics/mgca/unused_speculative_def_id.stderr index e087e046ec35d..14f80b6b1d71a 100644 --- a/tests/ui/const-generics/mgca/unused_speculative_def_id.stderr +++ b/tests/ui/const-generics/mgca/unused_speculative_def_id.stderr @@ -2,16 +2,7 @@ error[E0425]: cannot find value `ERR` in this scope --> $DIR/unused_speculative_def_id.rs:20:16 | LL | field: A<{ ERR:: }>, - | ^^^ - | - --> $SRC_DIR/core/src/result.rs:LL:COL - | - = note: similarly named tuple variant `Err` defined here -help: a tuple variant with a similar name exists - | -LL - field: A<{ ERR:: }>, -LL + field: A<{ Err:: }>, - | + | ^^^ not found in this scope error: aborting due to 1 previous error diff --git a/tests/ui/libstd-case-typo/libstd.stderr b/tests/ui/libstd-case-typo/libstd.stderr index da1efdac7b2c5..a8b963861575d 100644 --- a/tests/ui/libstd-case-typo/libstd.stderr +++ b/tests/ui/libstd-case-typo/libstd.stderr @@ -679,15 +679,7 @@ error[E0425]: cannot find type `cloned` in this scope --> $DIR/libstd.rs:163:20 | LL | fn test_cloned(_x: cloned<(), ()>){} - | ^^^^^^ - | - --> $SRC_DIR/core/src/clone.rs:LL:COL - | - = note: similarly named trait `Clone` defined here -help: a trait with a similar name exists - | -LL - fn test_cloned(_x: cloned<(), ()>){} -LL + fn test_cloned(_x: Clone<(), ()>){} + | ^^^^^^ not found in this scope | help: consider importing this struct | @@ -774,12 +766,6 @@ help: a trait with a similar name exists LL - fn test_fromfn(_x: Fromfn<()>){} LL + fn test_fromfn(_x: From<()>){} | -help: consider importing one of these structs - | -LL + use std::fmt::FromFn; - | -LL + use std::iter::FromFn; - | error[E0425]: cannot find type `fuse` in this scope --> $DIR/libstd.rs:179:18 @@ -1543,10 +1529,6 @@ help: a builtin type with a similar name exists LL - fn test_chars(_x: chars){} LL + fn test_chars(_x: char){} | -help: consider importing this struct - | -LL + use std::str::Chars; - | error[E0425]: cannot find type `EncodeUTF16` in this scope --> $DIR/libstd.rs:352:25 @@ -1932,10 +1914,6 @@ help: a struct with a similar name exists LL - fn test_systemtime(_x: Systemtime){} LL + fn test_systemtime(_x: SystemTome){} | -help: consider importing this struct - | -LL + use std::time::SystemTime; - | error[E0425]: cannot find type `SystemTime` in this scope --> $DIR/libstd.rs:431:25 diff --git a/tests/ui/resolve/112590-2.fixed b/tests/ui/resolve/112590-2.fixed index 3e9f5584767ee..2bda2197d6d47 100644 --- a/tests/ui/resolve/112590-2.fixed +++ b/tests/ui/resolve/112590-2.fixed @@ -29,7 +29,7 @@ fn _b() { } fn main() { - let _t: Vec = vec::new(); //~ ERROR cannot find + let _t: Vec = Vec::new(); //~ ERROR cannot find type _B = vec::Vec::; //~ ERROR cannot find let _t = AtomicBool::new(true); //~ ERROR cannot find } diff --git a/tests/ui/resolve/112590-2.stderr b/tests/ui/resolve/112590-2.stderr index b96dea594f848..75e7961cb35f4 100644 --- a/tests/ui/resolve/112590-2.stderr +++ b/tests/ui/resolve/112590-2.stderr @@ -31,23 +31,6 @@ LL - let _: Vec = fox::bar::baz::MyVec::new(); LL + let _: Vec = MyVec::new(); | -error[E0433]: cannot find module or crate `vec` in this scope - --> $DIR/112590-2.rs:24:24 - | -LL | let _t: Vec = vec::new(); - | ^^^ use of unresolved module or unlinked crate `vec` - | - = help: you might be missing a crate named `vec` -help: a struct with a similar name exists (notice the capitalization) - | -LL - let _t: Vec = vec::new(); -LL + let _t: Vec = Vec::new(); - | -help: consider importing this module - | -LL + use std::vec; - | - error[E0433]: cannot find module or crate `vec` in this scope --> $DIR/112590-2.rs:25:15 | @@ -76,6 +59,19 @@ LL - let _t = std::sync_error::atomic::AtomicBool::new(true); LL + let _t = AtomicBool::new(true); | +error[E0433]: cannot find module or crate `vec` in this scope + --> $DIR/112590-2.rs:24:24 + | +LL | let _t: Vec = vec::new(); + | ^^^ use of unresolved module or unlinked crate `vec` + | + = help: you might be missing a crate named `vec` +help: a struct with a similar name exists (notice the capitalization) + | +LL - let _t: Vec = vec::new(); +LL + let _t: Vec = Vec::new(); + | + error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/resolve/levenshtein.stderr b/tests/ui/resolve/levenshtein.stderr index 67328b9339745..48515b9e6bd51 100644 --- a/tests/ui/resolve/levenshtein.stderr +++ b/tests/ui/resolve/levenshtein.stderr @@ -74,15 +74,6 @@ help: a struct with a similar name exists (notice the capitalization) LL - let b: m::first = m::second; // Misspelled item in module. LL + let b: m::First = m::second; // Misspelled item in module. | -help: consider importing this struct - | -LL + use m::First; - | -help: if you import `first`, refer to it directly - | -LL - let b: m::first = m::second; // Misspelled item in module. -LL + let b: first = m::second; // Misspelled item in module. - | error[E0425]: cannot find value `second` in module `m` --> $DIR/levenshtein.rs:28:26 @@ -98,15 +89,6 @@ help: a unit struct with a similar name exists (notice the capitalization) LL - let b: m::first = m::second; // Misspelled item in module. LL + let b: m::first = m::Second; // Misspelled item in module. | -help: consider importing this unit struct - | -LL + use m::Second; - | -help: if you import `second`, refer to it directly - | -LL - let b: m::first = m::second; // Misspelled item in module. -LL + let b: m::first = second; // Misspelled item in module. - | error[E0425]: cannot find function `foobar` in this scope --> $DIR/levenshtein.rs:26:5 From 78af48766653a6e824eb6581938050e377b45c6d Mon Sep 17 00:00:00 2001 From: GTimothy <22472919+GTimothy@users.noreply.github.com> Date: Fri, 15 May 2026 20:59:39 +0200 Subject: [PATCH 16/16] fmt --- compiler/rustc_resolve/src/lib.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 625388afe95da..c1bcd884e6eba 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1680,15 +1680,15 @@ impl<'tcx> Resolver<'_, 'tcx> { } // Get count of expected parameters fn item_generics_num_type_or_const_params(&self, def_id: DefId) -> usize { - if let Some(def_id) = def_id.as_local() { - self.item_generics_num_type_or_const_params.get(&def_id).copied().unwrap_or(0) - } else { - // External crate metadata is already loaded — no cycle risk here. - let generics = self.tcx.generics_of(def_id); - let counts = generics.own_counts(); - counts.types.saturating_sub(generics.has_self as usize) + counts.consts + if let Some(def_id) = def_id.as_local() { + self.item_generics_num_type_or_const_params.get(&def_id).copied().unwrap_or(0) + } else { + // External crate metadata is already loaded — no cycle risk here. + let generics = self.tcx.generics_of(def_id); + let counts = generics.own_counts(); + counts.types.saturating_sub(generics.has_self as usize) + counts.consts + } } -} fn item_required_generic_args_suggestion(&self, def_id: DefId) -> String { if let Some(def_id) = def_id.as_local() {