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