weak contextual string-literal inference
This commit is contained in:
@@ -2804,9 +2804,9 @@ infer_call_comptime_values :: proc(
|
||||
for value_bound in bound {
|
||||
all_bound = all_bound && value_bound
|
||||
}
|
||||
// Concrete arguments bind first. Numeric constants and `null` are contextual and
|
||||
// therefore only contribute after stronger evidence has had a chance to bind the
|
||||
// parameter type.
|
||||
// Concrete arguments bind first. Numeric constants, string literals, and `null`
|
||||
// are contextual and therefore only contribute after stronger evidence has had a
|
||||
// chance to bind the parameter type.
|
||||
weak_passes := [2]bool{false, true}
|
||||
for weak in weak_passes {
|
||||
for arg_id, source_index in args {
|
||||
@@ -2819,7 +2819,8 @@ infer_call_comptime_values :: proc(
|
||||
}
|
||||
arg_expr := checker.ast_module.exprs[arg_id]
|
||||
is_null := arg_expr.kind == .Null
|
||||
is_weak := is_numeric_constant_expr(checker, arg_id) || is_null
|
||||
is_weak := is_numeric_constant_expr(checker, arg_id) ||
|
||||
arg_expr.kind == .String || is_null
|
||||
if is_weak != weak {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -4686,6 +4686,55 @@ main func() void {
|
||||
testing.expect(t, unrecoverable >= 3)
|
||||
}
|
||||
|
||||
@(test)
|
||||
string_literals_are_contextual_comptime_type_inference_evidence :: proc(t: ^testing.T) {
|
||||
text := `pair func($T type, expected, actual T) T {
|
||||
_ = expected
|
||||
return actual
|
||||
}
|
||||
identity func($T type, value T) T {
|
||||
return value
|
||||
}
|
||||
main func() void {
|
||||
actual []u8 :: "hello"
|
||||
contextual :: pair("hello", actual)
|
||||
exact :: identity("hello")
|
||||
_ = contextual
|
||||
_ = exact
|
||||
}
|
||||
`
|
||||
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)
|
||||
|
||||
pair_found := false
|
||||
identity_found := false
|
||||
for function in hir_module.functions {
|
||||
name := symbol.resolve(&symbols, function.name)
|
||||
if name == "pair" {
|
||||
pair_found = true
|
||||
testing.expect(t, types.is_slice(function.result, &hir_module.types))
|
||||
} else if name == "identity" {
|
||||
identity_found = true
|
||||
_, array, ok := types.array_pointer(function.result, &hir_module.types)
|
||||
testing.expect(t, ok && array.child == types.U8 && array.count == 5 &&
|
||||
array.has_sentinel && array.sentinel == 0)
|
||||
}
|
||||
}
|
||||
|
||||
testing.expect_value(t, len(diagnostics.items), 0)
|
||||
testing.expect(t, pair_found)
|
||||
testing.expect(t, identity_found)
|
||||
}
|
||||
|
||||
@(test)
|
||||
comptime_params_may_be_interleaved_and_are_erased_from_the_abi :: proc(t: ^testing.T) {
|
||||
text := `valid func($T type, $N usize, value T) [N]T {
|
||||
|
||||
Reference in New Issue
Block a user