@@ -1034,101 +1034,110 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
10341034 lifetime_names : & FxHashSet < ast:: Ident > ,
10351035 params : & [ ElisionFailureInfo ] ,
10361036 ) {
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+ ) ;
10511045
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 ( ) )
10951074 }
10961075 }
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+ }
11051098 }
11061099 }
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 ;
11301104 }
11311105 }
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+ _ => { }
11321141 }
11331142 }
11341143}
0 commit comments