inferred leading comptime params

This commit is contained in:
2026-07-12 17:02:12 +02:00
parent 0706188b98
commit 2dea7711f2
11 changed files with 769 additions and 84 deletions
+60 -2
View File
@@ -2573,8 +2573,8 @@ main func() void {
for diagnostic in diagnostics.items {
message := diagnostic.message
found_runtime_arg = found_runtime_arg || strings.contains(message, "must be a compile-time integer expression")
found_missing = found_missing || strings.contains(message, "expects 1 arguments, got 0")
found_extra = found_extra || strings.contains(message, "expects 1 arguments, got 2")
found_missing = found_missing || strings.contains(message, "cannot infer comptime parameter 'N'")
found_extra = found_extra || strings.contains(message, "expects 1 arguments with explicit comptime parameters or 0 with inferred comptime parameters, got 2")
found_negative = found_negative || strings.contains(message, "integer constant -1 does not fit in usize")
found_range = found_range || strings.contains(message, "integer constant 300 does not fit in u8")
found_bad_type = found_bad_type || strings.contains(message, "requires a concrete integer type")
@@ -2592,6 +2592,64 @@ main func() void {
testing.expect(t, found_address)
}
@(test)
inferred_comptime_params_diagnose_ambiguous_calls :: proc(t: ^testing.T) {
text := `Ignored func($T type) type {
return i32
}
Box func($T type) type {
return struct { value T }
}
BoxAlias func($T type) type {
return Box(T)
}
conflict func($T type, left, right T) T { return left }
unknown func($T type) T { value T = undefined; return value }
partial func($T type, $N usize, value T) T { return value }
use_ignored func($T type, value Ignored(T)) i32 { return value }
use_alias func($T type, value BoxAlias(T)) T { return value.value }
main func() void {
a i32 :: 1
b u32 :: 2
_ = conflict(a, b)
_ = unknown()
_ = partial(i32, a)
_ = use_ignored(a)
box Box(i32) :: Box(i32) { value = 1 }
_ = use_alias(box)
}
`
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)
found_conflict := false
found_unknown := false
found_partial := false
unrecoverable := 0
for diagnostic in diagnostics.items {
message := diagnostic.message
found_conflict = found_conflict || strings.contains(message, "conflicting inference for comptime parameter 'T': i32 and u32")
found_unknown = found_unknown || strings.contains(message, "cannot infer comptime parameter 'T'")
found_partial = found_partial || strings.contains(message, "expects 3 arguments with explicit comptime parameters or 1 with inferred comptime parameters, got 2")
if strings.contains(message, "cannot infer comptime parameter 'T'") {
unrecoverable += 1
}
}
testing.expect(t, found_conflict)
testing.expect(t, found_unknown)
testing.expect(t, found_partial)
testing.expect(t, unrecoverable >= 3)
}
@(test)
comptime_type_params_specialize_by_type_and_omit_runtime_args :: proc(t: ^testing.T) {
text := `Point :: struct {