Perhaps this is a silly reasoning, but my first impression is that a that a good jit compiler requires a fast compiler, so golang meet that requirement better than Rust, obviously Rust has a more advanced/featured compiler but in a jit compiler for ruby the optimizations are going to be mostly for short parts of code (no heavy math or long loops), so the jit could try to find places where the code use vectors, maps or list of same type elements to avoid having to determine the dynamic type. That is, my impression is that in web related tasks the greater benefit comes from detecting parts of code that can be transformed in static type code and then apply a fast compiler to that part.
But perhaps Rust was chosen by its security model rather than by its performance, in which case I agree. But I think that a variant of go using borrow/owner var semantic could be the best track to construct a great YJIT.
As far as I understand it the JIT compiler is written in Rust, that doesn't mean that it produces Rust. So the output of the JIT can be in assembly, C or something else that compiles fast and runs fast.
I haven't had a look at the YJIT design, but your reasoning:
> detecting parts of code [...] and then apply a fast compiler to that part
applies to the previous JIT (MJIT) design, which created C snippets and compiled them on the fly. I don't think this is the case for YJIT, although I'm not 100% sure.
Surely this isn't the case, for example, for TenderJIT, which, for the bytecode instructions, builds assembly code and (optionally) invokes the original interpreter functions.