这不是一个惯用的MVCE,但它应该说明这个问题.给出以下代码:
fn foo() -> Result<String, i32> {
return Ok("world".to_string());
}
fn bar() -> Result<String, i32> {
let mut value = String::new();
value.push_str(&try!(foo())); // this line here
return Ok("Hello ".to_string() + &value);
}
fn main() {
match bar() {
Ok(message) => println!("{}", message),
_ => return,
}
}
Run Code Online (Sandbox Code Playgroud)
Rust返回错误:
<std macros>:3:43: 3:46错误:不匹配的类型:
预期str,
找到collections::string::String
(预期str,
找到结构collections::string::String)[E0308]
<std macros>:3 $ crate:: result:: Result:: Ok ( val ) => val , $ crate:: result:: Result::
<std macros>:1:1: 6:48注意:在扩展try!
<std macros>:3:43: 3:46帮助:运行rustc --explain E0308以查看详细说明
错误:由于先前的错误而中止
如果我改为捕获结果try!并单独应用于&结果,它可以工作(并打印出来Hello world):
fn foo() -> Result<String, i32> {
return Ok("world".to_string());
}
fn bar() -> Result<String, i32> {
let mut value = String::new();
let foo_result = try!(foo()); // capture the result of try!
value.push_str(&foo_result); // now use the result with &
return Ok("Hello ".to_string() + &value);
}
fn main() {
match bar() {
Ok(message) => println!("{}", message),
_ => return,
}
}
Run Code Online (Sandbox Code Playgroud)
为什么let foo_result = try!(foo()); value.push_str(&foo_result);工作但value.push_str(&try!(foo()));不是?从我天真的角度来看,它们似乎是等价的,所以我不确定Rust的哪个关键部分我不理解.
Bar*_*Lee 12
似乎编译器以不同方式处理块的强制.try!()被扩展为match块,编译器无法自动解除它.您的问题可以缩写如下:
fn f(_: &str) {}
fn main() {
let x = "Akemi Homura".to_owned();
f(&x); // OK
f(&(x)); // OK
f(&{x}); // Error
}
Run Code Online (Sandbox Code Playgroud)
我认为这是编译器的一个错误.如RFC 401中所述,编译器应该能够使用适当的类型强制阻塞块.
块,如果一个块有类型
U,那么块中的最后一个表达式(如果它不是以分号结尾)是一个强制站点U.这包括作为控制流语句的一部分的块,例如if/else,如果块具有已知类型.
作为一种解决方法,我建议您直接转换String为&str使用&*try()或&try()[..].两者都有相同的含义,虽然我更喜欢前者.
我打开了一个问题来跟踪这一点.https://github.com/rust-lang/rust/issues/26978
| 归档时间: |
|
| 查看次数: |
247 次 |
| 最近记录: |