@@ -1034,101 +1034,125 @@ 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
+ let snippet = self . tcx . sess . source_map ( ) . span_to_snippet ( span) . ok ( ) ;
1051
1038
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
- }
1039
+ err. span_label (
1040
+ span,
1041
+ & format ! (
1042
+ "expected {} lifetime parameter{}" ,
1043
+ if count == 1 { "named" . to_string( ) } else { count. to_string( ) } ,
1044
+ pluralize!( count)
1045
+ ) ,
1046
+ ) ;
1047
+
1048
+ let suggest_existing = |err : & mut DiagnosticBuilder < ' _ > , sugg| {
1049
+ err. span_suggestion_verbose (
1050
+ span,
1051
+ & format ! ( "consider using the `{}` lifetime" , lifetime_names. iter( ) . next( ) . unwrap( ) ) ,
1052
+ sugg,
1053
+ Applicability :: MaybeIncorrect ,
1054
+ ) ;
1055
+ } ;
1056
+ let suggest_new = |err : & mut DiagnosticBuilder < ' _ > , sugg : & str | {
1057
+ for missing in self . missing_named_lifetime_spots . iter ( ) . rev ( ) {
1058
+ let mut introduce_suggestion = vec ! [ ] ;
1059
+ let msg;
1060
+ let should_break;
1061
+ introduce_suggestion. push ( match missing {
1062
+ MissingLifetimeSpot :: Generics ( generics) => {
1063
+ msg = "consider introducing a named lifetime parameter" . to_string ( ) ;
1064
+ should_break = true ;
1065
+ if let Some ( param) = generics. params . iter ( ) . find ( |p| match p. kind {
1066
+ hir:: GenericParamKind :: Type {
1067
+ synthetic : Some ( hir:: SyntheticTyParamKind :: ImplTrait ) ,
1068
+ ..
1069
+ } => false ,
1070
+ _ => true ,
1071
+ } ) {
1072
+ ( param. span . shrink_to_lo ( ) , "'a, " . to_string ( ) )
1073
+ } else {
1074
+ ( generics. span , "<'a>" . to_string ( ) )
1095
1075
}
1096
1076
}
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 ;
1077
+ MissingLifetimeSpot :: HigherRanked { span, span_type } => {
1078
+ msg = format ! (
1079
+ "consider making the {} lifetime-generic with a new `'a` lifetime" ,
1080
+ span_type. descr( ) ,
1081
+ ) ;
1082
+ should_break = false ;
1083
+ err. note (
1084
+ "for more information on higher-ranked polymorphism, visit \
1085
+ https://doc.rust-lang.org/nomicon/hrtb.html",
1086
+ ) ;
1087
+ ( * span, span_type. suggestion ( "'a" ) )
1088
+ }
1089
+ } ) ;
1090
+ for param in params {
1091
+ if let Ok ( snippet) = self . tcx . sess . source_map ( ) . span_to_snippet ( param. span ) {
1092
+ if snippet. starts_with ( '&' ) && !snippet. starts_with ( "&'" ) {
1093
+ introduce_suggestion
1094
+ . push ( ( param. span , format ! ( "&'a {}" , & snippet[ 1 ..] ) ) ) ;
1095
+ } else if snippet. starts_with ( "&'_ " ) {
1096
+ introduce_suggestion
1097
+ . push ( ( param. span , format ! ( "&'a {}" , & snippet[ 4 ..] ) ) ) ;
1098
+ }
1105
1099
}
1106
1100
}
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) ) ;
1101
+ introduce_suggestion. push ( ( span, sugg. to_string ( ) ) ) ;
1102
+ err. multipart_suggestion ( & msg, introduce_suggestion, Applicability :: MaybeIncorrect ) ;
1103
+ if should_break {
1104
+ break ;
1127
1105
}
1128
- _ => {
1129
- err. span_label ( span, "expected lifetime parameter" ) ;
1106
+ }
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 ( "" ) ) => {
1117
+ suggest_existing ( err, format ! ( "{}, " , name) . repeat ( count) ) ;
1118
+ }
1119
+ ( 1 , Some ( name) , Some ( snippet) ) if !snippet. ends_with ( '>' ) => {
1120
+ suggest_existing (
1121
+ err,
1122
+ format ! (
1123
+ "{}<{}>" ,
1124
+ snippet,
1125
+ std:: iter:: repeat( name. to_string( ) )
1126
+ . take( count)
1127
+ . collect:: <Vec <_>>( )
1128
+ . join( ", " )
1129
+ ) ,
1130
+ ) ;
1131
+ }
1132
+ ( 0 , _, Some ( "&" ) ) if count == 1 => {
1133
+ suggest_new ( err, "&'a " ) ;
1134
+ }
1135
+ ( 0 , _, Some ( "'_" ) ) if count == 1 => {
1136
+ suggest_new ( err, "'a" ) ;
1137
+ }
1138
+ ( 0 , _, Some ( snippet) ) if !snippet. ends_with ( '>' ) && count == 1 => {
1139
+ suggest_new ( err, & format ! ( "{}<'a>" , snippet) ) ;
1140
+ }
1141
+ ( n, ..) if n > 1 => {
1142
+ let spans: Vec < Span > = lifetime_names. iter ( ) . map ( |lt| lt. span ) . collect ( ) ;
1143
+ err. span_note ( spans, "these named lifetimes are available to use" ) ;
1144
+ if Some ( "" ) == snippet. as_deref ( ) {
1145
+ // This happens when we have `Foo<T>` where we point at the space before `T`,
1146
+ // but this can be confusing so we give a suggestion with placeholders.
1147
+ err. span_suggestion_verbose (
1148
+ span,
1149
+ "consider using one of the available lifetimes here" ,
1150
+ "'lifetime, " . repeat ( count) ,
1151
+ Applicability :: HasPlaceholders ,
1152
+ ) ;
1130
1153
}
1131
1154
}
1155
+ _ => { }
1132
1156
}
1133
1157
}
1134
1158
}
0 commit comments