@@ -28,13 +28,13 @@ use std::iter;
2828use std:: ops:: ControlFlow ;
2929
3030/// Check if a given constant can be evaluated.
31+ #[ instrument( skip( infcx) , level = "debug" ) ]
3132pub fn is_const_evaluatable < ' cx , ' tcx > (
3233 infcx : & InferCtxt < ' cx , ' tcx > ,
3334 uv : ty:: Unevaluated < ' tcx , ( ) > ,
3435 param_env : ty:: ParamEnv < ' tcx > ,
3536 span : Span ,
3637) -> Result < ( ) , NotConstEvaluatable > {
37- debug ! ( "is_const_evaluatable({:?})" , uv) ;
3838 let tcx = infcx. tcx ;
3939
4040 if tcx. features ( ) . generic_const_exprs {
@@ -185,6 +185,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
185185 }
186186}
187187
188+ #[ instrument( skip( tcx) , level = "debug" ) ]
188189fn satisfied_from_param_env < ' tcx > (
189190 tcx : TyCtxt < ' tcx > ,
190191 ct : AbstractConst < ' tcx > ,
@@ -197,11 +198,12 @@ fn satisfied_from_param_env<'tcx>(
197198 // Try to unify with each subtree in the AbstractConst to allow for
198199 // `N + 1` being const evaluatable even if theres only a `ConstEvaluatable`
199200 // predicate for `(N + 1) * 2`
200- let result =
201- walk_abstract_const ( tcx , b_ct , |b_ct| match try_unify ( tcx, ct, b_ct) {
201+ let result = walk_abstract_const ( tcx , b_ct , |b_ct| {
202+ match try_unify ( tcx, ct, b_ct, param_env ) {
202203 true => ControlFlow :: BREAK ,
203204 false => ControlFlow :: CONTINUE ,
204- } ) ;
205+ }
206+ } ) ;
205207
206208 if let ControlFlow :: Break ( ( ) ) = result {
207209 debug ! ( "is_const_evaluatable: abstract_const ~~> ok" ) ;
@@ -570,11 +572,12 @@ pub(super) fn thir_abstract_const<'tcx>(
570572pub ( super ) fn try_unify_abstract_consts < ' tcx > (
571573 tcx : TyCtxt < ' tcx > ,
572574 ( a, b) : ( ty:: Unevaluated < ' tcx , ( ) > , ty:: Unevaluated < ' tcx , ( ) > ) ,
575+ param_env : ty:: ParamEnv < ' tcx > ,
573576) -> bool {
574577 ( || {
575578 if let Some ( a) = AbstractConst :: new ( tcx, a) ? {
576579 if let Some ( b) = AbstractConst :: new ( tcx, b) ? {
577- return Ok ( try_unify ( tcx, a, b) ) ;
580+ return Ok ( try_unify ( tcx, a, b, param_env ) ) ;
578581 }
579582 }
580583
@@ -619,32 +622,59 @@ where
619622 recurse ( tcx, ct, & mut f)
620623}
621624
625+ // Substitutes generics repeatedly to allow AbstractConsts to unify where a
626+ // ConstKind::Unevalated could be turned into an AbstractConst that would unify e.g.
627+ // Param(N) should unify with Param(T), substs: [Unevaluated("T2", [Unevaluated("T3", [Param(N)])])]
628+ #[ inline]
629+ #[ instrument( skip( tcx) , level = "debug" ) ]
630+ fn try_replace_substs_in_root < ' tcx > (
631+ tcx : TyCtxt < ' tcx > ,
632+ mut abstr_const : AbstractConst < ' tcx > ,
633+ ) -> Option < AbstractConst < ' tcx > > {
634+ while let Node :: Leaf ( ct) = abstr_const. root ( tcx) {
635+ match AbstractConst :: from_const ( tcx, ct) {
636+ Ok ( Some ( act) ) => abstr_const = act,
637+ Ok ( None ) => break ,
638+ Err ( _) => return None ,
639+ }
640+ }
641+
642+ Some ( abstr_const)
643+ }
644+
622645/// Tries to unify two abstract constants using structural equality.
646+ #[ instrument( skip( tcx) , level = "debug" ) ]
623647pub ( super ) fn try_unify < ' tcx > (
624648 tcx : TyCtxt < ' tcx > ,
625- mut a : AbstractConst < ' tcx > ,
626- mut b : AbstractConst < ' tcx > ,
649+ a : AbstractConst < ' tcx > ,
650+ b : AbstractConst < ' tcx > ,
651+ param_env : ty:: ParamEnv < ' tcx > ,
627652) -> bool {
628- // We substitute generics repeatedly to allow AbstractConsts to unify where a
629- // ConstKind::Unevalated could be turned into an AbstractConst that would unify e.g.
630- // Param(N) should unify with Param(T), substs: [Unevaluated("T2", [Unevaluated("T3", [Param(N)])])]
631- while let Node :: Leaf ( a_ct) = a. root ( tcx) {
632- match AbstractConst :: from_const ( tcx, a_ct) {
633- Ok ( Some ( a_act) ) => a = a_act,
634- Ok ( None ) => break ,
635- Err ( _) => return true ,
653+ let a = match try_replace_substs_in_root ( tcx, a) {
654+ Some ( a) => a,
655+ None => {
656+ return true ;
636657 }
637- }
638- while let Node :: Leaf ( b_ct ) = b . root ( tcx ) {
639- match AbstractConst :: from_const ( tcx, b_ct ) {
640- Ok ( Some ( b_act ) ) => b = b_act ,
641- Ok ( None ) => break ,
642- Err ( _ ) => return true ,
658+ } ;
659+
660+ let b = match try_replace_substs_in_root ( tcx, b ) {
661+ Some ( b ) => b,
662+ None => {
663+ return true ;
643664 }
644- }
665+ } ;
645666
646- match ( a. root ( tcx) , b. root ( tcx) ) {
667+ let a_root = a. root ( tcx) ;
668+ let b_root = b. root ( tcx) ;
669+ debug ! ( ?a_root, ?b_root) ;
670+
671+ match ( a_root, b_root) {
647672 ( Node :: Leaf ( a_ct) , Node :: Leaf ( b_ct) ) => {
673+ let a_ct = a_ct. eval ( tcx, param_env) ;
674+ debug ! ( "a_ct evaluated: {:?}" , a_ct) ;
675+ let b_ct = b_ct. eval ( tcx, param_env) ;
676+ debug ! ( "b_ct evaluated: {:?}" , b_ct) ;
677+
648678 if a_ct. ty ( ) != b_ct. ty ( ) {
649679 return false ;
650680 }
@@ -678,23 +708,23 @@ pub(super) fn try_unify<'tcx>(
678708 }
679709 }
680710 ( Node :: Binop ( a_op, al, ar) , Node :: Binop ( b_op, bl, br) ) if a_op == b_op => {
681- try_unify ( tcx, a. subtree ( al) , b. subtree ( bl) )
682- && try_unify ( tcx, a. subtree ( ar) , b. subtree ( br) )
711+ try_unify ( tcx, a. subtree ( al) , b. subtree ( bl) , param_env )
712+ && try_unify ( tcx, a. subtree ( ar) , b. subtree ( br) , param_env )
683713 }
684714 ( Node :: UnaryOp ( a_op, av) , Node :: UnaryOp ( b_op, bv) ) if a_op == b_op => {
685- try_unify ( tcx, a. subtree ( av) , b. subtree ( bv) )
715+ try_unify ( tcx, a. subtree ( av) , b. subtree ( bv) , param_env )
686716 }
687717 ( Node :: FunctionCall ( a_f, a_args) , Node :: FunctionCall ( b_f, b_args) )
688718 if a_args. len ( ) == b_args. len ( ) =>
689719 {
690- try_unify ( tcx, a. subtree ( a_f) , b. subtree ( b_f) )
720+ try_unify ( tcx, a. subtree ( a_f) , b. subtree ( b_f) , param_env )
691721 && iter:: zip ( a_args, b_args)
692- . all ( |( & an, & bn) | try_unify ( tcx, a. subtree ( an) , b. subtree ( bn) ) )
722+ . all ( |( & an, & bn) | try_unify ( tcx, a. subtree ( an) , b. subtree ( bn) , param_env ) )
693723 }
694724 ( Node :: Cast ( a_kind, a_operand, a_ty) , Node :: Cast ( b_kind, b_operand, b_ty) )
695725 if ( a_ty == b_ty) && ( a_kind == b_kind) =>
696726 {
697- try_unify ( tcx, a. subtree ( a_operand) , b. subtree ( b_operand) )
727+ try_unify ( tcx, a. subtree ( a_operand) , b. subtree ( b_operand) , param_env )
698728 }
699729 // use this over `_ => false` to make adding variants to `Node` less error prone
700730 ( Node :: Cast ( ..) , _)
0 commit comments