Shizcow / hotpatch

Changing function definitions at runtime in Rust
Apache License 2.0
128 stars 6 forks source link

Tracking Issue: Methods #12

Open Shizcow opened 3 years ago

Shizcow commented 3 years ago

I intend to work on implementing methods when I next have time. An implementation draft can be found in #7.

I'm currently concerned with the need to import traits to use hotpatched methods. The reason can be summarized as follows:

struct Foo{}
impl Foo {
  static hotpatched_fn: Patchable;
}
// this trait will be auto-generated by a macro
trait HotpatchFoo {
  fn hotpatched_fn();
}

hotpatch_fn has a dual definition -- AFAIK this is required to get the .hotpatched_fn syntax working while still having a Patchable somewhere in the mix. Problem is that HotpatchFoo trait now needs to be imported.

Ideas around this:

As soon as I find an implementation I'm happy with I'll write a todo list in this issue.

Help Wanted

Ideas on how to get around having to import traits? Inherent traits aren't in nightly yet, and workarounds I know of don't allow duplicate definitions.

Shizcow commented 3 years ago

const members of traits are allowed, but make the issue a little more delicate. Actual methods would need to call the traits, complicating macros.

Shizcow commented 3 years ago

Turns out that a const member of a trait wouldn't help. :: always resolves to the impl, so Foo::f is of the wrong type. This is okay the other way around because the const can be a Patchable functor.

This is the best I can do so far:

mod inner {
    pub struct Foo {}
    impl Foo {
        #[allow(non_upper_case_globals)]
        pub const f: i32 = 0;
    }
    // this trait will be auto-generated by a macro
    pub trait HotpatchFoo {
        fn f(&self) {}
    }
    impl HotpatchFoo for Foo {}
}

fn main() {
    use inner::Foo;
    /////////////////////////////
    // How do we get rid of this?
    use inner::HotpatchFoo;

    println!("{}", Foo::f);

    let foo = Foo {};

    foo.f();

    // The following shouldn't compile but it's okay; we can make this a Patchable
    // Foo::f(foo);
}