@@ -6682,7 +6682,285 @@ fn resolvePeerTypesInner(analyser: *Analyser, peer_tys: []?Type) !?Type {
66826682 };
66836683 },
66846684
6685- .ptr = > return null , // TODO
6685+ .ptr = > {
6686+ var any_slice = false ;
6687+ var any_abi_aligned = false ;
6688+ var opt_ptr_info : ? PointerInfo = null ;
6689+
6690+ for (peer_tys ) | opt_ty | {
6691+ const ty = opt_ty orelse continue ;
6692+ const peer_info : PointerInfo = switch (ty .zigTypeTag (analyser ).? ) {
6693+ .pointer = > analyser .typePointerInfo (ty ).? ,
6694+ .@"fn" = > .{
6695+ .is_optional = false ,
6696+ .elem_ty = ty ,
6697+ .sentinel = .none ,
6698+ .flags = .{ .size = .one },
6699+ },
6700+ else = > return null ,
6701+ };
6702+
6703+ switch (peer_info .flags .size ) {
6704+ .one , .many = > {},
6705+ .slice = > any_slice = true ,
6706+ .c = > return null ,
6707+ }
6708+
6709+ var ptr_info = opt_ptr_info orelse {
6710+ opt_ptr_info = peer_info ;
6711+ continue ;
6712+ };
6713+
6714+ if (peer_info .flags .alignment == 0 ) {
6715+ any_abi_aligned = true ;
6716+ } else if (ptr_info .flags .alignment == 0 ) {
6717+ any_abi_aligned = true ;
6718+ ptr_info .flags .alignment = peer_info .flags .alignment ;
6719+ } else {
6720+ ptr_info .flags .alignment = @min (ptr_info .flags .alignment , peer_info .flags .alignment );
6721+ }
6722+
6723+ if (ptr_info .flags .address_space != peer_info .flags .address_space ) {
6724+ return null ;
6725+ }
6726+
6727+ ptr_info .flags .is_const = ptr_info .flags .is_const or peer_info .flags .is_const ;
6728+ ptr_info .flags .is_volatile = ptr_info .flags .is_volatile or peer_info .flags .is_volatile ;
6729+ ptr_info .flags .is_allowzero = ptr_info .flags .is_allowzero or peer_info .flags .is_allowzero ;
6730+
6731+ const peer_sentinel : InternPool.Index = switch (peer_info .flags .size ) {
6732+ .one = > switch (peer_info .elem_ty .data ) {
6733+ .array = > | array_info | array_info .sentinel ,
6734+ .ip_index = > | payload | switch (analyser .ip .indexToKey (payload .index orelse .unknown_type )) {
6735+ .array_type = > | info | info .sentinel ,
6736+ else = > .none ,
6737+ },
6738+ else = > .none ,
6739+ },
6740+ .many , .slice = > peer_info .sentinel ,
6741+ .c = > unreachable ,
6742+ };
6743+
6744+ const cur_sentinel : InternPool.Index = switch (ptr_info .flags .size ) {
6745+ .one = > switch (ptr_info .elem_ty .data ) {
6746+ .array = > | array_info | array_info .sentinel ,
6747+ .ip_index = > | payload | switch (analyser .ip .indexToKey (payload .index orelse .unknown_type )) {
6748+ .array_type = > | info | info .sentinel ,
6749+ else = > .none ,
6750+ },
6751+ else = > .none ,
6752+ },
6753+ .many , .slice = > ptr_info .sentinel ,
6754+ .c = > unreachable ,
6755+ };
6756+
6757+ const peer_pointee_array = analyser .typeIsArrayLike (peer_info .elem_ty );
6758+ const cur_pointee_array = analyser .typeIsArrayLike (ptr_info .elem_ty );
6759+
6760+ good : {
6761+ switch (peer_info .flags .size ) {
6762+ .one = > switch (ptr_info .flags .size ) {
6763+ .one = > {
6764+ if (ptr_info .elem_ty .eql (peer_info .elem_ty )) {
6765+ break :good ;
6766+ }
6767+ // TODO: coerce pointer types
6768+
6769+ const cur_arr = cur_pointee_array orelse return null ;
6770+ const peer_arr = peer_pointee_array orelse return null ;
6771+
6772+ if (cur_arr .elem_ty .eql (peer_arr .elem_ty )) {
6773+ const elem_ty = peer_arr .elem_ty ;
6774+ // *[n:x]T + *[n:y]T = *[n]T
6775+ if (cur_arr .len == peer_arr .len ) {
6776+ ptr_info .elem_ty = .{
6777+ .data = .{
6778+ .array = .{
6779+ .elem_count = cur_arr .len ,
6780+ .sentinel = .none ,
6781+ .elem_ty = try analyser .allocType (elem_ty ),
6782+ },
6783+ },
6784+ .is_type_val = true ,
6785+ };
6786+ break :good ;
6787+ }
6788+ // *[a]T + *[b]T = []T
6789+ ptr_info .flags .size = .slice ;
6790+ ptr_info .elem_ty = elem_ty ;
6791+ break :good ;
6792+ }
6793+ // TODO: coerce array types
6794+
6795+ if (peer_arr .elem_ty .isNoreturnType ()) {
6796+ // *struct{} + *[a]T = []T
6797+ ptr_info .flags .size = .slice ;
6798+ ptr_info .elem_ty = cur_arr .elem_ty ;
6799+ break :good ;
6800+ }
6801+
6802+ if (cur_arr .elem_ty .isNoreturnType ()) {
6803+ // *[a]T + *struct{} = []T
6804+ ptr_info .flags .size = .slice ;
6805+ ptr_info .elem_ty = peer_arr .elem_ty ;
6806+ break :good ;
6807+ }
6808+
6809+ return null ;
6810+ },
6811+ .many = > {
6812+ // Only works for *[n]T + [*]T -> [*]T
6813+ const arr = peer_pointee_array orelse return null ;
6814+ if (ptr_info .elem_ty .eql (arr .elem_ty )) {
6815+ break :good ;
6816+ }
6817+ // TODO: coerce array and many-item pointer types
6818+ return null ;
6819+ },
6820+ .slice = > {
6821+ // Only works for *[n]T + []T -> []T
6822+ const arr = peer_pointee_array orelse return null ;
6823+ if (ptr_info .elem_ty .eql (arr .elem_ty )) {
6824+ break :good ;
6825+ }
6826+ // TODO: coerce array and slice types
6827+ if (arr .elem_ty .isNoreturnType ()) {
6828+ // *struct{} + []T -> []T
6829+ break :good ;
6830+ }
6831+ return null ;
6832+ },
6833+ .c = > unreachable ,
6834+ },
6835+ .many = > switch (ptr_info .flags .size ) {
6836+ .one = > {
6837+ // Only works for [*]T + *[n]T -> [*]T
6838+ const arr = cur_pointee_array orelse return null ;
6839+ if (arr .elem_ty .eql (peer_info .elem_ty )) {
6840+ ptr_info .flags .size = .many ;
6841+ ptr_info .elem_ty = peer_info .elem_ty ;
6842+ break :good ;
6843+ }
6844+ // TODO: coerce many-item pointer and array types
6845+ return null ;
6846+ },
6847+ .many = > {
6848+ if (ptr_info .elem_ty .eql (peer_info .elem_ty )) {
6849+ break :good ;
6850+ }
6851+ // TODO: coerce many-item pointer types
6852+ return null ;
6853+ },
6854+ .slice = > {
6855+ // Only works if no peers are actually slices
6856+ if (any_slice ) {
6857+ return null ;
6858+ }
6859+ // Okay, then works for [*]T + "[]T" -> [*]T
6860+ if (ptr_info .elem_ty .eql (peer_info .elem_ty )) {
6861+ ptr_info .flags .size = .many ;
6862+ break :good ;
6863+ }
6864+ // TODO: coerce many-item pointer and "slice" types
6865+ return null ;
6866+ },
6867+ .c = > unreachable ,
6868+ },
6869+ .slice = > switch (ptr_info .flags .size ) {
6870+ .one = > {
6871+ // Only works for []T + *[n]T -> []T
6872+ const arr = cur_pointee_array orelse return null ;
6873+ if (arr .elem_ty .eql (peer_info .elem_ty )) {
6874+ ptr_info .flags .size = .slice ;
6875+ ptr_info .elem_ty = peer_info .elem_ty ;
6876+ break :good ;
6877+ }
6878+ // TODO: coerce slice and array types
6879+ if (arr .elem_ty .isNoreturnType ()) {
6880+ // []T + *struct{} -> []T
6881+ ptr_info .flags .size = .slice ;
6882+ ptr_info .elem_ty = peer_info .elem_ty ;
6883+ break :good ;
6884+ }
6885+ return null ;
6886+ },
6887+ .many = > {
6888+ return null ;
6889+ },
6890+ .slice = > {
6891+ if (ptr_info .elem_ty .eql (peer_info .elem_ty )) {
6892+ break :good ;
6893+ }
6894+ // TODO: coerce slice types
6895+ return null ;
6896+ },
6897+ .c = > unreachable ,
6898+ },
6899+ .c = > unreachable ,
6900+ }
6901+ }
6902+
6903+ sentinel : {
6904+ no_sentinel : {
6905+ if (peer_sentinel == .none ) break :no_sentinel ;
6906+ if (cur_sentinel == .none ) break :no_sentinel ;
6907+ if (peer_sentinel != cur_sentinel ) {
6908+ // TODO: coerce pointer sentinels
6909+ return null ;
6910+ }
6911+ break :sentinel ;
6912+ }
6913+ ptr_info .sentinel = .none ;
6914+ if (ptr_info .flags .size == .one ) switch (ptr_info .elem_ty .data ) {
6915+ .array = > | * array_info | array_info .sentinel = .none ,
6916+ .ip_index = > | * payload | switch (analyser .ip .indexToKey (payload .index orelse .unknown_type )) {
6917+ .array_type = > | info | {
6918+ payload .index = try analyser .ip .get (analyser .gpa , .{ .array_type = .{
6919+ .len = info .len ,
6920+ .child = info .child ,
6921+ .sentinel = .none ,
6922+ } });
6923+ },
6924+ else = > {},
6925+ },
6926+ else = > {},
6927+ };
6928+ }
6929+
6930+ opt_ptr_info = ptr_info ;
6931+ }
6932+
6933+ const info = opt_ptr_info .? ;
6934+ const pointee = info .elem_ty ;
6935+ if (pointee .isNoreturnType ()) {
6936+ return null ;
6937+ }
6938+ switch (pointee .data ) {
6939+ .array = > | array_info | {
6940+ if (array_info .elem_ty .isNoreturnType ()) {
6941+ return null ;
6942+ }
6943+ },
6944+ else = > {},
6945+ }
6946+
6947+ if (any_abi_aligned and info .flags .alignment != 0 ) {
6948+ // TODO: find minimum pointer alignment
6949+ return null ;
6950+ }
6951+
6952+ return .{
6953+ .data = .{
6954+ .pointer = .{
6955+ .elem_ty = try analyser .allocType (info .elem_ty ),
6956+ .sentinel = info .sentinel ,
6957+ .size = info .flags .size ,
6958+ .is_const = info .flags .is_const ,
6959+ },
6960+ },
6961+ .is_type_val = true ,
6962+ };
6963+ },
66866964
66876965 .func = > return null , // TODO
66886966
0 commit comments