Contradictory “missing lifetime specifier” error o

2020-02-15 08:09发布

问题:

I wrote code to model the following structure, where a node has a reference to its parent node:

struct Node<'a> {
    parent: &'a Node,
}

impl<'a> Node<'a> {
    fn new(parent: &'a Node) -> Node {
        Node { parent }
    }
}

I thought with the lifetime parameter on the parent attribute and on the parent parameter in the new function it is made clear that the value behind the reference to parent has to live at least as long as the child node that holds the reference.

However, the compiler gives me two "missing lifetime specifier" messages.

error[E0106]: missing lifetime specifier
 --> src/main.rs:2:17
  |
7 |     parent: &'a Node,
  |                 ^^^^ expected lifetime parameter

There is a lifetime parameter on the attribute. What the hell does the compiler want from me here?

error[E0106]: missing lifetime specifier
 --> src/main.rs:6:33
  |
6 |     fn new(parent: &'a Node) -> Node {
  |                                 ^^^^ expected lifetime parameter

Here I expected the compiler to assume that the return value has to live at least as long as 'a. Appearantly it does not. I thought it is syntactically impossible (because unnecessary) to annotate an owned value with a lifetime parameter. But still the compiler seemed to desire one here so I gave what it was asking for.

// --snip
fn new(parent: &'a Node) -> 'a Node {
// --snip

When I tried to compile that, the second error turned into a differnt one:

error: expected type, found `'a`
 --> src/main.rs:6:33
  |
6 |     fn new(parent: &'a Node) -> 'a Node {
  |                                 ^^

So now the compiler tells me that it doesn't expect a lifetime parameter here, which seems contradictory to the message from before.
How can I express this structure correctly, where a Node has a reference to its parent, which lives at least as long as the child node itself? Is it only possible with Rc and if yes, why?

回答1:

Your defintion of node is

struct Node<'a>

but later on you don't provide that lifetime anymore. Your new signature must look like

fn new(parent: &'a Node) -> Node<'a>;

same with your struct definition

struct Node<'a> {
    parent: &'a Node<'a>,
}