checker: add error for `type StructAlias = Struct struct Struct { field StructAlias }`
parent
64f1ea6fe9
commit
41e763f79c
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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 |
|
|
@ -0,0 +1,11 @@
|
|||
type Foo = Bar
|
||||
|
||||
struct Bar {
|
||||
pfield &Foo = 0
|
||||
field Foo = Bar{}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
bar := Bar{}
|
||||
println(bar)
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -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'
|
||||
|
|
Loading…
Reference in New Issue