lnshi
lnshi

Reputation: 2898

Rust return trait object from Option.unwrap_or() for T: IntoIterator

Here is the playground link, also the code snippet as below:

fn test_inner<Tag: AsRef<str>, Tags: IntoIterator<Item = Tag> + std::fmt::Debug>(tags: Tags) {
    println!("{:?}", tags);
}

fn test<Tag: AsRef<str>, Tags: IntoIterator<Item = Tag> + std::fmt::Debug>(tags: Option<Tags>) {
    test_inner(tags.unwrap_or(["abc"]));
    // test_inner(tags.unwrap_or(["abc"].into_iter()));
}

fn main() {
    test(None::<&[&str]>);
}

Now i got error:

|     test_inner(tags.unwrap_or(["abc"]));
|                               ^^^^^^^ expected type parameter `Tags`, found array `[&str; 1]`
|
  = note: expected type parameter `Tags`
                      found array `[&str; 1]`

How should i return a trait object from the tags.unwrap_or() to satisfy the T: <Tag: AsRef<str>, Tags: IntoIterator<Item = Tag>>?

I am still learning rust, and my intention is wrapping the inner method so that the external caller can pass None to the tags parameter, if the approach direction is totally wrong, pls help to correct it also.

Upvotes: 2

Views: 287

Answers (1)

user4815162342
user4815162342

Reputation: 155296

Not sure if you're aware of that option, but a simple way to write test is using an explicit if:

fn test<Tag: AsRef<str>, Tags: IntoIterator<Item = Tag> + std::fmt::Debug>(tags: Option<Tags>) {
    if let Some(tags) = tags {
        test_inner(tags)
    } else {
        test_inner(["abc"])
    }
}

The difference between this and the version with unwrap_or() is that this uses two different types in two different calls to test_inner(). The version with unwrap_or() attempts to come up with a single value of type Tags, and that can't work because it's the caller who gets to choose the type of Tags. A specific value like ["abc"] simply doesn't have the same type as the generic type determined by the caller.

Upvotes: 1

Related Questions