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,6 +16,132 @@ use crate::bounds::Bounds;
1616use crate :: errors;
1717
1818impl < ' 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+
19145 /// Sets `implicitly_sized` to true on `Bounds` if necessary
20146 pub ( crate ) fn add_implicitly_sized (
21147 & self ,
@@ -32,7 +158,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
32158 let mut search_bounds = |ast_bounds : & ' tcx [ hir:: GenericBound < ' tcx > ] | {
33159 for ab in ast_bounds {
34160 if let hir:: GenericBound :: Trait ( ptr, hir:: TraitBoundModifier :: Maybe ) = ab {
35- unbounds. push ( ptr)
161+ unbounds. push ( ptr) ;
36162 }
37163 }
38164 } ;
@@ -106,6 +232,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
106232 ast_bounds : I ,
107233 bounds : & mut Bounds < ' tcx > ,
108234 bound_vars : & ' tcx ty:: List < ty:: BoundVariableKind > ,
235+ binder_predicates : & ' tcx ty:: List < ty:: Clause < ' tcx > > ,
109236 only_self_bounds : OnlySelfBounds ,
110237 ) {
111238 for ast_bound in ast_bounds {
@@ -123,6 +250,10 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
123250 }
124251 hir:: TraitBoundModifier :: Maybe => continue ,
125252 } ;
253+
254+ // TODO: Add in the binder preds from the poly trait ref.
255+ let binder_predicates = binder_predicates;
256+
126257 let _ = self . instantiate_poly_trait_ref (
127258 & poly_trait_ref. trait_ref ,
128259 poly_trait_ref. span ,
@@ -131,6 +262,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
131262 param_ty,
132263 bounds,
133264 false ,
265+ binder_predicates,
134266 only_self_bounds,
135267 ) ;
136268 }
@@ -199,6 +331,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
199331 } ) ,
200332 & mut bounds,
201333 ty:: List :: empty ( ) ,
334+ ty:: List :: empty ( ) ,
202335 only_self_bounds,
203336 ) ;
204337 debug ! ( ?bounds) ;
@@ -503,6 +636,8 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
503636 ast_bounds. iter ( ) ,
504637 bounds,
505638 projection_ty. bound_vars ( ) ,
639+ // TODO: This is wrong, should take preds from binder
640+ ty:: List :: empty ( ) ,
506641 only_self_bounds,
507642 ) ;
508643 }
0 commit comments