@@ -6298,6 +6298,47 @@ pub const ReferencedType = struct {
62986298 };
62996299};
63006300
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 typeIsArrayLike (analyser : * Analyser , ty : Type ) ? ArrayLike {
6307+ std .debug .assert (ty .is_type_val );
6308+ return switch (ty .data ) {
6309+ .array = > | info | .{
6310+ .len = info .elem_count orelse return null ,
6311+ .elem_ty = info .elem_ty .* ,
6312+ },
6313+ .ip_index = > | payload | switch (payload .index orelse .unknown_type ) {
6314+ .empty_struct_type = > .{
6315+ .len = 0 ,
6316+ .elem_ty = Type .fromIP (analyser , .type_type , .noreturn_type ),
6317+ },
6318+ else = > | ip_index | switch (analyser .ip .indexToKey (ip_index )) {
6319+ .array_type = > | info | .{
6320+ .len = info .len ,
6321+ .elem_ty = Type .fromIP (analyser , .type_type , info .child ),
6322+ },
6323+ else = > null ,
6324+ },
6325+ },
6326+ .tuple = > | field_tys | {
6327+ const elem_ty = field_tys [0 ];
6328+ for (field_tys [1.. ]) | field_ty | {
6329+ if (! field_ty .eql (elem_ty )) {
6330+ return null ;
6331+ }
6332+ }
6333+ return .{
6334+ .len = field_tys .len ,
6335+ .elem_ty = elem_ty ,
6336+ };
6337+ },
6338+ else = > null ,
6339+ };
6340+ }
6341+
63016342// Based on src/Sema.zig from the zig codebase
63026343// https://github.com/ziglang/zig/blob/master/src/Sema.zig
63036344fn resolvePeerTypesInner (analyser : * Analyser , peer_tys : []? Type ) ! ? Type {
@@ -6544,7 +6585,78 @@ fn resolvePeerTypesInner(analyser: *Analyser, peer_tys: []?Type) !?Type {
65446585 };
65456586 },
65466587
6547- .array = > return null , // TODO
6588+ .array = > {
6589+ var len : ? u64 = null ;
6590+ var sentinel : InternPool.Index = .none ;
6591+ var elem_ty : ? Type = null ;
6592+
6593+ for (peer_tys ) | * ty_ptr | {
6594+ const ty = ty_ptr .* orelse continue ;
6595+
6596+ if (ty .data != .array ) {
6597+ const arr_like = analyser .typeIsArrayLike (ty ) orelse {
6598+ return null ;
6599+ };
6600+
6601+ if (len ) | cur_len | {
6602+ if (arr_like .len != cur_len ) return null ;
6603+ } else {
6604+ len = arr_like .len ;
6605+ }
6606+
6607+ sentinel = .none ;
6608+
6609+ continue ;
6610+ }
6611+
6612+ const arr_info = ty .data .array ;
6613+ const arr_len = arr_info .elem_count orelse {
6614+ return null ;
6615+ };
6616+
6617+ const cur_elem_ty = elem_ty orelse {
6618+ if (len ) | cur_len | {
6619+ if (arr_len != cur_len ) return null ;
6620+ } else {
6621+ len = arr_len ;
6622+ sentinel = arr_info .sentinel ;
6623+ }
6624+ elem_ty = arr_info .elem_ty .* ;
6625+ continue ;
6626+ };
6627+
6628+ if (arr_info .elem_count != len ) {
6629+ return null ;
6630+ }
6631+
6632+ const peer_elem_ty = arr_info .elem_ty .* ;
6633+ if (! peer_elem_ty .eql (cur_elem_ty )) {
6634+ // TODO: check if coercible
6635+ return null ;
6636+ }
6637+
6638+ if (sentinel != .none ) {
6639+ if (arr_info .sentinel != .none ) {
6640+ if (arr_info .sentinel != sentinel ) sentinel = .none ;
6641+ } else {
6642+ sentinel = .none ;
6643+ }
6644+ }
6645+ }
6646+
6647+ std .debug .assert (elem_ty != null );
6648+
6649+ return .{
6650+ .data = .{
6651+ .array = .{
6652+ .elem_count = len ,
6653+ .sentinel = sentinel ,
6654+ .elem_ty = try analyser .allocType (elem_ty .? ),
6655+ },
6656+ },
6657+ .is_type_val = true ,
6658+ };
6659+ },
65486660
65496661 .vector = > return null , // TODO
65506662
0 commit comments