0

I am trying to implement Deref for an enum:

use std::rc::Rc;
use std::ops::Deref;

pub trait tObject {
    fn name(&self) -> String;
    fn span(&self) -> u32;
}

pub struct t1 {
    pub name: String,
    pub bd: Option<String>,
    pub span: u32,
    pub label: Option<String>
}

pub struct t2 {
    pub name: String,
    pub vrf: Option<String>,
    pub span: u32,
    pub label: Option<String>,
    pub svi: u32
}

pub struct t3 {
    pub name: String,
    pub span: u32,
    pub label: Option<String>
}

impl tObject for t1 {
    fn name(&self) -> String {self.name.clone()}
    fn span(&self) -> u32 {self.span.clone()}
}

impl tObject for t2 {
    fn name(&self) -> String {self.name.clone()}
    fn span(&self) -> u32 {self.span.clone()}
}

impl tObject for t3 {
    fn name(&self) -> String {self.name.clone()}
    fn span(&self) -> u32 {self.span.clone()}
}

pub enum TType {
    t1(Rc<t1>),
    t2(Rc<t2>),
    t3(Rc<t3>)
}

impl Deref for TType {
    type Target = tObject;
    fn deref<'a>(&'a self) -> &'a tObject {
        match *self {
            TType::t1(ref x) => x as &t1,
            TType::t2(ref x) => x as &t2,
            TType::t3(ref x) => x as &t3
        }
    }
}

fn main() {
    let mut t1s: Vec<Rc<t1>> = Vec::new();
    let mut t2s: Vec<Rc<t2>> = Vec::new();
    let mut t3s: Vec<Rc<t3>> = Vec::new();

    let t_iter: Box<Iterator<Item=TType>> = Box::new(t1s.iter().map(|x| TType::t1(x.clone())).chain(
                                                t2s.iter().map(|x| TType::t2(x.clone())).chain(
                                                t3s.iter().map(|x| TType::t3(x.clone())))));
}

The compiler reports this error:

rustc 1.15.1 (021bd294c 2017-02-08)
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter 'a in generic type due to conflicting     requirements
  --> <anon>:53:5
   |
53 |       fn deref<'a>(&'a self) -> &'a tObject {
   |  _____^ starting here...
54 | |         match *self {
55 | |             TType::t1(ref x) => x as &t1,
56 | |             TType::t2(ref x) => x as &t2,
57 | |             TType::t3(ref x) => x as &t3
58 | |         }
59 | |     }
   | |_____^ ...ending here
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the body at 53:42...
  --> <anon>:53:43
   |
53 |       fn deref<'a>(&'a self) -> &'a tObject {
   |  ___________________________________________^ starting here...
54 | |         match *self {
55 | |             TType::t1(ref x) => x as &t1,
56 | |             TType::t2(ref x) => x as &t2,
57 | |             TType::t3(ref x) => x as &t3
58 | |         }
59 | |     }
   | |_____^ ...ending here
note: ...so that method type is compatible with trait (expected fn(&TType) -> &tObject + 'static, found     fn(&TType) -> &tObject)
  --> <anon>:53:5
   |
53 |       fn deref<'a>(&'a self) -> &'a tObject {
   |  _____^ starting here...
54 | |         match *self {
55 | |             TType::t1(ref x) => x as &t1,
56 | |             TType::t2(ref x) => x as &t2,
57 | |             TType::t3(ref x) => x as &t3
58 | |         }
59 | |     }
   | |_____^ ...ending here
   = note: but, the lifetime must be valid for the static lifetime...
note: ...so that method type is compatible with trait (expected fn(&TType) -> &tObject + 'static, found     fn(&TType) -> &tObject)
  --> <anon>:53:5
   |
53 |       fn deref<'a>(&'a self) -> &'a tObject {
   |  _____^ starting here...
54 | |         match *self {
55 | |             TType::t1(ref x) => x as &t1,
56 | |             TType::t2(ref x) => x as &t2,
57 | |             TType::t3(ref x) => x as &t3
58 | |         }
59 | |     }
   | |_____^ ...ending here   

If I make the return type of deref Self::Target instead of tObject, it compiles fine. I do not understand this behaviour.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Sree
  • 11
  • 2
  • 1
    Please review how to create a [MCVE]. For example, I bet you can reproduce your error with 1 or 2 enum variants instead of 3, your structs could have 0 or 1 fields, your trait could have 0 or 1 methods, you don't need anything inside of `main` etc. – Shepmaster Feb 18 '17 at 01:46
  • Note that you will have a large number of warnings because you are not following idiomatic Rust naming conventions. Please remove all warnings. – Shepmaster Feb 18 '17 at 01:49

1 Answers1

3

Here is a MCVE. Programmers use these to help narrow down the scope of a problem. For example, this MCVE rules out anything being due to the use of the enum, the Rc, any of the methods in the trait, or any of the fields in the structs. This allows us to focus on what is important:

use std::ops::Deref;

pub trait Trait {}

pub struct S {}
impl Trait for S {}

pub struct Container(S);

impl Deref for Container {
    type Target = Trait;

    // fn deref(&self) -> &Trait { // Fails!
    fn deref(&self) -> &Self::Target { // Works!
        &self.0
    }
}

From the code, we can intuit that, somehow, Trait and Self::Target are not the same type. It's a bit tricky to see the type here, but this code prints out the type as a compiler error:

fn deref(&self) -> &Self::Target {
    let a: Self::Target;
    &self.0
}
error[E0277]: the trait bound `Trait + 'static: std::marker::Sized` is not satisfied

We don't actually care about the error, but we've discovered the type: Trait + 'static. Let's see what happens if we try something like that:

fn deref(&self) -> &(Trait + 'static) {
    &self.0
}

This compiles.

In case you are unfamiliar with this syntax, there are plenty of questions about it. Here are some:

Community
  • 1
  • 1
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366