@@ -28,13 +28,13 @@ use std::iter;
28
28
use std:: ops:: ControlFlow ;
29
29
30
30
/// Check if a given constant can be evaluated.
31
+ #[ instrument( skip( infcx) , level = "debug" ) ]
31
32
pub fn is_const_evaluatable < ' cx , ' tcx > (
32
33
infcx : & InferCtxt < ' cx , ' tcx > ,
33
34
uv : ty:: Unevaluated < ' tcx , ( ) > ,
34
35
param_env : ty:: ParamEnv < ' tcx > ,
35
36
span : Span ,
36
37
) -> Result < ( ) , NotConstEvaluatable > {
37
- debug ! ( "is_const_evaluatable({:?})" , uv) ;
38
38
let tcx = infcx. tcx ;
39
39
40
40
if tcx. features ( ) . generic_const_exprs {
@@ -185,6 +185,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
185
185
}
186
186
}
187
187
188
+ #[ instrument( skip( tcx) , level = "debug" ) ]
188
189
fn satisfied_from_param_env < ' tcx > (
189
190
tcx : TyCtxt < ' tcx > ,
190
191
ct : AbstractConst < ' tcx > ,
@@ -197,11 +198,12 @@ fn satisfied_from_param_env<'tcx>(
197
198
// Try to unify with each subtree in the AbstractConst to allow for
198
199
// `N + 1` being const evaluatable even if theres only a `ConstEvaluatable`
199
200
// 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 ) {
202
203
true => ControlFlow :: BREAK ,
203
204
false => ControlFlow :: CONTINUE ,
204
- } ) ;
205
+ }
206
+ } ) ;
205
207
206
208
if let ControlFlow :: Break ( ( ) ) = result {
207
209
debug ! ( "is_const_evaluatable: abstract_const ~~> ok" ) ;
@@ -570,11 +572,12 @@ pub(super) fn thir_abstract_const<'tcx>(
570
572
pub ( super ) fn try_unify_abstract_consts < ' tcx > (
571
573
tcx : TyCtxt < ' tcx > ,
572
574
( a, b) : ( ty:: Unevaluated < ' tcx , ( ) > , ty:: Unevaluated < ' tcx , ( ) > ) ,
575
+ param_env : ty:: ParamEnv < ' tcx > ,
573
576
) -> bool {
574
577
( || {
575
578
if let Some ( a) = AbstractConst :: new ( tcx, a) ? {
576
579
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 ) ) ;
578
581
}
579
582
}
580
583
@@ -619,32 +622,59 @@ where
619
622
recurse ( tcx, ct, & mut f)
620
623
}
621
624
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
+
622
645
/// Tries to unify two abstract constants using structural equality.
646
+ #[ instrument( skip( tcx) , level = "debug" ) ]
623
647
pub ( super ) fn try_unify < ' tcx > (
624
648
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 > ,
627
652
) -> 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 ;
636
657
}
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 ;
643
664
}
644
- }
665
+ } ;
645
666
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) {
647
672
( 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
+
648
678
if a_ct. ty ( ) != b_ct. ty ( ) {
649
679
return false ;
650
680
}
@@ -678,23 +708,23 @@ pub(super) fn try_unify<'tcx>(
678
708
}
679
709
}
680
710
( 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 )
683
713
}
684
714
( 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 )
686
716
}
687
717
( Node :: FunctionCall ( a_f, a_args) , Node :: FunctionCall ( b_f, b_args) )
688
718
if a_args. len ( ) == b_args. len ( ) =>
689
719
{
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 )
691
721
&& 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 ) )
693
723
}
694
724
( Node :: Cast ( a_kind, a_operand, a_ty) , Node :: Cast ( b_kind, b_operand, b_ty) )
695
725
if ( a_ty == b_ty) && ( a_kind == b_kind) =>
696
726
{
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 )
698
728
}
699
729
// use this over `_ => false` to make adding variants to `Node` less error prone
700
730
( Node :: Cast ( ..) , _)
0 commit comments