@@ -6552,7 +6552,78 @@ fn resolvePeerTypesInner(analyser: *Analyser, peer_tys: []?Type) !?Type {
6552
6552
};
6553
6553
},
6554
6554
6555
- .array = > return null , // TODO
6555
+ .array = > {
6556
+ var len : ? u64 = null ;
6557
+ var sentinel : InternPool.Index = .none ;
6558
+ var elem_ty : ? Type = null ;
6559
+
6560
+ for (peer_tys ) | * ty_ptr | {
6561
+ const ty = ty_ptr .* orelse continue ;
6562
+
6563
+ if (ty .data != .array ) {
6564
+ const arr_like = analyser .typeIsArrayLike (ty ) orelse {
6565
+ return null ;
6566
+ };
6567
+
6568
+ if (len ) | cur_len | {
6569
+ if (arr_like .len != cur_len ) return null ;
6570
+ } else {
6571
+ len = arr_like .len ;
6572
+ }
6573
+
6574
+ sentinel = .none ;
6575
+
6576
+ continue ;
6577
+ }
6578
+
6579
+ const arr_info = ty .data .array ;
6580
+ const arr_len = arr_info .elem_count orelse {
6581
+ return null ;
6582
+ };
6583
+
6584
+ const cur_elem_ty = elem_ty orelse {
6585
+ if (len ) | cur_len | {
6586
+ if (arr_len != cur_len ) return null ;
6587
+ } else {
6588
+ len = arr_len ;
6589
+ sentinel = arr_info .sentinel ;
6590
+ }
6591
+ elem_ty = arr_info .elem_ty .* ;
6592
+ continue ;
6593
+ };
6594
+
6595
+ if (arr_info .elem_count != len ) {
6596
+ return null ;
6597
+ }
6598
+
6599
+ const peer_elem_ty = arr_info .elem_ty .* ;
6600
+ if (! peer_elem_ty .eql (cur_elem_ty )) {
6601
+ // TODO: check if coercible
6602
+ return null ;
6603
+ }
6604
+
6605
+ if (sentinel != .none ) {
6606
+ if (arr_info .sentinel != .none ) {
6607
+ if (arr_info .sentinel != sentinel ) sentinel = .none ;
6608
+ } else {
6609
+ sentinel = .none ;
6610
+ }
6611
+ }
6612
+ }
6613
+
6614
+ std .debug .assert (elem_ty != null );
6615
+
6616
+ return .{
6617
+ .data = .{
6618
+ .array = .{
6619
+ .elem_count = len ,
6620
+ .sentinel = sentinel ,
6621
+ .elem_ty = try analyser .allocType (elem_ty .? ),
6622
+ },
6623
+ },
6624
+ .is_type_val = true ,
6625
+ };
6626
+ },
6556
6627
6557
6628
.vector = > return null , // TODO
6558
6629
@@ -6640,3 +6711,46 @@ fn resolvePeerTypesInner(analyser: *Analyser, peer_tys: []?Type) !?Type {
6640
6711
},
6641
6712
}
6642
6713
}
6714
+
6715
+ const ArrayLike = struct {
6716
+ len : u64 ,
6717
+ /// `noreturn` indicates that this is `.{}` so can coerce to anything
6718
+ elem_ty : Type ,
6719
+ };
6720
+ fn typeIsArrayLike (analyser : * Analyser , ty : Type ) ? ArrayLike {
6721
+ std .debug .assert (ty .is_type_val );
6722
+ const ip_index = switch (ty .data ) {
6723
+ .ip_index = > | payload | payload .index orelse return null ,
6724
+ .array = > | info | return .{
6725
+ .len = info .elem_count orelse return null ,
6726
+ .elem_ty = info .elem_ty .* ,
6727
+ },
6728
+ .tuple = > | field_tys | {
6729
+ const elem_ty = field_tys [0 ];
6730
+ for (field_tys [1.. ]) | field_ty | {
6731
+ if (! field_ty .eql (elem_ty )) {
6732
+ return null ;
6733
+ }
6734
+ }
6735
+ return .{
6736
+ .len = field_tys .len ,
6737
+ .elem_ty = elem_ty ,
6738
+ };
6739
+ },
6740
+ else = > return null ,
6741
+ };
6742
+ if (ip_index == .empty_struct_type ) {
6743
+ return .{
6744
+ .len = 0 ,
6745
+ .elem_ty = Type .fromIP (analyser , .type_type , .noreturn_type ),
6746
+ };
6747
+ }
6748
+ return switch (analyser .ip .indexToKey (ip_index )) {
6749
+ .array_type = > | info | .{
6750
+ .len = info .len ,
6751
+ .elem_ty = Type .fromIP (analyser , .type_type , info .child ),
6752
+ },
6753
+ .tuple_type = > null , // TODO
6754
+ else = > null ,
6755
+ };
6756
+ }
0 commit comments