提交 c3a772f5 编写于 作者: B Bastian Kauschke

use abstract consts when unifying ConstKind::Unevaluated

上级 d327fa11
...@@ -263,6 +263,16 @@ fn describe_as_module(def_id: LocalDefId, tcx: TyCtxt<'_>) -> String { ...@@ -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( query mir_drops_elaborated_and_const_checked(
key: ty::WithOptConstParam<LocalDefId> key: ty::WithOptConstParam<LocalDefId>
) -> &'tcx Steal<mir::Body<'tcx>> { ) -> &'tcx Steal<mir::Body<'tcx>> {
......
...@@ -193,6 +193,22 @@ fn default_span(&self, tcx: TyCtxt<'_>) -> Span { ...@@ -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>) { impl<'tcx> Key for (LocalDefId, DefId, SubstsRef<'tcx>) {
type CacheSelector = DefaultCacheSelector; type CacheSelector = DefaultCacheSelector;
......
...@@ -576,7 +576,20 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>( ...@@ -576,7 +576,20 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
new_val.map(ty::ConstKind::Value) 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(a_def, a_substs, a_promoted),
ty::ConstKind::Unevaluated(b_def, b_substs, b_promoted), ty::ConstKind::Unevaluated(b_def, b_substs, b_promoted),
......
...@@ -269,7 +269,27 @@ pub(super) fn mir_abstract_const<'tcx>( ...@@ -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()) { match (a.root(), b.root()) {
(Node::Leaf(a_ct), Node::Leaf(b_ct)) => { (Node::Leaf(a_ct), Node::Leaf(b_ct)) => {
let a_ct = a_ct.subst(tcx, a.substs); let a_ct = a_ct.subst(tcx, a.substs);
......
...@@ -476,6 +476,25 @@ fn process_obligation( ...@@ -476,6 +476,25 @@ fn process_obligation(
ty::PredicateAtom::ConstEquate(c1, c2) => { ty::PredicateAtom::ConstEquate(c1, c2) => {
debug!("equating consts: c1={:?} c2={:?}", 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; let stalled_on = &mut pending_obligation.stalled_on;
......
...@@ -566,6 +566,7 @@ pub fn provide(providers: &mut ty::query::Providers) { ...@@ -566,6 +566,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
ty::WithOptConstParam { did, const_param_did: Some(param_did) }, ty::WithOptConstParam { did, const_param_did: Some(param_did) },
) )
}, },
try_unify_abstract_consts: const_evaluatable::try_unify_abstract_consts,
..*providers ..*providers
}; };
} }
error: generic parameters must not be used inside of non trivial constant values 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]; 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` | ^ 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 = 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
...@@ -5,10 +5,9 @@ ...@@ -5,10 +5,9 @@
#![feature(const_evaluatable_checked)] #![feature(const_evaluatable_checked)]
#![allow(incomplete_features)] #![allow(incomplete_features)]
type Arr<const N: usize> = [u8; N - 1]; fn test<const N: usize>() -> [u8; N - 1] where [u8; N - 1]: Default {
//[min]~^ ERROR generic parameters must not be used inside of non trivial constant values //[min]~^ ERROR generic parameters
//[min]~| ERROR generic parameters
fn test<const N: usize>() -> Arr<N> where Arr<N>: Default {
Default::default() Default::default()
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册