@@ -6298,6 +6298,35 @@ pub const ReferencedType = struct {
6298
6298
};
6299
6299
};
6300
6300
6301
+ const ArrayLike = struct {
6302
+ len : u64 ,
6303
+ /// `noreturn` indicates that this type is `struct{}` so can coerce to anything
6304
+ elem_ty : Type ,
6305
+ };
6306
+ fn arrayLikeFromStruct (analyser : * Analyser , ty : Type ) ? ArrayLike {
6307
+ std .debug .assert (ty .is_type_val );
6308
+ return switch (ty .zigTypeTag (analyser ).? ) {
6309
+ .@"struct" = > {
6310
+ if (ty .isNamespace ()) return .{
6311
+ .len = 0 ,
6312
+ .elem_ty = Type .fromIP (analyser , .type_type , .noreturn_type ),
6313
+ };
6314
+ if (ty .data != .tuple ) return null ;
6315
+ const elem_ty = ty .data .tuple [0 ];
6316
+ for (ty .data .tuple [1.. ]) | field_ty | {
6317
+ if (! field_ty .eql (elem_ty )) {
6318
+ return null ;
6319
+ }
6320
+ }
6321
+ return .{
6322
+ .len = ty .data .tuple .len ,
6323
+ .elem_ty = elem_ty ,
6324
+ };
6325
+ },
6326
+ else = > null ,
6327
+ };
6328
+ }
6329
+
6301
6330
// Based on src/Sema.zig from the zig codebase
6302
6331
// https://github.com/ziglang/zig/blob/master/src/Sema.zig
6303
6332
fn resolvePeerTypesInner (analyser : * Analyser , peer_tys : []? Type ) ! ? Type {
@@ -6544,7 +6573,78 @@ fn resolvePeerTypesInner(analyser: *Analyser, peer_tys: []?Type) !?Type {
6544
6573
};
6545
6574
},
6546
6575
6547
- .array = > return null , // TODO
6576
+ .array = > {
6577
+ var len : ? u64 = null ;
6578
+ var sentinel : InternPool.Index = .none ;
6579
+ var elem_ty : ? Type = null ;
6580
+
6581
+ for (peer_tys ) | * ty_ptr | {
6582
+ const ty = ty_ptr .* orelse continue ;
6583
+
6584
+ if (ty .data != .array ) {
6585
+ const arr_like = analyser .arrayLikeFromStruct (ty ) orelse {
6586
+ return null ;
6587
+ };
6588
+
6589
+ if (len ) | cur_len | {
6590
+ if (arr_like .len != cur_len ) return null ;
6591
+ } else {
6592
+ len = arr_like .len ;
6593
+ }
6594
+
6595
+ sentinel = .none ;
6596
+
6597
+ continue ;
6598
+ }
6599
+
6600
+ const arr_info = ty .data .array ;
6601
+ const arr_len = arr_info .elem_count orelse {
6602
+ return null ;
6603
+ };
6604
+
6605
+ const cur_elem_ty = elem_ty orelse {
6606
+ if (len ) | cur_len | {
6607
+ if (arr_len != cur_len ) return null ;
6608
+ } else {
6609
+ len = arr_len ;
6610
+ sentinel = arr_info .sentinel ;
6611
+ }
6612
+ elem_ty = arr_info .elem_ty .* ;
6613
+ continue ;
6614
+ };
6615
+
6616
+ if (arr_info .elem_count != len ) {
6617
+ return null ;
6618
+ }
6619
+
6620
+ const peer_elem_ty = arr_info .elem_ty .* ;
6621
+ if (! peer_elem_ty .eql (cur_elem_ty )) {
6622
+ // TODO: check if coercible
6623
+ return null ;
6624
+ }
6625
+
6626
+ if (sentinel != .none ) {
6627
+ if (arr_info .sentinel != .none ) {
6628
+ if (arr_info .sentinel != sentinel ) sentinel = .none ;
6629
+ } else {
6630
+ sentinel = .none ;
6631
+ }
6632
+ }
6633
+ }
6634
+
6635
+ std .debug .assert (elem_ty != null );
6636
+
6637
+ return .{
6638
+ .data = .{
6639
+ .array = .{
6640
+ .elem_count = len ,
6641
+ .sentinel = sentinel ,
6642
+ .elem_ty = try analyser .allocType (elem_ty .? ),
6643
+ },
6644
+ },
6645
+ .is_type_val = true ,
6646
+ };
6647
+ },
6548
6648
6549
6649
.vector = > return null , // TODO
6550
6650
0 commit comments