array size inference from value
This commit is contained in:
@@ -607,6 +607,25 @@ resolve_inferred_array :: proc(checker: ^Checker, value: types.Type, expr_id: as
|
||||
return types.with_array_count(&checker.module.types, value, u64(len(expr.args)))
|
||||
}
|
||||
|
||||
has_inferred_array_count :: proc(checker: ^Checker, value: types.Type) -> bool {
|
||||
item, ok := types.node(&checker.module.types, value)
|
||||
return ok && item.kind == .Array && item.inferred_count
|
||||
}
|
||||
|
||||
resolve_inferred_array_from_type :: proc(checker: ^Checker, value, inferred: types.Type) -> types.Type {
|
||||
item, ok := types.node(&checker.module.types, value)
|
||||
actual, actual_ok := types.node(&checker.module.types, inferred)
|
||||
if !ok || !actual_ok || item.kind != .Array || actual.kind != .Array || !item.inferred_count {
|
||||
return value
|
||||
}
|
||||
if item.child != actual.child || item.mutable != actual.mutable ||
|
||||
item.has_sentinel != actual.has_sentinel ||
|
||||
(item.has_sentinel && item.sentinel != actual.sentinel) {
|
||||
return value
|
||||
}
|
||||
return types.with_array_count(&checker.module.types, value, actual.count)
|
||||
}
|
||||
|
||||
function_index_less :: proc(left, right: Function_Index_Entry) -> bool {
|
||||
if left.scope != right.scope {
|
||||
return left.scope < right.scope
|
||||
@@ -2249,8 +2268,9 @@ infer_statements :: proc(
|
||||
value_type := types.INVALID
|
||||
if !is_undefined_expr(checker, statement.expr) {
|
||||
value_type = infer_expr(checker, statement.expr, locals^[:], pkg, file, demanded, local_types)
|
||||
declared_local = resolve_inferred_array_from_type(checker, declared_local, value_type)
|
||||
}
|
||||
if is_runtime_type(checker, declared_local) {
|
||||
if is_runtime_type(checker, declared_local) && !has_inferred_array_count(checker, declared_local) {
|
||||
value_type = declared_local
|
||||
} else if types.is_constraint(declared_local) {
|
||||
// Seed the binding in-family (INVALID on mismatch, which
|
||||
@@ -2823,8 +2843,12 @@ infer_all :: proc(checker: ^Checker) {
|
||||
// Demands accumulate in global_demands so the default never blocks a later
|
||||
// cross-family demand (e.g. integer literal -> unsigned or float).
|
||||
for global, index in checker.ast_module.globals {
|
||||
declared := type_from_syntax(checker, global.type, global.pkg, global.file)
|
||||
if is_runtime_type(checker, declared) {
|
||||
declared := resolve_inferred_array(
|
||||
checker,
|
||||
type_from_syntax(checker, global.type, global.pkg, global.file),
|
||||
global.expr,
|
||||
)
|
||||
if is_runtime_type(checker, declared) && !has_inferred_array_count(checker, declared) {
|
||||
checker.global_types[index] = declared
|
||||
continue
|
||||
}
|
||||
@@ -2871,7 +2895,20 @@ infer_all :: proc(checker: ^Checker) {
|
||||
continue
|
||||
}
|
||||
inferred := infer_expr(checker, global.expr, nil, global.pkg, global.file)
|
||||
if is_runtime_type(checker, type_from_syntax(checker, global.type, global.pkg, global.file)) {
|
||||
declared := resolve_inferred_array(
|
||||
checker,
|
||||
type_from_syntax(checker, global.type, global.pkg, global.file),
|
||||
global.expr,
|
||||
)
|
||||
if resolved := resolve_inferred_array_from_type(checker, declared, inferred);
|
||||
resolved != declared {
|
||||
if !types.equal(checker.global_types[index], resolved) {
|
||||
checker.global_types[index] = resolved
|
||||
changed = true
|
||||
}
|
||||
continue
|
||||
}
|
||||
if is_runtime_type(checker, declared) && !has_inferred_array_count(checker, declared) {
|
||||
continue
|
||||
}
|
||||
if is_runtime_type(checker, checker.global_demands[index]) {
|
||||
@@ -4935,7 +4972,7 @@ build_block :: proc(
|
||||
if statement_id != ast.INVALID_STMT && int(statement_id) < len(ctx.local_types) &&
|
||||
is_runtime_type(checker, ctx.local_types[statement_id]) &&
|
||||
(types.is_constraint(declared) || is_undefined_expr(checker, statement.expr) ||
|
||||
open_const_decl || numeric_arithmetic_decl) {
|
||||
open_const_decl || numeric_arithmetic_decl || has_inferred_array_count(checker, declared)) {
|
||||
declared = ctx.local_types[statement_id]
|
||||
}
|
||||
// A still-unresolved constraint means the initializer's numeric
|
||||
@@ -4974,7 +5011,7 @@ build_block :: proc(
|
||||
ctx.problematic^ = true
|
||||
continue
|
||||
}
|
||||
if !is_runtime_type(checker, declared) {
|
||||
if !is_runtime_type(checker, declared) || has_inferred_array_count(checker, declared) {
|
||||
id := source.addf(
|
||||
checker.diagnostics,
|
||||
statement.span,
|
||||
@@ -7477,6 +7514,10 @@ build_globals :: proc(checker: ^Checker) {
|
||||
calls: [dynamic]hir.Function_Id
|
||||
calls.allocator = checker.allocator
|
||||
declared := resolve_inferred_array(checker, type_from_syntax(checker, global.type, global.pkg, global.file), global.expr)
|
||||
if has_inferred_array_count(checker, declared) &&
|
||||
is_runtime_type(checker, checker.global_types[global_index]) {
|
||||
declared = checker.global_types[global_index]
|
||||
}
|
||||
expected := types.INVALID
|
||||
if is_runtime_type(checker, declared) {
|
||||
expected = declared
|
||||
|
||||
Reference in New Issue
Block a user