Parameterising type definitions with traits


#1

Is this not (yet) possible?

https://is.gd/AVBGEc

(And while we’re at it, when is copy+paste from/to the play pen going to get fixed?)


#2

It’s not yet possible and the compiler warns about that:

warning[E0122]: trait bounds are not (yet) enforced in type definitions

There’s currently only this open issue on it. Seems there is no progress so far.

What problems do you have regarding copy/paste and the playpen?


#3

Can you elaborate a bit on what you’re trying to do? That may help us describe workarounds, or provide context for those who know if/why/when this may/may not change.


#4

It doesn’t work. Never has, at least not since early versions. (Paste does nothing. Copy puts some weird unrenderable glyph in my clipboard.)

Parameterise a type definition (F) by a trait (A). There are no compiler errors on the type definition simply because the compiler doesn’t check it properly, but F<A> is impossible to instantiate. (Of course, normally bounds-checking only restricts applicable types, but the default is that all types must be sized, whereas here I want it unsized.)

About this “yet”… okay, I’ll look at the issue linked. Thanks.


#5

Actually, by a trait implementation satisfying. Maybe this requires HKT.

And I want to use this self-referentially within a trait, which is probably not possible:

struct X<T: A> {
    a: T,
}

trait A {
    fn get_f() -> fn(&mut obj: X<Self>) -> ();
}

The rationale for this is partly to avoid lifetime restrictions and partly to pass full control (over the instance of X) to f (within the function body):

impl<T: A> X<T> {
    fn run_f(&mut self) {
        let f = self.a.get_f();
        f(self);
    }
}

Perhaps this isn’t possible?


#6

You can do this:

trait A {
    fn get_f() -> fn(&mut X<Self>) -> () where Self: Sized; 
}

impl<T: A> X<T> {
    fn run_f(&mut self) {
        let f = A::get_f();
        f(self); 
    }
}

But at this point you may as well define something like this:

trait A {
     fn with_x(x: &mut X<Self>) where Self: Sized;
}

impl<T: A> X<T> {
    fn run_f(&mut self) {
         A::with_x(self);
    }
}

Note that in both cases the a field is unused as we don’t need any state from it.


#7

Of course I can; trait objects are Sized. Sorry, not sure why I thought I was parametrising with traits themselves. And you’re right, I don’t need the data pointer a in this case, and A::with_x is neater.


#8

I’m glad you managed to figure it out! I have a hard time following what you’re trying to do (still learning myself…) But I am glad the ever-awesome @vitalyd understood you enough to get you going.

Thanks also @jer for the useful issue link! That kind of crosslinking is really important!


#9

Ha, too kind! We’re all always learning :slight_smile: