From 4f7530d011c3a6f9dbce269bce663b109393a1e4 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Thu, 14 May 2026 08:30:37 +0300 Subject: [PATCH] tests: update checker error expectations v2: more fixes --- ...gn_immutable_reference_call_result_err.out | 22 ++++----- ...xed_array_new_syntax_size_mismatch_err.out | 4 +- .../tests/if_smartcast_mutation_err.out | 12 ++--- .../tests/orm_dynamic_unknown_field_err.out | 2 +- ...ol_processor_callback_array_return_err.out | 2 +- ...ool_processor_callback_array_return_err.vv | 2 +- vlib/v2/gen/cleanc/array.v | 9 +++- vlib/v2/gen/cleanc/fn.v | 11 +++++ vlib/v2/gen/cleanc/struct.v | 6 +-- vlib/v2/transformer/fn.v | 46 +++++++++-------- vlib/v2/transformer/struct.v | 46 +++++++++++++++-- vlib/v2/transformer/transformer.v | 49 ++++++++++++------- vlib/v2/transformer/types.v | 15 ++++-- vlib/v2/types/checker.v | 32 +++++++----- 14 files changed, 170 insertions(+), 88 deletions(-) diff --git a/vlib/v/checker/tests/assign_immutable_reference_call_result_err.out b/vlib/v/checker/tests/assign_immutable_reference_call_result_err.out index 74ef64e22..a78084c91 100644 --- a/vlib/v/checker/tests/assign_immutable_reference_call_result_err.out +++ b/vlib/v/checker/tests/assign_immutable_reference_call_result_err.out @@ -1,13 +1,13 @@ -vlib/v/checker/tests/assign_immutable_reference_call_result_err.vv:15:16: notice: `ja` is immutable, cannot have a mutable reference to an immutable object - 13 | fn main() { - 14 | ja := User{name: 'foo'} - 15 | mut x := rere(ja) +vlib/v/checker/tests/assign_immutable_reference_call_result_err.vv:17:16: notice: `ja` is immutable, cannot have a mutable reference to an immutable object + 15 | name: 'foo' + 16 | } + 17 | mut x := rere(ja) | ~~ - 16 | x.name = 'bar' - 17 | } -vlib/v/checker/tests/assign_immutable_reference_call_result_err.vv:16:4: error: `x.name` aliases mutable data from an immutable value - 14 | ja := User{name: 'foo'} - 15 | mut x := rere(ja) - 16 | x.name = 'bar' + 18 | x.name = 'bar' + 19 | } +vlib/v/checker/tests/assign_immutable_reference_call_result_err.vv:18:4: error: `x.name` aliases mutable data from an immutable value + 16 | } + 17 | mut x := rere(ja) + 18 | x.name = 'bar' | ~~~~ - 17 | } + 19 | } diff --git a/vlib/v/checker/tests/fixed_array_new_syntax_size_mismatch_err.out b/vlib/v/checker/tests/fixed_array_new_syntax_size_mismatch_err.out index 4d8102078..400be1a05 100644 --- a/vlib/v/checker/tests/fixed_array_new_syntax_size_mismatch_err.out +++ b/vlib/v/checker/tests/fixed_array_new_syntax_size_mismatch_err.out @@ -1,5 +1,5 @@ vlib/v/checker/tests/fixed_array_new_syntax_size_mismatch_err.vv:2:13: error: fixed array expects 2 value(s), but got 3 1 | fn main() { - 2 | _ := [2]int[1 2 3] - | ~~~~~~~ + 2 | _ := [2]int[1, 2, 3] + | ~~~~~~~~~ 3 | } diff --git a/vlib/v/checker/tests/if_smartcast_mutation_err.out b/vlib/v/checker/tests/if_smartcast_mutation_err.out index de9a597ec..56542cd63 100644 --- a/vlib/v/checker/tests/if_smartcast_mutation_err.out +++ b/vlib/v/checker/tests/if_smartcast_mutation_err.out @@ -1,7 +1,7 @@ -vlib/v/checker/tests/if_smartcast_mutation_err.vv:5:3: error: cannot mutate `a` in a non-mut smartcast, use `if mut a ...` - 3 | a := SmartcastValue(1) - 4 | if a is int { - 5 | a = 3 +vlib/v/checker/tests/if_smartcast_mutation_err.vv:6:3: error: cannot mutate `a` in a non-mut smartcast, use `if mut a ...` + 4 | a := SmartcastValue(1) + 5 | if a is int { + 6 | a = 3 | ^ - 6 | } - 7 | } + 7 | } + 8 | } diff --git a/vlib/v/checker/tests/orm_dynamic_unknown_field_err.out b/vlib/v/checker/tests/orm_dynamic_unknown_field_err.out index d19a8a43b..a1dd4f925 100644 --- a/vlib/v/checker/tests/orm_dynamic_unknown_field_err.out +++ b/vlib/v/checker/tests/orm_dynamic_unknown_field_err.out @@ -2,7 +2,7 @@ vlib/v/checker/tests/orm_dynamic_unknown_field_err.vv:11:13: error: ORM: `User` 2 possibilities: `id`, `name`. 9 | db := sqlite.connect(':memory:') or { panic(err) } 10 | where_expr := { - 11 | if true { zzz == 'Alice' }, + 11 | if true { zzz == 'Alice' } | ~~~ 12 | } 13 | _ := sql db { diff --git a/vlib/v/checker/tests/pool_processor_callback_array_return_err.out b/vlib/v/checker/tests/pool_processor_callback_array_return_err.out index b6ca5727e..193fd1d3f 100644 --- a/vlib/v/checker/tests/pool_processor_callback_array_return_err.out +++ b/vlib/v/checker/tests/pool_processor_callback_array_return_err.out @@ -2,6 +2,6 @@ vlib/v/checker/tests/pool_processor_callback_array_return_err.vv:9:3: error: can 7 | fn main() { 8 | _ := pool.new_pool_processor( 9 | callback: fn (mut pp pool.PoolProcessor, idx int, wid int) []Foo { - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 10 | _ = wid 11 | return [Foo{ diff --git a/vlib/v/checker/tests/pool_processor_callback_array_return_err.vv b/vlib/v/checker/tests/pool_processor_callback_array_return_err.vv index 31fafe05a..868c1a242 100644 --- a/vlib/v/checker/tests/pool_processor_callback_array_return_err.vv +++ b/vlib/v/checker/tests/pool_processor_callback_array_return_err.vv @@ -6,7 +6,7 @@ struct Foo { fn main() { _ := pool.new_pool_processor( - callback: fn (mut pp pool.PoolProcessor, idx int, wid int) []main.Foo { + callback: fn (mut pp pool.PoolProcessor, idx int, wid int) []Foo { _ = wid return [Foo{ page: pp.get_item[int](idx).str() diff --git a/vlib/v2/gen/cleanc/array.v b/vlib/v2/gen/cleanc/array.v index a0cb402dd..7146f51bb 100644 --- a/vlib/v2/gen/cleanc/array.v +++ b/vlib/v2/gen/cleanc/array.v @@ -503,6 +503,11 @@ fn (mut g Gen) infer_array_elem_type_from_expr(arr_expr ast.Expr) string { mut elem_type := g.extract_array_elem_type(arr_expr.typ) if arr_expr.exprs.len > 0 { first_expr_type := g.array_init_elem_type_from_expr(arr_expr.exprs[0]) + if elem_type.starts_with('Array_') + && (elem_type.ends_with('*') || elem_type.ends_with('ptr')) && first_expr_type != '' + && !first_expr_type.starts_with('Array_') && !first_expr_type.ends_with('*') { + return first_expr_type + } if elem_type != '' && first_expr_type != '' && first_expr_type.starts_with('${elem_type}_T_') { return first_expr_type @@ -707,8 +712,8 @@ fn (mut g Gen) gen_array_init_expr(node ast.ArrayInitExpr) { should_use_inferred := final_elem == '' || final_elem == 'int' || final_elem == 'int_literal' || (inferred != '' && final_elem != '' && inferred.starts_with('${final_elem}_T_')) - || (final_elem.starts_with('Array_') && final_elem.ends_with('ptr') - && inferred != '' && !inferred.starts_with('Array_') && !inferred.ends_with('*')) + || (final_elem.starts_with('Array_') && final_elem.ends_with('ptr') && inferred != '' + && !inferred.starts_with('Array_') && !inferred.ends_with('*')) if should_use_inferred && inferred != '' && inferred != 'array' && inferred != 'int' { final_elem = inferred } diff --git a/vlib/v2/gen/cleanc/fn.v b/vlib/v2/gen/cleanc/fn.v index 1e43e326a..50a81add0 100644 --- a/vlib/v2/gen/cleanc/fn.v +++ b/vlib/v2/gen/cleanc/fn.v @@ -3161,6 +3161,17 @@ fn (mut g Gen) gen_call_arg(fn_name string, idx int, arg ast.Expr) { g.expr(base_arg) return } + } + if param_types := g.fn_param_types[fn_name] { + if idx < param_types.len { + param_base := param_types[idx].trim_right('*') + if param_base != '' && param_base != 'void' { + g.gen_addr_of_expr(base_arg, param_base) + return + } + } + } + if raw := g.get_raw_type(base_arg) { c_type := g.types_type_to_c(raw) if c_type != '' { g.gen_addr_of_expr(base_arg, c_type) diff --git a/vlib/v2/gen/cleanc/struct.v b/vlib/v2/gen/cleanc/struct.v index 4da63e9e4..7c7502761 100644 --- a/vlib/v2/gen/cleanc/struct.v +++ b/vlib/v2/gen/cleanc/struct.v @@ -1623,8 +1623,7 @@ fn (mut g Gen) gen_init_expr(node ast.InitExpr) { mut wrote_defaults := 0 g.sb.write_string('((${type_name}){') for field in env_struct.fields { - expected_field_type := g.init_field_expected_type(type_name, env_struct, - field.name) + expected_field_type := g.init_field_expected_type(type_name, env_struct, field.name) if !g.struct_field_needs_explicit_default_for(type_name, env_struct, field) { continue } @@ -1848,8 +1847,7 @@ fn (mut g Gen) gen_init_expr(node ast.InitExpr) { if initialized_fields[field.name] { continue } - expected_field_type := g.init_field_expected_type(type_name, env_struct, - field.name) + expected_field_type := g.init_field_expected_type(type_name, env_struct, field.name) if !g.struct_field_needs_explicit_default_for(type_name, env_struct, field) { continue } diff --git a/vlib/v2/transformer/fn.v b/vlib/v2/transformer/fn.v index 6b7fb9608..d27107e6e 100644 --- a/vlib/v2/transformer/fn.v +++ b/vlib/v2/transformer/fn.v @@ -290,8 +290,8 @@ fn (t &Transformer) infer_receiver_generic_bindings(receiver ast.Expr) map[strin for template_field in template_struct.fields { for actual_field in actual_struct.fields { if template_field.name == actual_field.name { - infer_transformer_generic_bindings(template_field.typ, actual_field.typ, - mut bindings, 0) + infer_transformer_generic_bindings(template_field.typ, actual_field.typ, mut + bindings, 0) break } } @@ -306,26 +306,27 @@ fn infer_transformer_generic_bindings(param_type types.Type, arg_type types.Type match param_type { types.Alias { infer_transformer_generic_bindings(param_type.base_type, arg_type, mut bindings, + depth + 1) } types.Array { if arg_type is types.Array { - infer_transformer_generic_bindings(param_type.elem_type, arg_type.elem_type, - mut bindings, depth + 1) + infer_transformer_generic_bindings(param_type.elem_type, arg_type.elem_type, mut + bindings, depth + 1) } } types.ArrayFixed { if arg_type is types.ArrayFixed { - infer_transformer_generic_bindings(param_type.elem_type, arg_type.elem_type, - mut bindings, depth + 1) + infer_transformer_generic_bindings(param_type.elem_type, arg_type.elem_type, mut + bindings, depth + 1) } } types.Map { if arg_type is types.Map { - infer_transformer_generic_bindings(param_type.key_type, arg_type.key_type, - mut bindings, depth + 1) - infer_transformer_generic_bindings(param_type.value_type, arg_type.value_type, - mut bindings, depth + 1) + infer_transformer_generic_bindings(param_type.key_type, arg_type.key_type, mut + bindings, depth + 1) + infer_transformer_generic_bindings(param_type.value_type, arg_type.value_type, mut + bindings, depth + 1) } } types.NamedType { @@ -333,23 +334,24 @@ fn infer_transformer_generic_bindings(param_type types.Type, arg_type types.Type } types.OptionType { if arg_type is types.OptionType { - infer_transformer_generic_bindings(param_type.base_type, arg_type.base_type, - mut bindings, depth + 1) + infer_transformer_generic_bindings(param_type.base_type, arg_type.base_type, mut + bindings, depth + 1) } } types.Pointer { if arg_type is types.Pointer { - infer_transformer_generic_bindings(param_type.base_type, arg_type.base_type, - mut bindings, depth + 1) + infer_transformer_generic_bindings(param_type.base_type, arg_type.base_type, mut + bindings, depth + 1) } else { infer_transformer_generic_bindings(param_type.base_type, arg_type, mut bindings, + depth + 1) } } types.ResultType { if arg_type is types.ResultType { - infer_transformer_generic_bindings(param_type.base_type, arg_type.base_type, - mut bindings, depth + 1) + infer_transformer_generic_bindings(param_type.base_type, arg_type.base_type, mut + bindings, depth + 1) } } else {} @@ -364,21 +366,18 @@ fn substitute_transformer_generic_type(typ types.Type, bindings map[string]types types.Alias { return types.Type(types.Alias{ name: typ.name - base_type: substitute_transformer_generic_type(typ.base_type, bindings, - depth + 1) + base_type: substitute_transformer_generic_type(typ.base_type, bindings, depth + 1) }) } types.Array { return types.Type(types.Array{ - elem_type: substitute_transformer_generic_type(typ.elem_type, bindings, - depth + 1) + elem_type: substitute_transformer_generic_type(typ.elem_type, bindings, depth + 1) }) } types.ArrayFixed { return types.Type(types.ArrayFixed{ len: typ.len - elem_type: substitute_transformer_generic_type(typ.elem_type, bindings, - depth + 1) + elem_type: substitute_transformer_generic_type(typ.elem_type, bindings, depth + 1) }) } types.Channel { @@ -392,8 +391,7 @@ fn substitute_transformer_generic_type(typ types.Type, bindings map[string]types types.Map { return types.Type(types.Map{ key_type: substitute_transformer_generic_type(typ.key_type, bindings, depth + 1) - value_type: substitute_transformer_generic_type(typ.value_type, bindings, - depth + 1) + value_type: substitute_transformer_generic_type(typ.value_type, bindings, depth + 1) }) } types.NamedType { diff --git a/vlib/v2/transformer/struct.v b/vlib/v2/transformer/struct.v index 8701e814f..de4a1ff32 100644 --- a/vlib/v2/transformer/struct.v +++ b/vlib/v2/transformer/struct.v @@ -879,6 +879,28 @@ fn (mut t Transformer) transform_array_init_expr(expr ast.ArrayInitExpr) ast.Exp // First, try to get the array type from the type checker's annotations mut elem_type_name := 'int' mut elem_type_expr_resolved := elem_type_expr + if elem_type_expr_resolved !is ast.EmptyExpr && exprs.len > 0 { + mut inferred_elem_name := t.expr_to_type_name(elem_type_expr_resolved) + if inferred_elem_name == '' { + inferred_elem_name = t.type_expr_to_c_name(elem_type_expr_resolved) + } + if inferred_elem_name.starts_with('Array_') && inferred_elem_name.ends_with('ptr') { + mut first_name := if expr.exprs.len > 0 { + t.concrete_array_literal_elem_name(expr.exprs[0]) + } else { + '' + } + if first_name == '' { + first_name = t.concrete_array_literal_elem_name(exprs[0]) + } + if first_name != '' && !first_name.starts_with('Array_') && !first_name.ends_with('*') { + elem_type_name = first_name + elem_type_expr_resolved = ast.Expr(ast.Ident{ + name: first_name + }) + } + } + } if elem_type_expr_resolved is ast.EmptyExpr && exprs.len > 0 { if arr_type := t.env.get_expr_type(expr.pos.id) { match arr_type { @@ -889,6 +911,23 @@ fn (mut t Transformer) transform_array_init_expr(expr ast.ArrayInitExpr) ast.Exp elem_type_expr_resolved = ast.Expr(ast.Ident{ name: tn }) + if tn.starts_with('Array_') && tn.ends_with('ptr') { + mut first_name := if expr.exprs.len > 0 { + t.concrete_array_literal_elem_name(expr.exprs[0]) + } else { + '' + } + if first_name == '' { + first_name = t.concrete_array_literal_elem_name(exprs[0]) + } + if first_name != '' && !first_name.starts_with('Array_') + && !first_name.ends_with('*') { + elem_type_name = first_name + elem_type_expr_resolved = ast.Expr(ast.Ident{ + name: first_name + }) + } + } } } types.ArrayFixed { @@ -1923,8 +1962,9 @@ fn (mut t Transformer) add_missing_struct_field_defaults(struct_name string, fie } struct_info := base_type as types.Struct default_struct_short_name := if struct_info.name != '' { struct_info.name } else { struct_name } - default_struct_name := if default_struct_short_name.contains('__') || type_lookup.module_name == '' - || type_lookup.module_name == 'main' || type_lookup.module_name == 'builtin' { + default_struct_name := if default_struct_short_name.contains('__') + || type_lookup.module_name == '' || type_lookup.module_name == 'main' + || type_lookup.module_name == 'builtin' { default_struct_short_name } else { '${type_lookup.module_name}__${default_struct_short_name}' @@ -2167,7 +2207,7 @@ fn (mut t Transformer) transform_struct_field_default_expr(struct_name string, e old_module := t.cur_module t.cur_module = module_name transformed := t.transform_call_expr(ast.CallExpr{ - lhs: ast.Ident{ + lhs: ast.Ident{ name: '${module_name}__${fn_name}' pos: expr.pos } diff --git a/vlib/v2/transformer/transformer.v b/vlib/v2/transformer/transformer.v index 9975e878a..b1260a54d 100644 --- a/vlib/v2/transformer/transformer.v +++ b/vlib/v2/transformer/transformer.v @@ -1289,13 +1289,10 @@ pub fn (mut t Transformer) post_pass(mut result []ast.File) { t.env.set_expr_type(id, typ) } // Push cached_fn_scopes back to the environment for prop_types. - lock t.env.fn_scopes { - fn_scope_keys := t.cached_fn_scopes.keys() - for k in fn_scope_keys { - v := t.cached_fn_scopes[k] or { continue } - t.env.fn_scope_cache[k] = v - t.env.fn_scopes[k] = v - } + fn_scope_keys := t.cached_fn_scopes.keys() + for k in fn_scope_keys { + v := t.cached_fn_scopes[k] or { continue } + t.env.set_fn_scope_by_key(k, v) } t.propagate_types(result) } @@ -11452,6 +11449,25 @@ fn (mut t Transformer) resolve_enum_shorthand(expr ast.Expr, enum_type string) a return expr } +fn (t &Transformer) concrete_array_literal_elem_name(expr ast.Expr) string { + if expr is ast.ModifierExpr { + return t.concrete_array_literal_elem_name(expr.expr) + } + if expr is ast.ParenExpr { + return t.concrete_array_literal_elem_name(expr.expr) + } + if expr is ast.InitExpr { + return t.expr_to_type_name(expr.typ) + } + if expr is ast.CastExpr { + return t.expr_to_type_name(expr.typ) + } + if typ := t.get_expr_type(expr) { + return t.type_to_c_name(typ) + } + return '' +} + // transform_array_with_enum_context transforms an array init, resolving enum shorthand using the given enum type fn (mut t Transformer) transform_array_with_enum_context(arr ast.ArrayInitExpr, enum_type string) ast.Expr { mut exprs := []ast.Expr{cap: arr.exprs.len} @@ -11513,21 +11529,16 @@ fn (mut t Transformer) transform_array_init_with_exprs(arr ast.ArrayInitExpr, ex name: tn }) if arr.exprs.len > 0 { - mut first_name := '' - if arr.exprs[0] is ast.InitExpr { - first_name = t.expr_to_type_name((arr.exprs[0] as ast.InitExpr).typ) - } - if first_name == '' { - if first_type := t.get_expr_type(arr.exprs[0]) { - first_name = t.type_to_c_name(first_type) - } + mut first_name := t.concrete_array_literal_elem_name(arr.exprs[0]) + if first_name == '' && exprs.len > 0 { + first_name = t.concrete_array_literal_elem_name(exprs[0]) } if tn.starts_with('Array_') && tn.ends_with('ptr') && first_name != '' && !first_name.starts_with('Array_') && !first_name.ends_with('*') { - elem_type_name = first_name - elem_type_expr2 = ast.Expr(ast.Ident{ - name: first_name - }) + elem_type_name = first_name + elem_type_expr2 = ast.Expr(ast.Ident{ + name: first_name + }) } } } diff --git a/vlib/v2/transformer/types.v b/vlib/v2/transformer/types.v index 8582f0b42..9a98ac1dc 100644 --- a/vlib/v2/transformer/types.v +++ b/vlib/v2/transformer/types.v @@ -3868,12 +3868,21 @@ fn (t &Transformer) type_to_c_name_resolve_alias(typ types.Type) string { 'f64', 'rune'] // First check if the alias name itself is already a primitive // (in self-host mode, 'int' is stored as Alias with malformed .base_type) - alias_name := t.type_to_c_name(typ) + alias_typ := types.Type(typ) + raw_alias_name := types.type_name(alias_typ) + if raw_alias_name == '' { + return 'int' + } + alias_name := t.qualify_type_name(raw_alias_name) if alias_name in primitives { return alias_name } - // Resolve to the underlying type - base := typ.base_type + // Resolve to the underlying type. Use the helper instead of direct field + // access because self-hosted ARM64 aliases can carry a null data pointer. + base := types.resolve_alias(alias_typ) + if types.type_name(base) == '' { + return alias_name + } // If base is a primitive int type, use that base_name := t.type_to_c_name(base) if base_name in primitives { diff --git a/vlib/v2/types/checker.v b/vlib/v2/types/checker.v index bf9750389..c5d2d8084 100644 --- a/vlib/v2/types/checker.v +++ b/vlib/v2/types/checker.v @@ -14,6 +14,9 @@ const embed_file_helper_type_name = '__V2EmbedFileData' pub struct Environment { pub mut: + scope_cache map[string]&Scope + fn_scope_cache map[string]&Scope + method_cache map[string][]&Fn // errors with no default value scopes shared map[string]&Scope = map[string]&Scope{} // Function scopes - stores the scope for each function by qualified name (module__fn_name) @@ -22,9 +25,6 @@ pub mut: // types map[int]Type // methods - shared for parallel type checking methods shared map[string][]&Fn = map[string][]&Fn{} - scope_cache map[string]&Scope - fn_scope_cache map[string]&Scope - method_cache map[string][]&Fn generic_types map[string][]map[string]Type cur_generic_types []map[string]Type // Expression types - indexed directly by pos.id. @@ -184,10 +184,17 @@ pub fn (mut e Environment) add_method_for_type(type_name string, method &Fn) { } } +fn (mut e Environment) set_scope(module_name string, scope &Scope) { + e.scope_cache[module_name] = scope + lock e.scopes { + e.scopes[module_name] = scope + } +} + // lookup_fn looks up a function by module and name in the environment's scopes // Returns the function's FnType if found pub fn (e &Environment) lookup_fn(module_name string, fn_name string) ?FnType { - scope := e.scope_cache[module_name] or { return none } + scope := e.get_scope(module_name) or { return none } if obj := scope.lookup_parent(fn_name, 0) { if obj is Fn { typ := obj.get_typ() @@ -212,6 +219,11 @@ pub fn (e &Environment) lookup_local_var(scope &Scope, name string) ?Type { // set_fn_scope stores the scope for a function by its qualified name pub fn (mut e Environment) set_fn_scope(module_name string, fn_name string, scope &Scope) { key := if module_name == '' { fn_name } else { '${module_name}__${fn_name}' } + e.set_fn_scope_by_key(key, scope) +} + +// set_fn_scope_by_key stores the scope for a function by its fully-qualified key. +pub fn (mut e Environment) set_fn_scope_by_key(key string, scope &Scope) { e.fn_scope_cache[key] = scope lock e.fn_scopes { e.fn_scopes[key] = scope @@ -231,7 +243,7 @@ pub fn (e &Environment) get_scope(module_name string) ?&Scope { // register_global adds or updates a module global in the type environment. pub fn (mut e Environment) register_global(module_name string, name string, typ Type) { - mut scope := e.scope_cache[module_name] or { return } + mut scope := e.get_scope(module_name) or { return } scope.insert_or_update(name, Global{ name: name typ: typ @@ -497,14 +509,11 @@ fn fn_with_return_type(fn_type FnType, return_type Type) FnType { } pub fn (mut c Checker) get_module_scope(module_name string, parent &Scope) &Scope { - if scope := c.env.scope_cache[module_name] { + if scope := c.env.get_scope(module_name) { return scope } scope := new_scope(parent) - c.env.scope_cache[module_name] = scope - lock c.env.scopes { - c.env.scopes[module_name] = scope - } + c.env.set_scope(module_name, scope) return scope } @@ -2829,7 +2838,8 @@ fn (mut c Checker) sync_imported_const_type(source Const) { if source.mod == unsafe { nil } { return } - for _, scope_ptr in c.env.scope_cache { + scopes := c.env.snapshot_scopes() + for _, scope_ptr in scopes { mut scope := unsafe { scope_ptr } obj := scope.objects[source.name] or { continue } if obj is Const { -- 2.39.5