Not lexically, no, but dynamically, sure, all the time. JS lets me receive an arbitrary value in a variable `foo`, and "add" it to another arbitrary value in a variable `bar`, without having any opportunity to specify what semantics I mean by "add." Fixing the semantics of the operation is the whole point of specifying it!
Personally, I favor languages that go "almost too far" in the opposite direction, e.g. Elixir. In Elixir, operator[] (a.k.a. the Access protocol) is generic across several types, but the semantics are very strictly constrained; not only does the access have to "mean" getting some kind of element from a container, but it's also only defined where it has a fixed O(1) time-complexity.
This sort of design being conventional in Elixir, means that you can usually predict, just from the lexical environment (a.k.a. "the code on the screen") what the runtime behavior will be of said code—which includes being able to "read off" a time/space complexity for the code—without needing to check how each ADT involved has implemented its generics, let alone having to check for implicit type coercions.
Personally, I favor languages that go "almost too far" in the opposite direction, e.g. Elixir. In Elixir, operator[] (a.k.a. the Access protocol) is generic across several types, but the semantics are very strictly constrained; not only does the access have to "mean" getting some kind of element from a container, but it's also only defined where it has a fixed O(1) time-complexity.
This sort of design being conventional in Elixir, means that you can usually predict, just from the lexical environment (a.k.a. "the code on the screen") what the runtime behavior will be of said code—which includes being able to "read off" a time/space complexity for the code—without needing to check how each ADT involved has implemented its generics, let alone having to check for implicit type coercions.