0

I have the following public trait

pub trait UIElement {
    /// Is this UIElement a child of any other UIElement?
    fn parent<T: UIElement>(&self) -> Option<T>;

    /// Where to position
    /// TODO: Determine recursivly by checking the position of
    /// its parents.
    fn area(&self) -> Area;

    /// Should this UIElement be visible?
    fn visible(&self) -> bool;

    /// Is this UIElement actually visible?
    /// A UIElement can only be visible, if the parent (e.g. a container)
    /// is also visible (and its parent and so on resursively).
    fn actually_visible(&self) -> bool {
        let parent_visible: bool = if let Some(parent) = self.parent() {
            parent.actually_visible()
        }else { true };

        parent_visible && self.visible()
    }
}

actually_visible() is supposed to only return true, if itself is visible() and also the previous parent was actually_visible() recursive.

When I created the parent() method, I couldn't just use Option<impl UIElement> or Option<Self> (Self probably only works for actual structs if I'm not mistaken) as a return type. The syntax I chose however should basicially be the unsugared version of Option<impl UIElement>.
Using that, the compiler at least doesn't complain anymore. (Though I'm still a bit irriated, but that's not the point of this question).

The problem now lies within actually_visible().
It can't infer the type of parent, when trying to resolve actually_visible() from it.

error[E0282]: type annotations needed
error[E0282]: type annotations needed
  --> src/ui.rs:40:13
   |
40 |             parent.actually_visible()
   |             ^^^^^^ cannot infer type
   |
   = note: type must be known at this point
help: consider specifying the type argument in the method call
   |
39 |         let parent_visible: bool = if let Some(parent) = self.parent::<T>() {
   |                                                                     ^^^^^

How can I make this work?

P.S.: I've already looked into some other solutions. While Is there a way to signal that an impl trait type also implements additional traits? has a very similar question, that doesn't seem to work for me. Maybe the rust compiler has problems/restrictions with recursion?

halfer
  • 19,824
  • 17
  • 99
  • 186
LinusCDE
  • 141
  • 3
  • 8

1 Answers1

0

It looks like the only place you're attempting to use generics is on this line:

fn parent<T: UIElement>(&self) -> Option<T>;

This is not necessary as Rust already knows that the actual type being operated on will be a more concrete type that implements UIElement and so using a generic does not seem to be needed here.

With that said, because Rust does not know ahead of time the size of the actual object that will be used (since it can vary), you'll need to rely on the heap to hold such objects.

Therefore, I replaced the T in the return type with

Box<dyn UIElement>

like so...

fn parent(&self) -> Option<Box<dyn UIElement>>;

After adding a definition for Area

pub struct Area
{

}

I was able to get your code to compile (though what you use for "Area" is up to you).

Umutambyi Gad
  • 4,082
  • 3
  • 18
  • 39
Trec Apps
  • 221
  • 2
  • 9