Nie znalazłem żadnych reguł w dokumentacji rdzy, które wyjaśniałyby, w jaki sposób eliminacja na całe życie dotyczy zamknięć. Weźmy prosty przykład:Dlaczego firma Rust nie może określić prawidłowego okresu użytkowania w prostych zamknięciach lub w informacjach, które są sprzeczne?
fn foo(s: &str) {
let id = |x: &str| x;
println!("{}", id(s));
}
fn main() {
foo("string");
}
myślałem, że zamknięcie w funkcji foo
będzie działać podobnie do następującego kodu:
fn foo(s: &str) {
struct Id; // A helper structure for closure
impl Id {
fn id(self: Self, x: &str) -> &str { &x }
}
let id = Id; // Creating a closure
println!("{}", id.id(s));
}
Ten ostatni działa dobrze, ale były nie do kompilowania i produkuje długi komunikat o sprzecznych wymagań życiowych:
t3.rs:2:24: 2:25 error: cannot infer an appropriate lifetime due to conflicting requirements [E0495]
t3.rs:2 let id = |x: &str| x;
^
t3.rs:2:24: 2:25 note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the block at 2:23...
t3.rs:2 let id = |x: &str| x;
^
t3.rs:2:24: 2:25 note: ...so that expression is assignable (expected `&str`, found `&str`)
t3.rs:2 let id = |x: &str| x;
^
<std macros>:3:11: 3:36 note: but, the lifetime must be valid for the expression at 3:10...
<std macros>:3 print ! (concat ! ($ fmt , "\n") , $ ($ arg) *)) ;
^~~~~~~~~~~~~~~~~~~~~~~~~
<std macros>:2:25: 2:56 note: in this expansion of format_args!
<std macros>:3:1: 3:54 note: in this expansion of print! (defined in <std macros>)
t3.rs:3:5: 3:27 note: in this expansion of println! (defined in <std macros>)
<std macros>:3:11: 3:36 note: ...so type `(&&str,)` of expression is valid during the expression
<std macros>:3 print ! (concat ! ($ fmt , "\n") , $ ($ arg) *)) ;
^~~~~~~~~~~~~~~~~~~~~~~~~
<std macros>:2:25: 2:56 note: in this expansion of format_args!
<std macros>:3:1: 3:54 note: in this expansion of print! (defined in <std macros>)
t3.rs:3:5: 3:27 note: in this expansion of println! (defined in <std macros>)
error: aborting due to previous error
zastanawiam się, dlaczego nie można wywnioskować Rust właściwego życia w prostych zamknięć, takich jak ten, który Napisałem powyżej. Ponadto, dlaczego kompilator uważa, że istnieją wymagania w zakresie konfliktu w ciągu jednego cyklu życia na przestrzeni.
Zdjąć ': & str' i to działa. '& Str' nie oznacza, co myślisz, że to znaczy. Nie mam teraz czasu, aby wyjaśnić, jak powinienem być w łóżku. –
Właściwie miałem na myśli "& str", ponieważ jest to konieczne w nieco bardziej złożonym przypadku. W każdym razie moje pytanie nie brzmiało, jak zrobić ten trywialny przykład do działania, ale jakie są tu zasady? Dlaczego kompilator znajduje tutaj sprzeczne wymagania? – svat
@ChrisMorgan: Jeśli masz trochę czasu, byłoby wspaniale, gdybyś mógł wyjaśnić, co się dzieje. Mam wrażenie, że może to być spowodowane stwierdzeniem "dla <'a>", ale nie jest to całkiem jasne ... a brak odpowiedzi po 20 godzinach wydaje się oznaczać, że nie jestem jedynym, który nie jest pewien co się dzieje^^ –