Help getting this code snippet to compile

trait TMRecord {}

#[derive(Debug)]
struct A {
    name: String,
}

impl A {
    pub fn new(s: &str) -> Self {
        Self {
            name: s.to_string(),
        }
    }
}

#[derive(Debug)]
struct B {
    name: String,
}

impl B {
    pub fn new(s: &str) -> Self {
        Self {
            name: s.to_string(),
        }
    }
}

#[derive(Debug)]
pub struct Record<T> {
    pub r: T,
}

impl<T> Record<T> {
    pub fn new(s: T) -> Record<T> {
        Record { r: s }
    }
}
impl TMRecord for A {}
impl TMRecord for B {}

fn parse(s: &str, k: &str) -> Option<Record<T>> {
    match k {
        "byName" => Some(Record::<A>::new(A::new(s))),
        "byNbr" =>  Some(Record::<B>::new(B::new(s))),
        _ => None,
    }
}
fn main() {
    let s = "Some string key";

    let res = parse(&s, &"byName");
    let res = parse(&s, &"byNbr");
}

(Playground)

Errors:

   Compiling playground v0.0.1 (/playground)
error[E0412]: cannot find type `T` in this scope
  --> src/main.rs:43:45
   |
4  | struct A {
   | -------- similarly named struct `A` defined here
...
43 | fn parse(s: &str, k: &str) -> Option<Record<T>> {
   |                                             ^
   |
help: a struct with a similar name exists
   |
43 | fn parse(s: &str, k: &str) -> Option<Record<A>> {
   |                                             ~
help: you might be missing a type parameter
   |
43 | fn parse<T>(s: &str, k: &str) -> Option<Record<T>> {
   |         +++

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

Rust doesn't really work like this:

fn parse(s: &str, k: &str) -> Option<Record<T>> {
    match k {
        "byName" => Some(Record::<A>::new(A::new(s))),
        "byNbr" =>  Some(Record::<B>::new(B::new(s))),
        _ => None,
    }
}

The return type of a function needs to be known when compiling the code, and cannot depend on runtime parameters such as a string.

One option is to return an enum:

enum Either<T1, T2> {
    Left(T1),
    Right(T2),
}

impl<T1, T2> TMRecord for Either<T1, T2>
where
    T1: TMRecord,
    T2: TMRecord,
{}

fn parse(s: &str, k: &str) -> Option<Record<Either<A, B>>> {
    match k {
        "byName" => Some(Record::new(Either::Left(A::new(s)))),
        "byNbr" =>  Some(Record::new(Either::Right(B::new(s)))),
        _ => None,
    }
}
1 Like

Thank you!! That did the trick

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.