Skip to content

Commit ca7e3c4

Browse files
Keep going if normalized projection has unevaluated consts in QueryNormalizer
1 parent 6f18f0a commit ca7e3c4

File tree

7 files changed

+287
-1
lines changed

7 files changed

+287
-1
lines changed

compiler/rustc_trait_selection/src/traits/query/normalize.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
194194
// wait to fold the substs.
195195

196196
// Wrap this in a closure so we don't accidentally return from the outer function
197-
let res = (|| match *ty.kind() {
197+
let mut res = (|| match *ty.kind() {
198198
// This is really important. While we *can* handle this, this has
199199
// severe performance implications for large opaque types with
200200
// late-bound regions. See `issue-88862` benchmark.
@@ -317,6 +317,13 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
317317

318318
_ => ty.try_super_fold_with(self),
319319
})()?;
320+
321+
// `tcx.normalize_projection_ty` may normalize to a type that still has
322+
// unevaluated consts, so keep normalizing here if that's the case.
323+
if res != ty && res.has_type_flags(ty::TypeFlags::HAS_CT_PROJECTION) {
324+
res = res.try_super_fold_with(self)?;
325+
}
326+
320327
self.cache.insert(ty, res);
321328
Ok(res)
322329
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// build-pass
2+
3+
#![allow(incomplete_features)]
4+
#![feature(generic_const_exprs)]
5+
6+
trait TraitOne {
7+
const MY_NUM: usize;
8+
type MyErr: std::fmt::Debug;
9+
10+
fn do_one_stuff(arr: [u8; Self::MY_NUM]) -> Result<(), Self::MyErr>;
11+
}
12+
13+
trait TraitTwo {
14+
fn do_two_stuff();
15+
}
16+
17+
impl<O: TraitOne> TraitTwo for O
18+
where
19+
[(); Self::MY_NUM]:,
20+
{
21+
fn do_two_stuff() {
22+
O::do_one_stuff([5; Self::MY_NUM]).unwrap()
23+
}
24+
}
25+
26+
struct Blargotron;
27+
28+
#[derive(Debug)]
29+
struct ErrTy<const N: usize>([(); N]);
30+
31+
impl TraitOne for Blargotron {
32+
const MY_NUM: usize = 3;
33+
type MyErr = ErrTy<{ Self::MY_NUM }>;
34+
35+
fn do_one_stuff(_arr: [u8; Self::MY_NUM]) -> Result<(), Self::MyErr> {
36+
Ok(())
37+
}
38+
}
39+
40+
fn main() {
41+
Blargotron::do_two_stuff();
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// build-pass
2+
3+
#![allow(incomplete_features)]
4+
#![feature(generic_const_exprs)]
5+
6+
use std::convert::AsMut;
7+
use std::default::Default;
8+
9+
trait Foo: Sized {
10+
type Baz: Default + AsMut<[u8]>;
11+
fn bar() {
12+
Self::Baz::default().as_mut();
13+
}
14+
}
15+
16+
impl Foo for () {
17+
type Baz = [u8; 1 * 1];
18+
//type Baz = [u8; 1];
19+
}
20+
21+
fn main() {
22+
<() as Foo>::bar();
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// build-pass
2+
3+
#![allow(incomplete_features)]
4+
#![feature(generic_const_exprs)]
5+
6+
trait Collate<Op> {
7+
type Pass;
8+
type Fail;
9+
10+
fn collate(self) -> (Self::Pass, Self::Fail);
11+
}
12+
13+
impl<Op> Collate<Op> for () {
14+
type Pass = ();
15+
type Fail = ();
16+
17+
fn collate(self) -> ((), ()) {
18+
((), ())
19+
}
20+
}
21+
22+
trait CollateStep<X, Prev> {
23+
type Pass;
24+
type Fail;
25+
fn collate_step(x: X, prev: Prev) -> (Self::Pass, Self::Fail);
26+
}
27+
28+
impl<X, P, F> CollateStep<X, (P, F)> for () {
29+
type Pass = (X, P);
30+
type Fail = F;
31+
32+
fn collate_step(x: X, (p, f): (P, F)) -> ((X, P), F) {
33+
((x, p), f)
34+
}
35+
}
36+
37+
struct CollateOpImpl<const MASK: u32>;
38+
trait CollateOpStep {
39+
type NextOp;
40+
type Apply;
41+
}
42+
43+
impl<const MASK: u32> CollateOpStep for CollateOpImpl<MASK>
44+
where
45+
CollateOpImpl<{ MASK >> 1 }>: Sized,
46+
{
47+
type NextOp = CollateOpImpl<{ MASK >> 1 }>;
48+
type Apply = ();
49+
}
50+
51+
impl<H, T, Op: CollateOpStep> Collate<Op> for (H, T)
52+
where
53+
T: Collate<Op::NextOp>,
54+
Op::Apply: CollateStep<H, (T::Pass, T::Fail)>,
55+
{
56+
type Pass = <Op::Apply as CollateStep<H, (T::Pass, T::Fail)>>::Pass;
57+
type Fail = <Op::Apply as CollateStep<H, (T::Pass, T::Fail)>>::Fail;
58+
59+
fn collate(self) -> (Self::Pass, Self::Fail) {
60+
<Op::Apply as CollateStep<H, (T::Pass, T::Fail)>>::collate_step(self.0, self.1.collate())
61+
}
62+
}
63+
64+
fn collate<X, const MASK: u32>(x: X) -> (X::Pass, X::Fail)
65+
where
66+
X: Collate<CollateOpImpl<MASK>>,
67+
{
68+
x.collate()
69+
}
70+
71+
fn main() {
72+
dbg!(collate::<_, 5>(("Hello", (42, ('!', ())))));
73+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// build-pass
2+
3+
#![allow(incomplete_features)]
4+
#![feature(generic_const_exprs)]
5+
6+
pub trait Foo {
7+
fn foo(&self);
8+
}
9+
10+
pub struct FooImpl<const N: usize>;
11+
impl<const N: usize> Foo for FooImpl<N> {
12+
fn foo(&self) {}
13+
}
14+
15+
pub trait Bar: 'static {
16+
type Foo: Foo;
17+
fn get() -> &'static Self::Foo;
18+
}
19+
20+
struct BarImpl;
21+
impl Bar for BarImpl {
22+
type Foo = FooImpl<
23+
{
24+
{ 4 }
25+
},
26+
>;
27+
fn get() -> &'static Self::Foo {
28+
&FooImpl
29+
}
30+
}
31+
32+
pub fn boom<B: Bar>() {
33+
B::get().foo();
34+
}
35+
36+
fn main() {
37+
boom::<BarImpl>();
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// build-pass
2+
3+
#![feature(generic_const_exprs)]
4+
#![allow(incomplete_features)]
5+
6+
trait Foo {
7+
type Output;
8+
9+
fn foo() -> Self::Output;
10+
}
11+
12+
impl Foo for [u8; 3] {
13+
type Output = [u8; 1 + 2];
14+
15+
fn foo() -> [u8; 3] {
16+
[1u8; 3]
17+
}
18+
}
19+
20+
fn bug<const N: usize>()
21+
where
22+
[u8; N]: Foo,
23+
<[u8; N] as Foo>::Output: AsRef<[u8]>,
24+
{
25+
<[u8; N]>::foo().as_ref();
26+
}
27+
28+
fn main() {
29+
bug::<3>();
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// build-pass
2+
3+
#![allow(incomplete_features)]
4+
#![feature(generic_const_exprs)]
5+
6+
use std::marker::PhantomData;
7+
8+
fn main() {
9+
let x = FooImpl::<BarImpl<1>> { phantom: PhantomData };
10+
let _ = x.foo::<BarImpl<1>>();
11+
}
12+
13+
trait Foo<T>
14+
where
15+
T: Bar,
16+
{
17+
fn foo<U>(&self)
18+
where
19+
T: Operation<U>,
20+
<T as Operation<U>>::Output: Bar;
21+
}
22+
23+
struct FooImpl<T>
24+
where
25+
T: Bar,
26+
{
27+
phantom: PhantomData<T>,
28+
}
29+
30+
impl<T> Foo<T> for FooImpl<T>
31+
where
32+
T: Bar,
33+
{
34+
fn foo<U>(&self)
35+
where
36+
T: Operation<U>,
37+
<T as Operation<U>>::Output: Bar,
38+
{
39+
<<T as Operation<U>>::Output as Bar>::error_occurs_here();
40+
}
41+
}
42+
43+
trait Bar {
44+
fn error_occurs_here();
45+
}
46+
47+
struct BarImpl<const N: usize>;
48+
49+
impl<const N: usize> Bar for BarImpl<N> {
50+
fn error_occurs_here() {}
51+
}
52+
53+
trait Operation<Rhs> {
54+
type Output;
55+
}
56+
57+
//// Part-A: This causes error.
58+
impl<const M: usize, const N: usize> Operation<BarImpl<M>> for BarImpl<N>
59+
where
60+
BarImpl<{ N + M }>: Sized,
61+
{
62+
type Output = BarImpl<{ N + M }>;
63+
}
64+
65+
//// Part-B: This doesn't cause error.
66+
// impl<const M: usize, const N: usize> Operation<BarImpl<M>> for BarImpl<N> {
67+
// type Output = BarImpl<M>;
68+
// }
69+
70+
//// Part-C: This also doesn't cause error.
71+
// impl<const M: usize, const N: usize> Operation<BarImpl<M>> for BarImpl<N> {
72+
// type Output = BarImpl<{ M }>;
73+
// }

0 commit comments

Comments
 (0)