Add NamingProvider::get_canon_{type,fun}_name
[hiphop-php.git] / hphp / hack / doc / async / await-as-an-expression-spec.md
blobf1293599dcb4a0231e011033d4d840b287a7a337
1 For a summary, see the [await-as-an-expression](https://docs.hhvm.com/hack/asynchronous-operations/await-as-an-expression) docs.
3 The guiding principle of “unconditionally consumed with the statement” is to prevent computation from being thrown away. Since we could run the awaits before the statement, if they turn out to not be consumed, it will result in waste. We intentionally ignore the possibility of Exceptions being thrown for the definition of “conditional”.
5 For the position to be considered “unconditionally consumed” we require all parents of the await expression until the closest statement pass this check.
7 Valid positions:
9 * ConditionalExpression: Only first position is allowed
10     * `(await $yes) ? (await $no) : (await $no)`
11 * FunctionCallExpression: Any position is allowed as long as receive isn't conditionally executed. Only the receiver is allowed if the receiver is conditional.
12     * `(await $yes)->foo(await $yes, await $yes)`
13     * `(await $yes)?->foo(await $no, await $no)`
14 * SafeMemberSelectionExpression: Only the object is allowed.
15     * `(await $yes)?->(await $no)`
16 * Allow any valid expression position of all of the following expressions:
17     * CastExpression: `(<token>)(await $yes)`
18     * MemberSelectionExpression: `(await $yes)->(await $yes)`
19     * ScopeResolutionExpression: `(await $yes)::(await $yes)`
20     * IsExpression: `(await $yes) is Int`
21     * AsExpression: `(await $yes) as Int`
22     * NullableAsExpression: `(await $yes) ?as Int`
23     * EmptyExpression: `empty(await $yes)`
24     * IssetExpression: `isset(await $yes)`
25     * ParenthesizedExpression: `(await $yes)`
26     * BracedExpression: `{await $yes}`
27     * EmbeddedBracedExpression: `“{await $yes}"`
28     * CollectionLiteralExpression: `Map { await $yes => await $yes }` or `Vector { await $yes }`
29     * ObjectCreationExpression, ConstructorCall: `new (await $yes)(await $yes)`
30     * ShapeExpression, FieldInitializer: `shape('key'`` => await $yes)`
31     * TupleExpression: `tuple(await $yes, await $yes)`
32     * ArrayCreationExpression: `array(await $yes => await $yes)`
33     * ArrayIntrinsicExpression: `[await $yes => await $yes]`
34     * DarrayIntrinsicExpression: `darray[await $yes => await $yes]`
35     * VarrayIntrinsicExpression: `varray[await $yes]`
36     * DictionaryIntrinsicExpression: `dict[await $yes => await $yes]`
37     * KeysetIntrinsicExpression: `keyset[await $yes]`
38     * VectorIntrinsicExpression: `vec[await $yes]`
39     * ElementInitializer: `await $yes => await $yes`
40     * SubscriptExpression: `(await $yes)[await $yes]`
41     * EmbeddedSubscriptExpression: `{(await $yes)[await $yes]}`
42     * YieldExpression: `yield (await $yes)`
43     * SyntaxList, ListItem: `await $yes, await $yes`
44 * PrefixUnaryExpression | PostfixUnaryExpression | DecoratedExpression
45     * `!`: `!(await $yes)`
46     * `~`: `~(await $yes)`
47     * `+`: `+(await $yes)`
48     * `-`: `-(await $yes)`
49     * `@`: `@(await $yes)`
50     * `clone`: `clone (await $yes)`
51     * `print`: `print (await $yes)`
52 * BinaryExpression
53     * Binary operators that only allow await in the left position:
54         * `AND`: `(await $yes) AND (await $no)`
55         * `OR`: `(await $yes) OR (await $no)`
56         * `||`: `(await $yes) || (await $no)`
57         * `&&`: `(await $yes) && (await $no)`
58         * `?:`: `(await $yes) ?: (await $no)`
59         * `??`: `(await $yes) ?? (await $no)`
60     * Binary operators that do assignment:
61         * `=`: `(await $no) = (await $yes)`
62         * `|=`: `(await $no) |= (await $yes)`
63         * `+=`: `(await $no) += (await $yes)`
64         * `*=`: `(await $no) *= (await $yes)`
65         * `**=`: `(await $no) **= (await $yes)`
66         * `/=`: `(await $no) /= (await $yes)`
67         * `.=`: `(await $no) .= (await $yes)`
68         * `-=`: `(await $no) -= (await $yes)`
69         * `%=`: `(await $no) %= (await $yes)`
70         * `^=`: `(await $no) ^= (await $yes)`
71         * `&=`: `(await $no) &= (await $yes)`
72         * `<<=`: `(await $no) <<= (await $yes)`
73         * `>>=`: `(await $no) >>= (await $yes)`
74     * Null Coalescing Assignment is both, so it doesn't allow either:
75         * `??=`: `(await $no) ??= (await $no)`
76     * Binary operators that allow await in both positions:
77         * `+`: `(await $yes) + (await $yes)`
78         * `-`: `(await $yes) - (await $yes)`
79         * `*`: `(await $yes) * (await $yes)`
80         * `/`: `(await $yes) / (await $yes)`
81         * `**`: `(await $yes) ** (await $yes)`
82         * `===`: `(await $yes) === (await $yes)`
83         * `<`: `(await $yes) < (await $yes)`
84         * `>`: `(await $yes) > (await $yes)`
85         * `==`: `(await $yes) == (await $yes)`
86         * `%`: `(await $yes) % (await $yes)`
87         * `.`: `(await $yes) . (await $yes)`
88         * `!=`: `(await $yes) != (await $yes)`
89         * `<>`: `(await $yes) <> (await $yes)`
90         * `!==`: `(await $yes) !== (await $yes)`
91         * `<=`: `(await $yes) <= (await $yes)`
92         * `<=>`: `(await $yes) <=> (await $yes)`
93         * `>=`: `(await $yes) >= (await $yes)`
94         * `&`: `(await $yes) & (await $yes)`
95         * `|`: `(await $yes) | (await $yes)`
96         * `<<`: `(await $yes) << (await $yes)`
97         * `>>`: `(await $yes) >> (await $yes)`
98         * `^`: `(await $yes) ^ (await $yes)`
99 * Pipe BinaryExpression (`|>`): Since we disallow dependent awaits in a single statement (or concurrent block), we need to disallow awaits in pipe operators that de-sugar to nested awaits. The simple rule to disallow this: we treat the `$$` as an `await` if the left side contains an `await`.
100     * Disallowed: `(await $x) |> (await $$)` de-sugars into `(await (await $x))`
101     * Allowed: `$x |> (await $$)` de-sugars into `(await $x)`
102     * Allowed: `(await $x) |> f($$)` de-sugars into `f(await $x)`
103     * Allowed: `(await $x) |> (f($$) + await $y)` de-sugars into `f(await $x) + await $y`
104     * Disallowed: `(await $x) |> f($$) |> await g($$)` de-sugars into `await g(f(await $x))`
105     * Disallowed: `(await $x) |> $y ?? $$` de-sugars into `$y ?? (``await $x)`
106 * Statement position:
107     * ExpressionStatement: `await $yes;`
108     * ReturnStatement: `return await $yes;`
109     * UnsetStatement: `unset($a[await $yes]);`
110     * EchoStatement: `echo (await $yes);`
111     * PrintStatement: `print (await $yes);`
112     * IfStatement: `if (await $yes) { await $yes_but_new_statement; }`
113     * ThrowStatement: `throw (await $yes);`
114     * SwitchStatement: `switch (await $yes) { ... }`
115     * ForeachStatement: `foreach ((await $yes) [await] as ... ) { ... }`
116     * ForStatement: `for (await $yes; await $no; await $no) { ... }`
117 * Disallowed in all other unmentioned positions.