@@ -6552,7 +6552,78 @@ fn resolvePeerTypesInner(analyser: *Analyser, peer_tys: []?Type) !?Type {
65526552 };
65536553 },
65546554
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+ },
65566627
65576628 .vector = > return null , // TODO
65586629
@@ -6640,3 +6711,46 @@ fn resolvePeerTypesInner(analyser: *Analyser, peer_tys: []?Type) !?Type {
66406711 },
66416712 }
66426713}
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