onyx-lang / onyx

✨ The compiler and developer toolchain for Onyx
https://onyxlang.io
BSD 2-Clause "Simplified" License
576 stars 22 forks source link

Operator overload used on function return values gives weird results #151

Closed dgriffie79 closed 13 hours ago

dgriffie79 commented 6 months ago
use core {*}

V :: #distinct [4]f32

#operator* (a: V, b: V) -> V {
    return ~~ (cast([4]f32, a) * cast([4]f32, b))
}

makev :: () -> V {
    return ~~ f32.[1, 2, 3, 4]
}

main :: () {
    a: V = ~~ f32.[1, 2, 3, 4]
    b: V = ~~ f32.[1, 2, 3, 4]

    printf("{}\n", a * b)

    a = makev()
    b = makev()    
    printf("{}\n", a * b)

    printf("{}\n", makev() * makev())
}

Expected output:

V[[ 1.0000, 4.0000, 9.0000, 16.0000 ]]
V[[ 1.0000, 4.0000, 9.0000, 16.0000 ]]
V[[ 1.0000, 4.0000, 9.0000, 16.0000 ]]

Actual ouput:

V[[ 1.0000, 4.0000, 9.0000, 16.0000 ]]
V[[ 1.0000, 4.0000, 9.0000, 16.0000 ]]
V[[ 0.0000, 0.0000, 0.0000, 16.0000 ]]
dgriffie79 commented 5 months ago

Actually I think it is something wrong with the f32 array operators, here's an example where it works with i32 but not f32

use core {*}

foo :: (a: [2]f32) -> void {
    printf("{} {}\n", a, a + a)
}

f2 :: () -> [2]f32 {
    return .[1, 2]
}

ioo :: (a: [2]i32) -> void {
    printf("{} {}\n", a, a + a)
}

i2 :: () -> [2]i32 {
    return .[1, 2]
}

main :: () {
    foo(f2())
    ioo(i2())
}
[ 1.0000, 2.0000 ] [ 0.0000, 4.0000 ]
[ 1, 2 ] [ 2, 4 ]
brendanfh commented 13 hours ago

This has been addressed in the latest version of Onyx by making fixed-sized arrays ([N] T) pass-by-value instead of pass-by-pointer. They are now copied as arguments and return values, which fixed the weird aliasing issues you were running into.

This was fixed awhile ago, but I am finally getting around to cleaning up the issue list. Thanks for the bug report!