@@ -6776,7 +6776,284 @@ fn resolvePeerTypesInner(analyser: *Analyser, peer_tys: []?Type) !?Type {
67766776 };
67776777 },
67786778
6779- .ptr = > return null , // TODO
6779+ .ptr = > {
6780+ var any_slice = false ;
6781+ var any_abi_aligned = false ;
6782+ var opt_ptr_info : ? Type.PointerInfo = null ;
6783+
6784+ for (peer_tys ) | opt_ty | {
6785+ const ty = opt_ty orelse continue ;
6786+ const peer_info : Type.PointerInfo = switch (ty .zigTypeTag (analyser ).? ) {
6787+ .pointer = > ty .pointerInfo (analyser ).? ,
6788+ .@"fn" = > .{
6789+ .elem_ty = ty ,
6790+ .sentinel = .none ,
6791+ .flags = .{ .size = .one },
6792+ },
6793+ else = > return null ,
6794+ };
6795+
6796+ switch (peer_info .flags .size ) {
6797+ .one , .many = > {},
6798+ .slice = > any_slice = true ,
6799+ .c = > return null ,
6800+ }
6801+
6802+ var ptr_info = opt_ptr_info orelse {
6803+ opt_ptr_info = peer_info ;
6804+ continue ;
6805+ };
6806+
6807+ if (peer_info .flags .alignment == 0 ) {
6808+ any_abi_aligned = true ;
6809+ } else if (ptr_info .flags .alignment == 0 ) {
6810+ any_abi_aligned = true ;
6811+ ptr_info .flags .alignment = peer_info .flags .alignment ;
6812+ } else {
6813+ ptr_info .flags .alignment = @min (ptr_info .flags .alignment , peer_info .flags .alignment );
6814+ }
6815+
6816+ if (ptr_info .flags .address_space != peer_info .flags .address_space ) {
6817+ return null ;
6818+ }
6819+
6820+ ptr_info .flags .is_const = ptr_info .flags .is_const or peer_info .flags .is_const ;
6821+ ptr_info .flags .is_volatile = ptr_info .flags .is_volatile or peer_info .flags .is_volatile ;
6822+ ptr_info .flags .is_allowzero = ptr_info .flags .is_allowzero or peer_info .flags .is_allowzero ;
6823+
6824+ const peer_sentinel : InternPool.Index = switch (peer_info .flags .size ) {
6825+ .one = > switch (peer_info .elem_ty .data ) {
6826+ .array = > | array_info | array_info .sentinel ,
6827+ .ip_index = > | payload | switch (analyser .ip .indexToKey (payload .index orelse .unknown_type )) {
6828+ .array_type = > | info | info .sentinel ,
6829+ else = > .none ,
6830+ },
6831+ else = > .none ,
6832+ },
6833+ .many , .slice = > peer_info .sentinel ,
6834+ .c = > unreachable ,
6835+ };
6836+
6837+ const cur_sentinel : InternPool.Index = switch (ptr_info .flags .size ) {
6838+ .one = > switch (ptr_info .elem_ty .data ) {
6839+ .array = > | array_info | array_info .sentinel ,
6840+ .ip_index = > | payload | switch (analyser .ip .indexToKey (payload .index orelse .unknown_type )) {
6841+ .array_type = > | info | info .sentinel ,
6842+ else = > .none ,
6843+ },
6844+ else = > .none ,
6845+ },
6846+ .many , .slice = > ptr_info .sentinel ,
6847+ .c = > unreachable ,
6848+ };
6849+
6850+ const peer_pointee_array = analyser .typeIsArrayLike (peer_info .elem_ty );
6851+ const cur_pointee_array = analyser .typeIsArrayLike (ptr_info .elem_ty );
6852+
6853+ good : {
6854+ switch (peer_info .flags .size ) {
6855+ .one = > switch (ptr_info .flags .size ) {
6856+ .one = > {
6857+ if (ptr_info .elem_ty .eql (peer_info .elem_ty )) {
6858+ break :good ;
6859+ }
6860+ // TODO: coerce pointer types
6861+
6862+ const cur_arr = cur_pointee_array orelse return null ;
6863+ const peer_arr = peer_pointee_array orelse return null ;
6864+
6865+ if (cur_arr .elem_ty .eql (peer_arr .elem_ty )) {
6866+ const elem_ty = peer_arr .elem_ty ;
6867+ // *[n:x]T + *[n:y]T = *[n]T
6868+ if (cur_arr .len == peer_arr .len ) {
6869+ ptr_info .elem_ty = .{
6870+ .data = .{
6871+ .array = .{
6872+ .elem_count = cur_arr .len ,
6873+ .sentinel = .none ,
6874+ .elem_ty = try analyser .allocType (elem_ty ),
6875+ },
6876+ },
6877+ .is_type_val = true ,
6878+ };
6879+ break :good ;
6880+ }
6881+ // *[a]T + *[b]T = []T
6882+ ptr_info .flags .size = .slice ;
6883+ ptr_info .elem_ty = elem_ty ;
6884+ break :good ;
6885+ }
6886+ // TODO: coerce array types
6887+
6888+ if (peer_arr .elem_ty .isNoreturnType ()) {
6889+ // *struct{} + *[a]T = []T
6890+ ptr_info .flags .size = .slice ;
6891+ ptr_info .elem_ty = cur_arr .elem_ty ;
6892+ break :good ;
6893+ }
6894+
6895+ if (cur_arr .elem_ty .isNoreturnType ()) {
6896+ // *[a]T + *struct{} = []T
6897+ ptr_info .flags .size = .slice ;
6898+ ptr_info .elem_ty = peer_arr .elem_ty ;
6899+ break :good ;
6900+ }
6901+
6902+ return null ;
6903+ },
6904+ .many = > {
6905+ // Only works for *[n]T + [*]T -> [*]T
6906+ const arr = peer_pointee_array orelse return null ;
6907+ if (ptr_info .elem_ty .eql (arr .elem_ty )) {
6908+ break :good ;
6909+ }
6910+ // TODO: coerce array and many-item pointer types
6911+ return null ;
6912+ },
6913+ .slice = > {
6914+ // Only works for *[n]T + []T -> []T
6915+ const arr = peer_pointee_array orelse return null ;
6916+ if (ptr_info .elem_ty .eql (arr .elem_ty )) {
6917+ break :good ;
6918+ }
6919+ // TODO: coerce array and slice types
6920+ if (arr .elem_ty .isNoreturnType ()) {
6921+ // *struct{} + []T -> []T
6922+ break :good ;
6923+ }
6924+ return null ;
6925+ },
6926+ .c = > unreachable ,
6927+ },
6928+ .many = > switch (ptr_info .flags .size ) {
6929+ .one = > {
6930+ // Only works for [*]T + *[n]T -> [*]T
6931+ const arr = cur_pointee_array orelse return null ;
6932+ if (arr .elem_ty .eql (peer_info .elem_ty )) {
6933+ ptr_info .flags .size = .many ;
6934+ ptr_info .elem_ty = peer_info .elem_ty ;
6935+ break :good ;
6936+ }
6937+ // TODO: coerce many-item pointer and array types
6938+ return null ;
6939+ },
6940+ .many = > {
6941+ if (ptr_info .elem_ty .eql (peer_info .elem_ty )) {
6942+ break :good ;
6943+ }
6944+ // TODO: coerce many-item pointer types
6945+ return null ;
6946+ },
6947+ .slice = > {
6948+ // Only works if no peers are actually slices
6949+ if (any_slice ) {
6950+ return null ;
6951+ }
6952+ // Okay, then works for [*]T + "[]T" -> [*]T
6953+ if (ptr_info .elem_ty .eql (peer_info .elem_ty )) {
6954+ ptr_info .flags .size = .many ;
6955+ break :good ;
6956+ }
6957+ // TODO: coerce many-item pointer and "slice" types
6958+ return null ;
6959+ },
6960+ .c = > unreachable ,
6961+ },
6962+ .slice = > switch (ptr_info .flags .size ) {
6963+ .one = > {
6964+ // Only works for []T + *[n]T -> []T
6965+ const arr = cur_pointee_array orelse return null ;
6966+ if (arr .elem_ty .eql (peer_info .elem_ty )) {
6967+ ptr_info .flags .size = .slice ;
6968+ ptr_info .elem_ty = peer_info .elem_ty ;
6969+ break :good ;
6970+ }
6971+ // TODO: coerce slice and array types
6972+ if (arr .elem_ty .isNoreturnType ()) {
6973+ // []T + *struct{} -> []T
6974+ ptr_info .flags .size = .slice ;
6975+ ptr_info .elem_ty = peer_info .elem_ty ;
6976+ break :good ;
6977+ }
6978+ return null ;
6979+ },
6980+ .many = > {
6981+ return null ;
6982+ },
6983+ .slice = > {
6984+ if (ptr_info .elem_ty .eql (peer_info .elem_ty )) {
6985+ break :good ;
6986+ }
6987+ // TODO: coerce slice types
6988+ return null ;
6989+ },
6990+ .c = > unreachable ,
6991+ },
6992+ .c = > unreachable ,
6993+ }
6994+ }
6995+
6996+ sentinel : {
6997+ no_sentinel : {
6998+ if (peer_sentinel == .none ) break :no_sentinel ;
6999+ if (cur_sentinel == .none ) break :no_sentinel ;
7000+ if (peer_sentinel != cur_sentinel ) {
7001+ // TODO: coerce pointer sentinels
7002+ return null ;
7003+ }
7004+ break :sentinel ;
7005+ }
7006+ ptr_info .sentinel = .none ;
7007+ if (ptr_info .flags .size == .one ) switch (ptr_info .elem_ty .data ) {
7008+ .array = > | * array_info | array_info .sentinel = .none ,
7009+ .ip_index = > | * payload | switch (analyser .ip .indexToKey (payload .index orelse .unknown_type )) {
7010+ .array_type = > | info | {
7011+ payload .index = try analyser .ip .get (analyser .gpa , .{ .array_type = .{
7012+ .len = info .len ,
7013+ .child = info .child ,
7014+ .sentinel = .none ,
7015+ } });
7016+ },
7017+ else = > {},
7018+ },
7019+ else = > {},
7020+ };
7021+ }
7022+
7023+ opt_ptr_info = ptr_info ;
7024+ }
7025+
7026+ const info = opt_ptr_info .? ;
7027+ const pointee = info .elem_ty ;
7028+ if (pointee .isNoreturnType ()) {
7029+ return null ;
7030+ }
7031+ switch (pointee .data ) {
7032+ .array = > | array_info | {
7033+ if (array_info .elem_ty .isNoreturnType ()) {
7034+ return null ;
7035+ }
7036+ },
7037+ else = > {},
7038+ }
7039+
7040+ if (any_abi_aligned and info .flags .alignment != 0 ) {
7041+ // TODO: find minimum pointer alignment
7042+ return null ;
7043+ }
7044+
7045+ return .{
7046+ .data = .{
7047+ .pointer = .{
7048+ .elem_ty = try analyser .allocType (info .elem_ty ),
7049+ .sentinel = info .sentinel ,
7050+ .size = info .flags .size ,
7051+ .is_const = info .flags .is_const ,
7052+ },
7053+ },
7054+ .is_type_val = true ,
7055+ };
7056+ },
67807057
67817058 .func = > return null , // TODO
67827059
0 commit comments