From 731e942055c30cd82ce8cbdf5dd2932a9216d331 Mon Sep 17 00:00:00 2001 From: yuyi Date: Sat, 17 Apr 2021 13:29:06 +0800 Subject: [PATCH] checker: fix generics with different order of generics fn (#9765) --- vlib/v/checker/checker.v | 38 ++++++++++--------- .../generics_with_nested_generics_fn_test.v | 8 ++-- 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 3033cccfce..c8a90c36e3 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -6014,8 +6014,8 @@ pub fn (mut c Checker) map_init(mut node ast.MapInit) ast.Type { info := c.table.get_type_symbol(node.typ).map_info() c.ensure_type_exists(info.key_type, node.pos) or {} c.ensure_type_exists(info.value_type, node.pos) or {} - node.key_type = info.key_type - node.value_type = info.value_type + node.key_type = c.unwrap_generic(info.key_type) + node.value_type = c.unwrap_generic(info.value_type) return node.typ } if node.keys.len > 0 && node.vals.len > 0 { @@ -6052,13 +6052,12 @@ pub fn (mut c Checker) map_init(mut node ast.MapInit) ast.Type { c.check_dup_keys(node, i) } } + key0_type = c.unwrap_generic(key0_type) + val0_type = c.unwrap_generic(val0_type) mut map_type := ast.new_type(c.table.find_or_register_map(key0_type, val0_type)) node.typ = map_type node.key_type = key0_type node.value_type = val0_type - if node.key_type.has_flag(.generic) || node.value_type.has_flag(.generic) { - map_type = map_type.set_flag(.generic) - } return map_type } return node.typ @@ -6319,21 +6318,24 @@ fn (mut c Checker) fetch_and_verify_orm_fields(info ast.Struct, pos token.Positi fn (mut c Checker) post_process_generic_fns() { // Loop thru each generic function concrete type. // Check each specific fn instantiation. - for i in 0 .. c.file.generic_fns.len { - if c.table.fn_generic_types.len == 0 { - // no concrete types, so just skip: - continue - } - mut node := c.file.generic_fns[i] - c.mod = node.mod - for gen_types in c.table.fn_generic_types[node.name] { - node.cur_generic_types = gen_types - c.fn_decl(mut node) - if node.name in ['vweb.run_app', 'vweb.run'] { - c.vweb_gen_types << gen_types + // Check 2 times (in order to check nested generics fn) + for _ in 0 .. 2 { + for i in 0 .. c.file.generic_fns.len { + if c.table.fn_generic_types.len == 0 { + // no concrete types, so just skip: + continue } + mut node := c.file.generic_fns[i] + c.mod = node.mod + for gen_types in c.table.fn_generic_types[node.name] { + node.cur_generic_types = gen_types + c.fn_decl(mut node) + if node.name in ['vweb.run_app', 'vweb.run'] { + c.vweb_gen_types << gen_types + } + } + node.cur_generic_types = [] } - node.cur_generic_types = [] } } diff --git a/vlib/v/tests/generics_with_nested_generics_fn_test.v b/vlib/v/tests/generics_with_nested_generics_fn_test.v index 864778ab04..6574ffe02e 100644 --- a/vlib/v/tests/generics_with_nested_generics_fn_test.v +++ b/vlib/v/tests/generics_with_nested_generics_fn_test.v @@ -11,16 +11,16 @@ mut: context Context } +fn (ng NestedGeneric) nested_test(mut app T) { + app.context = Context{} +} + fn method_test(mut app T) int { ng := NestedGeneric{} ng.nested_test(app) return 22 } -fn (ng NestedGeneric) nested_test(mut app T) { - app.context = Context{} -} - fn test_generics_with_generics_fn() { mut app := App{} ret := method_test(mut app)