weak contextual string-literal inference
This commit is contained in:
@@ -2804,9 +2804,9 @@ infer_call_comptime_values :: proc(
|
|||||||
for value_bound in bound {
|
for value_bound in bound {
|
||||||
all_bound = all_bound && value_bound
|
all_bound = all_bound && value_bound
|
||||||
}
|
}
|
||||||
// Concrete arguments bind first. Numeric constants and `null` are contextual and
|
// Concrete arguments bind first. Numeric constants, string literals, and `null`
|
||||||
// therefore only contribute after stronger evidence has had a chance to bind the
|
// are contextual and therefore only contribute after stronger evidence has had a
|
||||||
// parameter type.
|
// chance to bind the parameter type.
|
||||||
weak_passes := [2]bool{false, true}
|
weak_passes := [2]bool{false, true}
|
||||||
for weak in weak_passes {
|
for weak in weak_passes {
|
||||||
for arg_id, source_index in args {
|
for arg_id, source_index in args {
|
||||||
@@ -2819,7 +2819,8 @@ infer_call_comptime_values :: proc(
|
|||||||
}
|
}
|
||||||
arg_expr := checker.ast_module.exprs[arg_id]
|
arg_expr := checker.ast_module.exprs[arg_id]
|
||||||
is_null := arg_expr.kind == .Null
|
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 {
|
if is_weak != weak {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4686,6 +4686,55 @@ main func() void {
|
|||||||
testing.expect(t, unrecoverable >= 3)
|
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)
|
@(test)
|
||||||
comptime_params_may_be_interleaved_and_are_erased_from_the_abi :: proc(t: ^testing.T) {
|
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 {
|
text := `valid func($T type, $N usize, value T) [N]T {
|
||||||
|
|||||||
Reference in New Issue
Block a user