Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: runtime traits to represent protocols #23

Open
udoprog opened this issue Sep 7, 2020 · 2 comments
Open

feature: runtime traits to represent protocols #23

udoprog opened this issue Sep 7, 2020 · 2 comments
Labels
enhancement New feature or request lang Issues related to language design. rust-likeness Issues related to making Rune more like Rust through feature parity.

Comments

@udoprog
Copy link
Collaborator

udoprog commented Sep 7, 2020

We currently have "protocols" to implement various functions. These are really just free instance functions with custom name hashes that can't be named dynamically.

This means that protocol impls currently can't be defined dynamically. So there is no way to make this run (which requires the STRING_DISPLAY protocol):

struct Foo;

fn main() {
    let foo = Foo;
    println(`{foo}`);
}

It should be possible to add "runtime traits" to Rune to represent these protocols. To allow for the following:

struct Foo;

impl std::fmt::Display for Foo {
    fn fmt(self, f) {
        write(f, "Foo as a string")
    }
}

fn main() {
    let foo = Foo;
    println(`{foo}`); // -> "Foo as a string"
}
@udoprog udoprog added enhancement New feature or request lang Issues related to language design. rust-likeness Issues related to making Rune more like Rust through feature parity. labels Sep 7, 2020
@tgolsson
Copy link
Contributor

tgolsson commented Jun 7, 2021

@udoprog I started thinking about this last night from a "native" side, since I want to emulate Deref for my generic structs - I've got something like

#[derive(Any)]
struct DerefProxy<T>
where
    T: runestick::Any,
{
    inner: AtomicRefMut<'static, T>, 
}

And this wrapper (whose sole purpose is to keep the lock alive) should be Deref<Target = T> just like the inner value is. I'm not sure about exact patterns to make it ergonomic and safe -- I guess there'll need to be some form of "cook" once all traits etc have been registered to generate a dispatch table. My current working idea for surface API is that there'll be something like this:

struct TraitApi { /* todo */ }
trait InstallTrait { /* todo */ }

impl<T> InstallTrait for T where T: std::fmt::Debug {
    fn api() -> TraitApi { ... }
    
    fn install(m: &mut Module) -> ... {
         m.inst_trait("std::fmt::Debug",
             Self::api().inst_fn("fmt", |s: &T, f: &mut String| { ... })
    }
}

Where each Module::inst_trait call is one segment of a virtual table. And then e.g STRING_DEBUG would be vm.dispatch("std::fmt::Debug", "fmt", target, args) or something like that. Haven't thought too much about this from the compiler perspective though, I guess there needs to be some form of resolution in untyped code -- e.g., how'd one differentiate between mutable/non-mutable access, etc, or simply name clashes between unrelated generic names (get, set, update, fetch, run, ...). You know more about the compiler than I do so I'd love to hear your thoughts on that side.

@tgolsson
Copy link
Contributor

tgolsson commented Jun 7, 2021

Started hacking on the compiler side just to see where it slots it on and where it'll land in the final data. Progress branch here: https://github.com/tgolsson/rune/tree/ts/traits.

This is the code that I want to get to compile, ~ish, as a proof of concept.

trait MyTrait {
    fn echo(self);
    fn name(self) {
        "Derek"
    }
}

struct MyStruct { a }

impl MyTrait for MyStruct {
    fn echo(self) { MyTrait::name(self) }
}

pub fn main() {
    let m = MyStruct { a: 10 };
    m.echo()    
}

@udoprog udoprog changed the title Runtime traits to represent protocols feature: runtime traits to represent protocols Aug 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request lang Issues related to language design. rust-likeness Issues related to making Rune more like Rust through feature parity.
Projects
None yet
Development

No branches or pull requests

2 participants