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