我有这样的功能:
fn edit0<S: AsRef<str>>(&self, w: S) -> Stream<String> {
let owned_word = w.as_ref().to_string();
let g = Gn::new_scoped(|mut s| {
s.yield_(owned_word);
done!();
});
return g;
}
此编译正常。
现在,如果我输入通用参数的别名,就像这样:
type Word = dyn AsRef<str>;
fn edit0(&self, w: Word) -> Stream<String> {
let owned_word = w.as_ref().to_string();
let g = Gn::new_scoped(|mut s| {
s.yield_(owned_word);
done!();
});
return g;
}
我收到一个错误的说法:
fn edit0(&self, w: Word) -> Stream<String> {
| ^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `(dyn std::convert::AsRef<str> + 'static)`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
= note: all local variables must have a statically known size
= help: unsized locals are gated as an unstable feature
为什么会这样?
edit0
方法需要在编译时知道其参数的大小。但是,您使用的变量w
是类型AsRef<str>
的特征对象,并且其大小无法在编译时确定。相反,您有2个选择:
您可以如下使用Box
传递指针:
fn edit0(&self, w: Box<Word>) -> Stream<String>
或以下参考:
fn edit0(&self, w: &Word) -> Stream<String>
另一种选择是避免完全使用特征对象。您可以改为使edit0
成为通用方法,如下所示:
fn edit0(&self, w: impl AsRef<str>) -> Stream<String>
或
fn edit0<W: AsRef<str>>(&self, w: W) -> Stream<String>
使用这种方法,编译器执行所谓的“单态化”,即在编译时准确确定要为您的泛型参数传递哪种类型,并为每个调用生成多个非泛型函数。 this SO question
中很好地解释了同质化