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