Skip to content

Commit

Permalink
Rollup merge of rust-lang#116730 - compiler-errors:unsoundness-tests-…
Browse files Browse the repository at this point in the history
…rpit, r=aliemjay

Add some unsoundness tests for opaques capturing hidden regions not in substs

Commit tests from rust-lang#116040 (comment) and rust-lang#59402 (comment) so that we make sure not to regress them the next time that we relax the opaque capture rules :^)
  • Loading branch information
matthiaskrgr authored Oct 14, 2023
2 parents 456139f + 3a0799d commit 77b578f
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// This test should never pass!

#![feature(type_alias_impl_trait)]

trait Captures<'a> {}
impl<T> 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() {}
Original file line number Diff line number Diff line change
@@ -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`.
32 changes: 32 additions & 0 deletions tests/ui/impl-trait/alias-liveness/rpit-hide-lifetime-for-swap.rs
Original file line number Diff line number Diff line change
@@ -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<T> Swap for Rc<RefCell<T>> {
fn swap(self, other: Self) {
<RefCell<T>>::swap(&self, &other);
}
}

fn hide<'a, 'b: 'a, T: 'static>(x: Rc<RefCell<&'b T>>) -> 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());
}
Original file line number Diff line number Diff line change
@@ -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<RefCell<&'b T>>) -> impl Swap + 'a {
| -- -------------- opaque type defined here
| |
| hidden type `Rc<RefCell<&'b T>>` 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<RefCell<&'b T>>) -> impl Swap + 'a + 'b {
| ++++

error: aborting due to previous error

For more information about this error, try `rustc --explain E0700`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// This test should never pass!

#![feature(type_alias_impl_trait)]

trait Captures<'a> {}
impl<T> 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() {}
Original file line number Diff line number Diff line change
@@ -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`.

0 comments on commit 77b578f

Please sign in to comment.