Union types are erased to their upper bound, so thereâ€™s no boxing (except where necessary).

You can use `:settings -Vprint:erasure`

in the REPL to show the output of the â€śerasureâ€ť phase, which happens â€śjustâ€ť before the java bytecode is emitted.

Here are some examples:

```
def f(x: String | Seq[String]) = () /* becomes f(x: java.lang.Object) */
def f(x: Int | Long) = () // becomes f(x: java.lang.Object) too, so here the parameter is boxed
class Parent
class C1 extends Parent
class C2 extends Parent
def f(x: C1 | C2) = () // becomes f(x: Parent)
```

edit: To conclude, choosing to use union types or not is not a matter of performance. It depends on what youâ€™re trying to achieve Using union types allows to put more restriction on the types in a very handy way.