authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-08-20 14:21:58-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-08-20 14:22:16-04:00
log3ee1b60edf8ee53ac7850aaee13c43f2db3a8661
tree9f0731920f495d9e117f056ae516c149da18c1da
parent53b18b079189cce355767ce4fde4fc586f0d3248

langref: add docs for peer type resolution

closes #1367

1 files changed, 136 insertions(+), 7 deletions(-)

doc/langref.html.in+136-7
...@@ -809,6 +809,8 @@ a += b</code></pre></td>...@@ -809,6 +809,8 @@ a += b</code></pre></td>
809 <td>Addition.809 <td>Addition.
810 <ul>810 <ul>
811 <li>Can cause {#link|overflow|Default Operations#} for integers.</li>811 <li>Can cause {#link|overflow|Default Operations#} for integers.</li>
812 <li>Invokes {#link|Peer Type Resolution#} for the operands.</li>
813 <li>See also {#link|@addWithOverflow#}.</li>
812 </ul>814 </ul>
813 </td>815 </td>
814 <td>816 <td>
...@@ -826,6 +828,7 @@ a +%= b</code></pre></td>...@@ -826,6 +828,7 @@ a +%= b</code></pre></td>
826 <td>Wrapping Addition.828 <td>Wrapping Addition.
827 <ul>829 <ul>
828 <li>Guaranteed to have twos-complement wrapping behavior.</li>830 <li>Guaranteed to have twos-complement wrapping behavior.</li>
831 <li>Invokes {#link|Peer Type Resolution#} for the operands.</li>
829 <li>See also {#link|@addWithOverflow#}.</li>832 <li>See also {#link|@addWithOverflow#}.</li>
830 </ul>833 </ul>
831 </td>834 </td>
...@@ -845,6 +848,8 @@ a -= b</code></pre></td>...@@ -845,6 +848,8 @@ a -= b</code></pre></td>
845 <td>Subtraction.848 <td>Subtraction.
846 <ul>849 <ul>
847 <li>Can cause {#link|overflow|Default Operations#} for integers.</li>850 <li>Can cause {#link|overflow|Default Operations#} for integers.</li>
851 <li>Invokes {#link|Peer Type Resolution#} for the operands.</li>
852 <li>See also {#link|@subWithOverflow#}.</li>
848 </ul>853 </ul>
849 </td>854 </td>
850 <td>855 <td>
...@@ -862,6 +867,8 @@ a -%= b</code></pre></td>...@@ -862,6 +867,8 @@ a -%= b</code></pre></td>
862 <td>Wrapping Subtraction.867 <td>Wrapping Subtraction.
863 <ul>868 <ul>
864 <li>Guaranteed to have twos-complement wrapping behavior.</li>869 <li>Guaranteed to have twos-complement wrapping behavior.</li>
870 <li>Invokes {#link|Peer Type Resolution#} for the operands.</li>
871 <li>See also {#link|@subWithOverflow#}.</li>
865 </ul>872 </ul>
866 </td>873 </td>
867 <td>874 <td>
...@@ -915,6 +922,8 @@ a *= b</code></pre></td>...@@ -915,6 +922,8 @@ a *= b</code></pre></td>
915 <td>Multiplication.922 <td>Multiplication.
916 <ul>923 <ul>
917 <li>Can cause {#link|overflow|Default Operations#} for integers.</li>924 <li>Can cause {#link|overflow|Default Operations#} for integers.</li>
925 <li>Invokes {#link|Peer Type Resolution#} for the operands.</li>
926 <li>See also {#link|@mulWithOverflow#}.</li>
918 </ul>927 </ul>
919 </td>928 </td>
920 <td>929 <td>
...@@ -932,6 +941,8 @@ a *%= b</code></pre></td>...@@ -932,6 +941,8 @@ a *%= b</code></pre></td>
932 <td>Wrapping Multiplication.941 <td>Wrapping Multiplication.
933 <ul>942 <ul>
934 <li>Guaranteed to have twos-complement wrapping behavior.</li>943 <li>Guaranteed to have twos-complement wrapping behavior.</li>
944 <li>Invokes {#link|Peer Type Resolution#} for the operands.</li>
945 <li>See also {#link|@mulWithOverflow#}.</li>
935 </ul>946 </ul>
936 </td>947 </td>
937 <td>948 <td>
...@@ -957,6 +968,7 @@ a /= b</code></pre></td>...@@ -957,6 +968,7 @@ a /= b</code></pre></td>
957 {#link|@divFloor#}, or968 {#link|@divFloor#}, or
958 {#link|@divExact#} instead of <code>/</code>.969 {#link|@divExact#} instead of <code>/</code>.
959 </li>970 </li>
971 <li>Invokes {#link|Peer Type Resolution#} for the operands.</li>
960 </ul>972 </ul>
961 </td>973 </td>
962 <td>974 <td>
...@@ -980,6 +992,7 @@ a %= b</code></pre></td>...@@ -980,6 +992,7 @@ a %= b</code></pre></td>
980 {#link|@rem#} or992 {#link|@rem#} or
981 {#link|@mod#} instead of <code>%</code>.993 {#link|@mod#} instead of <code>%</code>.
982 </li>994 </li>
995 <li>Invokes {#link|Peer Type Resolution#} for the operands.</li>
983 </ul>996 </ul>
984 </td>997 </td>
985 <td>998 <td>
...@@ -996,6 +1009,7 @@ a &lt;&lt;= b</code></pre></td>...@@ -996,6 +1009,7 @@ a &lt;&lt;= b</code></pre></td>
996 </td>1009 </td>
997 <td>Bit Shift Left.1010 <td>Bit Shift Left.
998 <ul>1011 <ul>
1012 <li><code>b</code> must be {#link|comptime-known|comptime#} or have a type with log2 number of bits as <code>a</code>.</li>
999 <li>See also {#link|@shlExact#}.</li>1013 <li>See also {#link|@shlExact#}.</li>
1000 <li>See also {#link|@shlWithOverflow#}.</li>1014 <li>See also {#link|@shlWithOverflow#}.</li>
1001 </ul>1015 </ul>
...@@ -1014,6 +1028,7 @@ a &gt;&gt;= b</code></pre></td>...@@ -1014,6 +1028,7 @@ a &gt;&gt;= b</code></pre></td>
1014 </td>1028 </td>
1015 <td>Bit Shift Right.1029 <td>Bit Shift Right.
1016 <ul>1030 <ul>
1031 <li><code>b</code> must be {#link|comptime-known|comptime#} or have a type with log2 number of bits as <code>a</code>.</li>
1017 <li>See also {#link|@shrExact#}.</li>1032 <li>See also {#link|@shrExact#}.</li>
1018 </ul>1033 </ul>
1019 </td>1034 </td>
...@@ -1030,6 +1045,9 @@ a &amp;= b</code></pre></td>...@@ -1030,6 +1045,9 @@ a &amp;= b</code></pre></td>
1030 </ul>1045 </ul>
1031 </td>1046 </td>
1032 <td>Bitwise AND.1047 <td>Bitwise AND.
1048 <ul>
1049 <li>Invokes {#link|Peer Type Resolution#} for the operands.</li>
1050 </ul>
1033 </td>1051 </td>
1034 <td>1052 <td>
1035 <pre><code class="zig">0b011 &amp; 0b101 == 0b001</code></pre>1053 <pre><code class="zig">0b011 &amp; 0b101 == 0b001</code></pre>
...@@ -1044,6 +1062,9 @@ a |= b</code></pre></td>...@@ -1044,6 +1062,9 @@ a |= b</code></pre></td>
1044 </ul>1062 </ul>
1045 </td>1063 </td>
1046 <td>Bitwise OR.1064 <td>Bitwise OR.
1065 <ul>
1066 <li>Invokes {#link|Peer Type Resolution#} for the operands.</li>
1067 </ul>
1047 </td>1068 </td>
1048 <td>1069 <td>
1049 <pre><code class="zig">0b010 | 0b100 == 0b110</code></pre>1070 <pre><code class="zig">0b010 | 0b100 == 0b110</code></pre>
...@@ -1058,6 +1079,9 @@ a ^= b</code></pre></td>...@@ -1058,6 +1079,9 @@ a ^= b</code></pre></td>
1058 </ul>1079 </ul>
1059 </td>1080 </td>
1060 <td>Bitwise XOR.1081 <td>Bitwise XOR.
1082 <ul>
1083 <li>Invokes {#link|Peer Type Resolution#} for the operands.</li>
1084 </ul>
1061 </td>1085 </td>
1062 <td>1086 <td>
1063 <pre><code class="zig">0b011 ^ 0b101 == 0b110</code></pre>1087 <pre><code class="zig">0b011 ^ 0b101 == 0b110</code></pre>
...@@ -1187,6 +1211,7 @@ unwrapped == 1234</code></pre>...@@ -1187,6 +1211,7 @@ unwrapped == 1234</code></pre>
1187 </td>1211 </td>
1188 <td>1212 <td>
1189 Returns <code>true</code> if a and b are equal, otherwise returns <code>false</code>.1213 Returns <code>true</code> if a and b are equal, otherwise returns <code>false</code>.
1214 Invokes {#link|Peer Type Resolution#} for the operands.
1190 </td>1215 </td>
1191 <td>1216 <td>
1192 <pre><code class="zig">(1 == 1) == true</code></pre>1217 <pre><code class="zig">(1 == 1) == true</code></pre>
...@@ -1219,6 +1244,7 @@ value == null</code></pre>...@@ -1219,6 +1244,7 @@ value == null</code></pre>
1219 </td>1244 </td>
1220 <td>1245 <td>
1221 Returns <code>false</code> if a and b are equal, otherwise returns <code>true</code>.1246 Returns <code>false</code> if a and b are equal, otherwise returns <code>true</code>.
1247 Invokes {#link|Peer Type Resolution#} for the operands.
1222 </td>1248 </td>
1223 <td>1249 <td>
1224 <pre><code class="zig">(1 != 1) == false</code></pre>1250 <pre><code class="zig">(1 != 1) == false</code></pre>
...@@ -1234,6 +1260,7 @@ value == null</code></pre>...@@ -1234,6 +1260,7 @@ value == null</code></pre>
1234 </td>1260 </td>
1235 <td>1261 <td>
1236 Returns <code>true</code> if a is greater than b, otherwise returns <code>false</code>.1262 Returns <code>true</code> if a is greater than b, otherwise returns <code>false</code>.
1263 Invokes {#link|Peer Type Resolution#} for the operands.
1237 </td>1264 </td>
1238 <td>1265 <td>
1239 <pre><code class="zig">(2 &gt; 1) == true</code></pre>1266 <pre><code class="zig">(2 &gt; 1) == true</code></pre>
...@@ -1249,6 +1276,7 @@ value == null</code></pre>...@@ -1249,6 +1276,7 @@ value == null</code></pre>
1249 </td>1276 </td>
1250 <td>1277 <td>
1251 Returns <code>true</code> if a is greater than or equal to b, otherwise returns <code>false</code>.1278 Returns <code>true</code> if a is greater than or equal to b, otherwise returns <code>false</code>.
1279 Invokes {#link|Peer Type Resolution#} for the operands.
1252 </td>1280 </td>
1253 <td>1281 <td>
1254 <pre><code class="zig">(2 &gt;= 1) == true</code></pre>1282 <pre><code class="zig">(2 &gt;= 1) == true</code></pre>
...@@ -1264,6 +1292,7 @@ value == null</code></pre>...@@ -1264,6 +1292,7 @@ value == null</code></pre>
1264 </td>1292 </td>
1265 <td>1293 <td>
1266 Returns <code>true</code> if a is less than b, otherwise returns <code>false</code>.1294 Returns <code>true</code> if a is less than b, otherwise returns <code>false</code>.
1295 Invokes {#link|Peer Type Resolution#} for the operands.
1267 </td>1296 </td>
1268 <td>1297 <td>
1269 <pre><code class="zig">(1 &lt; 2) == true</code></pre>1298 <pre><code class="zig">(1 &lt; 2) == true</code></pre>
...@@ -1279,6 +1308,7 @@ value == null</code></pre>...@@ -1279,6 +1308,7 @@ value == null</code></pre>
1279 </td>1308 </td>
1280 <td>1309 <td>
1281 Returns <code>true</code> if a is less than or equal to b, otherwise returns <code>false</code>.1310 Returns <code>true</code> if a is less than or equal to b, otherwise returns <code>false</code>.
1311 Invokes {#link|Peer Type Resolution#} for the operands.
1282 </td>1312 </td>
1283 <td>1313 <td>
1284 <pre><code class="zig">(1 &lt;= 2) == true</code></pre>1314 <pre><code class="zig">(1 &lt;= 2) == true</code></pre>
...@@ -3878,7 +3908,106 @@ test "float widening" {...@@ -3878,7 +3908,106 @@ test "float widening" {
3878 {#header_close#}3908 {#header_close#}
38793909
3880 {#header_open|Peer Type Resolution#}3910 {#header_open|Peer Type Resolution#}
3881 <p>TODO</p>3911 <p>Peer Type Resolution occurs in these places:</p>
3912 <ul>
3913 <li>{#link|switch#} expressions</li>
3914 <li>{#link|if#} expressions</li>
3915 <li>{#link|while#} expressions</li>
3916 <li>{#link|for#} expressions</li>
3917 <li>Multiple break statements in a block</li>
3918 <li>Some {#link|binary operations|Table of Operators#}</li>
3919 </ul>
3920 <p>
3921 This kind of type resolution chooses a type that all peer types can implicitly cast into. Here are
3922 some examples:
3923 </p>
3924 {#code_begin|test#}
3925const std = @import("std");
3926const assert = std.debug.assert;
3927const mem = std.mem;
3928
3929test "peer resolve int widening" {
3930 var a: i8 = 12;
3931 var b: i16 = 34;
3932 var c = a + b;
3933 assert(c == 46);
3934 assert(@typeOf(c) == i16);
3935}
3936
3937test "peer resolve arrays of different size to const slice" {
3938 assert(mem.eql(u8, boolToStr(true), "true"));
3939 assert(mem.eql(u8, boolToStr(false), "false"));
3940 comptime assert(mem.eql(u8, boolToStr(true), "true"));
3941 comptime assert(mem.eql(u8, boolToStr(false), "false"));
3942}
3943fn boolToStr(b: bool) []const u8 {
3944 return if (b) "true" else "false";
3945}
3946
3947test "peer resolve array and const slice" {
3948 testPeerResolveArrayConstSlice(true);
3949 comptime testPeerResolveArrayConstSlice(true);
3950}
3951fn testPeerResolveArrayConstSlice(b: bool) void {
3952 const value1 = if (b) "aoeu" else ([]const u8)("zz");
3953 const value2 = if (b) ([]const u8)("zz") else "aoeu";
3954 assert(mem.eql(u8, value1, "aoeu"));
3955 assert(mem.eql(u8, value2, "zz"));
3956}
3957
3958test "peer type resolution: ?T and T" {
3959 assert(peerTypeTAndOptionalT(true, false).? == 0);
3960 assert(peerTypeTAndOptionalT(false, false).? == 3);
3961 comptime {
3962 assert(peerTypeTAndOptionalT(true, false).? == 0);
3963 assert(peerTypeTAndOptionalT(false, false).? == 3);
3964 }
3965}
3966fn peerTypeTAndOptionalT(c: bool, b: bool) ?usize {
3967 if (c) {
3968 return if (b) null else usize(0);
3969 }
3970
3971 return usize(3);
3972}
3973
3974test "peer type resolution: [0]u8 and []const u8" {
3975 assert(peerTypeEmptyArrayAndSlice(true, "hi").len == 0);
3976 assert(peerTypeEmptyArrayAndSlice(false, "hi").len == 1);
3977 comptime {
3978 assert(peerTypeEmptyArrayAndSlice(true, "hi").len == 0);
3979 assert(peerTypeEmptyArrayAndSlice(false, "hi").len == 1);
3980 }
3981}
3982fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 {
3983 if (a) {
3984 return []const u8{};
3985 }
3986
3987 return slice[0..1];
3988}
3989test "peer type resolution: [0]u8, []const u8, and error![]u8" {
3990 {
3991 var data = "hi";
3992 const slice = data[0..];
3993 assert((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
3994 assert((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
3995 }
3996 comptime {
3997 var data = "hi";
3998 const slice = data[0..];
3999 assert((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
4000 assert((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
4001 }
4002}
4003fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) error![]u8 {
4004 if (a) {
4005 return []u8{};
4006 }
4007
4008 return slice[0..1];
4009}
4010 {#code_end#}
3882 {#header_close#}4011 {#header_close#}
3883 {#header_close#}4012 {#header_close#}
38844013
...@@ -4706,10 +4835,7 @@ async fn testSuspendBlock() void {...@@ -4706,10 +4835,7 @@ async fn testSuspendBlock() void {
4706 <p>4835 <p>
4707 {#link|Await#} counts as a suspend point.4836 {#link|Await#} counts as a suspend point.
4708 </p>4837 </p>
4709 {#header_open|Breaking from Suspend Blocks#}4838 {#header_open|Resuming from Suspend Blocks#}
4710 <p>
4711 Suspend blocks support labeled break, just like {#link|while#} and {#link|for#}.
4712 </p>
4713 <p>4839 <p>
4714 Upon entering a <code>suspend</code> block, the coroutine is already considered4840 Upon entering a <code>suspend</code> block, the coroutine is already considered
4715 suspended, and can be resumed. For example, if you started another kernel thread,4841 suspended, and can be resumed. For example, if you started another kernel thread,
...@@ -4742,6 +4868,9 @@ async fn testResumeFromSuspend(my_result: *i32) void {...@@ -4742,6 +4868,9 @@ async fn testResumeFromSuspend(my_result: *i32) void {
4742 my_result.* += 1;4868 my_result.* += 1;
4743}4869}
4744 {#code_end#}4870 {#code_end#}
4871 <p>
4872 This is guaranteed to be a tail call, and therefore will not cause a new stack frame.
4873 </p>
4745 {#header_close#}4874 {#header_close#}
4746 {#header_close#}4875 {#header_close#}
4747 {#header_open|Await#}4876 {#header_open|Await#}
...@@ -7544,8 +7673,8 @@ hljs.registerLanguage("zig", function(t) {...@@ -7544,8 +7673,8 @@ hljs.registerLanguage("zig", function(t) {
7544 },7673 },
7545 a = t.IR + "\\s*\\(",7674 a = t.IR + "\\s*\\(",
7546 c = {7675 c = {
7547 keyword: "const align var extern stdcallcc nakedcc volatile export pub noalias inline struct packed enum union break return try catch test continue unreachable comptime and or asm defer errdefer if else switch while for fn use bool f32 f64 void type noreturn error i8 u8 i16 u16 i32 u32 i64 u64 isize usize i8w u8w i16w i32w u32w i64w u64w isizew usizew c_short c_ushort c_int c_uint c_long c_ulong c_longlong c_ulonglong resume cancel await async orelse",7676 keyword: "const align var extern stdcallcc nakedcc volatile export pub noalias inline struct packed enum union break return try catch test continue unreachable comptime and or asm defer errdefer if else switch while for fn use bool f32 f64 void type noreturn error i8 u8 i16 u16 i32 u32 i64 u64 isize usize i8w u8w i16w i32w u32w i64w u64w isizew usizew c_short c_ushort c_int c_uint c_long c_ulong c_longlong c_ulonglong resume suspend cancel await async orelse",
7548 built_in: "atomicLoad breakpoint returnAddress frameAddress fieldParentPtr setFloatMode IntType OpaqueType compileError compileLog setCold setRuntimeSafety setEvalBranchQuota offsetOf memcpy inlineCall setGlobalLinkage divTrunc divFloor enumTagName intToPtr ptrToInt panic ptrCast intCast floatCast intToFloat floatToInt boolToInt bytesToSlice sliceToBytes errSetCast bitCast rem mod memset sizeOf alignOf alignCast maxValue minValue memberCount memberName memberType typeOf addWithOverflow subWithOverflow mulWithOverflow shlWithOverflow shlExact shrExact cInclude cDefine cUndef ctz clz popCount import cImport errorName embedFile cmpxchgStrong cmpxchgWeak fence divExact truncate atomicRmw sqrt field typeInfo typeName newStackCall errorToInt intToError enumToInt intToEnum",7677 built_in: "atomicLoad breakpoint returnAddress frameAddress fieldParentPtr setFloatMode IntType OpaqueType compileError compileLog setCold setRuntimeSafety setEvalBranchQuota offsetOf memcpy inlineCall setGlobalLinkage divTrunc divFloor enumTagName intToPtr ptrToInt panic ptrCast intCast floatCast intToFloat floatToInt boolToInt bytesToSlice sliceToBytes errSetCast bitCast rem mod memset sizeOf alignOf alignCast maxValue minValue memberCount memberName memberType typeOf addWithOverflow subWithOverflow mulWithOverflow shlWithOverflow shlExact shrExact cInclude cDefine cUndef ctz clz popCount import cImport errorName embedFile cmpxchgStrong cmpxchgWeak fence divExact truncate atomicRmw sqrt field typeInfo typeName newStackCall errorToInt intToError enumToInt intToEnum handle",
7549 literal: "true false null undefined"7678 literal: "true false null undefined"
7550 },7679 },
7551 n = [e, t.CLCM, t.CBCM, s, r];7680 n = [e, t.CLCM, t.CBCM, s, r];