11use std:: fmt;
2+ use std:: fmt:: Write as _;
23use std:: task:: Poll ;
34
45use crate :: core:: { Dependency , PackageId , Registry , Summary } ;
56use crate :: sources:: source:: QueryKind ;
7+ use crate :: sources:: IndexSummary ;
68use crate :: util:: edit_distance:: edit_distance;
79use crate :: util:: { GlobalContext , OptVersionReq , VersionExt } ;
810use anyhow:: Error ;
@@ -301,10 +303,23 @@ pub(super) fn activation_error(
301303
302304 msg
303305 } else {
306+ // Maybe something is wrong with the available versions
307+ let mut version_candidates = loop {
308+ match registry. query_vec ( & new_dep, QueryKind :: AlternativeVersions ) {
309+ Poll :: Ready ( Ok ( candidates) ) => break candidates,
310+ Poll :: Ready ( Err ( e) ) => return to_resolve_err ( e) ,
311+ Poll :: Pending => match registry. block_until_ready ( ) {
312+ Ok ( ( ) ) => continue ,
313+ Err ( e) => return to_resolve_err ( e) ,
314+ } ,
315+ }
316+ } ;
317+ version_candidates. sort_unstable_by_key ( |a| a. as_summary ( ) . version ( ) . clone ( ) ) ;
318+
304319 // Maybe the user mistyped the name? Like `dep-thing` when `Dep_Thing`
305320 // was meant. So we try asking the registry for a `fuzzy` search for suggestions.
306- let candidates = loop {
307- match registry. query_vec ( & new_dep, QueryKind :: Alternatives ) {
321+ let name_candidates = loop {
322+ match registry. query_vec ( & new_dep, QueryKind :: AlternativeNames ) {
308323 Poll :: Ready ( Ok ( candidates) ) => break candidates,
309324 Poll :: Ready ( Err ( e) ) => return to_resolve_err ( e) ,
310325 Poll :: Pending => match registry. block_until_ready ( ) {
@@ -313,58 +328,102 @@ pub(super) fn activation_error(
313328 } ,
314329 }
315330 } ;
316-
317- let mut candidates: Vec < _ > = candidates. into_iter ( ) . map ( |s| s. into_summary ( ) ) . collect ( ) ;
318-
319- candidates. sort_unstable_by_key ( |a| a. name ( ) ) ;
320- candidates. dedup_by ( |a, b| a. name ( ) == b. name ( ) ) ;
321- let mut candidates: Vec < _ > = candidates
331+ let mut name_candidates: Vec < _ > = name_candidates
332+ . into_iter ( )
333+ . map ( |s| s. into_summary ( ) )
334+ . collect ( ) ;
335+ name_candidates. sort_unstable_by_key ( |a| a. name ( ) ) ;
336+ name_candidates. dedup_by ( |a, b| a. name ( ) == b. name ( ) ) ;
337+ let mut name_candidates: Vec < _ > = name_candidates
322338 . iter ( )
323339 . filter_map ( |n| Some ( ( edit_distance ( & * new_dep. package_name ( ) , & * n. name ( ) , 3 ) ?, n) ) )
324340 . collect ( ) ;
325- candidates . sort_by_key ( |o| o. 0 ) ;
326- let mut msg : String ;
327- if candidates . is_empty ( ) {
328- msg = format ! ( "no matching package named `{}` found \n " , dep . package_name ( ) ) ;
329- } else {
330- msg = format ! (
331- "no matching package found \n searched package name: `{}`\n " ,
341+ name_candidates . sort_by_key ( |o| o. 0 ) ;
342+
343+ let mut msg = String :: new ( ) ;
344+ if !version_candidates . is_empty ( ) {
345+ let _ = writeln ! (
346+ & mut msg ,
347+ "no matching versions for `{}` found " ,
332348 dep. package_name( )
333349 ) ;
334- let mut names = candidates
350+ for candidate in version_candidates {
351+ match candidate {
352+ IndexSummary :: Candidate ( summary) => {
353+ // HACK: If this was a real candidate, we wouldn't hit this case.
354+ // so it must be a patch which get normalized to being a candidate
355+ let _ =
356+ writeln ! ( & mut msg, " version {} is unavailable" , summary. version( ) ) ;
357+ }
358+ IndexSummary :: Yanked ( summary) => {
359+ let _ = writeln ! ( & mut msg, " version {} is yanked" , summary. version( ) ) ;
360+ }
361+ IndexSummary :: Offline ( summary) => {
362+ let _ = writeln ! ( & mut msg, " version {} is not cached" , summary. version( ) ) ;
363+ }
364+ IndexSummary :: Unsupported ( summary, schema_version) => {
365+ if let Some ( rust_version) = summary. rust_version ( ) {
366+ // HACK: technically its unsupported and we shouldn't make assumptions
367+ // about the entry but this is limited and for diagnostics purposes
368+ let _ = writeln ! (
369+ & mut msg,
370+ " version {} requires cargo {}" ,
371+ summary. version( ) ,
372+ rust_version
373+ ) ;
374+ } else {
375+ let _ = writeln ! (
376+ & mut msg,
377+ " version {} requires a Cargo version that supports index version {}" ,
378+ summary. version( ) ,
379+ schema_version
380+ ) ;
381+ }
382+ }
383+ }
384+ }
385+ } else if !name_candidates. is_empty ( ) {
386+ let _ = writeln ! ( & mut msg, "no matching package found" , ) ;
387+ let _ = writeln ! ( & mut msg, "searched package name: `{}`" , dep. package_name( ) ) ;
388+ let mut names = name_candidates
335389 . iter ( )
336390 . take ( 3 )
337391 . map ( |c| c. 1 . name ( ) . as_str ( ) )
338392 . collect :: < Vec < _ > > ( ) ;
339393
340- if candidates . len ( ) > 3 {
394+ if name_candidates . len ( ) > 3 {
341395 names. push ( "..." ) ;
342396 }
343397 // Vertically align first suggestion with missing crate name
344398 // so a typo jumps out at you.
345- msg . push_str ( "perhaps you meant: " ) ;
346- msg . push_str ( & names . iter ( ) . enumerate ( ) . fold (
347- String :: default ( ) ,
348- |acc, ( i, el) | match i {
399+ let suggestions = names
400+ . iter ( )
401+ . enumerate ( )
402+ . fold ( String :: default ( ) , |acc, ( i, el) | match i {
349403 0 => acc + el,
350- i if names. len ( ) - 1 == i && candidates . len ( ) <= 3 => acc + " or " + el,
404+ i if names. len ( ) - 1 == i && name_candidates . len ( ) <= 3 => acc + " or " + el,
351405 _ => acc + ", " + el,
352- } ,
353- ) ) ;
354- msg. push ( '\n' ) ;
406+ } ) ;
407+ let _ = writeln ! ( & mut msg, "perhaps you meant: {suggestions}" ) ;
408+ } else {
409+ let _ = writeln ! (
410+ & mut msg,
411+ "no matching package named `{}` found" ,
412+ dep. package_name( )
413+ ) ;
355414 }
356415
357416 let mut location_searched_msg = registry. describe_source ( dep. source_id ( ) ) ;
358417 if location_searched_msg. is_empty ( ) {
359418 location_searched_msg = format ! ( "{}" , dep. source_id( ) ) ;
360419 }
361420
362- msg . push_str ( & format ! ( "location searched: {}\n " , location_searched_msg) ) ;
363- msg . push_str ( "required by " ) ;
364- msg . push_str ( & describe_path_in_context (
365- resolver_ctx ,
366- & parent. package_id ( ) ,
367- ) ) ;
421+ let _ = writeln ! ( & mut msg , "location searched: {}" , location_searched_msg) ;
422+ let _ = write ! (
423+ & mut msg ,
424+ "required by {}" ,
425+ describe_path_in_context ( resolver_ctx , & parent. package_id( ) ) ,
426+ ) ;
368427
369428 msg
370429 } ;
0 commit comments