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
|
- 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
|
- 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
|
- 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 }`
|
- 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 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
|
- 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
|
the resolved parameter type before ordinary coercion
|
||||||
- calls are all-explicit or all-inferred (no partial prefix omission); unconstrained/conflicting
|
- calls are all-explicit or all-inferred (no partial prefix omission); unconstrained/conflicting
|
||||||
values diagnose with the explicit call as the escape hatch
|
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
|
- 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
|
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)
|
has_comptime := function_has_comptime_params(function)
|
||||||
locals: [dynamic]symbol.Id
|
locals: [dynamic]symbol.Id
|
||||||
locals.allocator = checker.allocator
|
locals.allocator = checker.allocator
|
||||||
|
seen_runtime_param := false
|
||||||
|
comptime_order_reported := false
|
||||||
for param in function.params {
|
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
|
param_type := types.INVALID
|
||||||
if param.comptime_value || !has_comptime {
|
if param.comptime_value || !has_comptime {
|
||||||
param_type = type_from_syntax(checker, param.type, function.pkg, function.file)
|
param_type = type_from_syntax(checker, param.type, function.pkg, function.file)
|
||||||
|
|||||||
@@ -2650,6 +2650,42 @@ main func() void {
|
|||||||
testing.expect(t, unrecoverable >= 3)
|
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)
|
@(test)
|
||||||
comptime_type_params_specialize_by_type_and_omit_runtime_args :: proc(t: ^testing.T) {
|
comptime_type_params_specialize_by_type_and_omit_runtime_args :: proc(t: ^testing.T) {
|
||||||
text := `Point :: struct {
|
text := `Point :: struct {
|
||||||
|
|||||||
Reference in New Issue
Block a user