When you have a generic function, the only way you can make use of the generic types inside of the function are via the trait bounds of that function. The function can't "tell" what the original types was by design, and has to make sense (compile) for any type that meets the bounds. This way, if it compiles, you know it can be monomorphized (called) with any type that meets the bounds.
I.e. it's not a type-blind macro system. (Contrast with C++ templates, which might or might not error depending on what types you feed them.)
The very purpose of traits is to confer a common set of operations/capabilities on a set of types so that those types can be used uniformly, i.e. in generic contexts. What leads you to believe this is not the/a good way to do what you are trying to do?