@@ -31,7 +31,7 @@ use rustc_span::edit_distance::find_best_match_for_name;
31
31
use rustc_span:: edition:: Edition ;
32
32
use rustc_span:: hygiene:: MacroKind ;
33
33
use rustc_span:: symbol:: { kw, sym, Ident , Symbol } ;
34
- use rustc_span:: Span ;
34
+ use rustc_span:: { Span , DUMMY_SP } ;
35
35
36
36
use rustc_middle:: ty;
37
37
@@ -2718,10 +2718,11 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
2718
2718
suggest : impl Fn ( & mut Diag < ' _ > , bool , Span , Cow < ' static , str > , String ) -> bool ,
2719
2719
) {
2720
2720
let mut suggest_note = true ;
2721
+
2721
2722
for rib in self . lifetime_ribs . iter ( ) . rev ( ) {
2722
2723
let mut should_continue = true ;
2723
2724
match rib. kind {
2724
- LifetimeRibKind :: Generics { binder : _ , span, kind } => {
2725
+ LifetimeRibKind :: Generics { binder : node_id , span, kind } => {
2725
2726
// Avoid suggesting placing lifetime parameters on constant items unless the relevant
2726
2727
// feature is enabled. Suggest the parent item as a possible location if applicable.
2727
2728
if let LifetimeBinderKind :: ConstItem = kind
@@ -2750,32 +2751,68 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
2750
2751
| LifetimeBinderKind :: PolyTrait
2751
2752
| LifetimeBinderKind :: WhereBound
2752
2753
) ;
2753
- let ( span, sugg) = if span. is_empty ( ) {
2754
- let sugg = format ! (
2754
+
2755
+ let mut span = span;
2756
+ let mut rm_poly_trait_span = DUMMY_SP ;
2757
+ let mut sugg = format ! ( "{}, " , name. unwrap_or( "'a" ) ) ;
2758
+
2759
+ if span. is_empty ( ) {
2760
+ let mut generic_params = "" . to_string ( ) ;
2761
+ if let Some ( with_poly_trait_ref) = self . with_poly_trait_ref . get ( & node_id)
2762
+ && higher_ranked
2763
+ {
2764
+ generic_params = with_poly_trait_ref. generic_param_idents . iter ( ) . fold (
2765
+ "" . to_string ( ) ,
2766
+ |mut generic_params, x| {
2767
+ generic_params += x. as_str ( ) ;
2768
+ generic_params += ", " ;
2769
+ generic_params
2770
+ } ,
2771
+ ) ;
2772
+ if !generic_params. is_empty ( ) {
2773
+ rm_poly_trait_span = with_poly_trait_ref
2774
+ . poly_trait
2775
+ . with_hi ( with_poly_trait_ref. trait_ref . lo ( ) ) ;
2776
+ }
2777
+ }
2778
+
2779
+ sugg = format ! (
2755
2780
"{}<{}>{}" ,
2756
2781
if higher_ranked { "for" } else { "" } ,
2757
- name. unwrap_or( "'a" ) ,
2782
+ format! ( "{}{}" , generic_params , name. unwrap_or( "'a" ) ) ,
2758
2783
if higher_ranked { " " } else { "" } ,
2759
2784
) ;
2760
- ( span, sugg)
2761
2785
} else {
2762
- let span = self
2786
+ span = self
2763
2787
. r
2764
2788
. tcx
2765
2789
. sess
2766
2790
. source_map ( )
2767
2791
. span_through_char ( span, '<' )
2768
2792
. shrink_to_hi ( ) ;
2769
- let sugg = format ! ( "{}, " , name. unwrap_or( "'a" ) ) ;
2770
- ( span, sugg)
2771
- } ;
2793
+ }
2794
+
2772
2795
if higher_ranked {
2773
2796
let message = Cow :: from ( format ! (
2774
2797
"consider making the {} lifetime-generic with a new `{}` lifetime" ,
2775
2798
kind. descr( ) ,
2776
2799
name. unwrap_or( "'a" ) ,
2777
2800
) ) ;
2778
- should_continue = suggest ( err, true , span, message, sugg) ;
2801
+ should_continue = if !rm_poly_trait_span. is_dummy ( ) {
2802
+ // For poly-trait-ref like `for<'a> Trait<T>` in
2803
+ // `T: for<'a> Trait<T> + 'b { }`.
2804
+ // We should merge the higher-ranked lifetimes: existed `for<'a>` and suggestion `for<'b>`
2805
+ // or will get err:
2806
+ // `[E0316] nested quantification of lifetimes`.
2807
+ err. multipart_suggestion_verbose (
2808
+ message,
2809
+ vec ! [ ( span, sugg) , ( rm_poly_trait_span, "" . to_string( ) ) ] ,
2810
+ Applicability :: MaybeIncorrect ,
2811
+ ) ;
2812
+ false
2813
+ } else {
2814
+ suggest ( err, true , span, message. clone ( ) , sugg. clone ( ) )
2815
+ } ;
2779
2816
err. note_once (
2780
2817
"for more information on higher-ranked polymorphism, visit \
2781
2818
https://doc.rust-lang.org/nomicon/hrtb.html",
@@ -3298,7 +3335,6 @@ fn mk_where_bound_predicate(
3298
3335
poly_trait_ref : & ast:: PolyTraitRef ,
3299
3336
ty : & Ty ,
3300
3337
) -> Option < ast:: WhereBoundPredicate > {
3301
- use rustc_span:: DUMMY_SP ;
3302
3338
let modified_segments = {
3303
3339
let mut segments = path. segments . clone ( ) ;
3304
3340
let [ preceding @ .., second_last, last] = segments. as_mut_slice ( ) else {
0 commit comments