方法与具有混淆错误消息的特征不兼容

Eri*_*rik 4 rust

我冒险进入包含可变结构的生命世界和结构世界:

enum Resources {
    Food,
    Wood,
    Tools,
    Ore,
    Metal,
}

struct ResourceEntry {
    resource: Resources,
    amount: i32,
}

impl ResourceEntry {
    fn new(resource: Resources, amount: i32) -> ResourceEntry {
        ResourceEntry {
            resource: resource,
            amount: amount,
        }
    }
}

trait Agent {
    fn new<'a>(&'a mut Vec<ResourceEntry>) -> Self;
}

struct Miner<'a> {
    inventory: &'a mut Vec<ResourceEntry>,
}

impl<'a> Agent for Miner<'a> {
    fn new(starting_resource: &'a mut Vec<ResourceEntry>) -> Miner {
        Miner { inventory: starting_resource }
    }
}

fn main() {
    let mut resource = ResourceEntry::new(Resources::Food, 3);
    let mut vec = vec![resource];
    let miner: Miner = Miner::new(vec);

    miner.perform();
}
Run Code Online (Sandbox Code Playgroud)

我收到以下错误

error[E0308]: method not compatible with trait
  --> other.rs:47:5
   |
47 |     fn new(starting_resource: &'a mut Vec<ResourceEntry>) -> Miner
   |     ^ lifetime mismatch
   |
   = note: expected type `fn(&'a mut std::vec::Vec<ResourceEntry>) -> Miner<'a>`
   = note:    found type `fn(&'a mut std::vec::Vec<ResourceEntry>) -> Miner<'a>`
note: the lifetime 'a as defined on the block at 48:4...
  --> other.rs:48:5
   |
48 |     {
   |     ^
note: ...does not necessarily outlive the lifetime 'a as defined on the block at 48:4
  --> other.rs:48:5
   |
48 |     {
   |     ^
help: consider using an explicit lifetime parameter as shown: fn new(starting_resource: &'a mut Vec<ResourceEntry>) -> Miner
  --> other.rs:47:5
   |
47 |     fn new(starting_resource: &'a mut Vec<ResourceEntry>) -> Miner
   |     ^
Run Code Online (Sandbox Code Playgroud)

我不能为我的生活包围编译器告诉我的内容.错误消息说我正在做我正在做的事情.也许我是误会,但它说的是它的寿命a与寿命不符a?我认为我对借用和所有权有很好的把握,但使用显式生命周期和引用其他对象的对象让我感到困惑.

是问题

fn new <'a>(&'a mut Vec) - > Self;

我无法正确接受一生的新生活,我想知道这不是你应该在Rust做的事吗?

She*_*ter 6

这是一个非常糟糕的错误消息,我鼓励您报告它.如果更改通用生命周期参数名称...

trait Agent {
    fn new<'a>(&'a mut Vec<ResourceEntry>) -> Self;
}

struct Miner<'b> {
    inventory: &'b mut Vec<ResourceEntry>,
}

impl<'c> Agent for Miner<'c> {
    fn new(starting_resource: &'c mut Vec<ResourceEntry>) -> Miner {
        Miner { inventory: starting_resource }
    }
}
Run Code Online (Sandbox Code Playgroud)

你得到一个更好的错误:

error[E0308]: method not compatible with trait
  --> src/main.rs:32:5
   |
32 |     fn new(starting_resource: &'c mut Vec<ResourceEntry>) -> Miner {
   |     ^ lifetime mismatch
   |
   = note: expected type `fn(&'a mut std::vec::Vec<ResourceEntry>) -> Miner<'c>`
   = note:    found type `fn(&'c mut std::vec::Vec<ResourceEntry>) -> Miner<'c>`
Run Code Online (Sandbox Code Playgroud)

impl块添加生命周期不是指定每个函数的生命周期的简写 ; 他们有不同的范围.你可以看到你想要做的事情没有意义:

fn new<'a>(&'a mut Vec<ResourceEntry>) -> Self;
Run Code Online (Sandbox Code Playgroud)

该生命周期不会在输出中的任何位置使用.相反,你需要让生命在角色中发挥作用:

trait Agent<'a> {
    fn new(&'a mut Vec<ResourceEntry>) -> Self;
}

impl<'c> Agent<'c> for Miner<'c> {
    fn new(starting_resource: &'c mut Vec<ResourceEntry>) -> Miner<'c> {
        Miner { inventory: starting_resource }
    }
}
Run Code Online (Sandbox Code Playgroud)

就这样我确切地知道发生了什么,Agentfor 的实现Miner是不兼容的,因为特性Agent没有与之相关的生命周期.因此,当它试图new在实现中进行编译时,它发现它有一个生命周期,Agent::new但它a是一个随机的其他生命周期,它无法弄清楚,因为生命周期不在输出中.

的种类.它不兼容,因为在特征定义时,实现new没有生命周期参数(fn new<'x>).添加一个生命周期new就可以"解决"这个问题,但要么不编译也不能做你想要的.

特质级别的生命周期允许您关联impl块中的生命周期

特征级别的生命周期意味着实现特征的类型可以使用生命周期进行参数化.这个特质也会知道那一生.

你可以说代理人的生命周期与矿工相同吗?

我想你理解这个概念,但我会指出这个术语是巧妙的错误.在Miner将设置有一个具体的寿命的引用; 这与生命的一样Miner!Agentfor 的实现Miner将能够利用所提供的生命周期,但Agent本身并不具有生命周期; 这只是一个特点.

这是人类的弱点,也是我们如何快速和松散地谈论事物.值的生命周期是在它被移动之前生成的.在Rust中,'a是生命周期注释/通用生命周期参数,这些参数允许包含引用的值.当使用引用构造值时,具体生命周期将替换参数.