@@ -10,7 +10,7 @@ use rustc_ast::{
10
10
self as ast, AssocItemKind , Expr , ExprKind , GenericParam , GenericParamKind , Item , ItemKind ,
11
11
MethodCall , NodeId , Path , Ty , TyKind , DUMMY_NODE_ID ,
12
12
} ;
13
- use rustc_ast_pretty:: pprust:: path_segment_to_string ;
13
+ use rustc_ast_pretty:: pprust:: where_bound_predicate_to_string ;
14
14
use rustc_data_structures:: fx:: FxHashSet ;
15
15
use rustc_errors:: {
16
16
pluralize, struct_span_err, Applicability , Diagnostic , DiagnosticBuilder , ErrorGuaranteed ,
@@ -1050,7 +1050,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
1050
1050
} ;
1051
1051
1052
1052
// Confirm that the target is an associated type.
1053
- let ( ty, position , path) = if let ast:: TyKind :: Path ( Some ( qself) , path) = & bounded_ty. kind {
1053
+ let ( ty, _ , path) = if let ast:: TyKind :: Path ( Some ( qself) , path) = & bounded_ty. kind {
1054
1054
// use this to verify that ident is a type param.
1055
1055
let Some ( partial_res) = self . r . partial_res_map . get ( & bounded_ty. id ) else {
1056
1056
return false ;
@@ -1079,37 +1079,19 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
1079
1079
return false ;
1080
1080
}
1081
1081
if let (
1082
- [ ast:: PathSegment { ident : constrain_ident , args : None , .. } ] ,
1082
+ [ ast:: PathSegment { args : None , .. } ] ,
1083
1083
[ ast:: GenericBound :: Trait ( poly_trait_ref, ast:: TraitBoundModifier :: None ) ] ,
1084
1084
) = ( & type_param_path. segments [ ..] , & bounds[ ..] )
1085
1085
{
1086
1086
if let [ ast:: PathSegment { ident, args : None , .. } ] =
1087
1087
& poly_trait_ref. trait_ref . path . segments [ ..]
1088
1088
{
1089
1089
if ident. span == span {
1090
+ let Some ( new_where_bound_predicate) = mk_where_bound_predicate ( path, poly_trait_ref, ty) else { return false ; } ;
1090
1091
err. span_suggestion_verbose (
1091
1092
* where_span,
1092
1093
format ! ( "constrain the associated type to `{}`" , ident) ,
1093
- format ! (
1094
- "{}: {}<{} = {}>" ,
1095
- self . r
1096
- . tcx
1097
- . sess
1098
- . source_map( )
1099
- . span_to_snippet( ty. span) // Account for `<&'a T as Foo>::Bar`.
1100
- . unwrap_or_else( |_| constrain_ident. to_string( ) ) ,
1101
- path. segments[ ..position]
1102
- . iter( )
1103
- . map( |segment| path_segment_to_string( segment) )
1104
- . collect:: <Vec <_>>( )
1105
- . join( "::" ) ,
1106
- path. segments[ position..]
1107
- . iter( )
1108
- . map( |segment| path_segment_to_string( segment) )
1109
- . collect:: <Vec <_>>( )
1110
- . join( "::" ) ,
1111
- ident,
1112
- ) ,
1094
+ where_bound_predicate_to_string ( & new_where_bound_predicate) ,
1113
1095
Applicability :: MaybeIncorrect ,
1114
1096
) ;
1115
1097
}
@@ -2605,6 +2587,70 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
2605
2587
}
2606
2588
}
2607
2589
2590
+ fn mk_where_bound_predicate (
2591
+ path : & Path ,
2592
+ poly_trait_ref : & ast:: PolyTraitRef ,
2593
+ ty : & ast:: Ty ,
2594
+ ) -> Option < ast:: WhereBoundPredicate > {
2595
+ use rustc_span:: DUMMY_SP ;
2596
+ let modified_segments = {
2597
+ let mut segments = path. segments . clone ( ) ;
2598
+ let [ preceding @ .., second_last, last] = segments. as_mut_slice ( ) else { return None ; } ;
2599
+ let mut segments = ThinVec :: from ( preceding) ;
2600
+
2601
+ let added_constraint = ast:: AngleBracketedArg :: Constraint ( ast:: AssocConstraint {
2602
+ id : DUMMY_NODE_ID ,
2603
+ ident : last. ident ,
2604
+ gen_args : None ,
2605
+ kind : ast:: AssocConstraintKind :: Equality {
2606
+ term : ast:: Term :: Ty ( ast:: ptr:: P ( ast:: Ty {
2607
+ kind : ast:: TyKind :: Path ( None , poly_trait_ref. trait_ref . path . clone ( ) ) ,
2608
+ id : DUMMY_NODE_ID ,
2609
+ span : DUMMY_SP ,
2610
+ tokens : None ,
2611
+ } ) ) ,
2612
+ } ,
2613
+ span : DUMMY_SP ,
2614
+ } ) ;
2615
+
2616
+ match second_last. args . as_deref_mut ( ) {
2617
+ Some ( ast:: GenericArgs :: AngleBracketed ( ast:: AngleBracketedArgs { args, .. } ) ) => {
2618
+ args. push ( added_constraint) ;
2619
+ }
2620
+ Some ( _) => return None ,
2621
+ None => {
2622
+ second_last. args =
2623
+ Some ( ast:: ptr:: P ( ast:: GenericArgs :: AngleBracketed ( ast:: AngleBracketedArgs {
2624
+ args : ThinVec :: from ( [ added_constraint] ) ,
2625
+ span : DUMMY_SP ,
2626
+ } ) ) ) ;
2627
+ }
2628
+ }
2629
+
2630
+ segments. push ( second_last. clone ( ) ) ;
2631
+ segments
2632
+ } ;
2633
+
2634
+ let new_where_bound_predicate = ast:: WhereBoundPredicate {
2635
+ span : DUMMY_SP ,
2636
+ bound_generic_params : ThinVec :: new ( ) ,
2637
+ bounded_ty : ast:: ptr:: P ( ty. clone ( ) ) ,
2638
+ bounds : vec ! [ ast:: GenericBound :: Trait (
2639
+ ast:: PolyTraitRef {
2640
+ bound_generic_params: ThinVec :: new( ) ,
2641
+ trait_ref: ast:: TraitRef {
2642
+ path: ast:: Path { segments: modified_segments, span: DUMMY_SP , tokens: None } ,
2643
+ ref_id: DUMMY_NODE_ID ,
2644
+ } ,
2645
+ span: DUMMY_SP ,
2646
+ } ,
2647
+ ast:: TraitBoundModifier :: None ,
2648
+ ) ] ,
2649
+ } ;
2650
+
2651
+ Some ( new_where_bound_predicate)
2652
+ }
2653
+
2608
2654
/// Report lifetime/lifetime shadowing as an error.
2609
2655
pub ( super ) fn signal_lifetime_shadowing ( sess : & Session , orig : Ident , shadower : Ident ) {
2610
2656
let mut err = struct_span_err ! (
0 commit comments