@@ -1035,101 +1035,110 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
10351035 lifetime_names : & FxHashSet < ast:: Ident > ,
10361036 params : & [ ElisionFailureInfo ] ,
10371037 ) {
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+ ) ;
10521046
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 ( ) )
10961075 }
10971076 }
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+ }
11061099 }
11071100 }
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 ;
11311105 }
11321106 }
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+ _ => { }
11331142 }
11341143 }
11351144}
0 commit comments