about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2021-12-25 22:45:05 -0800
committerMichael Goulet <michael@errs.io>2022-03-14 15:35:06 -0700
commitf14a5fd7127af1e774b76deea5a749ced33b23a1 (patch)
tree28d6da30010cf9e2fb9e77e8396c0822dafe10b0
parent285fa7ecd05dcbfdaf2faaf20400f5f92b39b3c6 (diff)
downloadrust-f14a5fd7127af1e774b76deea5a749ced33b23a1.tar.gz
rust-f14a5fd7127af1e774b76deea5a749ced33b23a1.zip
check Projection supertrait bounds when confirming dyn candidate
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs4
-rw-r--r--src/test/ui/traits/object/enforce-supertrait-projection.rs24
-rw-r--r--src/test/ui/traits/object/enforce-supertrait-projection.stderr26
3 files changed, 53 insertions, 1 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index c7e0c35436a..8fd7664d578 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -468,7 +468,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             .predicates
             .into_iter()
         {
-            if let ty::PredicateKind::Trait(..) = super_trait.kind().skip_binder() {
+            if let ty::PredicateKind::Trait(..) | ty::PredicateKind::Projection(..) =
+                super_trait.kind().skip_binder()
+            {
                 let normalized_super_trait = normalize_with_depth_to(
                     self,
                     obligation.param_env,
diff --git a/src/test/ui/traits/object/enforce-supertrait-projection.rs b/src/test/ui/traits/object/enforce-supertrait-projection.rs
new file mode 100644
index 00000000000..0ea944ec2df
--- /dev/null
+++ b/src/test/ui/traits/object/enforce-supertrait-projection.rs
@@ -0,0 +1,24 @@
+trait SuperTrait {
+    type A;
+    type B;
+}
+
+trait Trait: SuperTrait<A = <Self as SuperTrait>::B> {}
+
+fn transmute<A, B>(x: A) -> B {
+    foo::<A, B, dyn Trait<A = A, B = B>>(x)
+    //~^ ERROR type mismatch resolving `<dyn Trait<A = A, B = B> as SuperTrait>::A == B`
+}
+
+fn foo<A, B, T: ?Sized>(x: T::A) -> B
+where
+    T: Trait<B = B>,
+{
+    x
+}
+
+static X: u8 = 0;
+fn main() {
+    let x = transmute::<&u8, &[u8; 1_000_000]>(&X);
+    println!("{:?}", x[100_000]);
+}
diff --git a/src/test/ui/traits/object/enforce-supertrait-projection.stderr b/src/test/ui/traits/object/enforce-supertrait-projection.stderr
new file mode 100644
index 00000000000..a3d17fabbe4
--- /dev/null
+++ b/src/test/ui/traits/object/enforce-supertrait-projection.stderr
@@ -0,0 +1,26 @@
+error[E0271]: type mismatch resolving `<dyn Trait<A = A, B = B> as SuperTrait>::A == B`
+  --> $DIR/enforce-supertrait-projection.rs:9:5
+   |
+LL | fn transmute<A, B>(x: A) -> B {
+   |              -  - expected type parameter
+   |              |
+   |              found type parameter
+LL |     foo::<A, B, dyn Trait<A = A, B = B>>(x)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `B`, found type parameter `A`
+   |
+   = note: expected type parameter `B`
+              found type parameter `A`
+   = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
+   = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
+note: required by a bound in `foo`
+  --> $DIR/enforce-supertrait-projection.rs:15:8
+   |
+LL | fn foo<A, B, T: ?Sized>(x: T::A) -> B
+   |    --- required by a bound in this
+LL | where
+LL |     T: Trait<B = B>,
+   |        ^^^^^^^^^^^^ required by this bound in `foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0271`.