close some gaps in the type system

This commit is contained in:
2026-07-19 01:01:11 +02:00
parent c7e3162ecb
commit 95f90cc306
12 changed files with 367 additions and 78 deletions
+27 -3
View File
@@ -625,14 +625,19 @@ ct_coerce_value :: proc(state: ^Ct_State, id: Ct_Value_Id, expected: types.Type,
}
if value.kind == .Function {
actual_item, actual_ok := types.node(store, value.type)
_, _, expected_function, expected_ok := types.function_pointer(expected, store)
_, _, expected_function, expected_pointer := types.function_pointer(expected, store)
expected_ok := expected_pointer
if expected_item, ok := types.node(store, expected); ok && expected_item.kind == .Function {
expected_function = expected
expected_ok = true
}
if actual_ok && actual_item.kind == .Function && expected_ok &&
types.equal(value.type, expected_function) {
value.type = expected
return ct_add_value(state, value), true
}
_, _, actual_function, actual_pointer := types.function_pointer(value.type, store)
if actual_pointer && expected_ok && types.equal(actual_function, expected_function) {
if actual_pointer && expected_pointer && types.equal(actual_function, expected_function) {
value.type = expected
return ct_add_value(state, value), true
}
@@ -1522,14 +1527,17 @@ ct_eval_struct_expr :: proc(state: ^Ct_State, expr: ast.Expr, expected: types.Ty
if values[index] != INVALID_CT_VALUE {
continue
}
field_default, has_default := find_struct_field_default(checker, struct_type, symbol.Id(field.name))
field_default, default_values, has_default := find_struct_field_default(checker, struct_type, symbol.Id(field.name))
if !has_default {
return INVALID_CT_VALUE, ct_flow(.Normal), ct_failf(state, .Not_Comptime, expr.span, "missing initializer for struct field '%s'", symbol_text(checker, symbol.Id(field.name)))
}
previous_pkg, previous_file := state.pkg, state.file
previous_comptime := checker.current_comptime_values
state.pkg, state.file = field_default.pkg, field_default.file
checker.current_comptime_values = default_values
value, flow, ok := ct_eval_expr(state, field_default.expr, field.type, depth+1)
state.pkg, state.file = previous_pkg, previous_file
checker.current_comptime_values = previous_comptime
if !ok || flow.kind != .Normal {
return INVALID_CT_VALUE, flow, ok
}
@@ -2102,6 +2110,16 @@ ct_eval_binary :: proc(state: ^Ct_State, op: ast.Expr_Kind, left_id, right_id: C
left := state.values[left_id]
right := state.values[right_id]
is_compare := op == .Eq || op == .Ne || op == .Lt || op == .Le || op == .Gt || op == .Ge
if left.kind == .Type || right.kind == .Type {
if left.kind != .Type || right.kind != .Type || (op != .Eq && op != .Ne) {
return INVALID_CT_VALUE, ct_flow(.Normal), ct_fail(state, .Not_Comptime, span, "type values only support '==' and '!=' with another type")
}
ok := types.equal(types.Type(left.index), types.Type(right.index))
if op == .Ne {
ok = !ok
}
return ct_add_value(state, Ct_Value{kind=.Bool, type=types.BOOL, integer=1 if ok else 0}), ct_flow(.Normal), true
}
if left.kind == .Bool && right.kind == .Bool {
if op != .Eq && op != .Ne {
return INVALID_CT_VALUE, ct_flow(.Normal), ct_fail(state, .Not_Comptime, span, "bool values only support '==' and '!='")
@@ -2897,6 +2915,12 @@ ct_eval_template_call :: proc(
if ct_value_references_dead_storage(state, result) {
return INVALID_CT_VALUE, ct_flow(.Normal), ct_fail(state, .Not_Comptime, span, "comptime function returned a pointer to expired storage")
}
if is_type_metatype_syntax(checker, function.result) && result != INVALID_CT_VALUE &&
int(result) < len(state.values) && state.values[result].kind == .Type {
record_type_factory_origin(
checker, types.Type(state.values[result].index), template, comptime_values,
)
}
if types.is_valid(expected) {
return ct_coerce_expr_value(state, result, expected, span)
}