From 6f474913cf862be4c5bd5596647c29f973bf598f Mon Sep 17 00:00:00 2001 From: joe-conigliaro Date: Fri, 11 Dec 2020 17:39:51 +1100 Subject: [PATCH] table: properly detect duplicate types --- vlib/v/checker/checker.v | 23 ++++++++++++--------- vlib/v/parser/struct.v | 13 ++++-------- vlib/v/table/table.v | 43 +++++++++++++++++----------------------- 3 files changed, 36 insertions(+), 43 deletions(-) diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 90fdc05cc0..079af02403 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -3603,15 +3603,20 @@ fn (mut c Checker) match_exprs(mut node ast.MatchExpr, type_sym table.TypeSymbol } agg_name.write(')') name := agg_name.str() - expr_type = c.table.register_type_symbol(table.TypeSymbol{ - name: name - cname: agg_cname.str() - kind: .aggregate - mod: c.mod - info: table.Aggregate{ - types: expr_types.map(it.typ) - } - }) + existing_idx := c.table.type_idxs[name] + if existing_idx > 0 { + expr_type = existing_idx + } else { + expr_type = c.table.register_type_symbol(table.TypeSymbol{ + name: name + cname: agg_cname.str() + kind: .aggregate + mod: c.mod + info: table.Aggregate{ + types: expr_types.map(it.typ) + } + }) + } } else { expr_type = expr_types[0].typ } diff --git a/vlib/v/parser/struct.v b/vlib/v/parser/struct.v index ea32f97a32..4c0ae4d636 100644 --- a/vlib/v/parser/struct.v +++ b/vlib/v/parser/struct.v @@ -277,15 +277,10 @@ fn (mut p Parser) struct_decl() ast.StructDecl { is_public: is_pub } mut ret := 0 - if p.builtin_mod && t.name in table.builtin_type_names { - // this allows overiding the builtins type - // with the real struct type info parsed from builtin - ret = p.table.register_builtin_type_symbol(t) - } else { - // println('reg type symbol $name mod=$p.mod') - ret = p.table.register_type_symbol(t) - } - if ret == -1 { + // println('reg type symbol $name mod=$p.mod') + ret = p.table.register_type_symbol(t) + // allow duplicate c struct declarations + if ret == -1 && language != .c { p.error_with_pos('cannot register struct `$name`, another type with this name exists', name_pos) return ast.StructDecl{} diff --git a/vlib/v/table/table.v b/vlib/v/table/table.v index 26d2526046..62f7619ecb 100644 --- a/vlib/v/table/table.v +++ b/vlib/v/table/table.v @@ -340,29 +340,6 @@ pub fn (t &Table) unalias_num_type(typ Type) Type { return typ } -// this will override or register builtin type -// allows prexisitng types added in register_builtins -// to be overriden with their real type info -[inline] -pub fn (mut t Table) register_builtin_type_symbol(typ TypeSymbol) int { - existing_idx := t.type_idxs[typ.name] - if existing_idx > 0 { - if existing_idx >= string_type_idx { - if existing_idx == string_type_idx { - existing_type := t.types[existing_idx] - t.types[existing_idx] = { - typ | - kind: existing_type.kind - } - } else { - t.types[existing_idx] = typ - } - } - return existing_idx - } - return t.register_type_symbol(typ) -} - [inline] pub fn (mut t Table) register_type_symbol(typ TypeSymbol) int { // println('register_type_symbol( $typ.name )') @@ -380,10 +357,21 @@ pub fn (mut t Table) register_type_symbol(typ TypeSymbol) int { return existing_idx } else { - if ex_type.kind == typ.kind { + // builtin + // this will override the already registered builtin types + // with the actual v struct declaration in the source + if existing_idx >= string_type_idx && existing_idx <= map_type_idx { + if existing_idx == string_type_idx { + // existing_type := t.types[existing_idx] + t.types[existing_idx] = { + typ | + kind: ex_type.kind + } + } else { + t.types[existing_idx] = typ + } return existing_idx } - // panic('cannot register type `$typ.name`, another type with this name exists') return -1 } } @@ -608,6 +596,11 @@ pub fn (mut t Table) find_or_register_fn_type(mod string, f Fn, is_anon bool, ha name := if f.name.len == 0 { 'fn ${t.fn_type_source_signature(f)}' } else { f.name.clone() } cname := if f.name.len == 0 { 'anon_fn_${t.fn_type_signature(f)}' } else { util.no_dots(f.name.clone()) } anon := f.name.len == 0 || is_anon + // existing + existing_idx := t.type_idxs[name] + if existing_idx > 0 && t.types[existing_idx].kind != .placeholder { + return existing_idx + } return t.register_type_symbol( kind: .function name: name