Thinking about Polymorphic Functions

I'm not too familiar with how code generation (and in particular monomorphization) works on a deep level.

I've been running into a lot of walls around creating object-safe traits and I'm curious if a future rust might lift some of these restrictions. More than that, I'd be interested to hear people's thoughts on somehow surfacing polymorphism in the type system (If that even makes sense).

Consider the following function:

fn pointer_identity<T>(v: &T) -> &T {

In pointer_identity, it seems like only the size/alignment of a generic parameter are required. While this isn't currently done, this doc (link) hints that some day rust may recognize such a function and polymorphize it (Compile it once and use it for all types, or compile one version per size rather than per type).

If it's compiled just once, it seems you should be able to put such a function into a vtable while keeping it's generic nature. On the other hand, doing so means the polymorphic nature of this function becomes a part of it's API. Some generic functions fit in a vtable and some do not.

This means that you'd likely want some way to express generic functions that are polymorphic in the type system. I'm not sure what that looks like though. I'm imagining some sort of pointer type that cannot be deferenced unless the type variable inside is somehow bound for the given context. I suppose it would allow unbound variables in pointers so long as you never use them? That seems like a pretty confusing feature, I suppose.

It really wouldn't be locally clear whether the following function is polymorphic. Is T defined somewhere or is it an unbound type variable?

fn pointer_identity(v: &T) -> &T {

Seems bad. I dunno!

1 Like

This is a bit more complicated than it seems, because (u64, u8) and [u64; 2] have the same size and alignment (on x64 today), but you have to be careful when trying to erase them to not do bad things with the padding.

You can erase them to MaybeUninit<[u64; 2]>, but that means you have to copy all 128 bits when copying, which isn't required when copying a (u64, 8) -- that's allowed to just copy the 72 bits instead, since the rest is considered meaningless.

(This is copy_nonoverlapping in std::ptr - Rust describes the copy as “untyped”.)

Aside: this thread is fine here, but if you ever wish to make a proposal to change Rust to be able to better do this, you'll want IRLO.


That's interesting.

There's a long list of things that can probably be made polymorphic and which maybe shouldn't have a way expressible in the type system. The way C does inheritance with structs seems like it might be on that list since Rust's data model is a moving target.

Having the same size and alignment may leave an opening for compiler optimizations that you wouldn't want any guarantees on in the language itself. I can definitely see many polymorphizations being implementation details to make the language faster without surfacing in syntax in any way.

But I do feel like there's a class of functions that orchestrate code by effectively just passing pointers around. Being able to shove those into object safe traits is interesting? Or maybe it isn't, I'm not sure.

The other side of that coin is that it might be frustrating to try to implement such a function for some trait because the author put this restriction on it to keep a trait object-safe.

Aside: I've bookmarked IRLO (Didn't know about it before, so thanks). This feels like a half-baked idea at the moment. Once/If I can dig a bit deeper into it, I'd definitely work on discussing it there too.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.