Thanks for replies, guys.
Another problem is the implicit nature that this feature would have, since that leads to the usual OOP issue where the implementations are all over the place and you need to rely on an LSP to find them exhaustively (assuming it’s not public). I suppose the explicit closed set version is not completely immune to this either, but at least the identifiers are listed in one place.
I also don’t like to dig through all sources to find all concrete types, union with all its types looked really good until I had to split it into packages.
The real problem I think is just the fact that packages have a very strict one-way dependency flow (by design), since they are supposed to be fully self-contained, and therefore a package can’t/shouldn’t make assumptions about what imports it.
Yes I agree, keeping one-way dependency flow is a good strategy for designing a software.
If a package does know what imports it, then there is (effectively) a cycle in the dependency graph, which indicates packages in that cycle are really the same package.
Yes, also agree, package should not know what imports it.
Here I think the dependency flow gets inverted. Usually one-way dependency to me looks like “concrete knows abstract”, this builds a graph which can then be reused at a higher level by more concrete things.
So when union has to import its types, flow reverses to “abstract knows concrete” this fights the design graph. Without this “reverse” nuance — “packages in that cycle are really the same package” goes away, and packages stop being that monolithic and become more flexible.
If your core package truly didn’t know anything about its variants, it wouldn’t be possible to make a blob+tag style union like Odin has. Rather, it would require a vtable or equivalent, and at that point you kind of get into more proper ‘Objects’.
A vtable is needed when the variant set is open at compile time, e.g. across separately-compiled units.
Here, if I understand correctly, the compiler still sees every package in the build, so it can compute max(size_of(variant)) and assign tags exactly like today. Blob+tag is preserved, the only difference is whether the list lives in core.odin or is collected from the packages.