2015-01-13 14 views
5

Tôi có một vấn đề với các checker mượn khi sử dụng những đặc điểm như tham số kiểu trong một cấu trúc:kiểm tra Mượn thất bại khi sử dụng những đặc điểm như tham số kiểu

trait Trait {} 

struct FooBar; 
impl Trait for FooBar{} 

struct Observer<Arg> { 
    action: Box<Fn(Arg) + Send>, 
    // Other fields 
} 

impl <Arg> Observer<Arg> { 
    fn new(action: Box<Fn(Arg) + Send>) -> Observer<Arg> { 
     Observer{action: action} 
    } 

    fn execute(&self, arg: Arg) { 
     (*self.action)(arg); 
    } 
} 

fn test() { 
    let mut foobar = FooBar; 
    { 
     let mut observer = Observer::new(Box::new(|&: param: &mut Trait| { 
      // do something with param here 
     })); 
     observer.execute(&mut foobar); // First borrow passes ... 
     observer.execute(&mut foobar); // This fails as "foobar" is already borrowed 
    } // The previous borrow ends here (lifetime of "observer") 
} 

Đầu ra là:

error: cannot borrow `foobar` as mutable more than once at a time 
    observer.execute(&mut foobar); // This fails as "foobar" is already borrowed 
          ^~~~~~ 
note: previous borrow of `foobar` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `foobar` until the borrow ends 
    observer.execute(&mut foobar); // First borrow passes ... 
          ^~~~~~ 
note: previous borrow ends here 
{ 
... 
} // The previous borrow ends here (lifetime of "observer") 
^ 

Tuy nhiên, ví dụ sau hoạt động:

trait Trait {} 

struct FooBar; 
impl Trait for FooBar{} 

struct Observer { 
    action: Box<Fn(&mut Trait) + Send>, 
    // Other fields 
} 

impl Observer { 
    fn new(action: Box<Fn(&mut Trait) + Send>) -> Observer { 
     Observer{action: action} 
    } 

    fn execute(&self, arg: &mut Trait) { 
     (*self.action)(arg); 
    } 
} 

fn test() { 
    let mut foobar = FooBar; 
    { 
     let mut observer = Observer::new(Box::new(|&: param: &mut Trait| { 
      // do something with param here 
     })); 
     observer.execute(&mut foobar); 
     observer.execute(&mut foobar); 
    } 
} 

Điều này có vẻ thực sự lạ đối với tôi, ví dụ thứ hai chỉ là một instanti ation của ví dụ đầu tiên, và tôi có thể (đau đớn) thực hiện điều tương tự với các macro.

Tôi đoán đây là khá phức tạp, như tôi cần phải biết kiểu của tham số thực hiện bởi việc đóng cửa, nhưng tôi không cần phải lưu trữ tài liệu tham khảo này ...

Đây có phải là một lỗi trong vay người kiểm tra? Hay tôi đang làm gì sai?

rustc 1.0.0-nightly (44a287e6e 2015-01-08 17:03:40 -0800) 

EDIT 1: precised các trường hợp sử dụng

EDIT 2: Như đã giải thích trong câu trả lời dưới đây, vấn đề là các checker mượn buộc cuộc đời của Observer<&mut Type> để được giống như các &mut Type, vì vậy trong thực tế vấn đề không liên quan đến thực tế là chúng ta sử dụng một đặc điểm như một tham số kiểu (nó giống như một cấu trúc thực tế).
Vì vậy, trong trường hợp của tôi, tôi có thể có một cách giải quyết bằng cách định nghĩa Observer<Arg> như thế này:

struct Observer<Arg> { 
    action: Box<Fn(&mut Arg) + Send>, 
} 

nên tham số kiểu Arg bản thân không phải là một tài liệu tham khảo, nhưng điều này làm cho đoạn code dưới generic. Bất kỳ ai có một giải pháp tốt hơn?

Trả lời

3

Vấn đề ở đây là trình kiểm tra mượn đang buộc thời hạn của tham chiếu &mut Trait giống với toàn bộ GenericStruct. Tôi tin rằng điều này là do tham chiếu là một tham số kiểu của cấu trúc.

Vì cấu trúc của bạn không có trường lưu trữ tham chiếu (nếu bạn cần làm điều này trong mã ban đầu của mình, vui lòng cập nhật câu hỏi của bạn), sau đó bạn có thể di chuyển tham số kiểu tới chính phương thức, thay vì cấu trúc:

trait Trait{} 

struct FooBar; 
impl Trait for FooBar{} 

struct GenericStruct; 

impl GenericStruct { 
    fn bar<T>(&self, _: T) {} 
} 

fn main() { 
    let mut foobar = FooBar; 

    { 
     let foo = GenericStruct; 
     foo.bar(&mut foobar); 
     foo.bar(&mut foobar); 
    } 
} 

Điều này sẽ chỉ thực hiện khoản vay này miễn là cuộc gọi đến foo.bar().

Các vấn đề liên quan