@@ -643,6 +643,122 @@ pub fn (mut c Checker) symmetric_check(left ast.Type, right ast.Type) bool {
643
643
return c.check_basic (left, right)
644
644
}
645
645
646
+ fn (mut c Checker) infer_generic_struct_init_concrete_types (typ ast.Type, node ast.StructInit) []ast.Type {
647
+ mut concrete_types := []ast.Type{}
648
+ sym := c.table.sym (typ)
649
+ if sym.info is ast.Struct {
650
+ generic_names := sym.info.generic_types.map (c.table.sym (it ).name)
651
+ gname: for gt_name in generic_names {
652
+ for ft in sym.info.fields {
653
+ field_sym := c.table.sym (ft.typ)
654
+ if field_sym.name == gt_name {
655
+ for t in node.fields {
656
+ if ft.name == t.name && t.typ != 0 {
657
+ concrete_types << t.typ
658
+ continue gname
659
+ }
660
+ }
661
+ }
662
+ if field_sym.kind == .array {
663
+ for t in node.fields {
664
+ if ft.name == t.name {
665
+ init_sym := c.table.sym (t.typ)
666
+ if init_sym.kind == .array {
667
+ mut init_elem_info := init_sym.info as ast.Array
668
+ mut field_elem_info := field_sym.info as ast.Array
669
+ mut init_elem_sym := c.table.sym (init_elem_info.elem_type)
670
+ mut field_elem_sym := c.table.sym (field_elem_info.elem_type)
671
+ for {
672
+ if init_elem_sym.kind == .array && field_elem_sym.kind == .array {
673
+ init_elem_info = init_elem_sym.info as ast.Array
674
+ init_elem_sym = c.table.sym (init_elem_info.elem_type)
675
+ field_elem_info = field_elem_sym.info as ast.Array
676
+ field_elem_sym = c.table.sym (field_elem_info.elem_type)
677
+ } else {
678
+ if field_elem_sym.name == gt_name {
679
+ mut elem_typ := init_elem_info.elem_type
680
+ if field_elem_info.elem_type.nr_muls () > 0
681
+ && elem_typ.nr_muls () > 0 {
682
+ elem_typ = elem_typ.set_nr_muls (0 )
683
+ }
684
+ concrete_types << elem_typ
685
+ continue gname
686
+ }
687
+ break
688
+ }
689
+ }
690
+ }
691
+ }
692
+ }
693
+ } else if field_sym.kind == .array_fixed {
694
+ for t in node.fields {
695
+ if ft.name == t.name {
696
+ init_sym := c.table.sym (t.typ)
697
+ if init_sym.kind == .array_fixed {
698
+ mut init_elem_info := init_sym.info as ast.ArrayFixed
699
+ mut field_elem_info := field_sym.info as ast.ArrayFixed
700
+ mut init_elem_sym := c.table.sym (init_elem_info.elem_type)
701
+ mut field_elem_sym := c.table.sym (field_elem_info.elem_type)
702
+ for {
703
+ if init_elem_sym.kind == .array_fixed
704
+ && field_elem_sym.kind == .array_fixed {
705
+ init_elem_info = init_elem_sym.info as ast.ArrayFixed
706
+ init_elem_sym = c.table.sym (init_elem_info.elem_type)
707
+ field_elem_info = field_elem_sym.info as ast.ArrayFixed
708
+ field_elem_sym = c.table.sym (field_elem_info.elem_type)
709
+ } else {
710
+ if field_elem_sym.name == gt_name {
711
+ mut elem_typ := init_elem_info.elem_type
712
+ if field_elem_info.elem_type.nr_muls () > 0
713
+ && elem_typ.nr_muls () > 0 {
714
+ elem_typ = elem_typ.set_nr_muls (0 )
715
+ }
716
+ concrete_types << elem_typ
717
+ continue gname
718
+ }
719
+ break
720
+ }
721
+ }
722
+ }
723
+ }
724
+ }
725
+ } else if field_sym.kind == .map {
726
+ for t in node.fields {
727
+ if ft.name == t.name {
728
+ init_sym := c.table.sym (t.typ)
729
+ if init_sym.kind == .map {
730
+ init_map_info := init_sym.info as ast.Map
731
+ field_map_info := field_sym.info as ast.Map
732
+ if field_map_info.key_type.has_flag (.generic)
733
+ && c.table.sym (field_map_info.key_type).name == gt_name {
734
+ mut key_typ := init_map_info.key_type
735
+ if field_map_info.key_type.nr_muls () > 0
736
+ && key_typ.nr_muls () > 0 {
737
+ key_typ = key_typ.set_nr_muls (0 )
738
+ }
739
+ concrete_types << key_typ
740
+ continue gname
741
+ }
742
+ if field_map_info.value_type.has_flag (.generic)
743
+ && c.table.sym (field_map_info.value_type).name == gt_name {
744
+ mut val_typ := init_map_info.value_type
745
+ if field_map_info.value_type.nr_muls () > 0
746
+ && val_typ.nr_muls () > 0 {
747
+ val_typ = val_typ.set_nr_muls (0 )
748
+ }
749
+ concrete_types << val_typ
750
+ continue gname
751
+ }
752
+ }
753
+ }
754
+ }
755
+ }
756
+ }
757
+ }
758
+ }
759
+ return concrete_types
760
+ }
761
+
646
762
pub fn (mut c Checker) infer_fn_generic_types (func ast.Fn, mut node ast.CallExpr) {
647
763
mut inferred_types := []ast.Type{}
648
764
for gi, gt_name in func.generic_names {
0 commit comments