error[E0521]: borrowed data escapes outside of method
--> src/event.rs:21:9
|
20 | fn add_assign(&mut self, rhs: &dyn Fn(Sig)->()) {
| --- - let's call the lifetime of this reference `'1`
| |
| `rhs` is a reference that is only valid in the method body
21 | self.listeners.push(MutRc::new(rhs));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| `rhs` escapes the method body here
| argument requires that `'1` must outlive `'static`
|
= note: requirement occurs because of a mutable reference to `Vec<MutRc<dyn Fn(Sig)>>`
= note: mutable references are invariant over their type parameter
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
Its not escaping because my MutRc<T> is a mutable reference counter.
MutRc source
use std::{ alloc::{GlobalAlloc, Layout, System}, any::{Any, TypeId}, ffi::c_void, marker::PhantomData, ops::*, ptr::{self, drop_in_place, null_mut}};
use libc;
struct MRcMeta{
pub borrows:usize,
pub copies:usize,
pub total_copies:usize,
pub is_valid:bool,
pub layout:Layout,
pub typ:TypeId,
pub vtable:*const usize
}
struct FatPtrPre{
data:*const u8,
vtable:*const usize
}
pub struct MutRc<T:?Sized>{
data:*mut u8,
metadata:*mut MRcMeta,
isweak:bool,
phantom:PhantomData<T>
}
#[derive(Debug)]
pub enum MRCCastErr {
DifferentType,
Borrowed,
Invalid
}
impl<T:?Sized> MutRc<T>{
pub fn new(obj:&T) -> MutRc<T>{
unsafe {
let meta = libc::malloc(size_of::<MRcMeta>()) as *mut MRcMeta;
let layout = Layout::for_value(obj);
let typ = layout.type_id();
let (objptr,objvt) = std::mem::transmute_copy::<&T,(*const u8,*const usize)>(&obj);
meta.write(MRcMeta {
borrows: 0,
copies: 1,
total_copies:1 ,
is_valid:true,
layout:layout,
typ:typ,
vtable:objvt
});
let data = System.alloc(layout);
data.copy_from(objptr, size_of_val(obj));
MutRc{ data: data, metadata: meta, isweak: false ,phantom:PhantomData::default()}
}
}
pub fn to_weak(&self) -> MutRc<T>{
unsafe{
self.meta().total_copies+=1;
}
MutRc { data: self.data, metadata: self.metadata, isweak: true ,phantom:PhantomData::default()}
}
pub fn to_strong(&self) -> MutRc<T>{
unsafe{
let meta = self.meta();
meta.total_copies+=1;
meta.copies+=1;
}
MutRc { data: self.data, metadata: self.metadata, isweak: false ,phantom:PhantomData::default()}
}
unsafe fn to_fat(&self) -> *mut T{
unsafe{
std::mem::transmute_copy::<FatPtrPre,*mut T>(&FatPtrPre{
data:self.data,
vtable:self.meta().vtable
})
}
}
unsafe fn access(&self)-> Option<&mut T>{
unsafe {
if self.meta().is_valid {
self.to_fat().as_mut()
} else { None }
}
}
unsafe fn meta(&self) -> &mut MRcMeta{
unsafe{self.metadata.as_mut()}.unwrap()
}
pub fn as_ref(&self) -> MutRcRef<T>{
unsafe{self.meta().borrows+=1;}
MutRcRef::new(self, false)
}
pub fn as_mut(&self) -> Option<MutRcRef<T>>{
unsafe {
let meta = self.meta();
if meta.borrows != 0 {
return None
}
meta.borrows+=1;
Some(MutRcRef::new(self, true))
}
}
unsafe fn clean(&mut self) {
unsafe {
let meta = self.metadata.as_mut().unwrap();
if self.data.is_null() || !meta.is_valid{
return;
}
meta.total_copies-=1;
if !self.isweak {
meta.copies-=1;
if meta.copies <= 0 {
drop_in_place(self.data);
libc::free(self.data as *mut c_void);
meta.is_valid = false;
}
}
if meta.total_copies <= 0 {
libc::free(self.metadata as *mut c_void);
self.metadata = null_mut();
}
}
}
pub fn is_valid(&self)-> bool{
unsafe {
(!self.metadata.is_null()) && self.meta().is_valid && (!self.data.is_null())
}
}
pub fn ptreq_mutrc(&self,other:MutRc<T>) -> bool{
ptr::addr_eq(self.data,other.data)
}
pub fn ptreq_ref(&self,other:&T) -> bool{
ptr::addr_eq(self.data,other)
}
pub fn is_borrowed(&self) -> bool{
unsafe {
self.meta().borrows != 0
}
}
pub unsafe fn cast_to_ref<Target:'static>(&self) -> Result<&Target,MRCCastErr>{
unsafe {
if self.meta().typ != TypeId::of::<Target>() {
return Err(MRCCastErr::DifferentType)
}
if !self.is_valid() {
return Err(MRCCastErr::Invalid)
}
Ok((self.data as *mut Target).as_ref().unwrap())
}
}
pub unsafe fn cast_to_mut<Target:'static>(&mut self) -> Result<&mut Target,MRCCastErr>{
unsafe {
if self.meta().typ != TypeId::of::<Target>() {
return Err(MRCCastErr::DifferentType)
}
if self.is_borrowed() {
return Err(MRCCastErr::Borrowed)
}
if !self.is_valid() {
return Err(MRCCastErr::Invalid)
}
Ok((self.data as *mut Target).as_mut().unwrap())
}
}
}
impl<T:?Sized> Clone for MutRc<T>{
fn clone(&self) -> Self {
if self.isweak {self.to_weak()} else {self.to_strong()}
}
fn clone_from(&mut self, source: &Self) {
if source.data == self.data && (!source.isweak){
return;
}
unsafe{
self.clean();
self.data=source.data;
self.metadata=source.metadata;
self.isweak=source.isweak;
self.meta().total_copies+=1;
if !self.isweak {
self.meta().copies+=1;
}
}
}
}
impl<T:?Sized> Drop for MutRc<T>{
fn drop(&mut self) {
unsafe {self.clean();}
}
}
impl<T:?Sized> Deref for MutRc<T>{
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe {self.to_fat().as_ref().unwrap()}
}
}
impl<T:?Sized> DerefMut for MutRc<T>{
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe{
if self.meta().borrows != 0 {
panic!("cannot mutably borrow an already borrowed value")
}
self.to_fat().as_mut().unwrap()
}
}
}
struct MutRcRef<T:?Sized>{
data:*mut u8,
metadata:*mut MRcMeta,
ismut:bool,
phantom:PhantomData<T>
}
impl<T:?Sized> MutRcRef<T>{
fn new(obj:&MutRc<T>,ismut:bool) -> MutRcRef<T>{
MutRcRef {
data: obj.data,
metadata:obj.metadata,
ismut: ismut,
phantom:PhantomData::default()
}
}
unsafe fn to_fat(&self) -> *mut T{
unsafe{
std::mem::transmute_copy::<FatPtrPre,*mut T>(&FatPtrPre{
data:self.data,
vtable:self.metadata.as_ref().unwrap().vtable
})
}
}
}
impl<T:?Sized> Deref for MutRcRef<T>{
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe {self.to_fat().as_ref().unwrap()}
}
}
impl<T:?Sized> DerefMut for MutRcRef<T>{
fn deref_mut(&mut self) -> &mut Self::Target {
if !self.ismut {
panic!("is not mutable");
}
unsafe {self.to_fat().as_mut().unwrap()}
}
}
impl<T:?Sized> Clone for MutRcRef<T>{
fn clone(&self) -> Self {
if self.ismut {
panic!("cannot copy a mutable reference")
}
unsafe{
self.metadata.as_mut().unwrap().borrows+=1;
}
MutRcRef { data: self.data, metadata: self.metadata, ismut:self.ismut, phantom:PhantomData::default() }
}
}
impl<T:?Sized> Drop for MutRcRef<T>{
fn drop(&mut self) {
unsafe{
self.metadata.as_mut().unwrap().borrows-=1;
}
}
}