about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBastian Kauschke <bastian_kauschke@hotmail.de>2020-09-10 18:48:18 +0200
committerBastian Kauschke <bastian_kauschke@hotmail.de>2020-09-18 17:11:34 +0200
commitc3a772f55f2263cd2f2709f2bb187f59a8b4a673 (patch)
tree11e0a450b865cde2c2cbe092a279d36b3f7d0982
parentd327fa112b8ca56e8c310a8ec9bf458909beacfe (diff)
downloadrust-c3a772f55f2263cd2f2709f2bb187f59a8b4a673.tar.gz
rust-c3a772f55f2263cd2f2709f2bb187f59a8b4a673.zip
use abstract consts when unifying ConstKind::Unevaluated
-rw-r--r--compiler/rustc_middle/src/query/mod.rs10
-rw-r--r--compiler/rustc_middle/src/ty/query/keys.rs16
-rw-r--r--compiler/rustc_middle/src/ty/relate.rs15
-rw-r--r--compiler/rustc_trait_selection/src/traits/const_evaluatable.rs22
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs19
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs1
-rw-r--r--src/test/ui/const-generics/const_evaluatable_checked/simple.min.stderr16
-rw-r--r--src/test/ui/const-generics/const_evaluatable_checked/simple.rs7
8 files changed, 96 insertions, 10 deletions
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 41b8bb60ef5..44d906dada5 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -263,6 +263,16 @@ rustc_queries! {
             }
         }
 
+        query try_unify_abstract_consts(key: (
+            (ty::WithOptConstParam<DefId>, SubstsRef<'tcx>),
+            (ty::WithOptConstParam<DefId>, SubstsRef<'tcx>)
+        )) -> bool {
+            desc {
+                |tcx| "trying to unify the generic constants {} and {}",
+                tcx.def_path_str(key.0.0.did), tcx.def_path_str(key.1.0.did)
+            }
+        }
+
         query mir_drops_elaborated_and_const_checked(
             key: ty::WithOptConstParam<LocalDefId>
         ) -> &'tcx Steal<mir::Body<'tcx>> {
diff --git a/compiler/rustc_middle/src/ty/query/keys.rs b/compiler/rustc_middle/src/ty/query/keys.rs
index 3f7a20bba2b..a005990264c 100644
--- a/compiler/rustc_middle/src/ty/query/keys.rs
+++ b/compiler/rustc_middle/src/ty/query/keys.rs
@@ -193,6 +193,22 @@ impl<'tcx> Key for (DefId, SubstsRef<'tcx>) {
     }
 }
 
+impl<'tcx> Key
+    for (
+        (ty::WithOptConstParam<DefId>, SubstsRef<'tcx>),
+        (ty::WithOptConstParam<DefId>, SubstsRef<'tcx>),
+    )
+{
+    type CacheSelector = DefaultCacheSelector;
+
+    fn query_crate(&self) -> CrateNum {
+        (self.0).0.did.krate
+    }
+    fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
+        (self.0).0.did.default_span(tcx)
+    }
+}
+
 impl<'tcx> Key for (LocalDefId, DefId, SubstsRef<'tcx>) {
     type CacheSelector = DefaultCacheSelector;
 
diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs
index 7d3634a75b0..c4df0bba726 100644
--- a/compiler/rustc_middle/src/ty/relate.rs
+++ b/compiler/rustc_middle/src/ty/relate.rs
@@ -576,7 +576,20 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
             new_val.map(ty::ConstKind::Value)
         }
 
-        // FIXME(const_generics): this is wrong, as it is a projection
+        (
+            ty::ConstKind::Unevaluated(a_def, a_substs, None),
+            ty::ConstKind::Unevaluated(b_def, b_substs, None),
+        ) if tcx.features().const_evaluatable_checked => {
+            if tcx.try_unify_abstract_consts(((a_def, a_substs), (b_def, b_substs))) {
+                Ok(a.val)
+            } else {
+                Err(TypeError::ConstMismatch(expected_found(relation, a, b)))
+            }
+        }
+
+        // While this is slightly incorrect, it shouldn't matter for `min_const_generics`
+        // and is the better alternative to waiting until `const_evaluatable_checked` can
+        // be stabilized.
         (
             ty::ConstKind::Unevaluated(a_def, a_substs, a_promoted),
             ty::ConstKind::Unevaluated(b_def, b_substs, b_promoted),
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
index 9d74de44d17..e14af1a27ef 100644
--- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
+++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
@@ -269,7 +269,27 @@ pub(super) fn mir_abstract_const<'tcx>(
     }
 }
 
-pub fn try_unify<'tcx>(tcx: TyCtxt<'tcx>, a: AbstractConst<'tcx>, b: AbstractConst<'tcx>) -> bool {
+pub(super) fn try_unify_abstract_consts<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    ((a, a_substs), (b, b_substs)): (
+        (ty::WithOptConstParam<DefId>, SubstsRef<'tcx>),
+        (ty::WithOptConstParam<DefId>, SubstsRef<'tcx>),
+    ),
+) -> bool {
+    if let Some(a) = AbstractConst::new(tcx, a, a_substs) {
+        if let Some(b) = AbstractConst::new(tcx, b, b_substs) {
+            return try_unify(tcx, a, b);
+        }
+    }
+
+    false
+}
+
+pub(super) fn try_unify<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    a: AbstractConst<'tcx>,
+    b: AbstractConst<'tcx>,
+) -> bool {
     match (a.root(), b.root()) {
         (Node::Leaf(a_ct), Node::Leaf(b_ct)) => {
             let a_ct = a_ct.subst(tcx, a.substs);
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index 1dd50d69a21..5b4314598de 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -476,6 +476,25 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
 
                 ty::PredicateAtom::ConstEquate(c1, c2) => {
                     debug!("equating consts: c1={:?} c2={:?}", c1, c2);
+                    if self.selcx.tcx().features().const_evaluatable_checked {
+                        // FIXME: we probably should only try to unify abstract constants
+                        // if the constants depend on generic parameters.
+                        //
+                        // Let's just see where this breaks :shrug:
+                        if let (
+                            ty::ConstKind::Unevaluated(a_def, a_substs, None),
+                            ty::ConstKind::Unevaluated(b_def, b_substs, None),
+                        ) = (c1.val, c2.val)
+                        {
+                            if self
+                                .selcx
+                                .tcx()
+                                .try_unify_abstract_consts(((a_def, a_substs), (b_def, b_substs)))
+                            {
+                                return ProcessResult::Changed(vec![]);
+                            }
+                        }
+                    }
 
                     let stalled_on = &mut pending_obligation.stalled_on;
 
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 2f0b66ec8c9..098336453bc 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -566,6 +566,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
                 ty::WithOptConstParam { did, const_param_did: Some(param_did) },
             )
         },
+        try_unify_abstract_consts: const_evaluatable::try_unify_abstract_consts,
         ..*providers
     };
 }
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/simple.min.stderr b/src/test/ui/const-generics/const_evaluatable_checked/simple.min.stderr
index da8ccdaee41..3cac604a7b3 100644
--- a/src/test/ui/const-generics/const_evaluatable_checked/simple.min.stderr
+++ b/src/test/ui/const-generics/const_evaluatable_checked/simple.min.stderr
@@ -1,10 +1,18 @@
 error: generic parameters must not be used inside of non trivial constant values
-  --> $DIR/simple.rs:8:33
+  --> $DIR/simple.rs:8:53
    |
-LL | type Arr<const N: usize> = [u8; N - 1];
-   |                                 ^ non-trivial anonymous constants must not depend on the parameter `N`
+LL | fn test<const N: usize>() -> [u8; N - 1] where [u8; N - 1]: Default {
+   |                                                     ^ non-trivial anonymous constants must not depend on the parameter `N`
    |
    = help: it is currently only allowed to use either `N` or `{ N }` as generic constants
 
-error: aborting due to previous error
+error: generic parameters must not be used inside of non trivial constant values
+  --> $DIR/simple.rs:8:35
+   |
+LL | fn test<const N: usize>() -> [u8; N - 1] where [u8; N - 1]: Default {
+   |                                   ^ non-trivial anonymous constants must not depend on the parameter `N`
+   |
+   = help: it is currently only allowed to use either `N` or `{ N }` as generic constants
+
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/const-generics/const_evaluatable_checked/simple.rs b/src/test/ui/const-generics/const_evaluatable_checked/simple.rs
index 27dc6b10320..dcf0071cb29 100644
--- a/src/test/ui/const-generics/const_evaluatable_checked/simple.rs
+++ b/src/test/ui/const-generics/const_evaluatable_checked/simple.rs
@@ -5,10 +5,9 @@
 #![feature(const_evaluatable_checked)]
 #![allow(incomplete_features)]
 
-type Arr<const N: usize> = [u8; N - 1];
-//[min]~^ ERROR generic parameters must not be used inside of non trivial constant values
-
-fn test<const N: usize>() -> Arr<N> where Arr<N>: Default {
+fn test<const N: usize>() -> [u8; N - 1] where [u8; N - 1]: Default {
+    //[min]~^ ERROR generic parameters
+    //[min]~| ERROR generic parameters
     Default::default()
 }