feat: union types
ref #442
it can match multiple types, like Text | Num | Null, and also failable ones like Text | Num | Num?.. the whole thing is covered by tests, you can see the code there
Edit: Didn't notice the update, this applies to the previous version.
While writing an example I found another bug. Here's the code:
fun test(a: Num | [Num]): Num {
echo "It runs, but it shouldn't!"
if {
a is Num: return 42
a is [Num]: return 69
}
}
echo test("hi, hello" as Num | Text)
First of all, the compiler should have never allowed the program to compile, because the function doesn't expect type Text as a possibility. Passing it an argument of type Text would make it return nothing, even though it is defined in the function signature that it must return Num.
It would, but the other bug is that the function actually returns 42, even though this return is guarded by a type check for Num. Obviously this is also due to the partial equality implementation that makes Num and Num | Text equivalent.
The second issue persists — the function returns 42 where it shouldn't, due to type comparisons using partial equality check. Here's a new example:
fun test(a: Num | [Num] | Text): Num {
if {
a is Num: return 42
a is [Num]: return 69
}
}
echo test("hi, hello" as Num | Text)
I really don't think it is the right approach to implement manual PartialEq, as it makes it impossible to strictly compare two types. This lesson was already learned in #300. You should instead call the union subset checking logic at the right places, like function parameters and the return statement.
Moreover, the current implementation breaks the transitive quality implied by derived Eq, which is a logic error. See std::cmp::Eq documentation.
Not a fan of the hash idea for the Type enum, this is getting out of hand. Please take a different approach from manually implementing PartialEq.
i don't know what you are talking about. the program doesnt compile on latest commit. the hashes are non collidable now
I've just checked out a fresh instance of your branch, and the code from the last example compiles perfectly (as it should), but the function returns 42 — and it should not.
the hashes are non collidable now
The hashes are an over engineered solution that doesn't work. Even though you wrote documentation for it, I still cannot (and frankly don't want to) comprehend how they function, and the random magic numbers are genuinely scaring me. We aren't writing embedded code here, there should be no such complexity for simple type checking logic.
While implementing generic arrays in #472, I've created a method where you can put the logic for verifying if the type is a subset of another one. This method is hooked up to all the right places — function arguments, and return statement. So those will automatically allow a type that is a subset of another type. Unlike with manual PartialEq, that wont happen when comparing types in expressions.
You can already try to build your PR on top of mine, or on top of master after I merge mine. Of course, you're welcome to review it first.
Never mind I just realized I reviewed an old piece of code
Actually we are going to have a duplicate code when https://github.com/amber-lang/amber/pull/472 gets merged. Can we wait for it and extend the is_subset_of function declared in this issue?
im going to close this because
- this has no chance of ever being properly implemented in this current stage of language - due to the lack of a code scanning solution and transform a union into a singular type
- the current code is very outdated, it will likely require a complete refactor before it can be merged