]> git.lizzy.rs Git - rust.git/commitdiff
use abstract consts when unifying ConstKind::Unevaluated
authorBastian Kauschke <bastian_kauschke@hotmail.de>
Thu, 10 Sep 2020 16:48:18 +0000 (18:48 +0200)
committerBastian Kauschke <bastian_kauschke@hotmail.de>
Fri, 18 Sep 2020 15:11:34 +0000 (17:11 +0200)
compiler/rustc_middle/src/query/mod.rs
compiler/rustc_middle/src/ty/query/keys.rs
compiler/rustc_middle/src/ty/relate.rs
compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
compiler/rustc_trait_selection/src/traits/fulfill.rs
compiler/rustc_trait_selection/src/traits/mod.rs
src/test/ui/const-generics/const_evaluatable_checked/simple.min.stderr
src/test/ui/const-generics/const_evaluatable_checked/simple.rs

index 41b8bb60ef5eaf6c28b2fb19b775b9484c10d063..44d906dada5f05b80974efec0767d407127edd8c 100644 (file)
@@ -263,6 +263,16 @@ fn describe_as_module(def_id: LocalDefId, tcx: TyCtxt<'_>) -> String {
             }
         }
 
+        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>> {
index 3f7a20bba2b9add597b91cf99d5dfea170c82f3e..a005990264cf11176443819ad7e8446804e15cb8 100644 (file)
@@ -193,6 +193,22 @@ fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
     }
 }
 
+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;
 
index 7d3634a75b0a7c9c41cddf26adaccf0493d0da41..c4df0bba726cb9d0929c355b7f0021e88061c0e0 100644 (file)
@@ -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),
index 9d74de44d171c8f1be90d671e81ce38df1675962..e14af1a27ef447be9449de339e0187eca81d59b3 100644 (file)
@@ -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);
index 1dd50d69a2195ce73e35bad9fd7ba4891d03a483..5b4314598deb5e43f7f3f6914895bd6b77df7d6d 100644 (file)
@@ -476,6 +476,25 @@ fn process_obligation(
 
                 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;
 
index 2f0b66ec8c941f1006b5f9bd4d910f06123c1b67..098336453bc6927d939e1553bf51b87f7e1d4aa6 100644 (file)
@@ -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
     };
 }
index da8ccdaee414661f554d939f2b7b8f895476a35b..3cac604a7b33a0d1e1b419c2ba87139c29884344 100644 (file)
@@ -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
 
index 27dc6b103200dc696517156b828103735d1bca33..dcf0071cb29b6eb5898367e390d3200939075243 100644 (file)
@@ -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()
 }