enforce leading comptime params
This commit is contained in:
@@ -58,6 +58,7 @@ roadmap and milestone history.
|
||||
- integer comptime value parameters such as `make_array func($N usize) [N]u8`, specialized by value and omitted from the runtime ABI
|
||||
- explicit comptime type parameters such as `max func($T type, a, b T) T`, specialized by type and omitted from the runtime ABI
|
||||
- leading comptime type/integer parameters may be omitted when uniquely recoverable from runtime argument types or the immediate expected result; explicit calls remain valid
|
||||
- comptime parameters must form one leading prefix before all runtime parameters
|
||||
- forced typed comptime expressions such as `$sum(1, 2)`, `$Point { x = 1, y = 2 }`, and comptime value blocks such as `${ yield 4 }`
|
||||
- comptime execution for bodyful Brolang functions with mutable locals, loops, `defer`, `match`, `try`/`catch`, pointer/slice storage mutation, pointer captures, and calls through comptime-known function values
|
||||
- comptime type factories such as `Box func($T type) type { return struct { value T } }`; calls like `Box(i32)` are concrete nominal types and may appear anywhere a type is expected
|
||||
|
||||
@@ -787,6 +787,7 @@
|
||||
the resolved parameter type before ordinary coercion
|
||||
- calls are all-explicit or all-inferred (no partial prefix omission); unconstrained/conflicting
|
||||
values diagnose with the explicit call as the escape hatch
|
||||
- comptime parameters must form one leading prefix before every runtime parameter
|
||||
- the existing specialization/HIR/LLVM ABI is unchanged; `std/mem` and `std/arraylist` now use the
|
||||
inferred form where their arguments or result provide enough information
|
||||
|
||||
|
||||
@@ -2060,7 +2060,21 @@ validate_declarations :: proc(checker: ^Checker) {
|
||||
has_comptime := function_has_comptime_params(function)
|
||||
locals: [dynamic]symbol.Id
|
||||
locals.allocator = checker.allocator
|
||||
seen_runtime_param := false
|
||||
comptime_order_reported := false
|
||||
for param in function.params {
|
||||
if param.comptime_value {
|
||||
if seen_runtime_param && !comptime_order_reported {
|
||||
checker.template_diagnostics[function_id] = source.add(
|
||||
checker.diagnostics,
|
||||
param.span,
|
||||
"comptime parameters must form a leading parameter prefix",
|
||||
)
|
||||
comptime_order_reported = true
|
||||
}
|
||||
} else {
|
||||
seen_runtime_param = true
|
||||
}
|
||||
param_type := types.INVALID
|
||||
if param.comptime_value || !has_comptime {
|
||||
param_type = type_from_syntax(checker, param.type, function.pkg, function.file)
|
||||
|
||||
@@ -2650,6 +2650,42 @@ main func() void {
|
||||
testing.expect(t, unrecoverable >= 3)
|
||||
}
|
||||
|
||||
@(test)
|
||||
comptime_params_must_form_leading_prefix :: proc(t: ^testing.T) {
|
||||
text := `valid func($T type, $N usize, value T) [N]T {
|
||||
result [N]T = undefined
|
||||
_ = value
|
||||
return result
|
||||
}
|
||||
runtime_first func(value i32, $T type, $N usize) T { return value }
|
||||
split func($T type, value T, $N usize) [N]T {
|
||||
result [N]T = undefined
|
||||
_ = value
|
||||
return result
|
||||
}
|
||||
main func() void {}
|
||||
`
|
||||
source_file := source.Source{path="test.bro", text=text}
|
||||
diagnostics := source.init_diagnostics(&source_file)
|
||||
defer source.destroy_diagnostics(&diagnostics)
|
||||
symbols := symbol.init_table()
|
||||
defer symbol.destroy_table(&symbols)
|
||||
stream := lexer.lex(&source_file, &diagnostics, &symbols)
|
||||
defer delete(stream.items)
|
||||
ast_module := parser.parse(&stream, &source_file, &diagnostics)
|
||||
defer ast.destroy_module(&ast_module)
|
||||
hir_module := checker.check(&ast_module, &diagnostics, &symbols)
|
||||
defer hir.destroy_module(&hir_module)
|
||||
|
||||
count := 0
|
||||
for diagnostic in diagnostics.items {
|
||||
if strings.contains(diagnostic.message, "comptime parameters must form a leading parameter prefix") {
|
||||
count += 1
|
||||
}
|
||||
}
|
||||
testing.expect_value(t, count, 2)
|
||||
}
|
||||
|
||||
@(test)
|
||||
comptime_type_params_specialize_by_type_and_omit_runtime_args :: proc(t: ^testing.T) {
|
||||
text := `Point :: struct {
|
||||
|
||||
Reference in New Issue
Block a user