1
- use rustc_data_structures:: fx:: FxHashMap ;
1
+ use rustc_data_structures:: fx:: { FxHashMap , FxIndexSet } ;
2
2
use rustc_errors:: struct_span_err;
3
3
use rustc_hir as hir;
4
4
use rustc_hir:: def:: { DefKind , Res } ;
5
5
use rustc_hir:: def_id:: { DefId , LocalDefId } ;
6
- use rustc_middle:: ty:: { self as ty, Ty } ;
6
+ use rustc_middle:: ty:: { self as ty, ToPredicate , Ty } ;
7
7
use rustc_span:: symbol:: Ident ;
8
8
use rustc_span:: { ErrorGuaranteed , Span } ;
9
9
use rustc_trait_selection:: traits;
@@ -16,23 +16,155 @@ use crate::bounds::Bounds;
16
16
use crate :: errors;
17
17
18
18
impl < ' tcx > dyn AstConv < ' tcx > + ' _ {
19
+ pub ( crate ) fn lower_where_predicates (
20
+ & self ,
21
+ params : & [ hir:: GenericParam < ' _ > ] ,
22
+ hir_predicates : & [ hir:: WherePredicate < ' _ > ] ,
23
+ predicates : & mut FxIndexSet < ( ty:: Clause < ' tcx > , Span ) > ,
24
+ ) {
25
+ // Collect the predicates that were written inline by the user on each
26
+ // type parameter (e.g., `<T: Foo>`). Also add `ConstArgHasType` predicates
27
+ // for each const parameter.
28
+ for param in params {
29
+ match param. kind {
30
+ hir:: GenericParamKind :: Lifetime { .. } => ( ) ,
31
+ hir:: GenericParamKind :: Type { .. } => {
32
+ let param_ty =
33
+ ty:: fold:: shift_vars ( self . tcx ( ) , self . hir_id_to_bound_ty ( param. hir_id ) , 1 ) ;
34
+ let mut bounds = Bounds :: default ( ) ;
35
+ // Params are implicitly sized unless a `?Sized` bound is found
36
+ self . add_implicitly_sized (
37
+ & mut bounds,
38
+ param_ty,
39
+ & [ ] ,
40
+ Some ( ( param. def_id , hir_predicates) ) ,
41
+ param. span ,
42
+ ) ;
43
+ trace ! ( ?bounds) ;
44
+ predicates. extend ( bounds. clauses ( ) ) ;
45
+ trace ! ( ?predicates) ;
46
+ }
47
+ hir:: GenericParamKind :: Const { .. } => {
48
+ let ct_ty = self
49
+ . tcx ( )
50
+ . type_of ( param. def_id . to_def_id ( ) )
51
+ . no_bound_vars ( )
52
+ . expect ( "const parameters cannot be generic" ) ;
53
+ let ct = ty:: fold:: shift_vars (
54
+ self . tcx ( ) ,
55
+ self . hir_id_to_bound_const ( param. hir_id , ct_ty) ,
56
+ 1 ,
57
+ ) ;
58
+ predicates. insert ( (
59
+ ty:: Binder :: bind_with_vars (
60
+ ty:: ClauseKind :: ConstArgHasType ( ct, ct_ty) ,
61
+ ty:: List :: empty ( ) ,
62
+ )
63
+ . to_predicate ( self . tcx ( ) ) ,
64
+ param. span ,
65
+ ) ) ;
66
+ }
67
+ }
68
+ }
69
+
70
+ // Add in the bounds that appear in the where-clause.
71
+ for predicate in hir_predicates {
72
+ match predicate {
73
+ hir:: WherePredicate :: BoundPredicate ( bound_pred) => {
74
+ let ty = self . ast_ty_to_ty ( bound_pred. bounded_ty ) ;
75
+ let bound_vars = self . tcx ( ) . late_bound_vars ( bound_pred. hir_id ) ;
76
+
77
+ let mut binder_predicates = FxIndexSet :: default ( ) ;
78
+ self . lower_where_predicates (
79
+ bound_pred. bound_generic_params ,
80
+ bound_pred. binder_predicates ,
81
+ & mut binder_predicates,
82
+ ) ;
83
+ let binder_predicates = self . tcx ( ) . mk_clauses_from_iter (
84
+ binder_predicates. into_iter ( ) . map ( |( clause, _) | clause) ,
85
+ ) ;
86
+
87
+ // Keep the type around in a dummy predicate, in case of no bounds.
88
+ // That way, `where Ty:` is not a complete noop (see #53696) and `Ty`
89
+ // is still checked for WF.
90
+ if bound_pred. bounds . is_empty ( ) {
91
+ if let ty:: Param ( _) = ty. kind ( ) {
92
+ // This is a `where T:`, which can be in the HIR from the
93
+ // transformation that moves `?Sized` to `T`'s declaration.
94
+ // We can skip the predicate because type parameters are
95
+ // trivially WF, but also we *should*, to avoid exposing
96
+ // users who never wrote `where Type:,` themselves, to
97
+ // compiler/tooling bugs from not handling WF predicates.
98
+ } else {
99
+ let span = bound_pred. bounded_ty . span ;
100
+ let predicate = ty:: Binder :: bind_with_vars (
101
+ ty:: ClauseKind :: WellFormed ( ty. into ( ) ) ,
102
+ bound_vars,
103
+ ) ;
104
+ predicates. insert ( ( predicate. to_predicate ( self . tcx ( ) ) , span) ) ;
105
+ }
106
+ }
107
+
108
+ let mut bounds = Bounds :: default ( ) ;
109
+ self . add_bounds (
110
+ ty,
111
+ bound_pred. bounds . iter ( ) ,
112
+ & mut bounds,
113
+ bound_vars,
114
+ binder_predicates,
115
+ OnlySelfBounds ( false ) ,
116
+ ) ;
117
+ predicates. extend ( bounds. clauses ( ) ) ;
118
+ }
119
+
120
+ hir:: WherePredicate :: RegionPredicate ( region_pred) => {
121
+ let r1 = self . ast_region_to_region ( & region_pred. lifetime , None ) ;
122
+ predicates. extend ( region_pred. bounds . iter ( ) . map ( |bound| {
123
+ let ( r2, span) = match bound {
124
+ hir:: GenericBound :: Outlives ( lt) => {
125
+ ( self . ast_region_to_region ( lt, None ) , lt. ident . span )
126
+ }
127
+ _ => bug ! ( ) ,
128
+ } ;
129
+ let pred = ty:: ClauseKind :: RegionOutlives ( ty:: OutlivesPredicate ( r1, r2) ) ;
130
+ // This predicate may have escaping bound vars, e.g. if
131
+ // we have `for<'a: 'a> ..`. Since outlives predicates
132
+ // don't implicitly have a binder added for them in
133
+ // resolve_bound_vars, we need to explicitly shift the
134
+ // vars in once here.
135
+ let pred = ty:: Binder :: bind_with_vars (
136
+ ty:: fold:: shift_vars ( self . tcx ( ) , pred, 1 ) ,
137
+ ty:: List :: empty ( ) ,
138
+ )
139
+ . to_predicate ( self . tcx ( ) ) ;
140
+ ( pred, span)
141
+ } ) )
142
+ }
143
+
144
+ hir:: WherePredicate :: EqPredicate ( ..) => {
145
+ // FIXME(#20041)
146
+ }
147
+ }
148
+ }
149
+ }
150
+
19
151
/// Sets `implicitly_sized` to true on `Bounds` if necessary
20
- pub ( crate ) fn add_implicitly_sized (
152
+ pub ( crate ) fn add_implicitly_sized < ' hir > (
21
153
& self ,
22
154
bounds : & mut Bounds < ' tcx > ,
23
155
self_ty : Ty < ' tcx > ,
24
- ast_bounds : & ' tcx [ hir:: GenericBound < ' tcx > ] ,
25
- self_ty_where_predicates : Option < ( LocalDefId , & ' tcx [ hir:: WherePredicate < ' tcx > ] ) > ,
156
+ ast_bounds : & ' hir [ hir:: GenericBound < ' hir > ] ,
157
+ self_ty_where_predicates : Option < ( LocalDefId , & ' hir [ hir:: WherePredicate < ' hir > ] ) > ,
26
158
span : Span ,
27
159
) {
28
160
let tcx = self . tcx ( ) ;
29
161
30
162
// Try to find an unbound in bounds.
31
163
let mut unbounds: SmallVec < [ _ ; 1 ] > = SmallVec :: new ( ) ;
32
- let mut search_bounds = |ast_bounds : & ' tcx [ hir:: GenericBound < ' tcx > ] | {
164
+ let mut search_bounds = |ast_bounds : & ' hir [ hir:: GenericBound < ' hir > ] | {
33
165
for ab in ast_bounds {
34
166
if let hir:: GenericBound :: Trait ( ptr, hir:: TraitBoundModifier :: Maybe ) = ab {
35
- unbounds. push ( ptr)
167
+ unbounds. push ( ptr) ;
36
168
}
37
169
}
38
170
} ;
@@ -106,6 +238,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
106
238
ast_bounds : I ,
107
239
bounds : & mut Bounds < ' tcx > ,
108
240
bound_vars : & ' tcx ty:: List < ty:: BoundVariableKind > ,
241
+ binder_predicates : & ' tcx ty:: List < ty:: Clause < ' tcx > > ,
109
242
only_self_bounds : OnlySelfBounds ,
110
243
) {
111
244
for ast_bound in ast_bounds {
@@ -123,6 +256,18 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
123
256
}
124
257
hir:: TraitBoundModifier :: Maybe => continue ,
125
258
} ;
259
+
260
+ let mut additional_binder_predicates = FxIndexSet :: default ( ) ;
261
+ self . lower_where_predicates (
262
+ poly_trait_ref. bound_generic_params ,
263
+ poly_trait_ref. binder_predicates ,
264
+ & mut additional_binder_predicates,
265
+ ) ;
266
+ let binder_predicates =
267
+ self . tcx ( ) . mk_clauses_from_iter ( binder_predicates. into_iter ( ) . chain (
268
+ additional_binder_predicates. into_iter ( ) . map ( |( clause, _) | clause) ,
269
+ ) ) ;
270
+
126
271
let _ = self . instantiate_poly_trait_ref (
127
272
& poly_trait_ref. trait_ref ,
128
273
poly_trait_ref. span ,
@@ -131,6 +276,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
131
276
param_ty,
132
277
bounds,
133
278
false ,
279
+ binder_predicates,
134
280
only_self_bounds,
135
281
) ;
136
282
}
@@ -199,6 +345,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
199
345
} ) ,
200
346
& mut bounds,
201
347
ty:: List :: empty ( ) ,
348
+ ty:: List :: empty ( ) ,
202
349
only_self_bounds,
203
350
) ;
204
351
debug ! ( ?bounds) ;
@@ -503,6 +650,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
503
650
ast_bounds. iter ( ) ,
504
651
bounds,
505
652
projection_ty. bound_vars ( ) ,
653
+ projection_ty. skip_binder_with_predicates ( ) . 1 ,
506
654
only_self_bounds,
507
655
) ;
508
656
}
0 commit comments