parser: fix generic structs from other modules (#6921)

pull/6926/head
Daniel Däschle 2020-11-23 23:21:11 +01:00 committed by GitHub
parent e0d64903f8
commit 9fbf38c798
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 20 additions and 2 deletions

View File

@ -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() { if !p.tok.lit[0].is_capital() {
p.error('imported types must start with a capital letter') 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 name = p.expr_mod + '.' + name
} else if p.mod != 'builtin' && name.len > 1 && name !in p.table.type_idxs { } else if p.mod != 'builtin' && name.len > 1 && name !in p.table.type_idxs {
// `Foo` in module `mod` means `mod.Foo` // `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 { pub fn (mut p Parser) parse_generic_struct_inst_type(name string) table.Type {
mut bs_name := name mut bs_name := name
p.next() p.next()
p.in_generic_params = true
bs_name += '<' bs_name += '<'
mut generic_types := []table.Type{} mut generic_types := []table.Type{}
mut is_instance := false mut is_instance := false
@ -361,6 +362,7 @@ pub fn (mut p Parser) parse_generic_struct_inst_type(name string) table.Type {
bs_name += ',' bs_name += ','
} }
p.check(.gt) p.check(.gt)
p.in_generic_params = false
bs_name += '>' bs_name += '>'
if is_instance && generic_types.len > 0 { if is_instance && generic_types.len > 0 {
mut gt_idx := p.table.find_type_idx(bs_name) 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) return table.new_type(gt_idx)
} }
gt_idx = p.table.add_placeholder_type(bs_name, .v) 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{ idx := p.table.register_type_symbol(table.TypeSymbol{
kind: .generic_struct_inst kind: .generic_struct_inst
name: bs_name name: bs_name
source_name: bs_name source_name: bs_name
mod: p.mod mod: p.mod
info: table.GenericStructInst{ info: table.GenericStructInst{
parent_idx: p.table.type_idxs[name] parent_idx: parent_idx
generic_types: generic_types generic_types: generic_types
} }
}) })

View File

@ -59,6 +59,7 @@ mut:
warnings []errors.Warning warnings []errors.Warning
vet_errors []string vet_errors []string
cur_fn_name string cur_fn_name string
in_generic_params bool // indicates if parsing between `<` and `>` of a method/function
} }
// for tests // for tests

View File

@ -1,3 +1,5 @@
import simplemodule
fn test_todo() { fn test_todo() {
} }
@ -281,6 +283,11 @@ fn test_generic_struct_method() {
assert foo_int.value() == '2' assert foo_int.value() == '2'
} }
fn test_struct_from_other_module() {
g := simplemodule.ThisIsGeneric<Permission>{}
assert g.msg.name == ''
}
/* /*
struct Abc{ x int y int z int } struct Abc{ x int y int z int }

View File

@ -7,3 +7,7 @@ pub fn iadd(x int, y int) int {
pub fn imul(x int, y int) int { pub fn imul(x int, y int) int {
return x * y return x * y
} }
pub struct ThisIsGeneric<T> {
msg T
}