@@ -21,7 +21,7 @@ use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue};
2121use rustc_middle:: infer:: unify_key:: { ConstVariableOrigin , ConstVariableOriginKind , ToType } ;
2222use rustc_middle:: mir:: interpret:: { ErrorHandled , EvalToValTreeResult } ;
2323use rustc_middle:: traits:: select;
24- use rustc_middle:: ty:: abstract_const:: AbstractConst ;
24+ use rustc_middle:: ty:: abstract_const:: { AbstractConst , FailureKind } ;
2525use rustc_middle:: ty:: error:: { ExpectedFound , TypeError } ;
2626use rustc_middle:: ty:: fold:: { TypeFoldable , TypeFolder , TypeSuperFoldable } ;
2727use rustc_middle:: ty:: relate:: RelateResult ;
@@ -1675,7 +1675,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
16751675 #[ instrument( skip( self ) , level = "debug" ) ]
16761676 pub fn const_eval_resolve (
16771677 & self ,
1678- param_env : ty:: ParamEnv < ' tcx > ,
1678+ mut param_env : ty:: ParamEnv < ' tcx > ,
16791679 unevaluated : ty:: Unevaluated < ' tcx > ,
16801680 span : Option < Span > ,
16811681 ) -> EvalToValTreeResult < ' tcx > {
@@ -1686,10 +1686,19 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
16861686 // variables
16871687 if substs. has_infer_types_or_consts ( ) {
16881688 let ac = AbstractConst :: new ( self . tcx , unevaluated. shrink ( ) ) ;
1689- if let Ok ( None ) = ac {
1690- substs = InternalSubsts :: identity_for_item ( self . tcx , unevaluated. def . did ) ;
1691- } else {
1692- return Err ( ErrorHandled :: TooGeneric ) ;
1689+ match ac {
1690+ Ok ( None ) => {
1691+ substs = InternalSubsts :: identity_for_item ( self . tcx , unevaluated. def . did ) ;
1692+ param_env = self . tcx . param_env ( unevaluated. def . did ) ;
1693+ }
1694+ Ok ( Some ( ct) ) => {
1695+ if ct. unify_failure_kind ( self . tcx ) == FailureKind :: Concrete {
1696+ substs = replace_param_and_infer_substs_with_placeholder ( self . tcx , substs) ;
1697+ } else {
1698+ return Err ( ErrorHandled :: TooGeneric ) ;
1699+ }
1700+ }
1701+ Err ( guar) => return Err ( ErrorHandled :: Reported ( guar) ) ,
16931702 }
16941703 }
16951704
@@ -2000,3 +2009,43 @@ impl<'tcx> fmt::Debug for RegionObligation<'tcx> {
20002009 )
20012010 }
20022011}
2012+
2013+ /// Replaces substs that reference param or infer variables with suitable
2014+ /// placeholders. This function is meant to remove these param and infer
2015+ /// substs when they're not actually needed to evaluate a constant.
2016+ fn replace_param_and_infer_substs_with_placeholder < ' tcx > (
2017+ tcx : TyCtxt < ' tcx > ,
2018+ substs : SubstsRef < ' tcx > ,
2019+ ) -> SubstsRef < ' tcx > {
2020+ tcx. mk_substs ( substs. iter ( ) . enumerate ( ) . map ( |( idx, arg) | {
2021+ match arg. unpack ( ) {
2022+ GenericArgKind :: Type ( _)
2023+ if arg. has_param_types_or_consts ( ) || arg. has_infer_types_or_consts ( ) =>
2024+ {
2025+ tcx. mk_ty ( ty:: Placeholder ( ty:: PlaceholderType {
2026+ universe : ty:: UniverseIndex :: ROOT ,
2027+ name : ty:: BoundVar :: from_usize ( idx) ,
2028+ } ) )
2029+ . into ( )
2030+ }
2031+ GenericArgKind :: Const ( ct)
2032+ if ct. has_infer_types_or_consts ( ) || ct. has_param_types_or_consts ( ) =>
2033+ {
2034+ let ty = ct. ty ( ) ;
2035+ // If the type references param or infer, replace that too...
2036+ if ty. has_param_types_or_consts ( ) || ty. has_infer_types_or_consts ( ) {
2037+ bug ! ( "const `{ct}`'s type should not reference params or types" ) ;
2038+ }
2039+ tcx. mk_const ( ty:: ConstS {
2040+ ty,
2041+ kind : ty:: ConstKind :: Placeholder ( ty:: PlaceholderConst {
2042+ universe : ty:: UniverseIndex :: ROOT ,
2043+ name : ty:: BoundConst { ty, var : ty:: BoundVar :: from_usize ( idx) } ,
2044+ } ) ,
2045+ } )
2046+ . into ( )
2047+ }
2048+ _ => arg,
2049+ }
2050+ } ) )
2051+ }
0 commit comments