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
6
use rustc_lint_defs:: Applicability ;
7
- use rustc_middle:: ty:: { self as ty, Ty , TypeVisitableExt } ;
7
+ use rustc_middle:: ty:: { self as ty, ToPredicate , Ty , TypeVisitableExt } ;
8
8
use rustc_span:: symbol:: Ident ;
9
9
use rustc_span:: { ErrorGuaranteed , Span } ;
10
10
use rustc_trait_selection:: traits;
@@ -16,6 +16,132 @@ 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 : & ' tcx [ hir:: GenericParam < ' tcx > ] ,
22
+ hir_predicates : & ' tcx [ hir:: WherePredicate < ' tcx > ] ,
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
+ if !binder_predicates. is_empty ( ) {
87
+ println ! ( "binder_predicates = {binder_predicates:#?}" ) ;
88
+ }
89
+
90
+ // Keep the type around in a dummy predicate, in case of no bounds.
91
+ // That way, `where Ty:` is not a complete noop (see #53696) and `Ty`
92
+ // is still checked for WF.
93
+ if bound_pred. bounds . is_empty ( ) {
94
+ if let ty:: Param ( _) = ty. kind ( ) {
95
+ // This is a `where T:`, which can be in the HIR from the
96
+ // transformation that moves `?Sized` to `T`'s declaration.
97
+ // We can skip the predicate because type parameters are
98
+ // trivially WF, but also we *should*, to avoid exposing
99
+ // users who never wrote `where Type:,` themselves, to
100
+ // compiler/tooling bugs from not handling WF predicates.
101
+ } else {
102
+ let span = bound_pred. bounded_ty . span ;
103
+ let predicate = ty:: Binder :: bind_with_vars (
104
+ ty:: ClauseKind :: WellFormed ( ty. into ( ) ) ,
105
+ bound_vars,
106
+ ) ;
107
+ predicates. insert ( ( predicate. to_predicate ( self . tcx ( ) ) , span) ) ;
108
+ }
109
+ }
110
+
111
+ let mut bounds = Bounds :: default ( ) ;
112
+ self . add_bounds (
113
+ ty,
114
+ bound_pred. bounds . iter ( ) ,
115
+ & mut bounds,
116
+ bound_vars,
117
+ binder_predicates,
118
+ OnlySelfBounds ( false ) ,
119
+ ) ;
120
+ predicates. extend ( bounds. clauses ( ) ) ;
121
+ }
122
+
123
+ hir:: WherePredicate :: RegionPredicate ( region_pred) => {
124
+ let r1 = self . ast_region_to_region ( & region_pred. lifetime , None ) ;
125
+ predicates. extend ( region_pred. bounds . iter ( ) . map ( |bound| {
126
+ let ( r2, span) = match bound {
127
+ hir:: GenericBound :: Outlives ( lt) => {
128
+ ( self . ast_region_to_region ( lt, None ) , lt. ident . span )
129
+ }
130
+ _ => bug ! ( ) ,
131
+ } ;
132
+ let pred = ty:: ClauseKind :: RegionOutlives ( ty:: OutlivesPredicate ( r1, r2) )
133
+ . to_predicate ( self . tcx ( ) ) ;
134
+ ( pred, span)
135
+ } ) )
136
+ }
137
+
138
+ hir:: WherePredicate :: EqPredicate ( ..) => {
139
+ // FIXME(#20041)
140
+ }
141
+ }
142
+ }
143
+ }
144
+
19
145
/// Sets `implicitly_sized` to true on `Bounds` if necessary
20
146
pub ( crate ) fn add_implicitly_sized (
21
147
& self ,
@@ -102,6 +228,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
102
228
ast_bounds : I ,
103
229
bounds : & mut Bounds < ' tcx > ,
104
230
bound_vars : & ' tcx ty:: List < ty:: BoundVariableKind > ,
231
+ binder_predicates : & ' tcx ty:: List < ty:: Clause < ' tcx > > ,
105
232
only_self_bounds : OnlySelfBounds ,
106
233
) {
107
234
for ast_bound in ast_bounds {
@@ -119,6 +246,10 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
119
246
}
120
247
hir:: TraitBoundModifier :: Maybe => continue ,
121
248
} ;
249
+
250
+ // TODO: Add in the binder preds from the poly trait ref.
251
+ let binder_predicates = binder_predicates;
252
+
122
253
let _ = self . instantiate_poly_trait_ref (
123
254
& poly_trait_ref. trait_ref ,
124
255
poly_trait_ref. span ,
@@ -127,6 +258,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
127
258
param_ty,
128
259
bounds,
129
260
false ,
261
+ binder_predicates,
130
262
only_self_bounds,
131
263
) ;
132
264
}
@@ -208,6 +340,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
208
340
} ) ,
209
341
& mut bounds,
210
342
ty:: List :: empty ( ) ,
343
+ ty:: List :: empty ( ) ,
211
344
only_self_bounds,
212
345
) ;
213
346
debug ! ( ?bounds) ;
@@ -577,6 +710,8 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
577
710
ast_bounds. iter ( ) ,
578
711
bounds,
579
712
projection_ty. bound_vars ( ) ,
713
+ // TODO: This is wrong, should take preds from binder
714
+ ty:: List :: empty ( ) ,
580
715
only_self_bounds,
581
716
) ;
582
717
}
0 commit comments