summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/normalize.rs23
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/issue-100217.rs42
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/issue-73298.rs23
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/issue-82268.rs73
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/issue-83972.rs38
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/issue-84669.rs30
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/issue-86710.rs73
7 files changed, 299 insertions, 3 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
index 38b3a4b7253..61c556b726d 100644
--- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
@@ -266,7 +266,15 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
                 debug!("QueryNormalizer: result = {:#?}", result);
                 debug!("QueryNormalizer: obligations = {:#?}", obligations);
                 self.obligations.extend(obligations);
-                Ok(result.normalized_ty)
+
+                let res = result.normalized_ty;
+                // `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) {
+                    Ok(res.try_super_fold_with(self)?)
+                } else {
+                    Ok(res)
+                }
             }
 
             ty::Projection(data) => {
@@ -305,18 +313,27 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
                 debug!("QueryNormalizer: result = {:#?}", result);
                 debug!("QueryNormalizer: obligations = {:#?}", obligations);
                 self.obligations.extend(obligations);
-                Ok(crate::traits::project::PlaceholderReplacer::replace_placeholders(
+
+                let res = crate::traits::project::PlaceholderReplacer::replace_placeholders(
                     infcx,
                     mapped_regions,
                     mapped_types,
                     mapped_consts,
                     &self.universes,
                     result.normalized_ty,
-                ))
+                );
+                // `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) {
+                    Ok(res.try_super_fold_with(self)?)
+                } else {
+                    Ok(res)
+                }
             }
 
             _ => ty.try_super_fold_with(self),
         })()?;
+
         self.cache.insert(ty, res);
         Ok(res)
     }
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-100217.rs b/src/test/ui/const-generics/generic_const_exprs/issue-100217.rs
new file mode 100644
index 00000000000..acdc348a385
--- /dev/null
+++ b/src/test/ui/const-generics/generic_const_exprs/issue-100217.rs
@@ -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();
+}
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-73298.rs b/src/test/ui/const-generics/generic_const_exprs/issue-73298.rs
new file mode 100644
index 00000000000..3c59e1b790a
--- /dev/null
+++ b/src/test/ui/const-generics/generic_const_exprs/issue-73298.rs
@@ -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();
+}
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-82268.rs b/src/test/ui/const-generics/generic_const_exprs/issue-82268.rs
new file mode 100644
index 00000000000..d08fc5beb75
--- /dev/null
+++ b/src/test/ui/const-generics/generic_const_exprs/issue-82268.rs
@@ -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, ('!', ())))));
+}
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-83972.rs b/src/test/ui/const-generics/generic_const_exprs/issue-83972.rs
new file mode 100644
index 00000000000..0063719b852
--- /dev/null
+++ b/src/test/ui/const-generics/generic_const_exprs/issue-83972.rs
@@ -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>();
+}
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-84669.rs b/src/test/ui/const-generics/generic_const_exprs/issue-84669.rs
new file mode 100644
index 00000000000..3933ff20a49
--- /dev/null
+++ b/src/test/ui/const-generics/generic_const_exprs/issue-84669.rs
@@ -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>();
+}
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-86710.rs b/src/test/ui/const-generics/generic_const_exprs/issue-86710.rs
new file mode 100644
index 00000000000..bdd8a21b3b9
--- /dev/null
+++ b/src/test/ui/const-generics/generic_const_exprs/issue-86710.rs
@@ -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 }>;
+// }