@@ -137,6 +137,9 @@ impl Ord for BindingError {
137
137
}
138
138
}
139
139
140
+ /// A span, message, replacement text, and applicability.
141
+ type Suggestion = ( Span , String , String , Applicability ) ;
142
+
140
143
enum ResolutionError < ' a > {
141
144
/// Error E0401: can't use type or const parameters from outer function.
142
145
GenericParamsFromOuterFunction ( Def ) ,
@@ -166,7 +169,7 @@ enum ResolutionError<'a> {
166
169
/// Error E0431: `self` import can only appear in an import list with a non-empty prefix.
167
170
SelfImportOnlyInImportListWithNonEmptyPrefix ,
168
171
/// Error E0433: failed to resolve.
169
- FailedToResolve ( & ' a str ) ,
172
+ FailedToResolve { label : String , suggestion : Option < Suggestion > } ,
170
173
/// Error E0434: can't capture dynamic environment in a fn item.
171
174
CannotCaptureDynamicEnvironmentInFnItem ,
172
175
/// 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<'_>,
380
383
err. span_label ( span, "can only appear in an import list with a non-empty prefix" ) ;
381
384
err
382
385
}
383
- ResolutionError :: FailedToResolve ( msg ) => {
386
+ ResolutionError :: FailedToResolve { label , suggestion } => {
384
387
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
+
387
395
err
388
396
}
389
397
ResolutionError :: CannotCaptureDynamicEnvironmentInFnItem => {
@@ -1050,7 +1058,12 @@ enum PathResult<'a> {
1050
1058
Module ( ModuleOrUniformRoot < ' a > ) ,
1051
1059
NonModule ( PathResolution ) ,
1052
1060
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
+ } ,
1054
1067
}
1055
1068
1056
1069
enum ModuleKind {
@@ -1775,13 +1788,18 @@ impl<'a> Resolver<'a> {
1775
1788
PathResult :: NonModule ( path_res) if path_res. unresolved_segments ( ) == 0 =>
1776
1789
path_res. base_def ( ) ,
1777
1790
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
+ } ) ;
1780
1795
Def :: Err
1781
1796
}
1782
1797
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
+ } ) ;
1785
1803
Def :: Err
1786
1804
}
1787
1805
} ;
@@ -3429,7 +3447,7 @@ impl<'a> Resolver<'a> {
3429
3447
// Such behavior is required for backward compatibility.
3430
3448
// The same fallback is used when `a` resolves to nothing.
3431
3449
PathResult :: Module ( ModuleOrUniformRoot :: Module ( _) ) |
3432
- PathResult :: Failed ( .. )
3450
+ PathResult :: Failed { .. }
3433
3451
if ( ns == TypeNS || path. len ( ) > 1 ) &&
3434
3452
self . primitive_type_table . primitive_types
3435
3453
. contains_key ( & path[ 0 ] . ident . name ) => {
@@ -3438,11 +3456,11 @@ impl<'a> Resolver<'a> {
3438
3456
}
3439
3457
PathResult :: Module ( ModuleOrUniformRoot :: Module ( module) ) =>
3440
3458
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 } ) ;
3443
3461
err_path_resolution ( )
3444
3462
}
3445
- PathResult :: Module ( ..) | PathResult :: Failed ( .. ) => return None ,
3463
+ PathResult :: Module ( ..) | PathResult :: Failed { .. } => return None ,
3446
3464
PathResult :: Indeterminate => bug ! ( "indetermined path result in resolve_qpath" ) ,
3447
3465
} ;
3448
3466
@@ -3550,7 +3568,12 @@ impl<'a> Resolver<'a> {
3550
3568
}
3551
3569
}
3552
3570
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
+ } ;
3554
3577
}
3555
3578
if i == 0 {
3556
3579
if name == keywords:: SelfLower . name ( ) {
@@ -3587,12 +3610,17 @@ impl<'a> Resolver<'a> {
3587
3610
} else {
3588
3611
format ! ( "`{}`" , name)
3589
3612
} ;
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 ( ) {
3591
3614
format ! ( "global paths cannot start with {}" , name_str)
3592
3615
} else {
3593
3616
format ! ( "{} in paths can only be used in start position" , name_str)
3594
3617
} ;
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
+ } ;
3596
3624
}
3597
3625
3598
3626
let binding = if let Some ( module) = module {
@@ -3653,9 +3681,12 @@ impl<'a> Resolver<'a> {
3653
3681
def, path. len ( ) - i - 1
3654
3682
) ) ;
3655
3683
} 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
+ } ;
3659
3690
}
3660
3691
}
3661
3692
Err ( Undetermined ) => return PathResult :: Indeterminate ,
@@ -3671,27 +3702,40 @@ impl<'a> Resolver<'a> {
3671
3702
Some ( ModuleOrUniformRoot :: Module ( module) ) => module. def ( ) ,
3672
3703
_ => None ,
3673
3704
} ;
3674
- let msg = if module_def == self . graph_root . def ( ) {
3705
+ let ( label , suggestion ) = if module_def == self . graph_root . def ( ) {
3675
3706
let is_mod = |def| match def { Def :: Mod ( ..) => true , _ => false } ;
3676
3707
let mut candidates =
3677
3708
self . lookup_import_candidates ( ident, TypeNS , is_mod) ;
3678
3709
candidates. sort_by_cached_key ( |c| {
3679
3710
( c. path . segments . len ( ) , c. path . to_string ( ) )
3680
3711
} ) ;
3681
3712
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
+ )
3683
3722
} else if !ident. is_reserved ( ) {
3684
- format ! ( "maybe a missing `extern crate {};`?" , ident)
3723
+ ( format ! ( "maybe a missing `extern crate {};`?" , ident) , None )
3685
3724
} else {
3686
3725
// the parser will already have complained about the keyword being used
3687
3726
return PathResult :: NonModule ( err_path_resolution ( ) ) ;
3688
3727
}
3689
3728
} else if i == 0 {
3690
- format ! ( "use of undeclared type or module `{}`" , ident)
3729
+ ( format ! ( "use of undeclared type or module `{}`" , ident) , None )
3691
3730
} 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,
3693
3738
} ;
3694
- return PathResult :: Failed ( ident. span , msg, is_last) ;
3695
3739
}
3696
3740
}
3697
3741
}
0 commit comments