I've managed to cook up three scenarios which to me seem on the surface to be the same, but behave differently, and I would appreciate if someone could clarify to me why...
The first scenario fails to complile, as I would actually expect :
fn main() {
let data = get_data();
println!("{}", data);
}
fn get_data() -> &'static str {
let x: String = String::from("hello");
return x.as_str(); // always fails with ownership issue
}
Run Code Online (Sandbox Code Playgroud)
Fails as expected: returns a reference to data owned by the current function
However the next two confound me given the above expectation:
This succeeds:
fn get_data() -> &'static str { // requires `'static` lifetime
let x = std::path::Path::new("thing");
match x.to_str() {
None => "",
Some(s) => s,
}
}
Run Code Online (Sandbox Code Playgroud)
I would have thought s was owned in the function so couldn't be returned, but in this case, adding &'static str as return type (compiler is unhappy otherwise) allows the operation.
More puzzlingly still, the following works (compiler is happy), and does not require the 'static lifetime:
use std::path::Path;
pub fn parent_of(caller_file: &str) -> &str { // `'static` not required ??
let caller_file_p: &Path = Path::new(caller_file);
match caller_file_p.parent() {
None => if caller_file.starts_with("/") { "/" } else { "." },
Some(p) => match p.to_str() {
None => {
eprintln!("Bad UTF-8 sequence specified : '{}'", caller_file);
std::process::exit(100);
},
Some(s) => s,
}
}
}
Run Code Online (Sandbox Code Playgroud)
I'm sure there's some methodical explanation as to the nuances of each scenario, but it eludes me. Clarifications most appreciated.
在第二种情况下,您将 a &'static str(字符串文字)转换为&Pathvia Path::new()。Path::new()保留引用的生命周期(因为Path不是自有类型,而是借用类型,基本上是其他人拥有的字节的一些包装器,无论是 a PathBuf、 a String,还是字符串文字情况下的二进制本身)。所以你得到了&'static PathBuf。将其转换回&strviaPath::to_str()你会得到&'static str.
在第三种情况下,您有字符串文字 ( &'static strs) 且&Path生命周期为caller_file。如果我们注释生命周期:
pub fn parent_of<'caller_file>(caller_file: &'caller_file str) -> &'caller_file str {
// `'static` not required ??
let caller_file_p: &'caller_file Path = Path::new(caller_file);
match caller_file_p.parent() {
None => {
if caller_file.starts_with("/") {
"/" // `&'static str`
} else {
"." // `&'static str`
}
}
Some(p) => match p.to_str() {
None => {
eprintln!("Bad UTF-8 sequence specified : '{}'", caller_file);
std::process::exit(100);
}
Some(s) => s, // `s` is `&'caller_file str`
},
}
}
Run Code Online (Sandbox Code Playgroud)
'caller_file假定返回类型的生命周期是通过生命周期省略规则实现的。字符串文字"/"和"."是&'static str,并且由于'static大于(或等于)任何生命周期,因此它们可以缩小为&'caller_file str。caller_file_pis &'caller_file Path,它的to_str()is &'caller_file str,所以这按预期工作。
| 归档时间: |
|
| 查看次数: |
123 次 |
| 最近记录: |