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]
 | 
					[inline]
 | 
				
			||||||
pub fn (t &Table) find_type(name string) ?&TypeSymbol {
 | 
					pub fn (t &Table) find_sym(name string) ?&TypeSymbol {
 | 
				
			||||||
	idx := t.type_idxs[name]
 | 
						idx := t.type_idxs[name]
 | 
				
			||||||
	if idx > 0 {
 | 
						if idx > 0 {
 | 
				
			||||||
		return t.type_symbols[idx]
 | 
							return t.type_symbols[idx]
 | 
				
			||||||
| 
						 | 
					@ -618,6 +618,15 @@ pub fn (t &Table) find_type(name string) ?&TypeSymbol {
 | 
				
			||||||
	return none
 | 
						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{
 | 
					pub const invalid_type_symbol = &TypeSymbol{
 | 
				
			||||||
	idx: -1
 | 
						idx: -1
 | 
				
			||||||
	parent_idx: -1
 | 
						parent_idx: -1
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2224,7 +2224,7 @@ fn (mut c Checker) import_stmt(node ast.Import) {
 | 
				
			||||||
	for sym in node.syms {
 | 
						for sym in node.syms {
 | 
				
			||||||
		name := '${node.mod}.$sym.name'
 | 
							name := '${node.mod}.$sym.name'
 | 
				
			||||||
		if sym.name[0].is_capital() {
 | 
							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.kind != .placeholder {
 | 
				
			||||||
					if !type_sym.is_public {
 | 
										if !type_sym.is_public {
 | 
				
			||||||
						c.error('module `$node.mod` type `$sym.name` is private', sym.pos)
 | 
											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 {
 | 
						if node.language == .v && !c.is_builtin_mod {
 | 
				
			||||||
		c.check_valid_pascal_case(node.name, 'struct name', node.pos)
 | 
							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
 | 
						mut has_generic_types := false
 | 
				
			||||||
	if mut struct_sym.info is ast.Struct {
 | 
						if mut struct_sym.info is ast.Struct {
 | 
				
			||||||
		for embed in node.embeds {
 | 
							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)
 | 
										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_ {
 | 
								if sym.kind == .struct_ {
 | 
				
			||||||
				info := sym.info as ast.Struct
 | 
									info := sym.info as ast.Struct
 | 
				
			||||||
				if info.is_heap && !field.typ.is_ptr() {
 | 
									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')
 | 
						g.enter_namespace('main')
 | 
				
			||||||
	// generate JS methods for interface methods
 | 
						// generate JS methods for interface methods
 | 
				
			||||||
	for iface_name, iface_types in g.table.iface_types {
 | 
						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 {
 | 
							for ty in iface_types {
 | 
				
			||||||
			sym := g.table.sym(ty)
 | 
								sym := g.table.sym(ty)
 | 
				
			||||||
			for method in iface.methods {
 | 
								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 {
 | 
						if pref.is_test {
 | 
				
			||||||
		all_fn_root_names << 'main.cb_assertion_ok'
 | 
							all_fn_root_names << 'main.cb_assertion_ok'
 | 
				
			||||||
		all_fn_root_names << 'main.cb_assertion_failed'
 | 
							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
 | 
								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_start'
 | 
				
			||||||
			all_fn_root_names << '${bts_type}.testing_step_end'
 | 
								all_fn_root_names << '${bts_type}.testing_step_end'
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue