Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit c3a772f

Browse files
committed
use abstract consts when unifying ConstKind::Unevaluated
1 parent d327fa1 commit c3a772f

File tree

8 files changed

+96
-10
lines changed

8 files changed

+96
-10
lines changed

compiler/rustc_middle/src/query/mod.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,16 @@ rustc_queries! {
263263
}
264264
}
265265

266+
query try_unify_abstract_consts(key: (
267+
(ty::WithOptConstParam<DefId>, SubstsRef<'tcx>),
268+
(ty::WithOptConstParam<DefId>, SubstsRef<'tcx>)
269+
)) -> bool {
270+
desc {
271+
|tcx| "trying to unify the generic constants {} and {}",
272+
tcx.def_path_str(key.0.0.did), tcx.def_path_str(key.1.0.did)
273+
}
274+
}
275+
266276
query mir_drops_elaborated_and_const_checked(
267277
key: ty::WithOptConstParam<LocalDefId>
268278
) -> &'tcx Steal<mir::Body<'tcx>> {

compiler/rustc_middle/src/ty/query/keys.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,22 @@ impl<'tcx> Key for (DefId, SubstsRef<'tcx>) {
193193
}
194194
}
195195

196+
impl<'tcx> Key
197+
for (
198+
(ty::WithOptConstParam<DefId>, SubstsRef<'tcx>),
199+
(ty::WithOptConstParam<DefId>, SubstsRef<'tcx>),
200+
)
201+
{
202+
type CacheSelector = DefaultCacheSelector;
203+
204+
fn query_crate(&self) -> CrateNum {
205+
(self.0).0.did.krate
206+
}
207+
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
208+
(self.0).0.did.default_span(tcx)
209+
}
210+
}
211+
196212
impl<'tcx> Key for (LocalDefId, DefId, SubstsRef<'tcx>) {
197213
type CacheSelector = DefaultCacheSelector;
198214

compiler/rustc_middle/src/ty/relate.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,20 @@ pub fn super_relate_consts<R: TypeRelation<'tcx>>(
576576
new_val.map(ty::ConstKind::Value)
577577
}
578578

579-
// FIXME(const_generics): this is wrong, as it is a projection
579+
(
580+
ty::ConstKind::Unevaluated(a_def, a_substs, None),
581+
ty::ConstKind::Unevaluated(b_def, b_substs, None),
582+
) if tcx.features().const_evaluatable_checked => {
583+
if tcx.try_unify_abstract_consts(((a_def, a_substs), (b_def, b_substs))) {
584+
Ok(a.val)
585+
} else {
586+
Err(TypeError::ConstMismatch(expected_found(relation, a, b)))
587+
}
588+
}
589+
590+
// While this is slightly incorrect, it shouldn't matter for `min_const_generics`
591+
// and is the better alternative to waiting until `const_evaluatable_checked` can
592+
// be stabilized.
580593
(
581594
ty::ConstKind::Unevaluated(a_def, a_substs, a_promoted),
582595
ty::ConstKind::Unevaluated(b_def, b_substs, b_promoted),

compiler/rustc_trait_selection/src/traits/const_evaluatable.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,27 @@ pub(super) fn mir_abstract_const<'tcx>(
269269
}
270270
}
271271

272-
pub fn try_unify<'tcx>(tcx: TyCtxt<'tcx>, a: AbstractConst<'tcx>, b: AbstractConst<'tcx>) -> bool {
272+
pub(super) fn try_unify_abstract_consts<'tcx>(
273+
tcx: TyCtxt<'tcx>,
274+
((a, a_substs), (b, b_substs)): (
275+
(ty::WithOptConstParam<DefId>, SubstsRef<'tcx>),
276+
(ty::WithOptConstParam<DefId>, SubstsRef<'tcx>),
277+
),
278+
) -> bool {
279+
if let Some(a) = AbstractConst::new(tcx, a, a_substs) {
280+
if let Some(b) = AbstractConst::new(tcx, b, b_substs) {
281+
return try_unify(tcx, a, b);
282+
}
283+
}
284+
285+
false
286+
}
287+
288+
pub(super) fn try_unify<'tcx>(
289+
tcx: TyCtxt<'tcx>,
290+
a: AbstractConst<'tcx>,
291+
b: AbstractConst<'tcx>,
292+
) -> bool {
273293
match (a.root(), b.root()) {
274294
(Node::Leaf(a_ct), Node::Leaf(b_ct)) => {
275295
let a_ct = a_ct.subst(tcx, a.substs);

compiler/rustc_trait_selection/src/traits/fulfill.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,25 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
476476

477477
ty::PredicateAtom::ConstEquate(c1, c2) => {
478478
debug!("equating consts: c1={:?} c2={:?}", c1, c2);
479+
if self.selcx.tcx().features().const_evaluatable_checked {
480+
// FIXME: we probably should only try to unify abstract constants
481+
// if the constants depend on generic parameters.
482+
//
483+
// Let's just see where this breaks :shrug:
484+
if let (
485+
ty::ConstKind::Unevaluated(a_def, a_substs, None),
486+
ty::ConstKind::Unevaluated(b_def, b_substs, None),
487+
) = (c1.val, c2.val)
488+
{
489+
if self
490+
.selcx
491+
.tcx()
492+
.try_unify_abstract_consts(((a_def, a_substs), (b_def, b_substs)))
493+
{
494+
return ProcessResult::Changed(vec![]);
495+
}
496+
}
497+
}
479498

480499
let stalled_on = &mut pending_obligation.stalled_on;
481500

compiler/rustc_trait_selection/src/traits/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
566566
ty::WithOptConstParam { did, const_param_did: Some(param_did) },
567567
)
568568
},
569+
try_unify_abstract_consts: const_evaluatable::try_unify_abstract_consts,
569570
..*providers
570571
};
571572
}
Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,18 @@
11
error: generic parameters must not be used inside of non trivial constant values
2-
--> $DIR/simple.rs:8:33
2+
--> $DIR/simple.rs:8:53
33
|
4-
LL | type Arr<const N: usize> = [u8; N - 1];
5-
| ^ non-trivial anonymous constants must not depend on the parameter `N`
4+
LL | fn test<const N: usize>() -> [u8; N - 1] where [u8; N - 1]: Default {
5+
| ^ non-trivial anonymous constants must not depend on the parameter `N`
66
|
77
= help: it is currently only allowed to use either `N` or `{ N }` as generic constants
88

9-
error: aborting due to previous error
9+
error: generic parameters must not be used inside of non trivial constant values
10+
--> $DIR/simple.rs:8:35
11+
|
12+
LL | fn test<const N: usize>() -> [u8; N - 1] where [u8; N - 1]: Default {
13+
| ^ non-trivial anonymous constants must not depend on the parameter `N`
14+
|
15+
= help: it is currently only allowed to use either `N` or `{ N }` as generic constants
16+
17+
error: aborting due to 2 previous errors
1018

src/test/ui/const-generics/const_evaluatable_checked/simple.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@
55
#![feature(const_evaluatable_checked)]
66
#![allow(incomplete_features)]
77

8-
type Arr<const N: usize> = [u8; N - 1];
9-
//[min]~^ ERROR generic parameters must not be used inside of non trivial constant values
10-
11-
fn test<const N: usize>() -> Arr<N> where Arr<N>: Default {
8+
fn test<const N: usize>() -> [u8; N - 1] where [u8; N - 1]: Default {
9+
//[min]~^ ERROR generic parameters
10+
//[min]~| ERROR generic parameters
1211
Default::default()
1312
}
1413

0 commit comments

Comments
 (0)