about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorYuki Okushi <huyuumi.dev@gmail.com>2021-01-28 15:09:15 +0900
committerGitHub <noreply@github.com>2021-01-28 15:09:15 +0900
commitf183e5f04c0576ec4dedefe3c7caaafaade3f267 (patch)
treef5528bad7e5c62449f93b3a8a270244dfb9c209a /compiler
parentb8eac50ff59fb67ee3338f0e90b9c21058c96a1a (diff)
parentab421a176240a658ed02e8eee70b7ea211c087e3 (diff)
downloadrust-f183e5f04c0576ec4dedefe3c7caaafaade3f267.tar.gz
rust-f183e5f04c0576ec4dedefe3c7caaafaade3f267.zip
Rollup merge of #81426 - BoxyUwU:boxychangesv2, r=oli-obk
const_evaluatable: expand abstract consts in try_unify

See this [zulip topic](https://rust-lang.zulipchat.com/#narrow/stream/260443-project-const-generics/topic/combining.20const.20bounds) for more info

cc ```@lcnr```
r? ```@oli-obk```
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_trait_selection/src/traits/const_evaluatable.rs26
1 files changed, 22 insertions, 4 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
index ad229e03b0b..b587ed6487e 100644
--- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
+++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
@@ -609,9 +609,29 @@ where
 /// Tries to unify two abstract constants using structural equality.
 pub(super) fn try_unify<'tcx>(
     tcx: TyCtxt<'tcx>,
-    a: AbstractConst<'tcx>,
-    b: AbstractConst<'tcx>,
+    mut a: AbstractConst<'tcx>,
+    mut b: AbstractConst<'tcx>,
 ) -> bool {
+    // We substitute generics repeatedly to allow AbstractConsts to unify where a
+    // ConstKind::Unevalated could be turned into an AbstractConst that would unify e.g.
+    // Param(N) should unify with Param(T), substs: [Unevaluated("T2", [Unevaluated("T3", [Param(N)])])]
+    while let Node::Leaf(a_ct) = a.root() {
+        let a_ct = a_ct.subst(tcx, a.substs);
+        match AbstractConst::from_const(tcx, a_ct) {
+            Ok(Some(a_act)) => a = a_act,
+            Ok(None) => break,
+            Err(_) => return true,
+        }
+    }
+    while let Node::Leaf(b_ct) = b.root() {
+        let b_ct = b_ct.subst(tcx, b.substs);
+        match AbstractConst::from_const(tcx, b_ct) {
+            Ok(Some(b_act)) => b = b_act,
+            Ok(None) => break,
+            Err(_) => return true,
+        }
+    }
+
     match (a.root(), b.root()) {
         (Node::Leaf(a_ct), Node::Leaf(b_ct)) => {
             let a_ct = a_ct.subst(tcx, a.substs);
@@ -632,8 +652,6 @@ pub(super) fn try_unify<'tcx>(
                 // we do not want to use `assert_eq!(a(), b())` to infer that `N` and `M` have to be `1`. This
                 // means that we only allow inference variables if they are equal.
                 (ty::ConstKind::Infer(a_val), ty::ConstKind::Infer(b_val)) => a_val == b_val,
-                // We may want to instead recurse into unevaluated constants here. That may require some
-                // care to prevent infinite recursion, so let's just ignore this for now.
                 (
                     ty::ConstKind::Unevaluated(a_def, a_substs, None),
                     ty::ConstKind::Unevaluated(b_def, b_substs, None),