@@ -1034,101 +1034,110 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
1034
1034
lifetime_names : & FxHashSet < ast:: Ident > ,
1035
1035
params : & [ ElisionFailureInfo ] ,
1036
1036
) {
1037
- if count > 1 {
1038
- err. span_label ( span, format ! ( "expected {} lifetime parameters" , count) ) ;
1039
- } else {
1040
- let snippet = self . tcx . sess . source_map ( ) . span_to_snippet ( span) . ok ( ) ;
1041
- let suggest_existing = |err : & mut DiagnosticBuilder < ' _ > , sugg| {
1042
- err. span_suggestion (
1043
- span,
1044
- "consider using the named lifetime" ,
1045
- sugg,
1046
- Applicability :: MaybeIncorrect ,
1047
- ) ;
1048
- } ;
1049
- let suggest_new = |err : & mut DiagnosticBuilder < ' _ > , sugg : & str | {
1050
- err. span_label ( span, "expected named lifetime parameter" ) ;
1037
+ err. span_label (
1038
+ span,
1039
+ & format ! (
1040
+ "expected {} lifetime parameter{}" ,
1041
+ if count == 1 { "named" . to_string( ) } else { count. to_string( ) } ,
1042
+ pluralize!( count)
1043
+ ) ,
1044
+ ) ;
1051
1045
1052
- for missing in self . missing_named_lifetime_spots . iter ( ) . rev ( ) {
1053
- let mut introduce_suggestion = vec ! [ ] ;
1054
- let msg;
1055
- let should_break;
1056
- introduce_suggestion. push ( match missing {
1057
- MissingLifetimeSpot :: Generics ( generics) => {
1058
- msg = "consider introducing a named lifetime parameter" . to_string ( ) ;
1059
- should_break = true ;
1060
- if let Some ( param) = generics. params . iter ( ) . find ( |p| match p. kind {
1061
- hir:: GenericParamKind :: Type {
1062
- synthetic : Some ( hir:: SyntheticTyParamKind :: ImplTrait ) ,
1063
- ..
1064
- } => false ,
1065
- _ => true ,
1066
- } ) {
1067
- ( param. span . shrink_to_lo ( ) , "'a, " . to_string ( ) )
1068
- } else {
1069
- ( generics. span , "<'a>" . to_string ( ) )
1070
- }
1071
- }
1072
- MissingLifetimeSpot :: HigherRanked { span, span_type } => {
1073
- msg = format ! (
1074
- "consider making the {} lifetime-generic with a new `'a` lifetime" ,
1075
- span_type. descr( ) ,
1076
- ) ;
1077
- should_break = false ;
1078
- err. note (
1079
- "for more information on higher-ranked polymorphism, visit \
1080
- https://doc.rust-lang.org/nomicon/hrtb.html",
1081
- ) ;
1082
- ( * span, span_type. suggestion ( "'a" ) )
1083
- }
1084
- } ) ;
1085
- for param in params {
1086
- if let Ok ( snippet) = self . tcx . sess . source_map ( ) . span_to_snippet ( param. span )
1087
- {
1088
- if snippet. starts_with ( '&' ) && !snippet. starts_with ( "&'" ) {
1089
- introduce_suggestion
1090
- . push ( ( param. span , format ! ( "&'a {}" , & snippet[ 1 ..] ) ) ) ;
1091
- } else if snippet. starts_with ( "&'_ " ) {
1092
- introduce_suggestion
1093
- . push ( ( param. span , format ! ( "&'a {}" , & snippet[ 4 ..] ) ) ) ;
1094
- }
1046
+ let snippet = self . tcx . sess . source_map ( ) . span_to_snippet ( span) . ok ( ) ;
1047
+ let suggest_existing = |err : & mut DiagnosticBuilder < ' _ > , sugg| {
1048
+ err. span_suggestion_verbose (
1049
+ span,
1050
+ "consider using the named lifetime" ,
1051
+ sugg,
1052
+ Applicability :: MaybeIncorrect ,
1053
+ ) ;
1054
+ } ;
1055
+ let suggest_new = |err : & mut DiagnosticBuilder < ' _ > , sugg : & str | {
1056
+ for missing in self . missing_named_lifetime_spots . iter ( ) . rev ( ) {
1057
+ let mut introduce_suggestion = vec ! [ ] ;
1058
+ let msg;
1059
+ let should_break;
1060
+ introduce_suggestion. push ( match missing {
1061
+ MissingLifetimeSpot :: Generics ( generics) => {
1062
+ msg = "consider introducing a named lifetime parameter" . to_string ( ) ;
1063
+ should_break = true ;
1064
+ if let Some ( param) = generics. params . iter ( ) . find ( |p| match p. kind {
1065
+ hir:: GenericParamKind :: Type {
1066
+ synthetic : Some ( hir:: SyntheticTyParamKind :: ImplTrait ) ,
1067
+ ..
1068
+ } => false ,
1069
+ _ => true ,
1070
+ } ) {
1071
+ ( param. span . shrink_to_lo ( ) , "'a, " . to_string ( ) )
1072
+ } else {
1073
+ ( generics. span , "<'a>" . to_string ( ) )
1095
1074
}
1096
1075
}
1097
- introduce_suggestion. push ( ( span, sugg. to_string ( ) ) ) ;
1098
- err. multipart_suggestion (
1099
- & msg,
1100
- introduce_suggestion,
1101
- Applicability :: MaybeIncorrect ,
1102
- ) ;
1103
- if should_break {
1104
- break ;
1076
+ MissingLifetimeSpot :: HigherRanked { span, span_type } => {
1077
+ msg = format ! (
1078
+ "consider making the {} lifetime-generic with a new `'a` lifetime" ,
1079
+ span_type. descr( ) ,
1080
+ ) ;
1081
+ should_break = false ;
1082
+ err. note (
1083
+ "for more information on higher-ranked polymorphism, visit \
1084
+ https://doc.rust-lang.org/nomicon/hrtb.html",
1085
+ ) ;
1086
+ ( * span, span_type. suggestion ( "'a" ) )
1087
+ }
1088
+ } ) ;
1089
+ for param in params {
1090
+ if let Ok ( snippet) = self . tcx . sess . source_map ( ) . span_to_snippet ( param. span ) {
1091
+ if snippet. starts_with ( '&' ) && !snippet. starts_with ( "&'" ) {
1092
+ introduce_suggestion
1093
+ . push ( ( param. span , format ! ( "&'a {}" , & snippet[ 1 ..] ) ) ) ;
1094
+ } else if snippet. starts_with ( "&'_ " ) {
1095
+ introduce_suggestion
1096
+ . push ( ( param. span , format ! ( "&'a {}" , & snippet[ 4 ..] ) ) ) ;
1097
+ }
1105
1098
}
1106
1099
}
1107
- } ;
1108
-
1109
- match ( lifetime_names. len ( ) , lifetime_names. iter ( ) . next ( ) , snippet. as_deref ( ) ) {
1110
- ( 1 , Some ( name) , Some ( "&" ) ) => {
1111
- suggest_existing ( err, format ! ( "&{} " , name) ) ;
1112
- }
1113
- ( 1 , Some ( name) , Some ( "'_" ) ) => {
1114
- suggest_existing ( err, name. to_string ( ) ) ;
1115
- }
1116
- ( 1 , Some ( name) , Some ( snippet) ) if !snippet. ends_with ( '>' ) => {
1117
- suggest_existing ( err, format ! ( "{}<{}>" , snippet, name) ) ;
1118
- }
1119
- ( 0 , _, Some ( "&" ) ) => {
1120
- suggest_new ( err, "&'a " ) ;
1121
- }
1122
- ( 0 , _, Some ( "'_" ) ) => {
1123
- suggest_new ( err, "'a" ) ;
1124
- }
1125
- ( 0 , _, Some ( snippet) ) if !snippet. ends_with ( '>' ) => {
1126
- suggest_new ( err, & format ! ( "{}<'a>" , snippet) ) ;
1127
- }
1128
- _ => {
1129
- err. span_label ( span, "expected lifetime parameter" ) ;
1100
+ introduce_suggestion. push ( ( span, sugg. to_string ( ) ) ) ;
1101
+ err. multipart_suggestion ( & msg, introduce_suggestion, Applicability :: MaybeIncorrect ) ;
1102
+ if should_break {
1103
+ break ;
1130
1104
}
1131
1105
}
1106
+ } ;
1107
+
1108
+ match ( lifetime_names. len ( ) , lifetime_names. iter ( ) . next ( ) , snippet. as_deref ( ) ) {
1109
+ ( 1 , Some ( name) , Some ( "&" ) ) => {
1110
+ suggest_existing ( err, format ! ( "&{} " , name) ) ;
1111
+ }
1112
+ ( 1 , Some ( name) , Some ( "'_" ) ) => {
1113
+ suggest_existing ( err, name. to_string ( ) ) ;
1114
+ }
1115
+ ( 1 , Some ( name) , Some ( "" ) ) => {
1116
+ suggest_existing ( err, format ! ( "{}, " , name) . repeat ( count) ) ;
1117
+ }
1118
+ ( 1 , Some ( name) , Some ( snippet) ) if !snippet. ends_with ( '>' ) => {
1119
+ suggest_existing (
1120
+ err,
1121
+ format ! (
1122
+ "{}<{}>" ,
1123
+ snippet,
1124
+ std:: iter:: repeat( name. to_string( ) )
1125
+ . take( count)
1126
+ . collect:: <Vec <_>>( )
1127
+ . join( ", " )
1128
+ ) ,
1129
+ ) ;
1130
+ }
1131
+ ( 0 , _, Some ( "&" ) ) if count == 1 => {
1132
+ suggest_new ( err, "&'a " ) ;
1133
+ }
1134
+ ( 0 , _, Some ( "'_" ) ) if count == 1 => {
1135
+ suggest_new ( err, "'a" ) ;
1136
+ }
1137
+ ( 0 , _, Some ( snippet) ) if !snippet. ends_with ( '>' ) && count == 1 => {
1138
+ suggest_new ( err, & format ! ( "{}<'a>" , snippet) ) ;
1139
+ }
1140
+ _ => { }
1132
1141
}
1133
1142
}
1134
1143
}
0 commit comments