@@ -856,89 +856,36 @@ fn elision_suggestions(
856856 . filter ( |param| !param. is_elided_lifetime ( ) && !param. is_impl_trait ( ) )
857857 . collect :: < Vec < _ > > ( ) ;
858858
859- if !elidable_lts
860- . iter ( )
861- . all ( |lt| explicit_params. iter ( ) . any ( |param| param. def_id == * lt) )
862- {
863- return None ;
864- }
865-
866- let mut suggestions = if elidable_lts. is_empty ( ) {
867- vec ! [ ]
868- } else if elidable_lts. len ( ) == explicit_params. len ( ) {
859+ let mut suggestions = if elidable_lts. len ( ) == explicit_params. len ( ) {
869860 // if all the params are elided remove the whole generic block
870861 //
871862 // fn x<'a>() {}
872863 // ^^^^
873864 vec ! [ ( generics. span, String :: new( ) ) ]
874865 } else {
875- match & explicit_params[ ..] {
876- // no params, nothing to elide
877- [ ] => unreachable ! ( "handled by `elidable_lts.is_empty()`" ) ,
878- [ param] => {
879- if elidable_lts. contains ( & param. def_id ) {
880- unreachable ! ( "handled by `elidable_lts.len() == explicit_params.len()`" )
866+ elidable_lts
867+ . iter ( )
868+ . map ( |& id| {
869+ let pos = explicit_params. iter ( ) . position ( |param| param. def_id == id) ?;
870+ let param = explicit_params. get ( pos) ?;
871+
872+ let span = if let Some ( next) = explicit_params. get ( pos + 1 ) {
873+ // fn x<'prev, 'a, 'next>() {}
874+ // ^^^^
875+ param. span . until ( next. span )
881876 } else {
882- unreachable ! ( "handled by `elidable_lts.is_empty()`" )
883- }
884- } ,
885- [ _, _, ..] => {
886- // Given a list like `<'a, 'b, 'c, 'd, ..>`,
887- //
888- // If there is a cluster of elidable lifetimes at the beginning, say `'a` and `'b`, we should
889- // suggest removing them _and_ the trailing comma. The span for that is `a.span.until(c.span)`:
890- // <'a, 'b, 'c, 'd, ..> => <'a, 'b, 'c, 'd, ..>
891- // ^^ ^^ ^^^^^^^^
892- //
893- // And since we know that `'c` isn't elidable--otherwise it would've been in the cluster--we can go
894- // over all the lifetimes after it, and for each elidable one, add a suggestion spanning the
895- // lifetime itself and the comma before, because each individual suggestion is guaranteed to leave
896- // the list valid:
897- // <.., 'c, 'd, 'e, 'f, 'g, ..> => <.., 'c, 'd, 'e, 'f, 'g, ..>
898- // ^^ ^^ ^^ ^^^^ ^^^^^^^^
899- //
900- // In case there is no such starting cluster, we only need to do the second part of the algorithm:
901- // <'a, 'b, 'c, 'd, 'e, 'f, 'g, ..> => <'a, 'b , 'c, 'd, 'e, 'f, 'g, ..>
902- // ^^ ^^ ^^ ^^ ^^^^^^^^^ ^^^^^^^^
903-
904- // Split off the starting cluster
905- // TODO: use `slice::split_once` once stabilized (github.com/rust-lang/rust/issues/112811):
906- // ```
907- // let Some(split) = explicit_params.split_once(|param| !elidable_lts.contains(¶m.def_id)) else {
908- // // there were no lifetime param that couldn't be elided
909- // unreachable!("handled by `elidable_lts.len() == explicit_params.len()`")
910- // };
911- // match split { /* .. */ }
912- // ```
913- let Some ( split_pos) = explicit_params
914- . iter ( )
915- . position ( |param| !elidable_lts. contains ( & param. def_id ) )
916- else {
917- // there were no lifetime param that couldn't be elided
918- unreachable ! ( "handled by `elidable_lts.len() == explicit_params.len()`" )
877+ // `pos` should be at least 1 here, because the param in position 0 would either have a `next`
878+ // param or would have taken the `elidable_lts.len() == explicit_params.len()` branch.
879+ let prev = explicit_params. get ( pos - 1 ) ?;
880+
881+ // fn x<'prev, 'a>() {}
882+ // ^^^^
883+ param. span . with_lo ( prev. span . hi ( ) )
919884 } ;
920- let split = explicit_params
921- . split_at_checked ( split_pos)
922- . expect ( "got `split_pos` from `position` on the same Vec" ) ;
923-
924- match split {
925- ( [ ..] , [ ] ) => unreachable ! ( "handled by `elidable_lts.len() == explicit_params.len()`" ) ,
926- ( [ ] , [ _] ) => unreachable ! ( "handled by `explicit_params.len() == 1`" ) ,
927- ( cluster, rest @ [ rest_first, ..] ) => {
928- // the span for the cluster
929- ( cluster. first ( ) . map ( |fw| fw. span . until ( rest_first. span ) ) . into_iter ( ) )
930- // the span for the remaining lifetimes (calculations independent of the cluster)
931- . chain (
932- rest. array_windows ( )
933- . filter ( |[ _, curr] | elidable_lts. contains ( & curr. def_id ) )
934- . map ( |[ prev, curr] | curr. span . with_lo ( prev. span . hi ( ) ) ) ,
935- )
936- . map ( |sp| ( sp, String :: new ( ) ) )
937- . collect ( )
938- } ,
939- }
940- } ,
941- }
885+
886+ Some ( ( span, String :: new ( ) ) )
887+ } )
888+ . collect :: < Option < Vec < _ > > > ( ) ?
942889 } ;
943890
944891 suggestions. extend ( usages. iter ( ) . map ( |& usage| {
0 commit comments