2014-07-20 17 views
9

Tôi đang gặp sự cố khi làm việc với các tham số suốt đời cho cấu trúc. Tôi không chắc chắn 100% làm thế nào để mô tả vấn đề, nhưng tôi đã tạo ra một trường hợp tầm thường cho thấy lỗi thời gian biên dịch của tôi.Lỗi thời gian tồn tại của thời gian tồn tại của bê tông nhưng tìm thấy giới hạn tuổi thọ

struct Ref; 

struct Container<'a> { 
    r : &'a Ref 
} 

struct ContainerB<'a> { 
    c : Container<'a> 
} 

trait ToC { 
    fn to_c<'a>(&self, r : &'a Ref) -> Container<'a>; 
} 

impl<'a> ToC for ContainerB<'a> { 
    fn to_c(&self, r : &'a Ref) -> Container<'a> { 
    self.c 
    } 
} 

Các lỗi Tôi nhận được với điều này là

test.rs:16:3: 18:4 error: method `to_c` has an incompatible type for trait: expected concrete lifetime, but found bound lifetime parameter 'a 
test.rs:16 fn to_c(&self, r : &'a Ref) -> Container<'a> { 
test.rs:17  self.c 
test.rs:18 } 
test.rs:16:48: 18:4 note: expected concrete lifetime is the lifetime 'a as defined on the block at 16:47 
test.rs:16 fn to_c(&self, r : &'a Ref) -> Container<'a> { 
test.rs:17  self.c 
test.rs:18 } 
error: aborting due to previous error 

Tôi đã thử nhiều biến thể và không thể có được điều này để biên dịch. Tôi tìm thấy một bài đăng khác ở đây (How to fix: expected concrete lifetime, but found bound lifetime parameter) nhưng dường như gặp phải vấn đề thay vì giải quyết nó. Tôi thực sự không thể hiểu tại sao vấn đề lại bắt nguồn. Tham chiếu & đang được chuyển qua các lần di chuyển để nó chỉ hoạt động đúng không?

Bất kỳ ý tưởng nào? Cảm ơn vì sự giúp đỡ.

Trả lời

13

Hãy so sánh hai định nghĩa. Thứ nhất, phương pháp đặc điểm:

fn to_c<'a>(&self, r: &'a Ref) -> Container<'a>; 

Và việc thực hiện:

fn to_c(&self, r: &'a Ref) -> Container<'a>; 

Thấy sự khác biệt? Cái sau không có số <'a>. <'a> đã được chỉ định ở nơi khác; thực tế là nó có cùng tên không quan trọng: đó là một điều hoàn toàn khác.

Về mặt chức năng, định nghĩa đặc điểm của bạn nói rằng container được trả về sẽ có một tham chiếu bên trong nó một cái gì đó từ r, nhưng gì từ self. Nó có thể sử dụng self bên trong phương pháp, nhưng nó có thể không lưu trữ bất kỳ tham chiếu đến nó trong giá trị trả lại.

bạn phương pháp định nghĩa, tuy nhiên, đang sử dụng một 'a rằng quan hệ đời sống của r và trở Container-self (có nghĩa là, cho các đối tượng chính nó, không phải là tài liệu tham khảo-the ρ₂ trong &'ρ₁ T<'ρ₂> -đó là một tinh tế nhưng đôi khi quan trọng sự khác biệt), trong khi định nghĩa tính trạng không có kết nối như vậy.

Hai giá trị này có thể được thực hiện để khớp với nhau bằng cách chèn <'a> vào định nghĩa phương thức trong quá trình triển khai. Nhưng hãy nhớ rằng đó là bóng tối 'a từ ContainerB<'a>; nó là không phải cùng một số 'a! Chúng tôi nên cung cấp cho nó một tên khác; cho thuận tiện, tôi sẽ thực hiện thay đổi theo chiều ngược lại, thay đổi nó trên impl thay vì phương pháp này (hoặc sẽ làm):

impl<'b> ToC for ContainerB<'b> { 
    fn to_c<'a>(&self, r: &'a Ref) -> Container<'a> { 
     self.c 
    } 
} 

Nhưng bây giờ tất nhiên bạn có một vấn đề: giá trị trả về là nhập Container<'b> (vì đó là trường số c trong số ContainerB<'b>), nhưng chữ ký của bạn yêu cầu Container<'a> (nội dung nào đó sử dụng tham chiếu từ r, không phải từ self).

Một cách khắc phục được là xác định tuổi thọ của &self'a trong cả định nghĩa tính trạng và cách triển khai; trong quá trình triển khai, điều này sau đó sẽ yêu cầu rằng 'b lớn hơn hoặc bằng 'a (do thực tế là bạn đã thực hiện thành công tham chiếu có tuổi thọ là 'a đối tượng có tuổi thọ là 'b và đối tượng phải nằm ngoài tham chiếu) do loại phụ ('a là một loại phụ của 'b) Container<'b> sẽ được ép buộc an toàn thành Container<'a>.

Những vấn đề về tuổi thọ này rất khó để suy nghĩ khi bạn không quen thuộc với chúng; nhưng trong thời gian chúng trở nên khá tự nhiên.

+1

Sửa lỗi khác sẽ là 'đặc điểm ToC <'a> {fn to_c (& self, r: & 'a Ref) -> Vùng chứa <'a>; } '. – huon

+0

Ồ vâng, và sau đó 'impl <'a> ToC <'a> cho ContainerB <'a>'. –

+0

Điều này chắc chắn sẽ giúp rất nhiều và cố định một số suy nghĩ sai lầm của tôi (ví dụ như bóng đời)! Cảm ơn. Điều này sửa chữa trường hợp này 100%, nhưng tôi dường như không thể áp dụng nó cho người khác. Tôi đã viết câu hỏi đó ở đây: http://stackoverflow.com/questions/24853111/rust-lifetime-error-expected-concrete-lifetime-part-2) – luke

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