about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-06-11 04:58:48 +0000
committerbors <bors@rust-lang.org>2020-06-11 04:58:48 +0000
commit3ddf48053e83f4949d00dcaf6eb8d9e28fc6bb95 (patch)
tree77896eb87d9a6d0986920cd169e4468003ee3938
parente93cb961ba67c73815401291ab42b81e3e5733ae (diff)
parentc99164e7a13d7b2451464f3c0c066be9c7516a2b (diff)
downloadrust-3ddf48053e83f4949d00dcaf6eb8d9e28fc6bb95.tar.gz
rust-3ddf48053e83f4949d00dcaf6eb8d9e28fc6bb95.zip
Auto merge of #71896 - spastorino:existential-assoc-types-variance, r=nikomatsakis
Relate existential associated types with variance Invariant

Fixes #71550 #72315

r? @nikomatsakis

The test case reported in that issue now errors with the following message ...

```
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter 'a in function call due to conflicting requirements
  --> /tmp/test.rs:25:5
   |
25 |     bad(&Bar(PhantomData), x)
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
   |
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 24:11...
  --> /tmp/test.rs:24:11
   |
24 | fn extend<'a, T>(x: &'a T) -> &'static T {
   |           ^^
note: ...so that reference does not outlive borrowed content
  --> /tmp/test.rs:25:28
   |
25 |     bad(&Bar(PhantomData), x)
   |                            ^
   = note: but, the lifetime must be valid for the static lifetime...
note: ...so that the types are compatible
  --> /tmp/test.rs:25:9
   |
25 |     bad(&Bar(PhantomData), x)
   |         ^^^^^^^^^^^^^^^^^
   = note: expected  `&'static T`
              found  `&T`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0495`.
```

I could also add that test case if we want to have a weaponized one too.
-rw-r--r--src/librustc_middle/ty/relate.rs4
-rw-r--r--src/test/ui/coercion/coerce-expect-unsized-ascribed.stderr2
-rw-r--r--src/test/ui/issues/issue-20605.stderr4
-rw-r--r--src/test/ui/variance/variance-associated-types2.nll.stderr12
-rw-r--r--src/test/ui/variance/variance-associated-types2.rs17
-rw-r--r--src/test/ui/variance/variance-associated-types2.stderr18
6 files changed, 52 insertions, 5 deletions
diff --git a/src/librustc_middle/ty/relate.rs b/src/librustc_middle/ty/relate.rs
index d507fcbc194..67426b87c24 100644
--- a/src/librustc_middle/ty/relate.rs
+++ b/src/librustc_middle/ty/relate.rs
@@ -250,8 +250,8 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialProjection<'tcx> {
                 &b.item_def_id,
             )))
         } else {
-            let ty = relation.relate(&a.ty, &b.ty)?;
-            let substs = relation.relate(&a.substs, &b.substs)?;
+            let ty = relation.relate_with_variance(ty::Invariant, &a.ty, &b.ty)?;
+            let substs = relation.relate_with_variance(ty::Invariant, &a.substs, &b.substs)?;
             Ok(ty::ExistentialProjection { item_def_id: a.item_def_id, substs, ty })
         }
     }
diff --git a/src/test/ui/coercion/coerce-expect-unsized-ascribed.stderr b/src/test/ui/coercion/coerce-expect-unsized-ascribed.stderr
index 44e5c6a99f7..93e16bac13b 100644
--- a/src/test/ui/coercion/coerce-expect-unsized-ascribed.stderr
+++ b/src/test/ui/coercion/coerce-expect-unsized-ascribed.stderr
@@ -121,7 +121,7 @@ error[E0308]: mismatched types
 LL |     let _ = Box::new(|x| (x as u8)): Box<dyn Fn(i32) -> _>;
    |             ^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn std::ops::Fn`, found closure
    |
-   = note: expected struct `std::boxed::Box<dyn std::ops::Fn(i32) -> _>`
+   = note: expected struct `std::boxed::Box<dyn std::ops::Fn(i32) -> u8>`
               found struct `std::boxed::Box<[closure@$DIR/coerce-expect-unsized-ascribed.rs:26:22: 26:35]>`
 
 error: aborting due to 14 previous errors
diff --git a/src/test/ui/issues/issue-20605.stderr b/src/test/ui/issues/issue-20605.stderr
index 89df58dd2dc..5e050f27ac5 100644
--- a/src/test/ui/issues/issue-20605.stderr
+++ b/src/test/ui/issues/issue-20605.stderr
@@ -1,10 +1,10 @@
-error[E0277]: the size for values of type `dyn std::iter::Iterator<Item = &mut u8>` cannot be known at compilation time
+error[E0277]: the size for values of type `dyn std::iter::Iterator<Item = &'a mut u8>` cannot be known at compilation time
   --> $DIR/issue-20605.rs:2:17
    |
 LL |     for item in *things { *item = 0 }
    |                 ^^^^^^^ doesn't have a size known at compile-time
    |
-   = help: the trait `std::marker::Sized` is not implemented for `dyn std::iter::Iterator<Item = &mut u8>`
+   = help: the trait `std::marker::Sized` is not implemented for `dyn std::iter::Iterator<Item = &'a mut u8>`
    = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
    = note: required by `std::iter::IntoIterator::into_iter`
 
diff --git a/src/test/ui/variance/variance-associated-types2.nll.stderr b/src/test/ui/variance/variance-associated-types2.nll.stderr
new file mode 100644
index 00000000000..27d1e184416
--- /dev/null
+++ b/src/test/ui/variance/variance-associated-types2.nll.stderr
@@ -0,0 +1,12 @@
+error: lifetime may not live long enough
+  --> $DIR/variance-associated-types2.rs:13:12
+   |
+LL | fn take<'a>(_: &'a u32) {
+   |         -- lifetime `'a` defined here
+LL |     let _: Box<dyn Foo<Bar = &'a u32>> = make();
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/variance/variance-associated-types2.rs b/src/test/ui/variance/variance-associated-types2.rs
new file mode 100644
index 00000000000..6a095fce7ab
--- /dev/null
+++ b/src/test/ui/variance/variance-associated-types2.rs
@@ -0,0 +1,17 @@
+// Test that dyn Foo<Bar = T> is invariant with respect to T.
+// Failure to enforce invariance here can be weaponized, see #71550 for details.
+
+trait Foo {
+    type Bar;
+}
+
+fn make() -> Box<dyn Foo<Bar = &'static u32>> {
+    panic!()
+}
+
+fn take<'a>(_: &'a u32) {
+    let _: Box<dyn Foo<Bar = &'a u32>> = make();
+    //~^ ERROR mismatched types [E0308]
+}
+
+fn main() {}
diff --git a/src/test/ui/variance/variance-associated-types2.stderr b/src/test/ui/variance/variance-associated-types2.stderr
new file mode 100644
index 00000000000..52cdd6493b0
--- /dev/null
+++ b/src/test/ui/variance/variance-associated-types2.stderr
@@ -0,0 +1,18 @@
+error[E0308]: mismatched types
+  --> $DIR/variance-associated-types2.rs:13:42
+   |
+LL |     let _: Box<dyn Foo<Bar = &'a u32>> = make();
+   |                                          ^^^^^^ lifetime mismatch
+   |
+   = note: expected trait object `dyn Foo<Bar = &'a u32>`
+              found trait object `dyn Foo<Bar = &'static u32>`
+note: the lifetime `'a` as defined on the function body at 12:9...
+  --> $DIR/variance-associated-types2.rs:12:9
+   |
+LL | fn take<'a>(_: &'a u32) {
+   |         ^^
+   = note: ...does not necessarily outlive the static lifetime
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.