@@ -137,6 +137,9 @@ impl Ord for BindingError {
137137 }
138138}
139139
140+ /// A span, message, replacement text, and applicability.
141+ type Suggestion = ( Span , String , String , Applicability ) ;
142+
140143enum ResolutionError < ' a > {
141144 /// Error E0401: can't use type or const parameters from outer function.
142145 GenericParamsFromOuterFunction ( Def ) ,
@@ -166,7 +169,7 @@ enum ResolutionError<'a> {
166169 /// Error E0431: `self` import can only appear in an import list with a non-empty prefix.
167170 SelfImportOnlyInImportListWithNonEmptyPrefix ,
168171 /// Error E0433: failed to resolve.
169- FailedToResolve ( & ' a str ) ,
172+ FailedToResolve { label : String , suggestion : Option < Suggestion > } ,
170173 /// Error E0434: can't capture dynamic environment in a fn item.
171174 CannotCaptureDynamicEnvironmentInFnItem ,
172175 /// Error E0435: attempt to use a non-constant value in a constant.
@@ -380,10 +383,15 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver<'_>,
380383 err. span_label ( span, "can only appear in an import list with a non-empty prefix" ) ;
381384 err
382385 }
383- ResolutionError :: FailedToResolve ( msg ) => {
386+ ResolutionError :: FailedToResolve { label , suggestion } => {
384387 let mut err = struct_span_err ! ( resolver. session, span, E0433 ,
385- "failed to resolve: {}" , msg) ;
386- err. span_label ( span, msg) ;
388+ "failed to resolve: {}" , & label) ;
389+ err. span_label ( span, label) ;
390+
391+ if let Some ( ( span, msg, suggestion, applicability) ) = suggestion {
392+ err. span_suggestion ( span, & msg, suggestion, applicability) ;
393+ }
394+
387395 err
388396 }
389397 ResolutionError :: CannotCaptureDynamicEnvironmentInFnItem => {
@@ -1050,7 +1058,12 @@ enum PathResult<'a> {
10501058 Module ( ModuleOrUniformRoot < ' a > ) ,
10511059 NonModule ( PathResolution ) ,
10521060 Indeterminate ,
1053- Failed ( Span , String , bool /* is the error from the last segment? */ ) ,
1061+ Failed {
1062+ span : Span ,
1063+ label : String ,
1064+ suggestion : Option < Suggestion > ,
1065+ is_error_from_last_segment : bool ,
1066+ } ,
10541067}
10551068
10561069enum ModuleKind {
@@ -1775,13 +1788,18 @@ impl<'a> Resolver<'a> {
17751788 PathResult :: NonModule ( path_res) if path_res. unresolved_segments ( ) == 0 =>
17761789 path_res. base_def ( ) ,
17771790 PathResult :: NonModule ( ..) => {
1778- let msg = "type-relative paths are not supported in this context" ;
1779- error_callback ( self , span, ResolutionError :: FailedToResolve ( msg) ) ;
1791+ error_callback ( self , span, ResolutionError :: FailedToResolve {
1792+ label : String :: from ( "type-relative paths are not supported in this context" ) ,
1793+ suggestion : None ,
1794+ } ) ;
17801795 Def :: Err
17811796 }
17821797 PathResult :: Module ( ..) | PathResult :: Indeterminate => unreachable ! ( ) ,
1783- PathResult :: Failed ( span, msg, _) => {
1784- error_callback ( self , span, ResolutionError :: FailedToResolve ( & msg) ) ;
1798+ PathResult :: Failed { span, label, suggestion, .. } => {
1799+ error_callback ( self , span, ResolutionError :: FailedToResolve {
1800+ label,
1801+ suggestion,
1802+ } ) ;
17851803 Def :: Err
17861804 }
17871805 } ;
@@ -3429,7 +3447,7 @@ impl<'a> Resolver<'a> {
34293447 // Such behavior is required for backward compatibility.
34303448 // The same fallback is used when `a` resolves to nothing.
34313449 PathResult :: Module ( ModuleOrUniformRoot :: Module ( _) ) |
3432- PathResult :: Failed ( .. )
3450+ PathResult :: Failed { .. }
34333451 if ( ns == TypeNS || path. len ( ) > 1 ) &&
34343452 self . primitive_type_table . primitive_types
34353453 . contains_key ( & path[ 0 ] . ident . name ) => {
@@ -3438,11 +3456,11 @@ impl<'a> Resolver<'a> {
34383456 }
34393457 PathResult :: Module ( ModuleOrUniformRoot :: Module ( module) ) =>
34403458 PathResolution :: new ( module. def ( ) . unwrap ( ) ) ,
3441- PathResult :: Failed ( span, msg , false ) => {
3442- resolve_error ( self , span, ResolutionError :: FailedToResolve ( & msg ) ) ;
3459+ PathResult :: Failed { is_error_from_last_segment : false , span, label , suggestion } => {
3460+ resolve_error ( self , span, ResolutionError :: FailedToResolve { label , suggestion } ) ;
34433461 err_path_resolution ( )
34443462 }
3445- PathResult :: Module ( ..) | PathResult :: Failed ( .. ) => return None ,
3463+ PathResult :: Module ( ..) | PathResult :: Failed { .. } => return None ,
34463464 PathResult :: Indeterminate => bug ! ( "indetermined path result in resolve_qpath" ) ,
34473465 } ;
34483466
@@ -3550,7 +3568,12 @@ impl<'a> Resolver<'a> {
35503568 }
35513569 }
35523570 let msg = "there are too many initial `super`s." . to_string ( ) ;
3553- return PathResult :: Failed ( ident. span , msg, false ) ;
3571+ return PathResult :: Failed {
3572+ span : ident. span ,
3573+ label : msg,
3574+ suggestion : None ,
3575+ is_error_from_last_segment : false ,
3576+ } ;
35543577 }
35553578 if i == 0 {
35563579 if name == keywords:: SelfLower . name ( ) {
@@ -3587,12 +3610,17 @@ impl<'a> Resolver<'a> {
35873610 } else {
35883611 format ! ( "`{}`" , name)
35893612 } ;
3590- let msg = if i == 1 && path[ 0 ] . ident . name == keywords:: PathRoot . name ( ) {
3613+ let label = if i == 1 && path[ 0 ] . ident . name == keywords:: PathRoot . name ( ) {
35913614 format ! ( "global paths cannot start with {}" , name_str)
35923615 } else {
35933616 format ! ( "{} in paths can only be used in start position" , name_str)
35943617 } ;
3595- return PathResult :: Failed ( ident. span , msg, false ) ;
3618+ return PathResult :: Failed {
3619+ span : ident. span ,
3620+ label,
3621+ suggestion : None ,
3622+ is_error_from_last_segment : false ,
3623+ } ;
35963624 }
35973625
35983626 let binding = if let Some ( module) = module {
@@ -3653,9 +3681,12 @@ impl<'a> Resolver<'a> {
36533681 def, path. len ( ) - i - 1
36543682 ) ) ;
36553683 } else {
3656- return PathResult :: Failed ( ident. span ,
3657- format ! ( "not a module `{}`" , ident) ,
3658- is_last) ;
3684+ return PathResult :: Failed {
3685+ span : ident. span ,
3686+ label : format ! ( "not a module `{}`" , ident) ,
3687+ suggestion : None ,
3688+ is_error_from_last_segment : is_last,
3689+ } ;
36593690 }
36603691 }
36613692 Err ( Undetermined ) => return PathResult :: Indeterminate ,
@@ -3671,27 +3702,40 @@ impl<'a> Resolver<'a> {
36713702 Some ( ModuleOrUniformRoot :: Module ( module) ) => module. def ( ) ,
36723703 _ => None ,
36733704 } ;
3674- let msg = if module_def == self . graph_root . def ( ) {
3705+ let ( label , suggestion ) = if module_def == self . graph_root . def ( ) {
36753706 let is_mod = |def| match def { Def :: Mod ( ..) => true , _ => false } ;
36763707 let mut candidates =
36773708 self . lookup_import_candidates ( ident, TypeNS , is_mod) ;
36783709 candidates. sort_by_cached_key ( |c| {
36793710 ( c. path . segments . len ( ) , c. path . to_string ( ) )
36803711 } ) ;
36813712 if let Some ( candidate) = candidates. get ( 0 ) {
3682- format ! ( "did you mean `{}`?" , candidate. path)
3713+ (
3714+ String :: from ( "unresolved import" ) ,
3715+ Some ( (
3716+ ident. span ,
3717+ String :: from ( "a similar path exists" ) ,
3718+ candidate. path . to_string ( ) ,
3719+ Applicability :: MaybeIncorrect ,
3720+ ) ) ,
3721+ )
36833722 } else if !ident. is_reserved ( ) {
3684- format ! ( "maybe a missing `extern crate {};`?" , ident)
3723+ ( format ! ( "maybe a missing `extern crate {};`?" , ident) , None )
36853724 } else {
36863725 // the parser will already have complained about the keyword being used
36873726 return PathResult :: NonModule ( err_path_resolution ( ) ) ;
36883727 }
36893728 } else if i == 0 {
3690- format ! ( "use of undeclared type or module `{}`" , ident)
3729+ ( format ! ( "use of undeclared type or module `{}`" , ident) , None )
36913730 } else {
3692- format ! ( "could not find `{}` in `{}`" , ident, path[ i - 1 ] . ident)
3731+ ( format ! ( "could not find `{}` in `{}`" , ident, path[ i - 1 ] . ident) , None )
3732+ } ;
3733+ return PathResult :: Failed {
3734+ span : ident. span ,
3735+ label,
3736+ suggestion,
3737+ is_error_from_last_segment : is_last,
36933738 } ;
3694- return PathResult :: Failed ( ident. span , msg, is_last) ;
36953739 }
36963740 }
36973741 }
0 commit comments