parent
							
								
									7e6d4ebfe1
								
							
						
					
					
						commit
						2d43fdb42a
					
				|  | @ -1345,7 +1345,7 @@ fn (t Tree) selector_expr(node ast.SelectorExpr) &Node { | |||
| 	obj.add('typ', t.type_node(node.typ)) | ||||
| 	obj.add('name_type', t.type_node(node.name_type)) | ||||
| 	obj.add('gkind_field', t.enum_node(node.gkind_field)) | ||||
| 	obj.add('from_embed_type', t.type_node(node.from_embed_type)) | ||||
| 	obj.add('from_embed_types', t.array_node_type(node.from_embed_types)) | ||||
| 	obj.add('next_token', t.token_node(node.next_token)) | ||||
| 	obj.add('pos', t.position(node.pos)) | ||||
| 	obj.add('scope', t.number_node(int(node.scope))) | ||||
|  |  | |||
|  | @ -229,7 +229,7 @@ pub mut: | |||
| 	name_type        Type // T in `T.name` or typeof in `typeof(expr).name`
 | ||||
| 	gkind_field      GenericKindField // `T.name` => ast.GenericKindField.name, `T.typ` => ast.GenericKindField.typ, or .unknown
 | ||||
| 	scope            &Scope | ||||
| 	from_embed_type Type // holds the type of the embed that the method is called from
 | ||||
| 	from_embed_types []Type // holds the type of the embed that the method is called from
 | ||||
| } | ||||
| 
 | ||||
| // root_ident returns the origin ident where the selector started.
 | ||||
|  |  | |||
|  | @ -503,22 +503,23 @@ pub fn (t &Table) find_field(s &TypeSymbol, name string) ?StructField { | |||
| pub fn (t &Table) find_field_from_embeds_recursive(sym &TypeSymbol, field_name string) ?(StructField, []Type) { | ||||
| 	if sym.info is Struct { | ||||
| 		mut found_fields := []StructField{} | ||||
| 		mut embeds_of_found_fields := [][]Type{} | ||||
| 		mut embeds_of_found_fields := []Type{} | ||||
| 		for embed in sym.info.embeds { | ||||
| 			embed_sym := t.get_type_symbol(embed) | ||||
| 			if field := t.find_field(embed_sym, field_name) { | ||||
| 				found_fields << field | ||||
| 				embeds_of_found_fields << [embed] | ||||
| 				embeds_of_found_fields << embed | ||||
| 			} else { | ||||
| 				field, types := t.find_field_from_embeds_recursive(embed_sym, field_name) or { | ||||
| 					StructField{}, []Type{} | ||||
| 					continue | ||||
| 				} | ||||
| 				found_fields << field | ||||
| 				embeds_of_found_fields << embed | ||||
| 				embeds_of_found_fields << types | ||||
| 			} | ||||
| 		} | ||||
| 		if found_fields.len == 1 { | ||||
| 			return found_fields[0], embeds_of_found_fields[0] | ||||
| 			return found_fields[0], embeds_of_found_fields | ||||
| 		} else if found_fields.len > 1 { | ||||
| 			return error('ambiguous field `$field_name`') | ||||
| 		} | ||||
|  | @ -526,7 +527,7 @@ pub fn (t &Table) find_field_from_embeds_recursive(sym &TypeSymbol, field_name s | |||
| 		for typ in sym.info.types { | ||||
| 			agg_sym := t.get_type_symbol(typ) | ||||
| 			field, embed_types := t.find_field_from_embeds_recursive(agg_sym, field_name) or { | ||||
| 				return err | ||||
| 				continue | ||||
| 			} | ||||
| 			if embed_types.len > 0 { | ||||
| 				return field, embed_types | ||||
|  | @ -578,7 +579,7 @@ pub fn (t &Table) find_field_with_embeds(sym &TypeSymbol, field_name string) ?St | |||
| 	} else { | ||||
| 		// look for embedded field
 | ||||
| 		first_err := err | ||||
| 		field, _ := t.find_field_from_embeds(sym, field_name) or { return first_err } | ||||
| 		field, _ := t.find_field_from_embeds_recursive(sym, field_name) or { return first_err } | ||||
| 		return field | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -3460,15 +3460,15 @@ pub fn (mut c Checker) selector_expr(mut node ast.SelectorExpr) ast.Type { | |||
| 		} else { | ||||
| 			// look for embedded field
 | ||||
| 			has_field = true | ||||
| 			mut embed_type := ast.Type(0) | ||||
| 			field, embed_type = c.table.find_field_from_embeds(sym, field_name) or { | ||||
| 			mut embed_types := []ast.Type{} | ||||
| 			field, embed_types = c.table.find_field_from_embeds_recursive(sym, field_name) or { | ||||
| 				if err.msg != '' { | ||||
| 					c.error(err.msg, node.pos) | ||||
| 				} | ||||
| 				has_field = false | ||||
| 				ast.StructField{}, ast.Type(0) | ||||
| 				ast.StructField{}, []ast.Type{} | ||||
| 			} | ||||
| 			node.from_embed_type = embed_type | ||||
| 			node.from_embed_types = embed_types | ||||
| 			if sym.kind in [.aggregate, .sum_type] { | ||||
| 				unknown_field_msg = err.msg | ||||
| 			} | ||||
|  | @ -3489,15 +3489,15 @@ pub fn (mut c Checker) selector_expr(mut node ast.SelectorExpr) ast.Type { | |||
| 			} else { | ||||
| 				// look for embedded field
 | ||||
| 				has_field = true | ||||
| 				mut embed_type := ast.Type(0) | ||||
| 				field, embed_type = c.table.find_field_from_embeds(gs, field_name) or { | ||||
| 				mut embed_types := []ast.Type{} | ||||
| 				field, embed_types = c.table.find_field_from_embeds_recursive(gs, field_name) or { | ||||
| 					if err.msg != '' { | ||||
| 						c.error(err.msg, node.pos) | ||||
| 					} | ||||
| 					has_field = false | ||||
| 					ast.StructField{}, ast.Type(0) | ||||
| 					ast.StructField{}, []ast.Type{} | ||||
| 				} | ||||
| 				node.from_embed_type = embed_type | ||||
| 				node.from_embed_types = embed_types | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  |  | |||
|  | @ -4226,8 +4226,8 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) { | |||
| 	} | ||||
| 	// struct embedding
 | ||||
| 	if sym.info in [ast.Struct, ast.Aggregate] { | ||||
| 		if node.from_embed_type != 0 { | ||||
| 			embed_sym := g.table.get_type_symbol(node.from_embed_type) | ||||
| 		for embed in node.from_embed_types { | ||||
| 			embed_sym := g.table.get_type_symbol(embed) | ||||
| 			embed_name := embed_sym.embed_name() | ||||
| 			if node.expr_type.is_ptr() { | ||||
| 				g.write('->') | ||||
|  | @ -4237,7 +4237,7 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) { | |||
| 			g.write(embed_name) | ||||
| 		} | ||||
| 	} | ||||
| 	if (node.expr_type.is_ptr() || sym.kind == .chan) && node.from_embed_type == 0 { | ||||
| 	if (node.expr_type.is_ptr() || sym.kind == .chan) && node.from_embed_types.len == 0 { | ||||
| 		g.write('->') | ||||
| 	} else { | ||||
| 		// g.write('. /*typ=  $it.expr_type */') // ${g.typ(it.expr_type)} /')
 | ||||
|  |  | |||
|  | @ -0,0 +1,20 @@ | |||
| struct Foo { | ||||
| mut: | ||||
| 	x int | ||||
| } | ||||
| 
 | ||||
| struct Bar { | ||||
| 	Foo | ||||
| } | ||||
| 
 | ||||
| struct Baz { | ||||
| 	Bar | ||||
| } | ||||
| 
 | ||||
| fn test_nested_struct_embed() { | ||||
| 	mut baz := Baz{} | ||||
| 	baz.x = 3 | ||||
| 
 | ||||
| 	println(baz.x) | ||||
| 	assert baz.x == 3 | ||||
| } | ||||
		Loading…
	
		Reference in New Issue