Allow type placeholder for item signatures if they constrain the associated types

#1

I tried to write following code which seems to be disallowed by Rust:

trait Foo {
    type Foo;
    fn get_foo(&self) -> &Self::Foo;
}

/* Not allowed
trait Bar1: Foo<Foo = Option<_>> {
    fn bar(&self) -> bool {
        self.get_foo().is_some()
    }
}
*/

/* Verbose as pollutes all usage of this trait */
trait Bar2<S>: Foo<Foo = Option<S>> {
    fn bar(&self) -> bool {
        self.get_foo().is_some()
    }
}

/* Less verbose for my case but awkward and more of a workaround */
trait Bar3: Foo {
    fn bar<S>(&self) -> bool where Self: Foo<Foo = Option<S>> {
        self.get_foo().is_some()
    }
}
0 Likes

#2

Right, you’ve invented a nicer syntax that Rust doesn’t support.

trait Bar2<S>: Foo<Foo = Option<S>> 

This means “for each S, make a new version of this trait”, which in this case is necessary, because every Option<S> may have different layout, and a different way of encoding Some, so every call to is_some() may be different. Rust just likes to be explicit about it.

0 Likes

#3

Yet :wink: https://github.com/rust-lang/rust/issues/41517

3 Likes

#4

This means “for each S, make a new version of this trait”, which in this case is necessary, because every Option<S> may have different layout, and a different way of encoding Some, so every call to is_some() may be different. Rust just likes to be explicit about it.

I’m not sure I’m following. Since type can implement Foo only once Self::Foo needs to be known during implementation anyway. All Foo = Option<_> does is restrict what Bar2 can be implemented for. The only thing that would be different as far as I can see is that default implementation needs to be generated - but from language user perspective that’s an implementation detail.

0 Likes

#5

BTW, I mixed up users/internals forums and I thought your post was a question, not a proposal.

I was referring to monomorphisation. There has to be a different is_some() call for Option<&Foo> (null check) and Option<Foo> (extra boolean field). In some way it is an implementation detail, but also it’s visible in the syntax when that approach is used.

0 Likes

#6

Doesn’t it need to happen anyway if the trait consumes objects (fn foo(self, foo: Self)) as Self might take different amount of space? Self::Foo is dependent type so if you monomorphise in type of object implementing trait the dependent trait monomorphosation shouldn’t be much different I think.

0 Likes

closed #7

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

0 Likes