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

时间:2016-12-05 18:55:59

标签: 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();
}

我收到以下错误

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
   |     ^

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

问题是什么

  

fn new&lt;'a&gt;(&amp;'a mut Vec) - &gt;自我;

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

1 个答案:

答案 0 :(得分:6)

这是一个非常糟糕的错误消息,我鼓励你to report it。如果更改通用生命周期参数名称......

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 }
    }
}

你得到一个更好的错误:

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>`

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

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

输出中的任何位置都没有使用。相反,你需要让生命在角色中发挥作用:

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 }
    }
}
  

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

有点儿。它不兼容,因为new的实现在特征定义时没有生命周期参数(fn new<'x>)。为new添加生命周期会“解决”这个问题,但要么不编译,要么不做你想要的。

  

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

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

  

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

我认为你理解这个概念,但我会指出这个术语是巧妙的错误。 Miner将提供参考 具体的一生;这Miner的生命周期相同! Agent Miner的实施将能够利用所提供的生命周期,但Agent本身不具有生命周期;这只是一个特点。

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