jpernst/rental

map_suffix on types without type parameter

Closed this issue · 4 comments

I have an API like the following

pub struct Tree;

pub struct Node<'t> {
    pub tree: &'t Tree,
}

impl<'t> Node<'t> {
    fn child(&self) -> Node<'t> {
        unimplemented!()
    }
}

To use child() with a rental wrapper, I'm having to use PhantomData with map_suffix, like below

#[macro_use]
extern crate rental;

use std::{rc::Rc, marker::PhantomData};

pub struct PhantomNode<'t, T>(Node<'t>, PhantomData<T>);

impl<'t> PhantomNode<'t, ()> {
    fn child(&self) -> Self {
        PhantomNode(self.0.child(), PhantomData)
    }
}

rental! {
    pub mod inner {
        use std::rc::Rc;

        #[rental(map_suffix = "T")]
        pub struct RentingNode<T: 'static> {
            tree: Rc<super::Tree>,
            node: super::PhantomNode<'tree, T>
        }
    }
}

type RentingNode = inner::RentingNode<()>;

fn child(node: RentingNode) -> RentingNode {
    node.map(|n| n.child())
}

Is there a better way to do this? Can we make map_suffix support types without type parameter?

The purpose of map_suffix is to map from one type parameter to another, so it wouldn't be able to really do anything if there are no type parameters.

Is there a cleaner approach for this use case of mapping the suffix to another value of the same type?

Unfortunately I overlooked this usecase. Wrapping it with a dummy type param like you're doing is probably the best workaround.

Hi, I found solution:

#[derive(Debug, Clone)]
pub struct T<'a> {
    i: &'a str 
} // This struct implements child()

#[rental(debug, clone)
pub struct OwnedT {
    source: Arc<Box<str>>,
    item: T<'source>
}

let parent: OwnedT = OwnedT::new(...); // Create parent.
let mut child = parent.clone();
    child.rent_mut(|c| *c = c.child());

It works because:

  • You have Rc - so cloning source works as well as mine Arc example
  • You don't have to use map_suffix at all.