diff --git a/vlib/v/ast/table.v b/vlib/v/ast/table.v index 42c60d7e0a..48253b8bb5 100644 --- a/vlib/v/ast/table.v +++ b/vlib/v/ast/table.v @@ -610,7 +610,7 @@ pub fn (t &Table) find_type_idx(name string) int { } [inline] -pub fn (t &Table) find_type(name string) ?&TypeSymbol { +pub fn (t &Table) find_sym(name string) ?&TypeSymbol { idx := t.type_idxs[name] if idx > 0 { return t.type_symbols[idx] @@ -618,6 +618,15 @@ pub fn (t &Table) find_type(name string) ?&TypeSymbol { return none } +[inline] +pub fn (t &Table) find_sym_and_type_idx(name string) (&TypeSymbol, int) { + idx := t.type_idxs[name] + if idx > 0 { + return t.type_symbols[idx], idx + } + return ast.invalid_type_symbol, idx +} + pub const invalid_type_symbol = &TypeSymbol{ idx: -1 parent_idx: -1 diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 9f4f041ef1..0fc80478d1 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -2224,7 +2224,7 @@ fn (mut c Checker) import_stmt(node ast.Import) { for sym in node.syms { name := '${node.mod}.$sym.name' if sym.name[0].is_capital() { - if type_sym := c.table.find_type(name) { + if type_sym := c.table.find_sym(name) { if type_sym.kind != .placeholder { if !type_sym.is_public { c.error('module `$node.mod` type `$sym.name` is private', sym.pos) diff --git a/vlib/v/checker/struct.v b/vlib/v/checker/struct.v index 5c2c4e6dd5..828f684285 100644 --- a/vlib/v/checker/struct.v +++ b/vlib/v/checker/struct.v @@ -8,7 +8,7 @@ pub fn (mut c Checker) struct_decl(mut node ast.StructDecl) { if node.language == .v && !c.is_builtin_mod { c.check_valid_pascal_case(node.name, 'struct name', node.pos) } - mut struct_sym := c.table.find_type(node.name) or { ast.invalid_type_symbol } + mut struct_sym, struct_typ_idx := c.table.find_sym_and_type_idx(node.name) mut has_generic_types := false if mut struct_sym.info is ast.Struct { for embed in node.embeds { @@ -48,6 +48,14 @@ pub fn (mut c Checker) struct_decl(mut node ast.StructDecl) { c.error('field name `$field.name` duplicate', field.pos) } } + if field.typ != 0 { + if !field.typ.is_ptr() { + if c.table.unaliased_type(field.typ) == struct_typ_idx { + c.error('Field `$field.name` is part of `$node.name`, they can not both have the same type', + field.type_pos) + } + } + } if sym.kind == .struct_ { info := sym.info as ast.Struct if info.is_heap && !field.typ.is_ptr() { diff --git a/vlib/v/checker/tests/field_can_not_be_from_the_same_type_as_containing_struct.out b/vlib/v/checker/tests/field_can_not_be_from_the_same_type_as_containing_struct.out new file mode 100644 index 0000000000..6058fd0263 --- /dev/null +++ b/vlib/v/checker/tests/field_can_not_be_from_the_same_type_as_containing_struct.out @@ -0,0 +1,7 @@ +vlib/v/checker/tests/field_can_not_be_from_the_same_type_as_containing_struct.vv:5:9: error: Field `field` is part of `Bar`, they can not both have the same type + 3 | struct Bar { + 4 | pfield &Foo = 0 + 5 | field Foo = Bar{} + | ~~~ + 6 | } + 7 | diff --git a/vlib/v/checker/tests/field_can_not_be_from_the_same_type_as_containing_struct.vv b/vlib/v/checker/tests/field_can_not_be_from_the_same_type_as_containing_struct.vv new file mode 100644 index 0000000000..298bbc52f9 --- /dev/null +++ b/vlib/v/checker/tests/field_can_not_be_from_the_same_type_as_containing_struct.vv @@ -0,0 +1,11 @@ +type Foo = Bar + +struct Bar { + pfield &Foo = 0 + field Foo = Bar{} +} + +fn main() { + bar := Bar{} + println(bar) +} diff --git a/vlib/v/gen/js/js.v b/vlib/v/gen/js/js.v index 92ca301bd3..e3a9f34fcd 100644 --- a/vlib/v/gen/js/js.v +++ b/vlib/v/gen/js/js.v @@ -175,7 +175,7 @@ pub fn gen(files []&ast.File, table &ast.Table, pref &pref.Preferences) string { g.enter_namespace('main') // generate JS methods for interface methods for iface_name, iface_types in g.table.iface_types { - iface := g.table.find_type(iface_name) or { panic('unreachable: interface must exist') } + iface := g.table.find_sym(iface_name) or { panic('unreachable: interface must exist') } for ty in iface_types { sym := g.table.sym(ty) for method in iface.methods { diff --git a/vlib/v/markused/markused.v b/vlib/v/markused/markused.v index f3bdef29d6..d02eee82c4 100644 --- a/vlib/v/markused/markused.v +++ b/vlib/v/markused/markused.v @@ -249,7 +249,7 @@ pub fn mark_used(mut table ast.Table, pref &pref.Preferences, ast_files []&ast.F if pref.is_test { all_fn_root_names << 'main.cb_assertion_ok' all_fn_root_names << 'main.cb_assertion_failed' - if benched_tests_sym := table.find_type('main.BenchedTests') { + if benched_tests_sym := table.find_sym('main.BenchedTests') { bts_type := benched_tests_sym.methods[0].params[0].typ all_fn_root_names << '${bts_type}.testing_step_start' all_fn_root_names << '${bts_type}.testing_step_end'