mirror of
https://github.com/odin-lang/Odin.git
synced 2026-08-26 06:51:34 +00:00
cmplx & quat take type from args
This commit is contained in:
@@ -3604,7 +3604,13 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
|
||||
default: GB_PANIC("Invalid type"); break;
|
||||
}
|
||||
|
||||
if (type_hint != nullptr && check_is_castable_to(c, operand, type_hint)) {
|
||||
// Only a complex hint of the same element type, or context-typing an untyped constant.
|
||||
// Castability is the rule for a conversion the programmer wrote; used here it adopted any
|
||||
// castable hint, which silently narrowed f64 to f32 and left the value with no element type
|
||||
// at all when the hint was `any` or a union
|
||||
if (type_hint != nullptr && is_type_complex(type_hint) &&
|
||||
(is_type_untyped(operand->type) ||
|
||||
are_types_identical(core_type(operand->type), core_type(type_hint)))) {
|
||||
operand->type = type_hint;
|
||||
}
|
||||
|
||||
@@ -3803,7 +3809,10 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
|
||||
default: GB_PANIC("Invalid type"); break;
|
||||
}
|
||||
|
||||
if (type_hint != nullptr && check_is_castable_to(c, operand, type_hint)) {
|
||||
// see the note in BuiltinProc_complex
|
||||
if (type_hint != nullptr && is_type_quaternion(type_hint) &&
|
||||
(is_type_untyped(operand->type) ||
|
||||
are_types_identical(core_type(operand->type), core_type(type_hint)))) {
|
||||
operand->type = type_hint;
|
||||
}
|
||||
|
||||
|
||||
55
tests/internal/test_complex_type_hint.odin
Normal file
55
tests/internal/test_complex_type_hint.odin
Normal file
@@ -0,0 +1,55 @@
|
||||
package test_internal
|
||||
|
||||
import "core:testing"
|
||||
|
||||
// `complex` and `quaternion` took their result type from any hint they were *castable* to, which is
|
||||
// the rule for a conversion the programmer writes. Used as an assignment rule it silently narrowed
|
||||
// f64 to f32, produced a quaternion from a two-component builtin with w and k uninitialised, and
|
||||
// left the value with no element type at all when the hint was `any` or a union -- a compiler panic
|
||||
@(test)
|
||||
complex_takes_its_type_from_its_arguments :: proc(t: ^testing.T) {
|
||||
a, b: f64 = 3, 4
|
||||
c, d: f32 = 3, 4
|
||||
|
||||
// the element type follows the arguments, not the hint
|
||||
x: complex128 = complex(a, b)
|
||||
y: complex64 = complex(c, d)
|
||||
testing.expect_value(t, real(x), f64(3))
|
||||
testing.expect_value(t, imag(x), f64(4))
|
||||
testing.expect_value(t, real(y), f32(3))
|
||||
testing.expect_value(t, imag(y), f32(4))
|
||||
|
||||
// a distinct complex of the same width still takes the hint, which core:c/libc relies on
|
||||
CD :: distinct complex128
|
||||
z: CD = complex(a, b)
|
||||
testing.expect_value(t, real(complex128(z)), f64(3))
|
||||
|
||||
// an untyped constant is still context-typed
|
||||
u: complex64 = complex(1, 2)
|
||||
testing.expect_value(t, real(u), f32(1))
|
||||
|
||||
q: quaternion256 = quaternion(w = a, x = b, y = a, z = b)
|
||||
testing.expect_value(t, real(q), f64(3))
|
||||
testing.expect_value(t, imag(q), f64(4))
|
||||
testing.expect_value(t, jmag(q), f64(3))
|
||||
testing.expect_value(t, kmag(q), f64(4))
|
||||
}
|
||||
|
||||
// a hint that is not a complex type is no longer adopted, so these reach the ordinary assignment
|
||||
// rule instead of the backend. `any` and a union both used to panic the compiler
|
||||
@(test)
|
||||
complex_into_any_and_union :: proc(t: ^testing.T) {
|
||||
U :: union { complex128 }
|
||||
|
||||
a, b: f64 = 3, 4
|
||||
|
||||
v: any = complex(a, b)
|
||||
if c, ok := v.(complex128); testing.expect(t, ok, "any did not hold a complex128") {
|
||||
testing.expect_value(t, real(c), f64(3))
|
||||
}
|
||||
|
||||
u: U = complex(a, b)
|
||||
if c, ok := u.(complex128); testing.expect(t, ok, "union did not hold a complex128") {
|
||||
testing.expect_value(t, imag(c), f64(4))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user