It's not the default, but Rust absolutely allows dynamic linking [1]. For example, Bevy encourages building the engine as a dynamic library during development to improve iteration turnaround times for the app code [2].
If I am not completely mistaken, if you produce a dynamic library with rust, you are limited to the C-ABI. For instance, you cannot import a polymorphic function from a dynamic library.
The rust abi isn't stable between compiler versions, but it does exist. Bevy can get away with using it because it's just to speed things up in development.
Polymorphism is a separate issue. One way to do polymorphism in rust is monomorphism, where your polymorphic function is compiled to a specific version with no generics per caller. If you don't know the callers ahead of time this can't work. Another way is dynamic dispatch, where you have one polymorphic function that chooses what code to run per type at runtime. This can work with dynamic linking
I haven't used it, but I don't believe that's the case. I think what you're describing is `#[crate_type = "cdylib"]` ("used when compiling a dynamic library to be loaded from another language"), whereas `#[crate_type = "dylib"]`
produces a "dynamic Rust library".
[1] https://doc.rust-lang.org/reference/linkage.html
[2] https://github.com/bevyengine/bevy/issues/791