diff --git a/vlib/v/parser/parse_type.v b/vlib/v/parser/parse_type.v index 3e5a18c2fb..1dfcaa9c94 100644 --- a/vlib/v/parser/parse_type.v +++ b/vlib/v/parser/parse_type.v @@ -211,7 +211,7 @@ pub fn (mut p Parser) parse_any_type(language table.Language, is_ptr bool, check if !p.tok.lit[0].is_capital() { p.error('imported types must start with a capital letter') } - } else if p.expr_mod != '' { + } else if p.expr_mod != '' && !p.in_generic_params { // p.expr_mod is from the struct and not from the generic parameter name = p.expr_mod + '.' + name } else if p.mod != 'builtin' && name.len > 1 && name !in p.table.type_idxs { // `Foo` in module `mod` means `mod.Foo` @@ -343,6 +343,7 @@ pub fn (mut p Parser) parse_generic_template_type(name string) table.Type { pub fn (mut p Parser) parse_generic_struct_inst_type(name string) table.Type { mut bs_name := name p.next() + p.in_generic_params = true bs_name += '<' mut generic_types := []table.Type{} mut is_instance := false @@ -361,6 +362,7 @@ pub fn (mut p Parser) parse_generic_struct_inst_type(name string) table.Type { bs_name += ',' } p.check(.gt) + p.in_generic_params = false bs_name += '>' if is_instance && generic_types.len > 0 { mut gt_idx := p.table.find_type_idx(bs_name) @@ -368,13 +370,17 @@ pub fn (mut p Parser) parse_generic_struct_inst_type(name string) table.Type { return table.new_type(gt_idx) } gt_idx = p.table.add_placeholder_type(bs_name, .v) + mut parent_idx := p.table.type_idxs[name] + if parent_idx == 0 { + parent_idx = p.table.add_placeholder_type(name, .v) + } idx := p.table.register_type_symbol(table.TypeSymbol{ kind: .generic_struct_inst name: bs_name source_name: bs_name mod: p.mod info: table.GenericStructInst{ - parent_idx: p.table.type_idxs[name] + parent_idx: parent_idx generic_types: generic_types } }) diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index 5827f67d62..c03036597f 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -59,6 +59,7 @@ mut: warnings []errors.Warning vet_errors []string cur_fn_name string + in_generic_params bool // indicates if parsing between `<` and `>` of a method/function } // for tests diff --git a/vlib/v/tests/generics_test.v b/vlib/v/tests/generics_test.v index 2fd4820c3c..5dd197dfa0 100644 --- a/vlib/v/tests/generics_test.v +++ b/vlib/v/tests/generics_test.v @@ -1,3 +1,5 @@ +import simplemodule + fn test_todo() { } @@ -281,6 +283,11 @@ fn test_generic_struct_method() { assert foo_int.value() == '2' } +fn test_struct_from_other_module() { + g := simplemodule.ThisIsGeneric{} + assert g.msg.name == '' +} + /* struct Abc{ x int y int z int } diff --git a/vlib/v/tests/modules/simplemodule/simplemodule.v b/vlib/v/tests/modules/simplemodule/simplemodule.v index fd3e125f5e..6d3b19a5d7 100644 --- a/vlib/v/tests/modules/simplemodule/simplemodule.v +++ b/vlib/v/tests/modules/simplemodule/simplemodule.v @@ -7,3 +7,7 @@ pub fn iadd(x int, y int) int { pub fn imul(x int, y int) int { return x * y } + +pub struct ThisIsGeneric { + msg T +}