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