Closed
Description
use std::{cell::RefCell, fmt};
use self_cell::self_cell;
self_cell! {
struct WrongVarianceExample {
owner: (),
#[covariant]
dependent: Dependent,
}
}
// this type is not covariant
type Dependent<'a> = RefCell<Box<dyn fmt::Display + 'a>>;
Dependent<'a>
is not covariant in 'a
, however unsize coercion still allows an OWNED value
RefCell<Box<dyn fmt::Display + 'x>>
to be coerced into
RefCell<Box<dyn fmt::Display + 'y>>
for lifetimes 'x: 'y
, hence _assert_covariance
compiles fine.
Unsoundness follows.
fn main() {
let cell = WrongVarianceExample::new((), |_| RefCell::new(Box::new("")));
let s = String::from("Hello World");
// borrow_dependent unsound due to incorrectly checked variance
*cell.borrow_dependent().borrow_mut() = Box::new(s.as_str());
// s still exists
cell.with_dependent(|_, d| println!("{}", d.borrow()));
drop(s);
// s is gone
cell.with_dependent(|_, d| println!("{}", d.borrow()));
}
Hello World
p����U���
A better _assert_covariance
needs to check whether coercing the Dependent
s behind a level of indirection is still possible.
Options include coercing Box<Dependent<'x>>
to Box<Dependent<'y>>
, or (more close to the actual use-case) coercing &'y Dependent<'x>
into &'y Dependent<'y>
.
Metadata
Metadata
Assignees
Labels
No labels