首页 文章

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

提问于
浏览
4

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

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

我可以't for the life of me wrap my head around what the compiler is telling me. The error messages are saying to do exactly what I am doing. Maybe I'误解但是它说 a 的生命周期与 a 的生命周期不匹配?我认为我对借用和所有权有很好的把握,但使用显式生命周期和引用其他对象的对象让我感到困惑 .

是问题

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

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

1 回答

  • 6

    那个's a pretty bad error message, and I' d鼓励你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>`
    

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

    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 for Miner的实现不兼容,因为特质代理没有与之相关的生命周期 . 因此,当它试图在实现中编译new时,它发现它有一个来自Agent :: new的生命周期,但是a是一个随机的其他生命周期,它无法弄清楚,因为该生命周期不在输出中 .

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

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

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

    并且您可以说代理商的生命周期与矿工相同?

    我想你理解这个概念,但我会指出这个术语是巧妙的错误 . Miner 将提供具有生命周期的参考;这和_983179的一生都不一样!对于 MinerAgent 的实现将能够利用提供的生命周期,但 Agent 本身不具有生命周期;这只是一个特点 .

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

相关问题