Skip to content

Commit 354e906

Browse files
committed
Fixes in Expressions, part I
1 parent 8a3239c commit 354e906

File tree

2 files changed

+96
-43
lines changed

2 files changed

+96
-43
lines changed

docs/src/md/kotlin.core/expressions.md

Lines changed: 92 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ As all expressions are valid [statements][Statements], standalone expressions ma
1515
An expression is used as an expression, if it is encountered in any position where a statement is not allowed, for example, as an operand to an operator or as an immediate argument for a function call.
1616
An expression is used as a statement if it is encountered in any position where a statement is allowed.
1717

18-
Some expressions are only allowed to be used as statements, if certain restrictions are met; this may affect the semantics, the compile-time type information or/and the safety of these expressions.
18+
Some expressions are allowed to be used as statements, only if certain restrictions are met; this may affect the semantics, the compile-time type information or/and the safety of these expressions.
1919

2020
### Constant literals
2121

@@ -75,12 +75,12 @@ Any of the decimal, hexadecimal or binary literals may be suffixed by the long l
7575
An integer literal with the long literal mark has type `kotlin.Long`.
7676
A literal without the mark has a special [integer literal type][Integer literal types] dependent on the value of the literal:
7777

78-
- If the value is greater than maximum `kotlin.Long` value (see [built-in integer types][Built-in integer types]), it is an illegal integer literal and a compiler error;
78+
- If the value is greater than maximum `kotlin.Long` value (see [built-in integer types][Built-in integer types]), it is an illegal integer literal and should be a compile-time error;
7979
- Otherwise, if the value is greater than maximum `kotlin.Int` value (see [built-in integer types][Built-in integer types]), it has type `kotlin.Long`;
80-
- Otherwise, it has an integer literal type containing all the built-in integer types that are guaranteed to be able to represent this value.
80+
- Otherwise, it has an integer literal type containing all the built-in integer types guaranteed to be able to represent this value.
8181

82-
> Note: for example, integer literal `0x01` has value $1$ and therefore has type $\LTS(\mathtt{kotlin.Byte}, \mathtt{kotlin.Short}, \mathtt{kotlin.Int}, \mathtt{kotlin.Long})$.
83-
> Integer literal `70000` has value $70000$, which is not representable using types `kotlin.Byte` and `kotlin.Short` and therefore has type $\LTS(\mathtt{kotlin.Int}, \mathtt{kotlin.Long})$.
82+
> Example: integer literal `0x01` has value $1$ and therefore has type $\LTS(\Byte, \Short, \Int, \Long)$.
83+
> Integer literal `70000` has value $70000$, which is not representable using types `kotlin.Byte` and `kotlin.Short` and therefore has type $\LTS(\Int, \Long)$.
8484
8585
#### Real literals
8686

@@ -187,8 +187,6 @@ All other situations mean that an exception is going to be propagated up the cal
187187
188188
The type of the try-expression is the [least upper bound][Least upper bound] of the types of the last expressions of the try body and the last expressions of all the catch blocks.
189189

190-
> Note: in some cases, the least upper bound is handled as described [here][The relations on types as constraints], from the point of view of type constraint system.
191-
192190
> Note: these rules mean the try-expression always may be used as an expression, as it always has a corresponding result value.
193191
194192
### Conditional expression
@@ -207,40 +205,40 @@ If the condition evaluates to `true`, the first branch (the *true branch*) is ev
207205
The value of the resulting expression is the same as the value of the chosen branch.
208206
209207
The type of the resulting expression is the [least upper bound][Least upper bound] of the types of two branches, if both branches are present.
210-
If either of the branches are omitted, the resulting conditional expression has type [`kotlin.Unit`][`kotlin.Unit`] and may used only as a statement.
211-
212-
Let's illustrate it with some examples:
208+
If either of the branches are omitted, the resulting conditional expression has type [`kotlin.Unit`][`kotlin.Unit`] and may be used only as a statement.
213209
214-
```kotlin
215-
// x has type kotlin.Int and value 1
216-
val x = if(true) 1 else 2
217-
// illegal, if expression without false branch cannot be used as an expression
218-
val y = if(true) 1
219-
```
210+
> Example:
211+
>
212+
> ```kotlin
213+
> // x has type kotlin.Int and value 1
214+
> val x = if (true) 1 else 2
215+
> // illegal, as if expression without false branch
216+
> // cannot be used as an expression
217+
> val y = if (true) 1
218+
> ```
220219
221-
The type of the condition expression must be a subtype of `kotlin.Boolean`, otherwise it is an error.
220+
The type of the condition expression must be a subtype of `kotlin.Boolean`, otherwise it is a compile-time error.
222221
223222
> Note: when used as expressions, conditional expressions are special w.r.t. operator precedence: they have the highest priority (the same as for all primary expressions) when placed on the right side of any binary expression, but when placed on the left side, they have the lowest priority.
224223
> For details, see Kotlin [grammar][Syntax grammar].
225224
>
226-
> For example:
225+
> Example:
227226
>
228227
> ```kotlin
229-
> x = if(true) 1 else 2
228+
> x = if (true) 1 else 2
230229
> ```
231230
> is the same as
232231
> ```kotlin
233-
> x = (if(true) 1 else 2)
232+
> x = (if (true) 1 else 2)
234233
> ```
235-
> while
234+
> At the same time
236235
> ```kotlin
237-
> if(true) x = 1 else x = 2
236+
> if (true) x = 1 else x = 2
238237
> ```
239238
> is the same as
240239
> ```kotlin
241-
> if(true) (x = 1) else (x = 2)
240+
> if (true) (x = 1) else (x = 2)
242241
> ```
243-
>
244242
245243
### When expression
246244
@@ -256,7 +254,7 @@ The type of the condition expression must be a subtype of `kotlin.Boolean`, othe
256254
:::
257255
258256
*When expression* is similar to a [conditional expression][Conditional expression] in that it allows one of several different [control structure bodies][Code blocks] (*cases*) to be evaluated, depending on some boolean conditions.
259-
The key difference is exactly that a when expressions may include several different conditions with their corresponding control structure bodies.
257+
The key difference is that a when expressions may include *several* different conditions with their corresponding control structure bodies.
260258
When expression has two different forms: with bound value and without it.
261259
262260
**When expression without bound value** (the form where the expression enclosed in parentheses after the `when` keyword is absent) evaluates one of the different CSBs based on its condition from the *when entry*.
@@ -268,31 +266,79 @@ All remaining conditions and expressions are not evaluated.
268266
The `else` condition is a special condition which evaluates to `true` if none of the branches above it evaluated to `true`.
269267
The `else` condition **must** also be in the last when entry of when expression, otherwise it is a compile-time error.
270268
271-
> Note: informally, you can always replace the `else` condition with an always-`true` condition (e.g., boolean literal `true`) with no change to the resulting semantics.
269+
> Note: informally, you can always replace the `else` condition with an always-`true` condition (e.g., boolean literal `true`) with no changes to the result of when expression.
272270
273-
**When expression with bound value** (the form where the expression enclosed in parentheses after the `when` keyword is present) are similar to the form without bound value, but use a different syntax for conditions.
274-
In fact, it supports three different condition forms:
271+
**When expression with bound value** (the form where the expression enclosed in parentheses after the `when` keyword is present) is similar to the form without bound value, but uses a different syntax and semantics for conditions.
272+
In fact, it supports four different condition forms:
275273
276274
- *Type test condition*: [type checking operator][Type-checking expression] followed by a type (`is T` or `!is T`).
277275
The resulting condition is a [type check expression][Type-checking expression] of the form `boundValue is T` or `boundValue !is T`.
278276
- *Contains test condition*: [containment operator][Containment-checking expression] followed by an expression (`in Expr` or `!in Expr`).
279277
The resulting condition is a [containment check expression][Containment-checking expression] of the form `boundValue in Expr` or `boundValue !in Expr`.
280-
- *Any other applicable expression* (`Expr`) besides the following.
281-
+ [Simple continue expression][Continue expression]
282-
+ [Simple break expression][Break expression]
283-
278+
- *Any other applicable expression* (`Expr`)
284279
The resulting condition is an [equality check][Equality expressions] of the form `boundValue == Expr`.
285280
- The `else` condition, which is a special condition which evaluates to `true` if none of the branches above it evaluated to `true`.
286281
The `else` condition **must** also be in the last when entry of when expression, otherwise it is a compile-time error.
287282
288-
TODO([Kotlin 1.3+] break and continue in when)
289-
290283
> Note: the rule for "any other expression" means that if a when expression with bound value contains a boolean condition, this condition is **checked for equality** with the bound value, instead of being used directly for when entry selection.
291284
292-
TODO(Examples)
285+
> Note: in Kotlin version 1.3 and earlier, simple (unlabeled) `break` and `continue` expressions were disallowed in when expressions.
286+
287+
The type of the resulting when expression is the [least upper bound][Least upper bound] of the types of all its entries.
288+
If when expression is not [exhaustive][Exhaustive when expressions], it has type [`kotlin.Unit`][`kotlin.Unit`] and may be used only as a statement.
293289
294-
The type of the resulting expression is the [least upper bound][Least upper bound] of the types of all its entries.
295-
If the when expression is not [exhaustive][Exhaustive when expressions], it has type [`kotlin.Unit`][`kotlin.Unit`] and may only be used as a statement.
290+
> Examples:
291+
>
292+
> ```kotlin
293+
> val a = 42
294+
> val b = -1
295+
>
296+
> when {
297+
> a == b -> {}
298+
> a != b -> {}
299+
> }
300+
>
301+
> // Error, as it is a non-exhaustive when expression
302+
> val c = when {
303+
> a == b -> {}
304+
> a != b -> {}
305+
> }
306+
>
307+
> val d = when {
308+
> a == b -> {}
309+
> a != b -> {}
310+
> else -> {}
311+
> }
312+
>
313+
> when {
314+
> a == b || a != b -> {}
315+
> 42 > 0 -> {}
316+
> }
317+
> ```
318+
>
319+
> ```kotlin
320+
> val a = 42
321+
> val b = -1
322+
>
323+
> val l = (1..10).toList()
324+
>
325+
> when (a) {
326+
> is Int, !is Int -> {}
327+
> in l, !in l -> {}
328+
> }
329+
>
330+
> // Error, as it is a non-exhaustive when expression
331+
> val c = when (a) {
332+
> is Int, !is Int -> {}
333+
> in l, !in l -> {}
334+
> }
335+
>
336+
> val d = when (a) {
337+
> is Int, !is Int -> {}
338+
> in l, !in l -> {}
339+
> else -> {}
340+
> }
341+
> ```
296342
297343
#### Exhaustive when expressions
298344
@@ -309,23 +355,26 @@ A when expression is called **_exhaustive_** if at least one of the following is
309355
- The bound expression is of an [`enum class`][Enum class declaration] type and all its enumerated values are checked for equality using constant expression;
310356
- The bound expression is of a [nullable type][Nullable types] $T?$ and one of the cases above is met for its non-nullable counterpart $T$ together with another condition which checks the bound value for equality with `null`.
311357
312-
For object types, the type test condition may be replaced with equality check with the object value:
358+
For object types, the type test condition may be replaced with equality check with the object value.
359+
360+
> Note: if one were to override `equals` for an object type incorrectly (i.e., so that an object is not equal to itself), it would break the exhaustiveness check.
361+
> Such situations are considered to have undefined behaviour.
313362
314363
```kotlin
315364
sealed class Base
316-
class Derived1(): Base()
317-
object Derived2(): Base
365+
class Derived1: Base()
366+
object Derived2: Base()
318367
319-
...
320368
val b: Base = ...
321-
... = when(b) {
369+
370+
val c = when(b) {
322371
is Derived1 -> ...
323372
Derived2 -> ...
324373
// no else needed here
325374
}
326375
```
327376
328-
> Note: informally, an exhaustive when expression is guaranteed to evaluate one of its CSBs regardless of the specific when conditions.
377+
> Informally: an exhaustive when expression is guaranteed to evaluate one of its CSBs regardless of the specific when conditions.
329378
330379
### Logical disjunction expression
331380

docs/src/md/kotlin.core/type-system.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1014,6 +1014,8 @@ This normalization procedure, if finite, creates a *canonical* representation of
10141014
- if $A = (L_A..U_A)$ and $B = (L_B..U_B)$, $\LUB(A, B) = (\LUB(L_A, L_B)..\LUB(U_A, U_B))$
10151015
- if $A = (L_A..U_A)$ and $B$ is not flexible, $\LUB(A, B) = (\LUB(L_A, B)..\LUB(U_A, B))$
10161016
1017+
> Important: in some cases, the least upper bound is handled as described [here][The relations on types as constraints], from the point of view of type constraint system.
1018+
10171019
TODO(actual algorithm for computing LUB)
10181020
10191021
TODO(LUB for 3+ types)
@@ -1075,6 +1077,8 @@ This normalization procedure, if finite, creates a *canonical* representation of
10751077
- if $A = (L_A..U_A)$ and $B = (L_B..U_B)$, $\GLB(A, B) = (\GLB(L_A, L_B)..\GLB(U_A, U_B))$
10761078
- if $A = (L_A..U_A)$ and $B$ is not flexible, $\GLB(A, B) = (\GLB(L_A, B)..\GLB(U_A, B))$
10771079
1080+
> Important: in some cases, the greatest lower bound is handled as described [here][The relations on types as constraints], from the point of view of type constraint system.
1081+
10781082
TODO(actual algorithm for computing GLB)
10791083
10801084
TODO(GLB for 3+ types)

0 commit comments

Comments
 (0)