Skip to content

Commit 47f78a2

Browse files
committed
try to evaluate in try_unify
1 parent d8e5647 commit 47f78a2

File tree

4 files changed

+66
-35
lines changed

4 files changed

+66
-35
lines changed

compiler/rustc_infer/src/infer/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -691,11 +691,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
691691
&self,
692692
a: ty::Unevaluated<'tcx, ()>,
693693
b: ty::Unevaluated<'tcx, ()>,
694+
param_env: ty::ParamEnv<'tcx>,
694695
) -> bool {
695696
let canonical = self.canonicalize_query((a, b), &mut OriginalQueryValues::default());
696697
debug!("canonical consts: {:?}", &canonical.value);
697698

698-
self.tcx.try_unify_abstract_consts(canonical.value)
699+
self.tcx.try_unify_abstract_consts(param_env.and(canonical.value))
699700
}
700701

701702
pub fn is_in_snapshot(&self) -> bool {

compiler/rustc_middle/src/query/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -329,12 +329,12 @@ rustc_queries! {
329329
}
330330
}
331331

332-
query try_unify_abstract_consts(key: (
333-
ty::Unevaluated<'tcx, ()>, ty::Unevaluated<'tcx, ()>
334-
)) -> bool {
332+
query try_unify_abstract_consts(key:
333+
ty::ParamEnvAnd<'tcx, (ty::Unevaluated<'tcx, ()>, ty::Unevaluated<'tcx, ()>
334+
)>) -> bool {
335335
desc {
336336
|tcx| "trying to unify the generic constants {} and {}",
337-
tcx.def_path_str(key.0.def.did), tcx.def_path_str(key.1.def.did)
337+
tcx.def_path_str(key.value.0.def.did), tcx.def_path_str(key.value.1.def.did)
338338
}
339339
}
340340

compiler/rustc_middle/src/ty/relate.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -585,7 +585,7 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
585585
(ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu))
586586
if tcx.features().generic_const_exprs =>
587587
{
588-
tcx.try_unify_abstract_consts((au.shrink(), bu.shrink()))
588+
tcx.try_unify_abstract_consts(relation.param_env().and((au.shrink(), bu.shrink())))
589589
}
590590

591591
// While this is slightly incorrect, it shouldn't matter for `min_const_generics`

compiler/rustc_trait_selection/src/traits/const_evaluatable.rs

Lines changed: 59 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,13 @@ use std::iter;
2828
use std::ops::ControlFlow;
2929

3030
/// Check if a given constant can be evaluated.
31+
#[instrument(skip(infcx), level = "debug")]
3132
pub 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")]
188189
fn 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>(
570572
pub(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")]
623647
pub(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

Comments
 (0)