@@ -9,8 +9,8 @@ use rustc_hir::def::DefKind;
9
9
use rustc_hir:: def_id:: { DefId , LocalDefId } ;
10
10
use rustc_hir:: intravisit:: { self , Visitor } ;
11
11
use rustc_middle:: ty:: subst:: InternalSubsts ;
12
- use rustc_middle:: ty:: ToPredicate ;
13
12
use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
13
+ use rustc_middle:: ty:: { GenericPredicates , ToPredicate } ;
14
14
use rustc_span:: symbol:: { sym, Ident } ;
15
15
use rustc_span:: { Span , DUMMY_SP } ;
16
16
@@ -151,7 +151,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
151
151
trace ! ( ?generics) ;
152
152
153
153
// Collect the predicates that were written inline by the user on each
154
- // type parameter (e.g., `<T: Foo>`).
154
+ // type parameter (e.g., `<T: Foo>`). Also add `ConstArgHasType` predicates
155
+ // for each const parameter.
155
156
for param in ast_generics. params {
156
157
match param. kind {
157
158
// We already dealt with early bound lifetimes above.
@@ -175,7 +176,19 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
175
176
trace ! ( ?predicates) ;
176
177
}
177
178
GenericParamKind :: Const { .. } => {
178
- // Bounds on const parameters are currently not possible.
179
+ let name = param. name . ident ( ) . name ;
180
+ let param_const = ty:: ParamConst :: new ( index, name) ;
181
+
182
+ let ct_ty = tcx. type_of ( param. def_id . to_def_id ( ) ) . subst_identity ( ) ;
183
+
184
+ let ct = tcx. mk_const ( param_const, ct_ty) ;
185
+
186
+ let predicate = ty:: Binder :: dummy ( ty:: PredicateKind :: Clause (
187
+ ty:: Clause :: ConstArgHasType ( ct, ct_ty) ,
188
+ ) )
189
+ . to_predicate ( tcx) ;
190
+ predicates. insert ( ( predicate, param. span ) ) ;
191
+
179
192
index += 1 ;
180
193
}
181
194
}
@@ -439,7 +452,9 @@ pub(super) fn explicit_predicates_of<'tcx>(
439
452
let hir_id = tcx. hir ( ) . local_def_id_to_hir_id ( def_id. expect_local ( ) ) ;
440
453
let parent_def_id = tcx. hir ( ) . get_parent_item ( hir_id) ;
441
454
442
- if tcx. hir ( ) . opt_const_param_default_param_def_id ( hir_id) . is_some ( ) {
455
+ if let Some ( defaulted_param_def_id) =
456
+ tcx. hir ( ) . opt_const_param_default_param_def_id ( hir_id)
457
+ {
443
458
// In `generics_of` we set the generics' parent to be our parent's parent which means that
444
459
// we lose out on the predicates of our actual parent if we dont return those predicates here.
445
460
// (See comment in `generics_of` for more information on why the parent shenanigans is necessary)
@@ -452,7 +467,39 @@ pub(super) fn explicit_predicates_of<'tcx>(
452
467
//
453
468
// In the above code we want the anon const to have predicates in its param env for `T: Trait`
454
469
// and we would be calling `explicit_predicates_of(Foo)` here
455
- return tcx. explicit_predicates_of ( parent_def_id) ;
470
+ let parent_preds = tcx. explicit_predicates_of ( parent_def_id) ;
471
+
472
+ // If we dont filter out `ConstArgHasType` predicates then every single defaulted const parameter
473
+ // will ICE because of #106994. FIXME(generic_const_exprs): remove this when a more general solution
474
+ // to #106994 is implemented.
475
+ let filtered_predicates = parent_preds
476
+ . predicates
477
+ . into_iter ( )
478
+ . filter ( |( pred, _) | {
479
+ if let ty:: PredicateKind :: Clause ( ty:: Clause :: ConstArgHasType ( ct, _) ) =
480
+ pred. kind ( ) . skip_binder ( )
481
+ {
482
+ match ct. kind ( ) {
483
+ ty:: ConstKind :: Param ( param_const) => {
484
+ let defaulted_param_idx = tcx
485
+ . generics_of ( parent_def_id)
486
+ . param_def_id_to_index [ & defaulted_param_def_id. to_def_id ( ) ] ;
487
+ param_const. index < defaulted_param_idx
488
+ }
489
+ _ => bug ! (
490
+ "`ConstArgHasType` in `predicates_of`\
491
+ that isn't a `Param` const"
492
+ ) ,
493
+ }
494
+ } else {
495
+ true
496
+ }
497
+ } )
498
+ . cloned ( ) ;
499
+ return GenericPredicates {
500
+ parent : parent_preds. parent ,
501
+ predicates : { tcx. arena . alloc_from_iter ( filtered_predicates) } ,
502
+ } ;
456
503
}
457
504
458
505
let parent_def_kind = tcx. def_kind ( parent_def_id) ;
0 commit comments