@@ -6687,7 +6687,285 @@ fn resolvePeerTypesInner(analyser: *Analyser, peer_tys: []?Type) !?Type {
6687
6687
};
6688
6688
},
6689
6689
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
+ },
6691
6969
6692
6970
.func = > return null , // TODO
6693
6971
0 commit comments