From 3a0799d6d0c36a4c67603b12a15c481b46e82dd9 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 14 Oct 2023 13:25:46 +0000 Subject: [PATCH] Add some unsoundness tests for opaques capturing hidden regions not in substs --- .../rpit-hidden-erased-unsoundness.rs | 25 +++++++++++++++ .../rpit-hidden-erased-unsoundness.stderr | 18 +++++++++++ .../rpit-hide-lifetime-for-swap.rs | 32 +++++++++++++++++++ .../rpit-hide-lifetime-for-swap.stderr | 18 +++++++++++ .../tait-hidden-erased-unsoundness.rs | 28 ++++++++++++++++ .../tait-hidden-erased-unsoundness.stderr | 13 ++++++++ 6 files changed, 134 insertions(+) create mode 100644 tests/ui/impl-trait/alias-liveness/rpit-hidden-erased-unsoundness.rs create mode 100644 tests/ui/impl-trait/alias-liveness/rpit-hidden-erased-unsoundness.stderr create mode 100644 tests/ui/impl-trait/alias-liveness/rpit-hide-lifetime-for-swap.rs create mode 100644 tests/ui/impl-trait/alias-liveness/rpit-hide-lifetime-for-swap.stderr create mode 100644 tests/ui/impl-trait/alias-liveness/tait-hidden-erased-unsoundness.rs create mode 100644 tests/ui/impl-trait/alias-liveness/tait-hidden-erased-unsoundness.stderr diff --git a/tests/ui/impl-trait/alias-liveness/rpit-hidden-erased-unsoundness.rs b/tests/ui/impl-trait/alias-liveness/rpit-hidden-erased-unsoundness.rs new file mode 100644 index 0000000000000..6863a3c73badf --- /dev/null +++ b/tests/ui/impl-trait/alias-liveness/rpit-hidden-erased-unsoundness.rs @@ -0,0 +1,25 @@ +// This test should never pass! + +#![feature(type_alias_impl_trait)] + +trait Captures<'a> {} +impl Captures<'_> for T {} + +struct MyTy<'a, 'b>(Option<*mut &'a &'b ()>); +unsafe impl Send for MyTy<'_, 'static> {} + +fn step1<'a, 'b: 'a>() -> impl Sized + Captures<'b> + 'a { + MyTy::<'a, 'b>(None) +} + +fn step2<'a, 'b: 'a>() -> impl Sized + 'a { + step1::<'a, 'b>() + //~^ ERROR hidden type for `impl Sized + 'a` captures lifetime that does not appear in bounds +} + +fn step3<'a, 'b: 'a>() -> impl Send + 'a { + step2::<'a, 'b>() + // This should not be Send unless `'b: 'static` +} + +fn main() {} diff --git a/tests/ui/impl-trait/alias-liveness/rpit-hidden-erased-unsoundness.stderr b/tests/ui/impl-trait/alias-liveness/rpit-hidden-erased-unsoundness.stderr new file mode 100644 index 0000000000000..168a5aa18ec45 --- /dev/null +++ b/tests/ui/impl-trait/alias-liveness/rpit-hidden-erased-unsoundness.stderr @@ -0,0 +1,18 @@ +error[E0700]: hidden type for `impl Sized + 'a` captures lifetime that does not appear in bounds + --> $DIR/rpit-hidden-erased-unsoundness.rs:16:5 + | +LL | fn step2<'a, 'b: 'a>() -> impl Sized + 'a { + | -- --------------- opaque type defined here + | | + | hidden type `impl Captures<'b> + 'a` captures the lifetime `'b` as defined here +LL | step1::<'a, 'b>() + | ^^^^^^^^^^^^^^^^^ + | +help: to declare that `impl Sized + 'a` captures `'b`, you can add an explicit `'b` lifetime bound + | +LL | fn step2<'a, 'b: 'a>() -> impl Sized + 'a + 'b { + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0700`. diff --git a/tests/ui/impl-trait/alias-liveness/rpit-hide-lifetime-for-swap.rs b/tests/ui/impl-trait/alias-liveness/rpit-hide-lifetime-for-swap.rs new file mode 100644 index 0000000000000..4de2ffbb80870 --- /dev/null +++ b/tests/ui/impl-trait/alias-liveness/rpit-hide-lifetime-for-swap.rs @@ -0,0 +1,32 @@ +// This test should never pass! + +use std::cell::RefCell; +use std::rc::Rc; + +trait Swap: Sized { + fn swap(self, other: Self); +} + +impl Swap for Rc> { + fn swap(self, other: Self) { + >::swap(&self, &other); + } +} + +fn hide<'a, 'b: 'a, T: 'static>(x: Rc>) -> impl Swap + 'a { + x + //~^ ERROR hidden type for `impl Swap + 'a` captures lifetime that does not appear in bounds +} + +fn dangle() -> &'static [i32; 3] { + let long = Rc::new(RefCell::new(&[4, 5, 6])); + let x = [1, 2, 3]; + let short = Rc::new(RefCell::new(&x)); + hide(long.clone()).swap(hide(short)); + let res: &'static [i32; 3] = *long.borrow(); + res +} + +fn main() { + println!("{:?}", dangle()); +} diff --git a/tests/ui/impl-trait/alias-liveness/rpit-hide-lifetime-for-swap.stderr b/tests/ui/impl-trait/alias-liveness/rpit-hide-lifetime-for-swap.stderr new file mode 100644 index 0000000000000..cabba4bafafdd --- /dev/null +++ b/tests/ui/impl-trait/alias-liveness/rpit-hide-lifetime-for-swap.stderr @@ -0,0 +1,18 @@ +error[E0700]: hidden type for `impl Swap + 'a` captures lifetime that does not appear in bounds + --> $DIR/rpit-hide-lifetime-for-swap.rs:17:5 + | +LL | fn hide<'a, 'b: 'a, T: 'static>(x: Rc>) -> impl Swap + 'a { + | -- -------------- opaque type defined here + | | + | hidden type `Rc>` captures the lifetime `'b` as defined here +LL | x + | ^ + | +help: to declare that `impl Swap + 'a` captures `'b`, you can add an explicit `'b` lifetime bound + | +LL | fn hide<'a, 'b: 'a, T: 'static>(x: Rc>) -> impl Swap + 'a + 'b { + | ++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0700`. diff --git a/tests/ui/impl-trait/alias-liveness/tait-hidden-erased-unsoundness.rs b/tests/ui/impl-trait/alias-liveness/tait-hidden-erased-unsoundness.rs new file mode 100644 index 0000000000000..40efd941e338c --- /dev/null +++ b/tests/ui/impl-trait/alias-liveness/tait-hidden-erased-unsoundness.rs @@ -0,0 +1,28 @@ +// This test should never pass! + +#![feature(type_alias_impl_trait)] + +trait Captures<'a> {} +impl Captures<'_> for T {} + +struct MyTy<'a, 'b>(Option<*mut &'a &'b ()>); +unsafe impl Send for MyTy<'_, 'static> {} + +fn step1<'a, 'b: 'a>() -> impl Sized + Captures<'b> + 'a { + MyTy::<'a, 'b>(None) +} + +mod tait { + type Tait<'a> = impl Sized + 'a; + pub(super) fn step2<'a, 'b: 'a>() -> Tait<'a> { + super::step1::<'a, 'b>() + //~^ ERROR hidden type for `Tait<'a>` captures lifetime that does not appear in bounds + } +} + +fn step3<'a, 'b: 'a>() -> impl Send + 'a { + tait::step2::<'a, 'b>() + // This should not be Send unless `'b: 'static` +} + +fn main() {} diff --git a/tests/ui/impl-trait/alias-liveness/tait-hidden-erased-unsoundness.stderr b/tests/ui/impl-trait/alias-liveness/tait-hidden-erased-unsoundness.stderr new file mode 100644 index 0000000000000..baeec6d5892d1 --- /dev/null +++ b/tests/ui/impl-trait/alias-liveness/tait-hidden-erased-unsoundness.stderr @@ -0,0 +1,13 @@ +error[E0700]: hidden type for `Tait<'a>` captures lifetime that does not appear in bounds + --> $DIR/tait-hidden-erased-unsoundness.rs:18:9 + | +LL | type Tait<'a> = impl Sized + 'a; + | --------------- opaque type defined here +LL | pub(super) fn step2<'a, 'b: 'a>() -> Tait<'a> { + | -- hidden type `impl Captures<'b> + 'a` captures the lifetime `'b` as defined here +LL | super::step1::<'a, 'b>() + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0700`.