Amber icon indicating copy to clipboard operation
Amber copied to clipboard

feat: union types

Open b1ek opened this issue 1 year ago • 9 comments

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

b1ek avatar Sep 07 '24 04:09 b1ek

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.

mks-h avatar Sep 08 '24 05:09 mks-h

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.

mks-h avatar Sep 08 '24 06:09 mks-h

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.

mks-h avatar Sep 08 '24 06:09 mks-h

i don't know what you are talking about. the program doesnt compile on latest commit. the hashes are non collidable now

b1ek avatar Sep 08 '24 06:09 b1ek

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.

mks-h avatar Sep 08 '24 06:09 mks-h

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.

mks-h avatar Sep 08 '24 06:09 mks-h

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.

mks-h avatar Sep 09 '24 10:09 mks-h

Never mind I just realized I reviewed an old piece of code

Ph0enixKM avatar Sep 15 '24 10:09 Ph0enixKM

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?

Ph0enixKM avatar Sep 15 '24 11:09 Ph0enixKM

im going to close this because

  1. 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
  2. the current code is very outdated, it will likely require a complete refactor before it can be merged

b1ek avatar May 21 '25 09:05 b1ek