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