mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-26 16:54:01 +00:00
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`
This commit is contained in:
commit
91f9806208
@ -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()
|
||||
}
|
||||
|
@ -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![]);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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() {}
|
@ -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() {}
|
@ -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() {}
|
@ -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() {}
|
@ -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() {}
|
@ -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() {}
|
@ -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() {}
|
@ -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() {}
|
@ -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() {}
|
Loading…
Reference in New Issue
Block a user