如何为`AsRef`提供类型注释?

9
以下代码展示了问题的起源。由于 as_slice() 已经被弃用,因此建议使用 as_ref() 进行替换。
但是,在这种情况下使用时,需要添加类型注释。
let s = "Hi";             // This is a string slice
// warning: use of deprecated item: use std::convert::AsRef<str> instead, #[warn(deprecated)] on by default
assert!(s.replace("Hi", "Ho").as_slice() == "Ho");
// tests/lang.rs:120:35: 120:43 error: type annotations required: cannot resolve `collections::string::String : core::convert::AsRef<_>` [E0283]
// assert!(s.replace("Hi", "Ho").as_ref() == "Ho");

如何提供这样的类型注释?我唯一能找到有些适用的语法是<MyType as AsRef>::as_ref(),但我不知道如何在实例中使用它。

我正在使用rustc 1.0.0-nightly (be9bd7c93 2015-04-05) (built 2015-04-05)


顺便说一下:这个例子是基于我以前的一个测试,已经移植到了最新的rustc。在过去,仍然需要使用as_slice()。现在,人们只需依赖各种答案中描述的自动转换即可。 - Byron
2个回答

9

在您的情况下,即涉及到String&str的情况,最简单的方法是使用Index语法:

let s: String = "foo".to_string();
let slice: &str = &s[..]; // full range index

在您的情况下,这将给出以下结果:
let s = "Hi";
assert!(&s.replace("Hi", "Ho")[..] == "Ho");

然而,对于像as_ref()这样的特征方法,你也可以使用以下语法调用它们:

Trait::method(obj); // equivalent to obj.method();

这允许您像这样设置类型参数:

Trait::<T>::method(obj);

在您的情况下,另一种语法可以是这样的:
let s = "Hi";
assert!(AsRef::<str>::as_ref(&s.replace("Hi", "Ho")) == "Ho");

实际上,&s(即无切片)更加简单。 - user395760
@delnan 是的,确实没想到。但这并不总是有效的(例如,如果您想将一个String与一组&str值进行匹配,就像这样http://is.gd/VDuUjn) - Levans
是的,它必须在应用deref coercion的上下文中。不过,我们总是可以执行 let foo_str: &str = &foo; 并使用它。 - user395760

8
在这种情况下,您不需要任何花哨的东西: String 可以与 &str 进行比较(String 上有一个 PartialEq<&str> 实现),因此您可以直接进行比较:
let s = "Hi";
assert!(s.replace("Hi", "Ho") == "Ho");
// Or, if you prefer:
assert_eq!(s.replace("Hi", "Ho"), "Ho");

在现实生活中,你通常不需要调用as_ref,原因如下。


2
这不是 Deref 实现/解引用,而是 impl<'a> PartialEq<&'a str> for String: http://doc.rust-lang.org/std/string/struct.String.html - huon
@huon-dbaupp:说得好。我还没有停下来好好想过,但确实像==这样的东西不会自动引用/解引用。 - Chris Morgan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接