2016-04-24 9 views
0

Ich versuche zu verstehen, wie man ein paar einfache Dinge in Rust macht, aber am Ende kämpfe ich gegen den Border Checker und bin mir nicht sicher warum. Ich habe eine einfache Funktion geschrieben, in der Sie einen Dateinamen übergeben und den Pfad zu dieser Datei in Ihrem Home-Verzeichnis angeben.Wie kommt es, dass diese Rost-Funktion nicht funktioniert?

Hier ist das Programm:

use std::env; 

fn filename_in_homedir(filename: &str) -> Option<&str> { 
    let mut homedir = match env::home_dir() { 
     None => return None, 
     Some(p) => p 
    }; 
    homedir.push(filename); 
    homedir.to_str() 
} 

fn main() { 
    match filename_in_homedir(".ssh/id_rsa.pub") { 
     Some(s) => println!("{}", s), 
     None => println!("Oops can't get it") 
    }; 
} 

Wenn ich es versuche, den Aufbau bekomme ich diesen Fehler:

$ cargo build 
    Compiling homedir-test v0.1.0 (file:///home/user/code/homedir-test) 
src/main.rs:9:5: 9:12 error: `homedir` does not live long enough 
src/main.rs:9  homedir.to_str() 
        ^~~~~~~ 
src/main.rs:3:56: 10:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 3:55... 
src/main.rs:3 fn filename_in_homedir(filename: &str) -> Option<&str> { 
src/main.rs:4  let mut homedir = match env::home_dir() { 
src/main.rs:5   None => return None, 
src/main.rs:6   Some(p) => p 
src/main.rs:7  }; 
src/main.rs:8  homedir.push(filename); 
       ... 
src/main.rs:7:7: 10:2 note: ...but borrowed value is only valid for the block suffix following statement 0 at 7:6 
src/main.rs: 7  }; 
src/main.rs: 8  homedir.push(filename); 
src/main.rs: 9  homedir.to_str() 
src/main.rs:10 } 
error: aborting due to previous error 
Could not compile `homedir-test`. 

Ich verstehe nicht, warum nicht funktioniert. Wenn env::home_dir() fehlschlägt, gibt die Funktion None zurück. Wenn es erfolgreich ist, erhält die veränderbare Variable homedir ihren Wert (was eine std::path::PathBuf ist). An dieser Stelle sollte die homedir Variable dem Bereich filename_in_homedir gehören. Die nächste Zeile ändert homedir, um den Dateinamen am Ende hinzuzufügen, und das funktioniert gut. Die letzte Zeile ruft .to_str(), und Option<&str> selbst auf.

Da ich Rückkehr letztlich eine &str, die in homedir irgendwo zeigt ist, vielleicht, wenn der filename_in_homedir Umfang endet und homedir wird gelöscht, dass &str auch der Fall ist, weshalb es diesen Fehler zu werfen?

Wie ändere ich diese Funktion, um ordnungsgemäß zu funktionieren, und was mache ich falsch?

Antwort

2

Since I'm ultimately returning a &str that's pointing somewhere inside homedir, maybe when the filename_in_homedir scope ends and homedir gets deleted, that &str does too, which is why it's throwing this error?

Das ist richtig: Sie versuchen, einen Zeiger auf einen Wert von filename_in_homedir ‚s Stack-Frame im Besitz zurückzukehren, die gelöscht werden, sobald sie zurückkehrt, um den Zeiger ungültig zu machen. Sie müssen eine String anstelle einer &str zurückgeben. Hier ist ein Weg, es zu tun:

use std::env; 
use std::borrow::ToOwned; 

fn filename_in_homedir(filename: &str) -> Option<String> { 
    let mut homedir = match env::home_dir() { 
     None => return None, 
     Some(p) => p 
    }; 
    homedir.push(filename); 
    homedir.to_str().map(ToOwned::to_owned) 
} 

fn main() { 
    match filename_in_homedir(".ssh/id_rsa.pub") { 
     Some(s) => println!("{}", s), 
     None => println!("Oops can't get it") 
    }; 
} 
+0

Vielen Dank, das funktioniert super! Ich denke, ich sollte "std :: borrow" lesen, es scheint, als müsste ich es oft verwenden. – micah

Verwandte Themen