parent
							
								
									8c43d2450f
								
							
						
					
					
						commit
						665279938e
					
				|  | @ -1298,36 +1298,3 @@ pub fn (mut t Table) resolve_generic_to_concrete(generic_type Type, generic_name | |||
| 	} | ||||
| 	return none | ||||
| } | ||||
| 
 | ||||
| // generic struct instantiations to concrete types
 | ||||
| pub fn (mut t Table) generic_struct_insts_to_concrete() { | ||||
| 	for mut typ in t.type_symbols { | ||||
| 		if typ.kind == .generic_struct_inst { | ||||
| 			info := typ.info as GenericStructInst | ||||
| 			parent := t.type_symbols[info.parent_idx] | ||||
| 			if parent.kind == .placeholder { | ||||
| 				typ.kind = .placeholder | ||||
| 				continue | ||||
| 			} | ||||
| 			mut parent_info := parent.info as Struct | ||||
| 			mut fields := parent_info.fields.clone() | ||||
| 			if parent_info.generic_types.len == info.concrete_types.len { | ||||
| 				generic_names := parent_info.generic_types.map(t.get_type_symbol(it).name) | ||||
| 				for i in 0 .. fields.len { | ||||
| 					if t_typ := t.resolve_generic_to_concrete(fields[i].typ, generic_names, | ||||
| 						info.concrete_types) | ||||
| 					{ | ||||
| 						fields[i].typ = t_typ | ||||
| 					} | ||||
| 				} | ||||
| 				parent_info.is_generic = false | ||||
| 				parent_info.concrete_types = info.concrete_types.clone() | ||||
| 				parent_info.fields = fields | ||||
| 				parent_info.parent_type = new_type(info.parent_idx).set_flag(.generic) | ||||
| 				typ.is_public = true | ||||
| 				typ.kind = .struct_ | ||||
| 				typ.info = parent_info | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -80,7 +80,7 @@ pub fn (mut b Builder) front_stages(v_files []string) ? { | |||
| 
 | ||||
| pub fn (mut b Builder) middle_stages() ? { | ||||
| 	util.timing_start('CHECK') | ||||
| 	b.table.generic_struct_insts_to_concrete() | ||||
| 	b.checker.generic_struct_insts_to_concrete() | ||||
| 	b.checker.check_files(b.parsed_files) | ||||
| 	util.timing_measure('CHECK') | ||||
| 	b.print_warnings_and_errors() | ||||
|  |  | |||
|  | @ -664,10 +664,18 @@ fn (mut c Checker) unwrap_generic_struct(struct_type ast.Type, generic_names []s | |||
| 				// fields type translate to concrete type
 | ||||
| 				mut fields := ts.info.fields.clone() | ||||
| 				for i in 0 .. fields.len { | ||||
| 					if t_typ := c.table.resolve_generic_to_concrete(fields[i].typ, generic_names, | ||||
| 						concrete_types) | ||||
| 					{ | ||||
| 						fields[i].typ = t_typ | ||||
| 					if fields[i].typ.has_flag(.generic) { | ||||
| 						sym := c.table.get_type_symbol(fields[i].typ) | ||||
| 						if sym.kind == .struct_ && fields[i].typ.idx() != struct_type.idx() { | ||||
| 							fields[i].typ = c.unwrap_generic_struct(fields[i].typ, generic_names, | ||||
| 								concrete_types) | ||||
| 						} else { | ||||
| 							if t_typ := c.table.resolve_generic_to_concrete(fields[i].typ, | ||||
| 								generic_names, concrete_types) | ||||
| 							{ | ||||
| 								fields[i].typ = t_typ | ||||
| 							} | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 				// update concrete types
 | ||||
|  | @ -698,6 +706,47 @@ fn (mut c Checker) unwrap_generic_struct(struct_type ast.Type, generic_names []s | |||
| 	return struct_type | ||||
| } | ||||
| 
 | ||||
| // generic struct instantiations to concrete types
 | ||||
| pub fn (mut c Checker) generic_struct_insts_to_concrete() { | ||||
| 	for mut typ in c.table.type_symbols { | ||||
| 		if typ.kind == .generic_struct_inst { | ||||
| 			info := typ.info as ast.GenericStructInst | ||||
| 			parent := c.table.type_symbols[info.parent_idx] | ||||
| 			if parent.kind == .placeholder { | ||||
| 				typ.kind = .placeholder | ||||
| 				continue | ||||
| 			} | ||||
| 			mut parent_info := parent.info as ast.Struct | ||||
| 			mut fields := parent_info.fields.clone() | ||||
| 			if parent_info.generic_types.len == info.concrete_types.len { | ||||
| 				generic_names := parent_info.generic_types.map(c.table.get_type_symbol(it).name) | ||||
| 				for i in 0 .. fields.len { | ||||
| 					if fields[i].typ.has_flag(.generic) { | ||||
| 						sym := c.table.get_type_symbol(fields[i].typ) | ||||
| 						if sym.kind == .struct_ && fields[i].typ.idx() != info.parent_idx { | ||||
| 							fields[i].typ = c.unwrap_generic_struct(fields[i].typ, generic_names, | ||||
| 								info.concrete_types) | ||||
| 						} else { | ||||
| 							if t_typ := c.table.resolve_generic_to_concrete(fields[i].typ, | ||||
| 								generic_names, info.concrete_types) | ||||
| 							{ | ||||
| 								fields[i].typ = t_typ | ||||
| 							} | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 				parent_info.is_generic = false | ||||
| 				parent_info.concrete_types = info.concrete_types.clone() | ||||
| 				parent_info.fields = fields | ||||
| 				parent_info.parent_type = ast.new_type(info.parent_idx).set_flag(.generic) | ||||
| 				typ.is_public = true | ||||
| 				typ.kind = .struct_ | ||||
| 				typ.info = parent_info | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| pub fn (mut c Checker) struct_init(mut node ast.StructInit) ast.Type { | ||||
| 	if node.typ == ast.void_type { | ||||
| 		// Short syntax `({foo: bar})`
 | ||||
|  |  | |||
|  | @ -0,0 +1,24 @@ | |||
| fn test_nested_generic_struct_init() { | ||||
| 	mut list1 := &List<int>{} | ||||
| 	println(list1) | ||||
| 	assert '$list1'.contains('head: &nil') | ||||
| 
 | ||||
| 	mut list2 := list_new<int>() | ||||
| 	println(list2) | ||||
| 	assert '$list2'.contains('head: &nil') | ||||
| } | ||||
| 
 | ||||
| struct List<T> { | ||||
| pub mut: | ||||
| 	head &ListNode<T> = 0 | ||||
| } | ||||
| 
 | ||||
| struct ListNode<T> { | ||||
| pub mut: | ||||
| 	value T | ||||
| 	next  &ListNode<T> = 0 | ||||
| } | ||||
| 
 | ||||
| pub fn list_new<T>() &List<T> { | ||||
| 	return &List<T>{} | ||||
| } | ||||
		Loading…
	
		Reference in New Issue