Generic declaration of trait bounded variable

Greetings,

I have a trait bounded struct. I'd like to declare a variable, but would like to avoid specifying the exact type.

use std::path::Path;

pub struct Foo<P>
where
    P: AsRef<Path>,
{
    file_path: P,
}

impl<P> Foo<P>
where
    P: AsRef<Path>,
{
    fn new(
        file_path: P,
    ) -> Self {
        Self {
            file_path,
        }
    }
}

fn main(
) {
    let foo: Foo<&str>;
    let foo: Foo<&Path>;

    let some_condition = false;

    if some_condition {
        foo = Foo::new(
            "/etc/passwd",
        );
    }
    else {
        foo = Foo::new(
            Path::new("/etc/passwd"),
        );
    }
}

but I don't know how to generalize the:

    let foo: Foo<&str>;
    let foo: Foo<&Path>;

When I pick one of the two options, I get an error like:

   Compiling pathbuf_struct v0.1.0 (/home/mzagrabe/git/internal/rust/projects/pathbuf_struct)
error[E0308]: mismatched types
  --> src/main.rs:32:13
   |
32 |             "/etc/passwd",
   |             ^^^^^^^^^^^^^ expected struct `Path`, found `str`
   |
   = note: expected reference `&Path`
              found reference `&'static str`

For more information about this error, try `rustc --explain E0308`.
error: could not compile `pathbuf_struct` due to previous error

Is it possible to declare a trait bounded type without specifying a specific type?

Thanks for any help!

-m

A variable can't have two different types at the same time. In this specific case, you can just not declare Foo as generic, and initialize its field with the already as_ref()-converted value.

Hi @H2CO3 ,

Could you spare a code sample of what you are describing?

I understand the first sentence, however how do I "not declare Foo as generic"?

Thanks,

-m

struct Foo<'a> {
    file_path: &'a Path,
}

Also note that most "executable" (ie. non-declaration) constructs in Rust are expressions, so declaring an uninitialized variable and assigning to it twice is unnecessary and non-idiomatic. Just use the value of the if expression:

    let foo = if some_condition {
        Foo {
            file_path: "/etc/passwd".as_ref(),
        }
    } else {
        Foo {
            file_path: Path::new("/etc/passwd"),
        }
    };

Thanks for the insight, @H2CO3. I appreciate the help.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.