comptime storage and function values

This commit is contained in:
2026-07-03 23:23:36 +02:00
parent ee41a54e41
commit 4ebe9c90e9
8 changed files with 1255 additions and 119 deletions
+42 -20
View File
@@ -903,13 +903,16 @@ function_value_signature :: proc(
return nil, types.INVALID, false
}
function := checker.ast_module.functions[template]
if !function.c_abi || types.is_valid(function.error) {
return nil, types.INVALID, false
}
if function_has_comptime_params(function) {
return nil, types.INVALID, false
}
result = type_from_syntax(checker, function.result, function.pkg, function.file)
if function.c_abi && types.is_valid(function.error) {
return nil, types.INVALID, false
}
if !function.c_abi && (!function.has_body || function.variadic) {
return nil, types.INVALID, false
}
result = function_channel_type(checker, function)
if !types.is_void(result) && !is_runtime_type(checker, result) {
return nil, types.INVALID, false
}
@@ -929,6 +932,7 @@ function_pointer_type_for_template :: proc(
checker: ^Checker,
template: ast.Function_Id,
demanded: ^[dynamic]Spec_Id = nil,
demand_spec := true,
) -> (types.Type, Spec_Id, bool) {
params, result, ok := function_value_signature(checker, template)
if !ok {
@@ -936,16 +940,20 @@ function_pointer_type_for_template :: proc(
}
defer delete(params, checker.allocator)
function := checker.ast_module.functions[template]
function_type := types.function(&checker.module.types, params, result, true, function.variadic)
function_type := types.function(&checker.module.types, params, result, function.c_abi, function.variadic)
pointer_type := types.pointer(&checker.module.types, function_type, false, true)
spec := INVALID_SPEC
if demanded == nil {
spec = ensure_spec(checker, template, params)
if demand_spec {
spec = ensure_spec(checker, template, params)
} else {
spec = find_spec(checker, template, params)
}
} else {
spec = find_spec(checker, template, params)
mark_spec_demanded(checker, spec, demanded)
}
return pointer_type, spec, spec != INVALID_SPEC
return pointer_type, spec, spec != INVALID_SPEC || !demand_spec
}
contains_name :: proc(names: []symbol.Id, name: symbol.Id) -> bool {
@@ -1391,16 +1399,30 @@ validate_type_nodes :: proc(checker: ^Checker) {
}
}
if item.kind == .Function {
if !item.c_abi {
source.add(checker.diagnostics, source.Span{}, "only c_func function pointer types are supported")
}
for param in types.params_for(&checker.module.types, id) {
if types.is_void(param.type) || !types.is_c_signature_type(param.type, &checker.module.types) {
source.add(checker.diagnostics, source.Span{}, "function pointer parameters must be concrete C signature types")
if item.c_abi {
if types.kind(item.child, &checker.module.types) == .Fallible {
source.add(checker.diagnostics, source.Span{}, "c_func pointer results cannot be fallible")
}
for param in types.params_for(&checker.module.types, id) {
if types.is_void(param.type) || !types.is_c_signature_type(param.type, &checker.module.types) {
source.add(checker.diagnostics, source.Span{}, "c_func pointer parameters must be concrete C signature types")
}
}
if !types.is_c_signature_type(item.child, &checker.module.types, true) {
source.add(checker.diagnostics, source.Span{}, "c_func pointer results must be concrete C signature types or void")
}
} else {
if item.variadic {
source.add(checker.diagnostics, source.Span{}, "native function pointer types do not support variadic parameters")
}
for param in types.params_for(&checker.module.types, id) {
if types.is_void(param.type) || !is_runtime_type(checker, param.type) {
source.add(checker.diagnostics, source.Span{}, "native function pointer parameters must be concrete runtime types")
}
}
if !types.is_void(item.child) && !is_runtime_type(checker, item.child) {
source.add(checker.diagnostics, source.Span{}, "native function pointer results must be concrete runtime types or void")
}
}
if !types.is_c_signature_type(item.child, &checker.module.types, true) {
source.add(checker.diagnostics, source.Span{}, "function pointer results must be concrete C signature types or void")
}
}
}
@@ -1597,7 +1619,7 @@ infer_compound_expr :: proc(
store := &checker.module.types
#partial switch expr.kind {
case .Comptime:
return infer_comptime_expr_type(checker, expr, pkg, file)
return infer_comptime_expr_type(checker, expr, pkg, file, demanded)
case .Bool:
return types.BOOL
case .Not:
@@ -3535,13 +3557,13 @@ build_function_value :: proc(
id := source.addf(
checker.diagnostics,
span,
"function '%s' cannot be used as a C callback; expected a concrete c_func",
"function '%s' cannot be used as a function value; expected a concrete non-comptime signature",
symbol_text(checker, function.name),
)
return invalid_hir_expr(checker, span, id)
}
defer delete(params, checker.allocator)
function_type := types.function(&checker.module.types, params, result, true, function.variadic)
function_type := types.function(&checker.module.types, params, result, function.c_abi, function.variadic)
pointer_type := types.pointer(&checker.module.types, function_type, false, true)
spec := find_spec(checker, template, params)
if spec == INVALID_SPEC {
@@ -4444,7 +4466,7 @@ build_expr :: proc(
last = build_global_reference(checker, global, expr.span, global_reads)
} else {
template := find_template(checker, expr.name, target_pkg)
if template != ast.INVALID_FUNCTION && checker.ast_module.functions[template].c_abi {
if template != ast.INVALID_FUNCTION {
last = build_function_value(checker, template, expr.span, frame.expected)
} else {
id := add_unsupported_diagnostic(checker, expr.span, target_pkg, expr.name)