This is semantically not the same as a sum type (as understood in the sense of Rust, which is afaik the academically accepted way)!
Python's `A | B` is a union operation, but in Rust a sum type is always a disjoint union. In Python, if `A = B = None`, then `A | B` has one possible instance.
In Rust, this sum type has two possible instances. This might not sound like a big deal, but the semantics are quite different.
There's no difference there because the types are already disjoint.
Say you wanted to define some function taking `YYMMDD | MMDDYY`. If both YYMMDD and MMDDYY are just aliases to `str`, then you gain no information, you cannot discriminate on which one it is, since the union `str | str` just reduces to `str`.
Sum types are disjointed unions, you can't just say `str | str`, the terms are wrapped in unique nominal data constructors, like:
enum Date { MMDDYY(String), YYMMDD(String) }
Then when accepting a `Date` you can discriminate which format it's in. You could do the same in Python by defining two unique types and using `MMDDYY | YYMMDD`.
Every dynamically typed language effectively has one big Sum type that holds all of the other types. IMO this is one reason why dynamic languages have been so popular (because Sum types are incredibly useful, and mainstream statically typed languages have historically had very poor support for them).
Python's `A | B` is a union operation, but in Rust a sum type is always a disjoint union. In Python, if `A = B = None`, then `A | B` has one possible instance.
In Rust, this sum type has two possible instances. This might not sound like a big deal, but the semantics are quite different.