2015-10-11 9 views
7

Ich lerne Rust und ich habe in ein verwirrendes Verhalten geraten. Der folgende Code kompiliert fein und funktioniert wie erwartet (bearbeiten: added anderen Code als Testfunktion, weggelassen vorher):Typ Inferenz und Kreditaufnahme vs Eigentumsübertragung

struct Container<'a> { 
    contents : &'a mut i32, 
} 

fn main() { 
    let mut one = Container { contents: &mut 5 }; 
    test(&mut one); 
    println!("Contents: {}",one.contents); 
} 

fn test<'a>(mut x : &'a mut Container) { 
    *x.contents += 1; 
    let y = x; 
    *y.contents += 1; 
    x = y; 
    println!("{:?}",*x.contents) 
} 

nun in der Erklärung

let y = x; 

der Typ abgeleitet. Da x vom Typ &'a mut Container, dachte ich, dass dies wäre gleichbedeutend:

let y: &'a mut Container = x; 

Aber wenn ich das tue, der Compiler nimmt Ausgabe:

test_3.rs:25:5: 25:10 error: cannot assign to `x` because it is borrowed 
test_3.rs:25  x = y; 
       ^~~~~ 
test_3.rs:23:33: 23:34 note: borrow of `x` occurs here 
test_3.rs:23  let y: &'a mut Container = x; 

Wie wird x nicht von diesem Punkt in der geliehene richtig funktionierendes Beispiel? Getestet habe ich durch die Linie x = y; von der korrekt funktionierende Version weggelassen und die Compiler sagte:

test_3.rs:24:13: 24:14 note: `x` moved here because it has type `&mut Container<'_>`, which is moved by default 

So bin ich eine Bewegung bekommen, wenn ich den Typen nicht explizit definieren, sondern Borrow anders. Was passiert, wie bekomme ich das gleiche Verhalten wie vorher, während ich explizit den Typ gebe, und was bewirkt das Bewegungsverhalten in einem Fall, sondern leiht es in dem anderen?

Edited mit vollem Programm

+2

Vielleicht ein [Beispiel wie folgt] (http://is.gd/Ht32Jl)? – Shepmaster

+0

Hallo, tut mir leid; Hier ist ein [der vollständige Code] (http://is.gd/9oz2kT). Ihr Beispiel erfasst das Problem genau. –

+1

Related: http://stackoverflow.com/q/32154387/1763356 – Veedrac

Antwort

6

Wenn Sie

let y = x; 

eine Bewegung geschieht tun. x wird sozusagen geleert und das Eigentum wird auf y übertragen.

Wenn Sie das tun, entweder von

let y: &mut _ = x; 
let y: &'a mut _ = x; 

x wird neu aufgenommen, die Lebensdauer zu unterstützen entsprechen. Dies führt in etwa

let y: &mut _ = &mut *x; 
let y: &'a mut _ = &mut *x; 

Diese x nicht leere Blätter, eine aliased wandelbar borrow halten. Zuweisen muss also auf y warten, um zerstört zu werden. Alternativ können Sie im Voraus bewegen es

let tmp = x; 
let y: &'a mut _ = tmp; 

Ich lasse es nicht offensichtliche Verhalten ist, und es ist schade, dass Sie nicht den Inhalt eines Wertes ohne Kreditaufnahme den gesamten Wert leihen.

+1

* mit einem Aliasing veränderbaren Borgen * - Ich hatte den Eindruck, dass das ist eindeutig eine Sache, die Safe Rust verbietet? – Shepmaster

+3

Rust verbietet keine Alias-Mutable-Kredite - es verbietet die Verwendung von mehr als einer auf einmal, oder überlappt sie in nicht-lexikalischen Weisen. Wenn Sie '& mut x' schreiben, ist' x' immer noch ein gültiger Stapelspeicherort - es ist einfach nicht erlaubt, darauf zu lesen oder zu schreiben. – Veedrac

+0

Interessant. Ich habe mich immer gewundert, welche genauen Regeln der Compiler verwendet, um Bewegung-gegen-Wiederaufnahme zu bestimmen.Bis jetzt nahm ich an, dass das erneute Aufnehmen nur in Funktionsaufrufen erfolgt, bei denen die Funktion ein & mut nimmt. Aber anscheinend ist es expliziter * innerhalb * einer Funktion, sich auch für einen Reborrow zu qualifizieren. – sellibitze

Verwandte Themen