Trait fn calling function that depends on trait

pub trait BarT {
    fn x(&self);
    fn y(&self) {
        foo(&self)
    }
}

fn foo(bar: &dyn BarT) {
    bar.x()
}

Why does this function not compile? It seems obvious that the called of BarT::y has a &self that satisfies &dyn BarT.

When a function is defined with &self, the type of self is &Self, so &self is of type &&Self.

And even if you call foo(self), that won't work either:

pub
trait BarT {
    fn x (self: &'_ Self)
    ;
    fn y (self: &'_ Self)
    {
        foo(self)
    }
}

fn foo (bar: &'_ (dyn BarT))
{
    bar.x()
}

Indeed you can only coerce an &'_ (impl BarT + Sized) to the &'_ (dyn BarT) type; you cannot coerce a &'_ (impl BarT + ?Sized). And unless you opt out through some trait bound, inside a trait the Self parameter defaults to ?Sized.

The reason for that, I think, is that at some point there could be:

trait SubTrait : BarT { ... }

leading to the type dyn SubTrait : BarT, so for Self = dyn SubTrait, the default method would monomorphise to:

fn y (self: &'_ (dyn SubTrait))
{
    foo(self); // Error, expected `&'_ (dyn Bar)`, found `&'_ dyn SubTrait`
}

The solution, in a word with partial implementations (a feature that, for some reason, is intertwined with specialization), would be:

pub
trait BarT {
    fn x (self: &'_ Self)
    ;
    fn y (self: &'_ Self)
    {
        foo(self)
    }
}

default // partial
impl<T : BarT /* + Sized */> BarT for T {
    fn y (self: &'_ T)
    {
        foo(self)
    }
}

And a translation of that in stable Rust is:

pub
trait BarT : BarT_y {
    fn x (self: &'_ Self)
    ;
}

pub
trait BarT_y {
    fn y (self: &'_ Self)
    ;
}
impl<T : BarT /* + Sized */> BarT_y for T {
    fn y (self: &'_ T)
    {
        foo(self)
    }
}
1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.