@@ -9,8 +9,8 @@ use rustc_hir::def::DefKind;
99use rustc_hir:: def_id:: { DefId , LocalDefId } ;
1010use rustc_hir:: intravisit:: { self , Visitor } ;
1111use rustc_middle:: ty:: subst:: InternalSubsts ;
12- use rustc_middle:: ty:: ToPredicate ;
1312use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
13+ use rustc_middle:: ty:: { GenericPredicates , ToPredicate } ;
1414use rustc_span:: symbol:: { sym, Ident } ;
1515use rustc_span:: { Span , DUMMY_SP } ;
1616
@@ -151,7 +151,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
151151 trace ! ( ?generics) ;
152152
153153 // 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.
155156 for param in ast_generics. params {
156157 match param. kind {
157158 // We already dealt with early bound lifetimes above.
@@ -175,7 +176,19 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
175176 trace ! ( ?predicates) ;
176177 }
177178 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+
179192 index += 1 ;
180193 }
181194 }
@@ -439,7 +452,9 @@ pub(super) fn explicit_predicates_of<'tcx>(
439452 let hir_id = tcx. hir ( ) . local_def_id_to_hir_id ( def_id. expect_local ( ) ) ;
440453 let parent_def_id = tcx. hir ( ) . get_parent_item ( hir_id) ;
441454
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+ {
443458 // In `generics_of` we set the generics' parent to be our parent's parent which means that
444459 // we lose out on the predicates of our actual parent if we dont return those predicates here.
445460 // (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>(
452467 //
453468 // In the above code we want the anon const to have predicates in its param env for `T: Trait`
454469 // 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+ } ;
456503 }
457504
458505 let parent_def_kind = tcx. def_kind ( parent_def_id) ;
0 commit comments