2015-07-11 46 views
9

這不完全是一個慣用的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, 
    } 
} 

鏽返回錯誤:

<std macros>:3:43: 3:46 error: mismatched types:
expected str ,
found collections::string::String
(expected str ,
found struct collections::string::String) [E0308]
<std macros>:3 $ crate:: result:: Result:: Ok (val) => val , $ crate:: result:: Result::
<std macros>:1:1: 6:48 note: in expansion of try!
<std macros>:3:43: 3:46 help: run rustc --explain E0308 to see a detailed explanation
error: aborting due to previous error

如果我不是捕捉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, 
    } 
} 

爲什麼let foo_result = try!(foo()); value.push_str(&foo_result);工作但value.push_str(&try!(foo()));不?從我的天真的角度來看,它們看起來是等價的,所以我不確定Rust的關鍵部分我不理解。

+0

這是一個非常好的MVCE。不是答案,但仍然是我通常所做的一些事情:http://is.gd/PZKWz0 – ArtemGr

+0

即使使用value.push_str(&& try!(foo()))也可以解決問題。 – eulerdisk

+0

謝謝@Shepmaster。你是完全正確的。 – Cornstalks

回答

12

看來,編譯器不同地處理塊的強制轉換。 try!()擴展爲match塊,編譯器無法自動解除它。你的問題可以縮寫如下:

fn f(_: &str) {} 

fn main() { 
    let x = "Akemi Homura".to_owned(); 

    f(&x); // OK 
    f(&(x)); // OK 
    f(&{x}); // Error 
} 

我認爲這是編譯器的錯誤。如RFC 401中所述,編譯器應該能夠使用適當的類型強制塊。

blocks, if a block has type U , then the last expression in the block (if it is not semicolon-terminated) is a coercion site to U . This includes blocks which are part of control flow statements, such as if/else , if the block has a known type.

作爲一種解決辦法,我建議你String轉換成&str直接使用&*try()&try()[..]。兩者具有相同的含義,但我更喜歡前者。

我打開了一個問題來跟蹤它。 https://github.com/rust-lang/rust/issues/26978

相關問題