4 votes

Méthode non compatible avec le trait avec un message d'erreur confus

Je m'aventure dans le monde des durées de vie et des structures qui contiennent des structures mutables :

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

J'obtiens l'erreur suivante

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

Je n'arrive pas à comprendre ce que me dit le compilateur. Les messages d'erreur me disent de faire exactement ce que je fais. Peut-être ai-je mal compris, mais il est dit que la durée de vie de a ne correspond pas à la durée de vie de a ? Je pensais avoir une bonne compréhension de l'emprunt et de la propriété, mais l'utilisation de durées de vie explicites et d'objets qui font référence à d'autres objets me laisse perplexe.

Le problème est-il

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

J'ai eu du mal à faire accepter correctement une durée de vie à new et je me demande si ce n'est pas quelque chose qu'il faut faire en Rust ?

6voto

Shepmaster Points 1732

Il s'agit d'un message d'erreur plutôt mauvais, et je vous encourage à pour le signaler . Si vous modifiez les noms des paramètres de la durée de vie générique...

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

vous obtenez une meilleure erreur :

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

Ajouter une durée de vie à un impl Le bloc est pas une abréviation pour spécifier une durée de vie pour chaque fonction ; elles ont des portées différentes. Vous pouvez voir que ce que vous essayez de faire n'a pas de sens :

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

Cette durée de vie n'est pas utilisé n'importe où dans la sortie. Au lieu de cela, vous devez faire en sorte que la durée de vie joue un rôle dans le trait :

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

Pour que je sache exactement ce qui s'est passé, la mise en œuvre de Agent para Miner n'était pas compatible car le trait Agent n'avait pas de durée de vie associée. Ainsi, lorsqu'il essayait de compiler new dans la mise en œuvre, il a constaté qu'il disposait d'une durée de vie de l'ordre du jour. Agent::new pero a était une autre durée de vie aléatoire qu'il ne pouvait pas déterminer puisque cette durée de vie ne figurait pas dans la sortie.

En quelque sorte. Il n'était pas compatible parce que l'implémentation de new n'avait pas de paramètre de durée de vie ( fn new<'x> ) alors que la définition du trait le faisait. L'ajout d'une durée de vie à new aurait "résolu" ce problème, mais ne compilerait pas ou ne ferait pas ce que vous voulez.

La durée de vie au niveau du trait permet d'associer la durée de vie au bloc impl.

La durée de vie au niveau du trait signifie que les types qui mettent en œuvre le trait peuvent être paramétrés avec une durée de vie. Le trait connaîtra également cette durée de vie.

Et vous pouvez dire que l'agent aura la même durée de vie que le mineur ?

Je pense que vous comprenez le concept, mais je tiens à souligner que cette terminologie est subtilement erronée. Les Miner recevra une référence d'une durée de vie concrète ; il s'agit no la même chose que la Miner La vie d'un homme ! La mise en œuvre de la Agent para Miner sera en mesure d'utiliser la durée de vie fournie, mais les Agent n'a pas de durée de vie en soi, c'est juste un trait.

Il s'agit là d'une faiblesse de l'être humain et de la façon dont nous parlons des choses de manière rapide et décousue. La durée de vie d'une valeur s'étend de sa naissance à son déplacement. En rouille, 'a sont des annotations de durée de vie / des paramètres génériques de durée de vie, qui permettent à une valeur de contenir des références. La durée de vie concrète remplacera le paramètre lorsque la valeur sera construite avec une référence.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X