Skip to content

Commit 91f9806

Browse files
committed
Auto merge of #88166 - BoxyUwU:const-equate-canon, r=lcnr
canonicalize consts before calling try_unify_abstract_consts query Fixes #88022 Fixes #86953 Fixes #77708 Fixes #82034 Fixes #85031 these ICEs were all caused by calling the `try_unify_abstract_consts` query with inference vars in substs r? `@lcnr`
2 parents 7481e6d + c2b61fb commit 91f9806

File tree

12 files changed

+221
-9
lines changed

12 files changed

+221
-9
lines changed

compiler/rustc_infer/src/infer/mod.rs

+16
Original file line numberDiff line numberDiff line change
@@ -671,6 +671,22 @@ pub struct CombinedSnapshot<'a, 'tcx> {
671671
}
672672

673673
impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
674+
/// calls `tcx.try_unify_abstract_consts` after
675+
/// canonicalizing the consts.
676+
pub fn try_unify_abstract_consts(
677+
&self,
678+
a: ty::Unevaluated<'tcx>,
679+
b: ty::Unevaluated<'tcx>,
680+
) -> bool {
681+
let canonical = self.canonicalize_query(
682+
((a.def, a.substs), (b.def, b.substs)),
683+
&mut OriginalQueryValues::default(),
684+
);
685+
debug!("canonical consts: {:?}", &canonical.value);
686+
687+
self.tcx.try_unify_abstract_consts(canonical.value)
688+
}
689+
674690
pub fn is_in_snapshot(&self) -> bool {
675691
self.in_snapshot.get()
676692
}

compiler/rustc_trait_selection/src/traits/fulfill.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -578,11 +578,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
578578
if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) =
579579
(c1.val, c2.val)
580580
{
581-
if self
582-
.selcx
583-
.tcx()
584-
.try_unify_abstract_consts(((a.def, a.substs), (b.def, b.substs)))
585-
{
581+
if infcx.try_unify_abstract_consts(a, b) {
586582
return ProcessResult::Changed(vec![]);
587583
}
588584
}

compiler/rustc_trait_selection/src/traits/select/mod.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -624,10 +624,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
624624
if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) =
625625
(c1.val, c2.val)
626626
{
627-
if self
628-
.tcx()
629-
.try_unify_abstract_consts(((a.def, a.substs), (b.def, b.substs)))
630-
{
627+
if self.infcx.try_unify_abstract_consts(a, b) {
631628
return Ok(EvaluatedToOk);
632629
}
633630
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// revisions: cfail
2+
#![feature(const_generics, const_evaluatable_checked)]
3+
#![allow(incomplete_features, unused_braces)]
4+
5+
trait Delegates<T> {}
6+
7+
struct FileCap<const Op: bool> {}
8+
9+
fn writes_to_path<C>(cap: &C)
10+
where
11+
C: Delegates<FileCap<{ false }>>,
12+
{
13+
writes_to_specific_path(&cap);
14+
//~^ error: the trait bound
15+
}
16+
17+
fn writes_to_specific_path<C>(cap: &C)
18+
where
19+
C: Delegates<FileCap<{ false }>>,
20+
{
21+
}
22+
23+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// revisions: rpass
2+
#![feature(const_generics, const_evaluatable_checked)]
3+
#![allow(incomplete_features)]
4+
5+
struct Z;
6+
const fn one() -> usize {
7+
1
8+
}
9+
10+
fn from_a_to_b<T>(source: [u8; one()]) -> T {
11+
todo!()
12+
}
13+
14+
fn not_main() {
15+
let _: &Z = from_a_to_b([0; 1]);
16+
}
17+
18+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// revisions: rpass
2+
#![feature(const_generics, const_evaluatable_checked)]
3+
#![allow(incomplete_features)]
4+
5+
use std::{convert::TryFrom, num::NonZeroUsize};
6+
7+
struct A<const N: NonZeroUsize>([u8; N.get()])
8+
where
9+
[u8; N.get()]: Sized;
10+
11+
impl<'a, const N: NonZeroUsize> TryFrom<&'a [u8]> for A<N>
12+
where
13+
[u8; N.get()]: Sized,
14+
{
15+
type Error = ();
16+
fn try_from(slice: &'a [u8]) -> Result<A<N>, ()> {
17+
let _x = <&[u8; N.get()] as TryFrom<&[u8]>>::try_from(slice);
18+
unimplemented!();
19+
}
20+
}
21+
22+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// revisions: rpass
2+
#![feature(const_generics, const_evaluatable_checked)]
3+
#![allow(incomplete_features)]
4+
pub trait IsTrue {}
5+
pub trait IsFalse {}
6+
7+
pub struct Assert<const CHECK: bool> {}
8+
9+
impl IsTrue for Assert<true> {}
10+
impl IsFalse for Assert<false> {}
11+
12+
pub struct SliceConstWriter<'a, const N: usize> {
13+
ptr: &'a mut [u8],
14+
}
15+
impl<'a, const N: usize> SliceConstWriter<'a, { N }> {
16+
pub fn from_slice(vec: &'a mut [u8]) -> Self {
17+
Self { ptr: vec }
18+
}
19+
20+
pub fn convert<const NN: usize>(mut self) -> SliceConstWriter<'a, { NN }> {
21+
SliceConstWriter { ptr: self.ptr }
22+
}
23+
}
24+
25+
impl<'a, const N: usize> SliceConstWriter<'a, { N }>
26+
where
27+
Assert<{ N >= 2 }>: IsTrue,
28+
{
29+
pub fn write_u8(mut self) -> SliceConstWriter<'a, { N - 2 }> {
30+
self.convert()
31+
}
32+
}
33+
34+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// revisions: rpass
2+
#![feature(const_generics, const_evaluatable_checked)]
3+
#![allow(incomplete_features)]
4+
5+
pub struct Ref<'a, const NUM: usize>(&'a i32);
6+
7+
impl<'a, const NUM: usize> Ref<'a, NUM> {
8+
pub fn foo<const A: usize>(r: Ref<'a, A>) -> Self
9+
where
10+
([(); NUM - A], [(); A - NUM]): Sized,
11+
{
12+
Self::bar(r)
13+
}
14+
15+
pub fn bar<const A: usize>(r: Ref<'a, A>) -> Self
16+
where
17+
([(); NUM - A], [(); A - NUM]): Sized,
18+
{
19+
Self(r.0)
20+
}
21+
}
22+
23+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// revisions: cfail
2+
#![allow(incomplete_features)]
3+
#![feature(const_generics, const_evaluatable_checked)]
4+
5+
pub struct Ref<'a>(&'a i32);
6+
7+
impl<'a> Ref<'a> {
8+
pub fn foo<const A: usize>() -> [(); A - 0] {
9+
Self::foo()
10+
//~^ error: type annotations needed
11+
}
12+
}
13+
14+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// revisions: rpass
2+
#![feature(const_generics, const_evaluatable_checked)]
3+
#![allow(incomplete_features)]
4+
5+
fn test<const SIZE: usize>() {}
6+
7+
trait SomeTrait {
8+
const SIZE: usize;
9+
}
10+
11+
struct A<'a, T> {
12+
some_ref: &'a str,
13+
_maker: core::marker::PhantomData<T>,
14+
}
15+
16+
impl<'a, T: SomeTrait> A<'a, T>
17+
where
18+
[(); T::SIZE]: ,
19+
{
20+
fn call_test() {
21+
test::<{ T::SIZE }>();
22+
}
23+
}
24+
25+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// revisions: rpass
2+
#![feature(const_generics, const_evaluatable_checked)]
3+
#![allow(incomplete_features)]
4+
5+
struct Foo;
6+
impl<'a> std::ops::Add<&'a Foo> for Foo
7+
where
8+
[(); 0 + 0]: Sized,
9+
{
10+
type Output = ();
11+
fn add(self, _: &Foo) -> Self::Output {
12+
loop {}
13+
}
14+
}
15+
16+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// revisions: cfail
2+
#![feature(const_generics, const_evaluatable_checked)]
3+
#![allow(incomplete_features, unused_braces)]
4+
5+
struct Buffer<T, const S: usize>
6+
where
7+
[(); { S * 2 }]: Default,
8+
{
9+
data: [T; { S * 2 }],
10+
}
11+
12+
struct BufferIter<'a, T, const S: usize>(&'a Buffer<T, S>)
13+
where
14+
[(); { S * 2 }]: Default;
15+
16+
impl<'a, T, const S: usize> Iterator for BufferIter<'a, T, S> {
17+
//~^ error: the trait bound
18+
//~^^ error: unconstrained generic constant
19+
type Item = &'a T;
20+
21+
fn next(&mut self) -> Option<Self::Item> {
22+
//~^ error: the trait bound
23+
//~^^ error: unconstrained generic constant
24+
None
25+
}
26+
}
27+
28+
fn main() {}

0 commit comments

Comments
 (0)