没有从在 Rust 中实现特征的结构推断出特征?

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

我有 2 个结构,都实现了一个特征:

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
    }
}



但是在尝试编译代码时:

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

我得到一个错误:

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 `()`

怎么了?

PS1。我发现 ; 实际上受伤了,但现在我得到:

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

它不能检测到他们实际上实现了特征吗?

PS2。我必须明确指定 : dyn TFilter 否则编译器会从第一个 if 分支推断它并检测为 CommentFilter (这显然不适用于负分支)。

试试不用分号:

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

由于编译器不知道 TFilter 的大小,因此您需要将其存储在包装在 Box 中的堆中,如下所示:

      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()))
        };