Stream: general

Topic: Array of pointers to methods, for type with lifetimes?


Arlie Davis (Apr 10 2020 at 21:36, on Zulip):

I'm working on an interpreter for a niche language. It uses a dispatch table to point to functions; pretty simple. However, I've tried converting these functions to methods, and I can't seem to find any way to express the fn type that goes in the dispatch table.

My instruction handler functions all take a &mut Foo<'a>, where Foo is my interpreted program context and 'a is a lifetime parameter for data that the interpreted program operates on. If I write the handlers as free functions fn do_thing<'a>(&mut Foo<'a>) { ... }, then I can build a dispatch table: static DISPATCH_TABLE: [fn(&mut Foo<'_>)] = .... But if I convert a function to an associated function / method, then the Foo::do_thing items cannot be converted to the type that I'm using for the dispatch table.

Is there a way to express this? Or is this not possible?

Playground link: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=c6180a4457c595cec9f1768bb49c4003

RalfJ (Apr 11 2020 at 06:50, on Zulip):

@Arlie Davis hm, that is interesting. I would have expected this to work. I think the fact that you have two lifetime parameters in these functions is also involved in causing the problem here.

RalfJ (Apr 11 2020 at 06:51, on Zulip):

There might be already a bug report for this somewhere (@eddyb ?), but I'd say it is also justified to open a new report.

marmeladema (Apr 11 2020 at 09:51, on Zulip):

If you wrap in a closure, it works though: |t| Foo::do_fancy_thing(t), // <-- now it succeeds

eddyb (Apr 11 2020 at 09:59, on Zulip):

@Arlie Davis in impl<'a> Foo<'a>, 'a is early-bound which means you can't turn it into the late-bound version

eddyb (Apr 11 2020 at 10:00, on Zulip):

this is nothing you should be able to observe sigh I wonder if Chalk has a better model

eddyb (Apr 11 2020 at 10:01, on Zulip):

I feel like maybe ty::FnDef should have a Binder or something so it can late-bind early-bound lifetimes (cc @nikomatsakis)

RalfJ (Apr 11 2020 at 10:02, on Zulip):

I think @eddyb is saying that opening an issue for this would be worth it. ;)

eddyb (Apr 11 2020 at 10:02, on Zulip):

no

eddyb (Apr 11 2020 at 10:02, on Zulip):

there's probably a dozen issues about this :P

eddyb (Apr 11 2020 at 10:02, on Zulip):

that nobody has triaged in ages or w/e

eddyb (Apr 11 2020 at 10:03, on Zulip):

I don't know the landscape well, just the root cause

eddyb (Apr 11 2020 at 10:04, on Zulip):

since it's a ZST struct, it can be as generic as you need it to be - e.g. it could be like:

struct Foo_do_fancy_thing;
impl<'a, 'a> Fn(&'s mut Foo<'a>) for Foo_do_fancy_thing {...}
eddyb (Apr 11 2020 at 10:04, on Zulip):

which is pretty much what you get from introducing a closure :P

eddyb (Apr 11 2020 at 10:04, on Zulip):

@Arlie Davis I think @marmeladema's suggestion will work well enough if you wrap it in a macro or something

Arlie Davis (Apr 11 2020 at 20:46, on Zulip):

Ah, thank you all. I don't understand early-bound vs. late-bound, so I'm going to go learn about that. Meanwhile, @eddyb, it sounds like you think it's not worth opening an issue on this? Why not? It seems like a reasonable thing to do, and the asymmetry between pointers-to-fns and pointers-to-methods seems undesirable.

marmeladema (Apr 11 2020 at 20:49, on Zulip):

I think what eddyb meant is that there are most certainly already issues for that.

Arlie Davis (Apr 11 2020 at 20:49, on Zulip):

Gotcha. Thanks.

eddyb (Apr 12 2020 at 00:30, on Zulip):

@Arlie Davis you can try to find an existing issue and add a comment to it, maybe

Last update: May 29 2020 at 18:00UTC