Во-первых, важно понимать разницу между временем жизни и областью действия.У ссылок есть время жизни, которые зависят от областей действия переменных, к которым они относятся.
Область действия переменной является лексической:
fn main() {
let string1 = String::from("long string is long"); // <-- scope of string1 begins here
let result;
{
let string2 = String::from("xyz"); // <-- scope of string2 begins here
result = longest(string1.as_str(), string2.as_str());
// <-- scope of string2 ends here
}
println!("The longest string is {}", result);
// <-- scope of string1 ends here
}
Когда вы создаете новую ссылку на переменную, время жизниссылки привязаны исключительно к области видимости переменной.К другим ссылкам прикреплена различная информация о времени жизни, в зависимости от того, откуда появилась ссылка и какая информация известна в этом контексте.Когда вы помещаете именованные аннотации времени жизни в тип, средство проверки типов просто гарантирует, что информация о времени жизни, прикрепленная к любым ссылкам, совместима с аннотациями.
fn main() {
let string1 = String::from("long string is long");
let result;
{
let string2 = String::from("xyz");
// The lifetime of result cannot be longer than `'a`
result = longest(string1.as_str(), string2.as_str());
// But a reference to string2 also has lifetime `'a`, which means that
// the lifetime `'a` is only valid for the scope of string2
// <-- i.e. to here
}
// But then we try to use it here — oops!
println!("The longest string is {}", result);
}
Мы сказали Rust, что время жизниссылки, возвращаемой самой длинной функцией, совпадает с меньшим временем жизни ссылок, переданных в.
В некотором роде.Мы действительно сообщили эту информацию Rust, однако, заемщик все равно проверит, верна ли она!Если это не уже истина, то мы получим ошибку.Мы не можем изменить правдивость этой информации, мы можем только сказать Rust об ограничениях, которые нам нужны, и он скажет нам, если мы правы.
В вашем примере вы могли бы сделать функцию main
действительнойизменив аннотации времени жизни на longest
:
fn longest<'a, 'b>(x: &'a str, y: &'b str) -> &'a str {
if x.len() > y.len() {
x
} else {
y // oops!
}
}
Но теперь вы получаете ошибку внутри longest
, поскольку она больше не отвечает требованиям: теперь она никогда не будет действительной для возвратаy
потому что его время жизни может быть короче 'a
.Фактически, единственные способы правильно реализовать эту функцию:
- Возврат
x
- Возврат среза
x
- Возврат
&'static str
- поскольку 'static
переживает все другие времена жизни - Используйте
unsafe
код