@@ -6735,7 +6735,284 @@ fn resolvePeerTypesInner(analyser: *Analyser, peer_tys: []?Type) !?Type {
67356735 };
67366736 },
67376737
6738- .ptr = > return null , // TODO
6738+ .ptr = > {
6739+ var any_slice = false ;
6740+ var any_abi_aligned = false ;
6741+ var opt_ptr_info : ? Type.PointerInfo = null ;
6742+
6743+ for (peer_tys ) | opt_ty | {
6744+ const ty = opt_ty orelse continue ;
6745+ const peer_info : Type.PointerInfo = switch (ty .zigTypeTag (analyser ).? ) {
6746+ .pointer = > ty .pointerInfo (analyser ).? ,
6747+ .@"fn" = > .{
6748+ .elem_ty = ty ,
6749+ .sentinel = .none ,
6750+ .flags = .{ .size = .one },
6751+ },
6752+ else = > return null ,
6753+ };
6754+
6755+ switch (peer_info .flags .size ) {
6756+ .one , .many = > {},
6757+ .slice = > any_slice = true ,
6758+ .c = > return null ,
6759+ }
6760+
6761+ var ptr_info = opt_ptr_info orelse {
6762+ opt_ptr_info = peer_info ;
6763+ continue ;
6764+ };
6765+
6766+ if (peer_info .flags .alignment == 0 ) {
6767+ any_abi_aligned = true ;
6768+ } else if (ptr_info .flags .alignment == 0 ) {
6769+ any_abi_aligned = true ;
6770+ ptr_info .flags .alignment = peer_info .flags .alignment ;
6771+ } else {
6772+ ptr_info .flags .alignment = @min (ptr_info .flags .alignment , peer_info .flags .alignment );
6773+ }
6774+
6775+ if (ptr_info .flags .address_space != peer_info .flags .address_space ) {
6776+ return null ;
6777+ }
6778+
6779+ ptr_info .flags .is_const = ptr_info .flags .is_const or peer_info .flags .is_const ;
6780+ ptr_info .flags .is_volatile = ptr_info .flags .is_volatile or peer_info .flags .is_volatile ;
6781+ ptr_info .flags .is_allowzero = ptr_info .flags .is_allowzero or peer_info .flags .is_allowzero ;
6782+
6783+ const peer_sentinel : InternPool.Index = switch (peer_info .flags .size ) {
6784+ .one = > switch (peer_info .elem_ty .data ) {
6785+ .array = > | array_info | array_info .sentinel ,
6786+ .ip_index = > | payload | switch (analyser .ip .indexToKey (payload .index orelse .unknown_type )) {
6787+ .array_type = > | info | info .sentinel ,
6788+ else = > .none ,
6789+ },
6790+ else = > .none ,
6791+ },
6792+ .many , .slice = > peer_info .sentinel ,
6793+ .c = > unreachable ,
6794+ };
6795+
6796+ const cur_sentinel : InternPool.Index = switch (ptr_info .flags .size ) {
6797+ .one = > switch (ptr_info .elem_ty .data ) {
6798+ .array = > | array_info | array_info .sentinel ,
6799+ .ip_index = > | payload | switch (analyser .ip .indexToKey (payload .index orelse .unknown_type )) {
6800+ .array_type = > | info | info .sentinel ,
6801+ else = > .none ,
6802+ },
6803+ else = > .none ,
6804+ },
6805+ .many , .slice = > ptr_info .sentinel ,
6806+ .c = > unreachable ,
6807+ };
6808+
6809+ const peer_pointee_array = analyser .typeIsArrayLike (peer_info .elem_ty );
6810+ const cur_pointee_array = analyser .typeIsArrayLike (ptr_info .elem_ty );
6811+
6812+ good : {
6813+ switch (peer_info .flags .size ) {
6814+ .one = > switch (ptr_info .flags .size ) {
6815+ .one = > {
6816+ if (ptr_info .elem_ty .eql (peer_info .elem_ty )) {
6817+ break :good ;
6818+ }
6819+ // TODO: coerce pointer types
6820+
6821+ const cur_arr = cur_pointee_array orelse return null ;
6822+ const peer_arr = peer_pointee_array orelse return null ;
6823+
6824+ if (cur_arr .elem_ty .eql (peer_arr .elem_ty )) {
6825+ const elem_ty = peer_arr .elem_ty ;
6826+ // *[n:x]T + *[n:y]T = *[n]T
6827+ if (cur_arr .len == peer_arr .len ) {
6828+ ptr_info .elem_ty = .{
6829+ .data = .{
6830+ .array = .{
6831+ .elem_count = cur_arr .len ,
6832+ .sentinel = .none ,
6833+ .elem_ty = try analyser .allocType (elem_ty ),
6834+ },
6835+ },
6836+ .is_type_val = true ,
6837+ };
6838+ break :good ;
6839+ }
6840+ // *[a]T + *[b]T = []T
6841+ ptr_info .flags .size = .slice ;
6842+ ptr_info .elem_ty = elem_ty ;
6843+ break :good ;
6844+ }
6845+ // TODO: coerce array types
6846+
6847+ if (peer_arr .elem_ty .isNoreturnType ()) {
6848+ // *struct{} + *[a]T = []T
6849+ ptr_info .flags .size = .slice ;
6850+ ptr_info .elem_ty = cur_arr .elem_ty ;
6851+ break :good ;
6852+ }
6853+
6854+ if (cur_arr .elem_ty .isNoreturnType ()) {
6855+ // *[a]T + *struct{} = []T
6856+ ptr_info .flags .size = .slice ;
6857+ ptr_info .elem_ty = peer_arr .elem_ty ;
6858+ break :good ;
6859+ }
6860+
6861+ return null ;
6862+ },
6863+ .many = > {
6864+ // Only works for *[n]T + [*]T -> [*]T
6865+ const arr = peer_pointee_array orelse return null ;
6866+ if (ptr_info .elem_ty .eql (arr .elem_ty )) {
6867+ break :good ;
6868+ }
6869+ // TODO: coerce array and many-item pointer types
6870+ return null ;
6871+ },
6872+ .slice = > {
6873+ // Only works for *[n]T + []T -> []T
6874+ const arr = peer_pointee_array orelse return null ;
6875+ if (ptr_info .elem_ty .eql (arr .elem_ty )) {
6876+ break :good ;
6877+ }
6878+ // TODO: coerce array and slice types
6879+ if (arr .elem_ty .isNoreturnType ()) {
6880+ // *struct{} + []T -> []T
6881+ break :good ;
6882+ }
6883+ return null ;
6884+ },
6885+ .c = > unreachable ,
6886+ },
6887+ .many = > switch (ptr_info .flags .size ) {
6888+ .one = > {
6889+ // Only works for [*]T + *[n]T -> [*]T
6890+ const arr = cur_pointee_array orelse return null ;
6891+ if (arr .elem_ty .eql (peer_info .elem_ty )) {
6892+ ptr_info .flags .size = .many ;
6893+ ptr_info .elem_ty = peer_info .elem_ty ;
6894+ break :good ;
6895+ }
6896+ // TODO: coerce many-item pointer and array types
6897+ return null ;
6898+ },
6899+ .many = > {
6900+ if (ptr_info .elem_ty .eql (peer_info .elem_ty )) {
6901+ break :good ;
6902+ }
6903+ // TODO: coerce many-item pointer types
6904+ return null ;
6905+ },
6906+ .slice = > {
6907+ // Only works if no peers are actually slices
6908+ if (any_slice ) {
6909+ return null ;
6910+ }
6911+ // Okay, then works for [*]T + "[]T" -> [*]T
6912+ if (ptr_info .elem_ty .eql (peer_info .elem_ty )) {
6913+ ptr_info .flags .size = .many ;
6914+ break :good ;
6915+ }
6916+ // TODO: coerce many-item pointer and "slice" types
6917+ return null ;
6918+ },
6919+ .c = > unreachable ,
6920+ },
6921+ .slice = > switch (ptr_info .flags .size ) {
6922+ .one = > {
6923+ // Only works for []T + *[n]T -> []T
6924+ const arr = cur_pointee_array orelse return null ;
6925+ if (arr .elem_ty .eql (peer_info .elem_ty )) {
6926+ ptr_info .flags .size = .slice ;
6927+ ptr_info .elem_ty = peer_info .elem_ty ;
6928+ break :good ;
6929+ }
6930+ // TODO: coerce slice and array types
6931+ if (arr .elem_ty .isNoreturnType ()) {
6932+ // []T + *struct{} -> []T
6933+ ptr_info .flags .size = .slice ;
6934+ ptr_info .elem_ty = peer_info .elem_ty ;
6935+ break :good ;
6936+ }
6937+ return null ;
6938+ },
6939+ .many = > {
6940+ return null ;
6941+ },
6942+ .slice = > {
6943+ if (ptr_info .elem_ty .eql (peer_info .elem_ty )) {
6944+ break :good ;
6945+ }
6946+ // TODO: coerce slice types
6947+ return null ;
6948+ },
6949+ .c = > unreachable ,
6950+ },
6951+ .c = > unreachable ,
6952+ }
6953+ }
6954+
6955+ sentinel : {
6956+ no_sentinel : {
6957+ if (peer_sentinel == .none ) break :no_sentinel ;
6958+ if (cur_sentinel == .none ) break :no_sentinel ;
6959+ if (peer_sentinel != cur_sentinel ) {
6960+ // TODO: coerce pointer sentinels
6961+ return null ;
6962+ }
6963+ break :sentinel ;
6964+ }
6965+ ptr_info .sentinel = .none ;
6966+ if (ptr_info .flags .size == .one ) switch (ptr_info .elem_ty .data ) {
6967+ .array = > | * array_info | array_info .sentinel = .none ,
6968+ .ip_index = > | * payload | switch (analyser .ip .indexToKey (payload .index orelse .unknown_type )) {
6969+ .array_type = > | info | {
6970+ payload .index = try analyser .ip .get (analyser .gpa , .{ .array_type = .{
6971+ .len = info .len ,
6972+ .child = info .child ,
6973+ .sentinel = .none ,
6974+ } });
6975+ },
6976+ else = > {},
6977+ },
6978+ else = > {},
6979+ };
6980+ }
6981+
6982+ opt_ptr_info = ptr_info ;
6983+ }
6984+
6985+ const info = opt_ptr_info .? ;
6986+ const pointee = info .elem_ty ;
6987+ if (pointee .isNoreturnType ()) {
6988+ return null ;
6989+ }
6990+ switch (pointee .data ) {
6991+ .array = > | array_info | {
6992+ if (array_info .elem_ty .isNoreturnType ()) {
6993+ return null ;
6994+ }
6995+ },
6996+ else = > {},
6997+ }
6998+
6999+ if (any_abi_aligned and info .flags .alignment != 0 ) {
7000+ // TODO: find minimum pointer alignment
7001+ return null ;
7002+ }
7003+
7004+ return .{
7005+ .data = .{
7006+ .pointer = .{
7007+ .elem_ty = try analyser .allocType (info .elem_ty ),
7008+ .sentinel = info .sentinel ,
7009+ .size = info .flags .size ,
7010+ .is_const = info .flags .is_const ,
7011+ },
7012+ },
7013+ .is_type_val = true ,
7014+ };
7015+ },
67397016
67407017 .func = > return null , // TODO
67417018
0 commit comments