Vincent
Vincent

Reputation: 443

How deal with Option<Ref<T>> and Option<&T>

In the example we assume that we have two codes that has their perimeter and tested individually.

The code 1 return the type Option<Rc<RefCell<T>>> and code 2 that have to consume &T.

I have an issues with the following example playground.

use std::cell::RefCell;
use std::rc::Rc;

// Code 2
fn action(data_1: Option<&i32>, data_2: Option<&i32>) {
    println!("data_1:{:?}, data_2:{:?}", data_1, data_2);
}

fn main() {
    // Code 1
    let data_1 = Some(Rc::new(RefCell::new(2)));
    let data_2 = Some(Rc::new(RefCell::new(5)));

    let ref_data_1 = data_1.as_ref().map(|r| r.borrow());
    let ref_data_2 = data_2.as_ref().map(|r| r.borrow());

    action(ref_data_1, ref_data_2); // Error: mismatched types
}

The example fail because of mismatch types between Ref<T> is found and &T is expected. My only way that I have founded is to change Option<&i32> to Option<Ref<i32>> but that break the interface of code 2.

Upvotes: 0

Views: 313

Answers (1)

Peter Hall
Peter Hall

Reputation: 58725

You can change the action function to accept either Option<&i32> or Option<Ref<i32>> by using a generic argument with a Deref<Target = i32> bound, which both of those types satisfy:

use std::ops::Deref;

fn action<T>(data_1: Option<T>, data_2: Option<T>)
where
    T: Deref<Target = i32>,
{
    println!("data_1:{:?}, data_2:{:?}", data_1.as_deref(), data_2.as_deref());
}

If you can't or don't want to change the signature of action, then you can call as_deref() on the arguments when you pass them in:

action(ref_data_1.as_deref(), ref_data_2.as_deref());

Upvotes: 4

Related Questions