Okay, I just came up with a ridiculous #rustlang trick that... somehow works.

You know how building an API on top of trait objects (like `dyn Fn`) usually requires you to 'commit' to a pre-defined set of marker types (like Send/Sync), breaking any clients that want to use another set of bounds?

It turns out that you can abuse the specialization feature to 'smuggle' these marker traits into the final type without mentioning the type they're originally derived from, making it possible to write code that does dynamic dispatch without sacrificing the flexibility of user-defined marker traits.

Here's an example of the horrible hack in action: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2024&gist=f323d504bef9daca9e61d0b07c29b082

Rust Playground

A browser interface to the Rust compiler to experiment with the language

This ends up being actually useful in practice too!

https://codeberg.org/zesterer/chumsky/pulls/973

WIP: Implement a way of marking dynamic dispatch parsers as send/sync based on their input types

There are evil crimes being committed here. The idea is... sort of simple. For dynamically dispatched parsers (i.e: those that contain a `dyn Parser` internally, such as `recursive` and `boxed`), we usually have to commit to a particular set of marker traits (like `Send + Sync`). All users ...

Codeberg.org
@jsbarretto Reminds me of C++ template metaprogramming.
Man, I wish I had those years back.
@marshray The temptation of Turing-complete type systems is just too great
@jsbarretto Any kind of type-aware compile time metaprogramming system would have filled the need.