Skip to content

Commit

Permalink
Auto merge of #88166 - BoxyUwU:const-equate-canon, r=lcnr
Browse files Browse the repository at this point in the history
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`
  • Loading branch information
bors committed Aug 22, 2021
2 parents 7481e6d + c2b61fb commit 91f9806
Show file tree
Hide file tree
Showing 12 changed files with 221 additions and 9 deletions.
16 changes: 16 additions & 0 deletions compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -671,6 +671,22 @@ pub struct CombinedSnapshot<'a, 'tcx> {
}

impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
/// calls `tcx.try_unify_abstract_consts` after
/// canonicalizing the consts.
pub fn try_unify_abstract_consts(
&self,
a: ty::Unevaluated<'tcx>,
b: ty::Unevaluated<'tcx>,
) -> bool {
let canonical = self.canonicalize_query(
((a.def, a.substs), (b.def, b.substs)),
&mut OriginalQueryValues::default(),
);
debug!("canonical consts: {:?}", &canonical.value);

self.tcx.try_unify_abstract_consts(canonical.value)
}

pub fn is_in_snapshot(&self) -> bool {
self.in_snapshot.get()
}
Expand Down
6 changes: 1 addition & 5 deletions compiler/rustc_trait_selection/src/traits/fulfill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -578,11 +578,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) =
(c1.val, c2.val)
{
if self
.selcx
.tcx()
.try_unify_abstract_consts(((a.def, a.substs), (b.def, b.substs)))
{
if infcx.try_unify_abstract_consts(a, b) {
return ProcessResult::Changed(vec![]);
}
}
Expand Down
5 changes: 1 addition & 4 deletions compiler/rustc_trait_selection/src/traits/select/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -624,10 +624,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) =
(c1.val, c2.val)
{
if self
.tcx()
.try_unify_abstract_consts(((a.def, a.substs), (b.def, b.substs)))
{
if self.infcx.try_unify_abstract_consts(a, b) {
return Ok(EvaluatedToOk);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// revisions: cfail
#![feature(const_generics, const_evaluatable_checked)]
#![allow(incomplete_features, unused_braces)]

trait Delegates<T> {}

struct FileCap<const Op: bool> {}

fn writes_to_path<C>(cap: &C)
where
C: Delegates<FileCap<{ false }>>,
{
writes_to_specific_path(&cap);
//~^ error: the trait bound
}

fn writes_to_specific_path<C>(cap: &C)
where
C: Delegates<FileCap<{ false }>>,
{
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// revisions: rpass
#![feature(const_generics, const_evaluatable_checked)]
#![allow(incomplete_features)]

struct Z;
const fn one() -> usize {
1
}

fn from_a_to_b<T>(source: [u8; one()]) -> T {
todo!()
}

fn not_main() {
let _: &Z = from_a_to_b([0; 1]);
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// revisions: rpass
#![feature(const_generics, const_evaluatable_checked)]
#![allow(incomplete_features)]

use std::{convert::TryFrom, num::NonZeroUsize};

struct A<const N: NonZeroUsize>([u8; N.get()])
where
[u8; N.get()]: Sized;

impl<'a, const N: NonZeroUsize> TryFrom<&'a [u8]> for A<N>
where
[u8; N.get()]: Sized,
{
type Error = ();
fn try_from(slice: &'a [u8]) -> Result<A<N>, ()> {
let _x = <&[u8; N.get()] as TryFrom<&[u8]>>::try_from(slice);
unimplemented!();
}
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// revisions: rpass
#![feature(const_generics, const_evaluatable_checked)]
#![allow(incomplete_features)]
pub trait IsTrue {}
pub trait IsFalse {}

pub struct Assert<const CHECK: bool> {}

impl IsTrue for Assert<true> {}
impl IsFalse for Assert<false> {}

pub struct SliceConstWriter<'a, const N: usize> {
ptr: &'a mut [u8],
}
impl<'a, const N: usize> SliceConstWriter<'a, { N }> {
pub fn from_slice(vec: &'a mut [u8]) -> Self {
Self { ptr: vec }
}

pub fn convert<const NN: usize>(mut self) -> SliceConstWriter<'a, { NN }> {
SliceConstWriter { ptr: self.ptr }
}
}

impl<'a, const N: usize> SliceConstWriter<'a, { N }>
where
Assert<{ N >= 2 }>: IsTrue,
{
pub fn write_u8(mut self) -> SliceConstWriter<'a, { N - 2 }> {
self.convert()
}
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// revisions: rpass
#![feature(const_generics, const_evaluatable_checked)]
#![allow(incomplete_features)]

pub struct Ref<'a, const NUM: usize>(&'a i32);

impl<'a, const NUM: usize> Ref<'a, NUM> {
pub fn foo<const A: usize>(r: Ref<'a, A>) -> Self
where
([(); NUM - A], [(); A - NUM]): Sized,
{
Self::bar(r)
}

pub fn bar<const A: usize>(r: Ref<'a, A>) -> Self
where
([(); NUM - A], [(); A - NUM]): Sized,
{
Self(r.0)
}
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// revisions: cfail
#![allow(incomplete_features)]
#![feature(const_generics, const_evaluatable_checked)]

pub struct Ref<'a>(&'a i32);

impl<'a> Ref<'a> {
pub fn foo<const A: usize>() -> [(); A - 0] {
Self::foo()
//~^ error: type annotations needed
}
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// revisions: rpass
#![feature(const_generics, const_evaluatable_checked)]
#![allow(incomplete_features)]

fn test<const SIZE: usize>() {}

trait SomeTrait {
const SIZE: usize;
}

struct A<'a, T> {
some_ref: &'a str,
_maker: core::marker::PhantomData<T>,
}

impl<'a, T: SomeTrait> A<'a, T>
where
[(); T::SIZE]: ,
{
fn call_test() {
test::<{ T::SIZE }>();
}
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// revisions: rpass
#![feature(const_generics, const_evaluatable_checked)]
#![allow(incomplete_features)]

struct Foo;
impl<'a> std::ops::Add<&'a Foo> for Foo
where
[(); 0 + 0]: Sized,
{
type Output = ();
fn add(self, _: &Foo) -> Self::Output {
loop {}
}
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// revisions: cfail
#![feature(const_generics, const_evaluatable_checked)]
#![allow(incomplete_features, unused_braces)]

struct Buffer<T, const S: usize>
where
[(); { S * 2 }]: Default,
{
data: [T; { S * 2 }],
}

struct BufferIter<'a, T, const S: usize>(&'a Buffer<T, S>)
where
[(); { S * 2 }]: Default;

impl<'a, T, const S: usize> Iterator for BufferIter<'a, T, S> {
//~^ error: the trait bound
//~^^ error: unconstrained generic constant
type Item = &'a T;

fn next(&mut self) -> Option<Self::Item> {
//~^ error: the trait bound
//~^^ error: unconstrained generic constant
None
}
}

fn main() {}

0 comments on commit 91f9806

Please sign in to comment.