1- use rustc_data_structures:: fx:: FxHashMap ;
1+ use rustc_data_structures:: fx:: { FxHashMap , FxIndexSet } ;
22use rustc_errors:: struct_span_err;
33use rustc_hir as hir;
44use rustc_hir:: def:: { DefKind , Res } ;
55use 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 } ;
77use rustc_span:: symbol:: Ident ;
88use rustc_span:: { ErrorGuaranteed , Span } ;
99use rustc_trait_selection:: traits;
@@ -16,23 +16,155 @@ use crate::bounds::Bounds;
1616use crate :: errors;
1717
1818impl < ' 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+
19151 /// Sets `implicitly_sized` to true on `Bounds` if necessary
20- pub ( crate ) fn add_implicitly_sized (
152+ pub ( crate ) fn add_implicitly_sized < ' hir > (
21153 & self ,
22154 bounds : & mut Bounds < ' tcx > ,
23155 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 > ] ) > ,
26158 span : Span ,
27159 ) {
28160 let tcx = self . tcx ( ) ;
29161
30162 // Try to find an unbound in bounds.
31163 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 > ] | {
33165 for ab in ast_bounds {
34166 if let hir:: GenericBound :: Trait ( ptr, hir:: TraitBoundModifier :: Maybe ) = ab {
35- unbounds. push ( ptr)
167+ unbounds. push ( ptr) ;
36168 }
37169 }
38170 } ;
@@ -106,6 +238,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
106238 ast_bounds : I ,
107239 bounds : & mut Bounds < ' tcx > ,
108240 bound_vars : & ' tcx ty:: List < ty:: BoundVariableKind > ,
241+ binder_predicates : & ' tcx ty:: List < ty:: Clause < ' tcx > > ,
109242 only_self_bounds : OnlySelfBounds ,
110243 ) {
111244 for ast_bound in ast_bounds {
@@ -123,6 +256,18 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
123256 }
124257 hir:: TraitBoundModifier :: Maybe => continue ,
125258 } ;
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+
126271 let _ = self . instantiate_poly_trait_ref (
127272 & poly_trait_ref. trait_ref ,
128273 poly_trait_ref. span ,
@@ -131,6 +276,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
131276 param_ty,
132277 bounds,
133278 false ,
279+ binder_predicates,
134280 only_self_bounds,
135281 ) ;
136282 }
@@ -199,6 +345,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
199345 } ) ,
200346 & mut bounds,
201347 ty:: List :: empty ( ) ,
348+ ty:: List :: empty ( ) ,
202349 only_self_bounds,
203350 ) ;
204351 debug ! ( ?bounds) ;
@@ -503,6 +650,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
503650 ast_bounds. iter ( ) ,
504651 bounds,
505652 projection_ty. bound_vars ( ) ,
653+ projection_ty. skip_binder_with_predicates ( ) . 1 ,
506654 only_self_bounds,
507655 ) ;
508656 }
0 commit comments