@@ -6776,7 +6776,284 @@ fn resolvePeerTypesInner(analyser: *Analyser, peer_tys: []?Type) !?Type {
6776
6776
};
6777
6777
},
6778
6778
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
+ },
6780
7057
6781
7058
.func = > return null , // TODO
6782
7059
0 commit comments