@@ -6298,6 +6298,35 @@ 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 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+
63016330// Based on src/Sema.zig from the zig codebase
63026331// https://github.com/ziglang/zig/blob/master/src/Sema.zig
63036332fn resolvePeerTypesInner (analyser : * Analyser , peer_tys : []? Type ) ! ? Type {
@@ -6423,7 +6452,78 @@ fn resolvePeerTypesInner(analyser: *Analyser, peer_tys: []?Type) !?Type {
64236452 };
64246453 },
64256454
6426- .array = > return null , // TODO
6455+ .array = > {
6456+ var len : ? u64 = null ;
6457+ var sentinel : InternPool.Index = .none ;
6458+ var elem_ty : ? Type = null ;
6459+
6460+ for (peer_tys ) | * ty_ptr | {
6461+ const ty = ty_ptr .* orelse continue ;
6462+
6463+ if (ty .data != .array ) {
6464+ const arr_like = analyser .arrayLikeFromStruct (ty ) orelse {
6465+ return null ;
6466+ };
6467+
6468+ if (len ) | cur_len | {
6469+ if (arr_like .len != cur_len ) return null ;
6470+ } else {
6471+ len = arr_like .len ;
6472+ }
6473+
6474+ sentinel = .none ;
6475+
6476+ continue ;
6477+ }
6478+
6479+ const arr_info = ty .data .array ;
6480+ const arr_len = arr_info .elem_count orelse {
6481+ return null ;
6482+ };
6483+
6484+ const cur_elem_ty = elem_ty orelse {
6485+ if (len ) | cur_len | {
6486+ if (arr_len != cur_len ) return null ;
6487+ } else {
6488+ len = arr_len ;
6489+ sentinel = arr_info .sentinel ;
6490+ }
6491+ elem_ty = arr_info .elem_ty .* ;
6492+ continue ;
6493+ };
6494+
6495+ if (arr_info .elem_count != len ) {
6496+ return null ;
6497+ }
6498+
6499+ const peer_elem_ty = arr_info .elem_ty .* ;
6500+ if (! peer_elem_ty .eql (cur_elem_ty )) {
6501+ // TODO: check if coercible
6502+ return null ;
6503+ }
6504+
6505+ if (sentinel != .none ) {
6506+ if (arr_info .sentinel != .none ) {
6507+ if (arr_info .sentinel != sentinel ) sentinel = .none ;
6508+ } else {
6509+ sentinel = .none ;
6510+ }
6511+ }
6512+ }
6513+
6514+ std .debug .assert (elem_ty != null );
6515+
6516+ return .{
6517+ .data = .{
6518+ .array = .{
6519+ .elem_count = len ,
6520+ .sentinel = sentinel ,
6521+ .elem_ty = try analyser .allocType (elem_ty .? ),
6522+ },
6523+ },
6524+ .is_type_val = true ,
6525+ };
6526+ },
64276527
64286528 .vector = > return null , // TODO
64296529
0 commit comments