@@ -6682,7 +6682,285 @@ fn resolvePeerTypesInner(analyser: *Analyser, peer_tys: []?Type) !?Type {
6682
6682
};
6683
6683
},
6684
6684
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
+ },
6686
6964
6687
6965
.func = > return null , // TODO
6688
6966
0 commit comments