Shizcow/hotpatch

Tracking Issue: Methods

Opened this issue · 2 comments

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:

  • See if the static can be placed in the trait instead. I don't think this will work but would at least make a trait import only required when hotpatching. EDIT: This works.
  • See if generic traits can be specialized with additional associated functions. This way, an auto-generated const-generic parameter could do all the magic, leaving only a single crate-wide import directly from hotpatch::MethodTrait required. Don't think this will work either, but it seems the most promising solution.
  • impl<const HOTPATCH_ID: usize> Deref for fn::<HOTPATCH_ID>(&Foo, Args...) -> Ret. I highly doubt you can impl Deref for a method (and I don't know the syntax to get this right), but this MIGHT be possible with specialization (and would be the best way forward imo)

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.

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

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);
}