@@ -6735,7 +6735,284 @@ fn resolvePeerTypesInner(analyser: *Analyser, peer_tys: []?Type) !?Type {
6735
6735
};
6736
6736
},
6737
6737
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
+ },
6739
7016
6740
7017
.func = > return null , // TODO
6741
7018
0 commit comments