Keep going if normalized projection has unevaluated consts in QueryNormalizer
This commit is contained in:
parent
6f18f0a9d4
commit
ca7e3c4a83
@ -194,7 +194,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
|
||||
// wait to fold the substs.
|
||||
|
||||
// Wrap this in a closure so we don't accidentally return from the outer function
|
||||
let res = (|| match *ty.kind() {
|
||||
let mut res = (|| match *ty.kind() {
|
||||
// This is really important. While we *can* handle this, this has
|
||||
// severe performance implications for large opaque types with
|
||||
// late-bound regions. See `issue-88862` benchmark.
|
||||
@ -317,6 +317,13 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
|
||||
|
||||
_ => ty.try_super_fold_with(self),
|
||||
})()?;
|
||||
|
||||
// `tcx.normalize_projection_ty` may normalize to a type that still has
|
||||
// unevaluated consts, so keep normalizing here if that's the case.
|
||||
if res != ty && res.has_type_flags(ty::TypeFlags::HAS_CT_PROJECTION) {
|
||||
res = res.try_super_fold_with(self)?;
|
||||
}
|
||||
|
||||
self.cache.insert(ty, res);
|
||||
Ok(res)
|
||||
}
|
||||
|
@ -0,0 +1,42 @@
|
||||
// build-pass
|
||||
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(generic_const_exprs)]
|
||||
|
||||
trait TraitOne {
|
||||
const MY_NUM: usize;
|
||||
type MyErr: std::fmt::Debug;
|
||||
|
||||
fn do_one_stuff(arr: [u8; Self::MY_NUM]) -> Result<(), Self::MyErr>;
|
||||
}
|
||||
|
||||
trait TraitTwo {
|
||||
fn do_two_stuff();
|
||||
}
|
||||
|
||||
impl<O: TraitOne> TraitTwo for O
|
||||
where
|
||||
[(); Self::MY_NUM]:,
|
||||
{
|
||||
fn do_two_stuff() {
|
||||
O::do_one_stuff([5; Self::MY_NUM]).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
struct Blargotron;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct ErrTy<const N: usize>([(); N]);
|
||||
|
||||
impl TraitOne for Blargotron {
|
||||
const MY_NUM: usize = 3;
|
||||
type MyErr = ErrTy<{ Self::MY_NUM }>;
|
||||
|
||||
fn do_one_stuff(_arr: [u8; Self::MY_NUM]) -> Result<(), Self::MyErr> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
Blargotron::do_two_stuff();
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
// build-pass
|
||||
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(generic_const_exprs)]
|
||||
|
||||
use std::convert::AsMut;
|
||||
use std::default::Default;
|
||||
|
||||
trait Foo: Sized {
|
||||
type Baz: Default + AsMut<[u8]>;
|
||||
fn bar() {
|
||||
Self::Baz::default().as_mut();
|
||||
}
|
||||
}
|
||||
|
||||
impl Foo for () {
|
||||
type Baz = [u8; 1 * 1];
|
||||
//type Baz = [u8; 1];
|
||||
}
|
||||
|
||||
fn main() {
|
||||
<() as Foo>::bar();
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
// build-pass
|
||||
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(generic_const_exprs)]
|
||||
|
||||
trait Collate<Op> {
|
||||
type Pass;
|
||||
type Fail;
|
||||
|
||||
fn collate(self) -> (Self::Pass, Self::Fail);
|
||||
}
|
||||
|
||||
impl<Op> Collate<Op> for () {
|
||||
type Pass = ();
|
||||
type Fail = ();
|
||||
|
||||
fn collate(self) -> ((), ()) {
|
||||
((), ())
|
||||
}
|
||||
}
|
||||
|
||||
trait CollateStep<X, Prev> {
|
||||
type Pass;
|
||||
type Fail;
|
||||
fn collate_step(x: X, prev: Prev) -> (Self::Pass, Self::Fail);
|
||||
}
|
||||
|
||||
impl<X, P, F> CollateStep<X, (P, F)> for () {
|
||||
type Pass = (X, P);
|
||||
type Fail = F;
|
||||
|
||||
fn collate_step(x: X, (p, f): (P, F)) -> ((X, P), F) {
|
||||
((x, p), f)
|
||||
}
|
||||
}
|
||||
|
||||
struct CollateOpImpl<const MASK: u32>;
|
||||
trait CollateOpStep {
|
||||
type NextOp;
|
||||
type Apply;
|
||||
}
|
||||
|
||||
impl<const MASK: u32> CollateOpStep for CollateOpImpl<MASK>
|
||||
where
|
||||
CollateOpImpl<{ MASK >> 1 }>: Sized,
|
||||
{
|
||||
type NextOp = CollateOpImpl<{ MASK >> 1 }>;
|
||||
type Apply = ();
|
||||
}
|
||||
|
||||
impl<H, T, Op: CollateOpStep> Collate<Op> for (H, T)
|
||||
where
|
||||
T: Collate<Op::NextOp>,
|
||||
Op::Apply: CollateStep<H, (T::Pass, T::Fail)>,
|
||||
{
|
||||
type Pass = <Op::Apply as CollateStep<H, (T::Pass, T::Fail)>>::Pass;
|
||||
type Fail = <Op::Apply as CollateStep<H, (T::Pass, T::Fail)>>::Fail;
|
||||
|
||||
fn collate(self) -> (Self::Pass, Self::Fail) {
|
||||
<Op::Apply as CollateStep<H, (T::Pass, T::Fail)>>::collate_step(self.0, self.1.collate())
|
||||
}
|
||||
}
|
||||
|
||||
fn collate<X, const MASK: u32>(x: X) -> (X::Pass, X::Fail)
|
||||
where
|
||||
X: Collate<CollateOpImpl<MASK>>,
|
||||
{
|
||||
x.collate()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
dbg!(collate::<_, 5>(("Hello", (42, ('!', ())))));
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
// build-pass
|
||||
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(generic_const_exprs)]
|
||||
|
||||
pub trait Foo {
|
||||
fn foo(&self);
|
||||
}
|
||||
|
||||
pub struct FooImpl<const N: usize>;
|
||||
impl<const N: usize> Foo for FooImpl<N> {
|
||||
fn foo(&self) {}
|
||||
}
|
||||
|
||||
pub trait Bar: 'static {
|
||||
type Foo: Foo;
|
||||
fn get() -> &'static Self::Foo;
|
||||
}
|
||||
|
||||
struct BarImpl;
|
||||
impl Bar for BarImpl {
|
||||
type Foo = FooImpl<
|
||||
{
|
||||
{ 4 }
|
||||
},
|
||||
>;
|
||||
fn get() -> &'static Self::Foo {
|
||||
&FooImpl
|
||||
}
|
||||
}
|
||||
|
||||
pub fn boom<B: Bar>() {
|
||||
B::get().foo();
|
||||
}
|
||||
|
||||
fn main() {
|
||||
boom::<BarImpl>();
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
// build-pass
|
||||
|
||||
#![feature(generic_const_exprs)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
trait Foo {
|
||||
type Output;
|
||||
|
||||
fn foo() -> Self::Output;
|
||||
}
|
||||
|
||||
impl Foo for [u8; 3] {
|
||||
type Output = [u8; 1 + 2];
|
||||
|
||||
fn foo() -> [u8; 3] {
|
||||
[1u8; 3]
|
||||
}
|
||||
}
|
||||
|
||||
fn bug<const N: usize>()
|
||||
where
|
||||
[u8; N]: Foo,
|
||||
<[u8; N] as Foo>::Output: AsRef<[u8]>,
|
||||
{
|
||||
<[u8; N]>::foo().as_ref();
|
||||
}
|
||||
|
||||
fn main() {
|
||||
bug::<3>();
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
// build-pass
|
||||
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(generic_const_exprs)]
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
fn main() {
|
||||
let x = FooImpl::<BarImpl<1>> { phantom: PhantomData };
|
||||
let _ = x.foo::<BarImpl<1>>();
|
||||
}
|
||||
|
||||
trait Foo<T>
|
||||
where
|
||||
T: Bar,
|
||||
{
|
||||
fn foo<U>(&self)
|
||||
where
|
||||
T: Operation<U>,
|
||||
<T as Operation<U>>::Output: Bar;
|
||||
}
|
||||
|
||||
struct FooImpl<T>
|
||||
where
|
||||
T: Bar,
|
||||
{
|
||||
phantom: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T> Foo<T> for FooImpl<T>
|
||||
where
|
||||
T: Bar,
|
||||
{
|
||||
fn foo<U>(&self)
|
||||
where
|
||||
T: Operation<U>,
|
||||
<T as Operation<U>>::Output: Bar,
|
||||
{
|
||||
<<T as Operation<U>>::Output as Bar>::error_occurs_here();
|
||||
}
|
||||
}
|
||||
|
||||
trait Bar {
|
||||
fn error_occurs_here();
|
||||
}
|
||||
|
||||
struct BarImpl<const N: usize>;
|
||||
|
||||
impl<const N: usize> Bar for BarImpl<N> {
|
||||
fn error_occurs_here() {}
|
||||
}
|
||||
|
||||
trait Operation<Rhs> {
|
||||
type Output;
|
||||
}
|
||||
|
||||
//// Part-A: This causes error.
|
||||
impl<const M: usize, const N: usize> Operation<BarImpl<M>> for BarImpl<N>
|
||||
where
|
||||
BarImpl<{ N + M }>: Sized,
|
||||
{
|
||||
type Output = BarImpl<{ N + M }>;
|
||||
}
|
||||
|
||||
//// Part-B: This doesn't cause error.
|
||||
// impl<const M: usize, const N: usize> Operation<BarImpl<M>> for BarImpl<N> {
|
||||
// type Output = BarImpl<M>;
|
||||
// }
|
||||
|
||||
//// Part-C: This also doesn't cause error.
|
||||
// impl<const M: usize, const N: usize> Operation<BarImpl<M>> for BarImpl<N> {
|
||||
// type Output = BarImpl<{ M }>;
|
||||
// }
|
Loading…
x
Reference in New Issue
Block a user