Pre-RFC: trait class for single inheritance

It looks cool!

Then consider there are 2 classes (written in my proc-macro):

// The library API
class! {
    // Here `abstract` means it may have pure-virtual methods
    // and cannot be instantiated.
    pub abstract class Element {
        struct {
            parent: Cell<Option<Weak<Element>>>,
            dirty: Cell<bool>,
        }
        pub fn rebuild(&self) {
            if self.dirty.get() {
                self.perform_rebuild();
            }
        }
        pub fn perform_rebuild(&self); // pure-virtual method
        pub fn mount(&self, parent: Option<Rc<Element>>) {
            self.parent.set(parent.as_ref().map(Rc::downgrade));
            self.rebuild();
        }
    }
}
// The user code
class! {
    class MyElement extends Element {
        struct {
            my_own_data: Cell<u32>,
        }
        // implement the pure-virtual method
        pub override fn perform_rebuild(&self) {
             // ... 
        }

        // override the super method
        pub override fn mount(&self, parent: Option<Rc<Element>>) {
            // do something else
            // then call the super method
            super.mount(parent);
        }
        fn my_own_method(&self) {
            // ...
        }
    }
}

According to your suggestion:

pub struct ElementData {
    parent: Cell<Option<Weak<dyn Element>>>,
    dirty: Cell<bool>,
}

pub struct ElementVtable {
    rebuild: fn(&dyn Element),
    perform_rebuild: fn(&dyn Element),
    mount: fn(&dyn Element, parent: Option<Rc<dyn Element>>),
}

pub trait Element {
    fn data(&self) -> &ElementData;
    fn vtable(&self) -> &'static ElementVtable;
}

impl Element for ElementData {
    fn data(&self) -> &ElementData { self }
    fn vtable(&self) -> &'static ElementVtable {
        &ELEMENT_VTABLE
    }
}

static ELEMENT_VTABLE: ElementVtable = ElementVtable {
    rebuild: <dyn Element>::rebuild,
    perform_rebuild: <dyn Element>::perform_rebuild,
    mount: <dyn Element>::mount,
};

impl dyn Element {
    pub fn rebuild(&self) {
        if self.data().dirty.get() {
            (self.vtable().perform_rebuild)();
        }
    }
    pub fn perform_rebuild(&self) {
        unimplemented!()
    }
    pub fn mount(&self, parent: Option<Rc<dyn Element>>) {
        self.data().parent.set(parent.as_ref().map(Rc::downgrade));
        (self.vtable().rebuild)();
    }
}

Then the library code:

#[repr(C)]
pub MyElementData {
    _super: ElementData,
    my_own_data: Cell<u32>,
}

#[repr(C)]
pub struct MyElementVtable {
    _super: ElementVtable,
    my_own_method: fn(&dyn MyElement),
}

pub trait MyElement: Element {
    fn data(&self) -> &MyElementData { self }
    fn vtable(&self) -> &MyElementVtable { &MY_ELEMENT_VTABLE }
}

impl Element for MyElementData {
    fn data(&self) -> ElementData { &self._super }
    fn vtable(&self) -> ElementVtable { &MY_ELEMENT_VTABLE._super }
}

impl MyElement for MyElement Data {
    fn data(&self) -> MyElementData { self }
    fn vtable(&self) -> MyElementVtable { &MY_ELEMENT_VTABLE }
}

static MY_ELEMENT_VTABLE: MyElementVtable = MyElementVtable {
    _super: ElementVtable {
        rebuild: ELEMENT_VTABLE.rebuild,
        perform_rebuild: |this| <dyn MyElement>::rebuild(
            // SAFETY: safe because `MyElementData` is `#[repr(C)]` and `ElementData` has offset 0
            unsafe { &*ptr::from_ref(this.data()).cast::<ElementData>() as &dyn MyElement },
        ),
        mount: |this, parent| <dyn MyElement>::mount(
            // SAFETY: safe because `MyElementData` is `#[repr(C)]` and `ElementData` has offset 0
            unsafe { &*ptr::from_ref(this.data()).cast::<ElementData>() as &dyn MyElement },
            parent,
        ),
    },
    my_own_method: <dyn MyElement>::my_own_method,
};

impl dyn Mylement {
    pub fn perform_rebuild(&self) {
        // ...
    }
    pub fn mount(&self, parent: Option<Rc<dyn Element>>) {
        // ...
        (self as &dyn Element).mount(parent);
    }
    fn my_own_method(&self) {
        // ...
    }
}

The only problem is, I don't like the unimplemented!() in the pure-virtual methods, and I want a compile error instead if a concrete class doesn't implement any pure-virtual methods in its superclass.

In my current implementation, I used an ElementVtableOpt where all the function pointers are wrapped into an Option. Then a vtable of each class is initialized from the top superclass to the bottom, and the overriding can be handled correctly as subclass's vtable are set after the superclass's. After all, unwrapping all the Optional function pointers in the vtable of concrete class being instantiated, which will cause a panic (in a const context) and turned into a compile error.

However, this cannot be done in your suggested WithCustomVtable style unless I add a vtable_opt(&self) method to it, but checking the absent implementations can still not be done in the const context.