简体   繁体   中英

No trait inferred from structs that implement a trait in Rust?

I have 2 structs, both implement a trait:

pub trait TFilter {
    fn getText(&self) -> String;
}

pub struct CommentFilter {
    comment: String
}

impl TFilter for CommentFilter {
    fn getText(&self) -> String {
        return self.comment;
    }
}

impl CommentFilter {
    pub fn from_text(context: &Context, text: String) -> Self {
        return CommentFilter {
            comment: text
        }
    }
}

// ---

pub struct RegExpFilter {
    text: String
}

impl RegExpFilter {
    pub fn from_text(context: &Context, text: String) -> Self {
        return RegExpFilter {
            text
        }
    }
}

impl TFilter for RegExpFilter {
    fn getText(&self) -> String {
        return self.text
    }
}



But when trying to compile the code:

      let filter: dyn TFilter = if text.chars().nth(0).unwrap() == '!' {
                CommentFilter::from_text(context, text);
            } else {
                RegExpFilter::from_text(context, "test".to_string());
            };

i get an error:

error[E0308]: mismatched types
   --> src/filter.rs:113:20
    |
113 |               } else {
    |  ____________________^
114 | |                 RegExpFilter::from_text(context, "test".to_string());
115 | |             };
    | |_____________^ expected trait object `dyn filter::TFilter`, found `()`

What's wrong?

PS1. I found ; actually hurt, but now i'm getting:

expected trait object dyn filter::TFilter , found struct filter::CommentFilter

Can't it detect they actually implement the trait?

PS2. I had to explicitly specify : dyn TFilter as otherwise the compiler infers it from the first if branch and detected as CommentFilter (which obviously does not work for the negative branch).

Try without the semicolons:

      let filter: dyn TFilter = if text.chars().nth(0).unwrap() == '!' {
            CommentFilter::from_text(context, text)
        } else {
            RegExpFilter::from_text(context, "test".to_string())
        };

Since the compiler does not know the size of TFilter you need to store it on the heap wrapped in a Box like this:

      let filter: Box<dyn TFilter> = if text.chars().nth(0).unwrap() == '!' {
            Box::new(CommentFilter::from_text(context, text))
        } else {
            Box::new(RegExpFilter::from_text(context, "test".to_string()))
        };

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM