Skip to content

Context receivers #87

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 12 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 34 additions & 1 deletion docs/src/md/kotlin.core/declarations.md
Original file line number Diff line number Diff line change
Expand Up @@ -1045,7 +1045,7 @@ This parameter is not named and must always be supplied (either explicitly or im
Calling such a function is special because the receiver parameter is not supplied as an argument of the call, but as the [_receiver_][Receivers] of the call, be it implicit or explicit.
This parameter is available inside the scope of the function as the implicit receiver or `this`-expression, while nested scopes may introduce additional receivers that take precedence over this one.
See [the receiver section][Receivers] for details.
This receiver is also available (as usual) in nested scope using labeled `this` syntax using the name of the declared function as the label.
This receiver is also available (as usual) in nested scope using labeled `this` syntax using the name of the declared function or the receiver type classifier name as the label.

For more information on how a particular receiver for each call is chosen, please refer to the [overloading section][Overload resolution].

Expand All @@ -1068,6 +1068,22 @@ class Bar {
}
```

#### Contextual function declaration

A _contextual function declaration_ further extends the extension function declaration syntax with a number of additional special function parameters, the _context receiver parameters_, provided in the form of their respectable types using the special `context` soft keyword.
As with extension receivers, these parameters are not named an must always be supplied.
Unlike extension receivers, context receivers may only be provided implicitly at call site.
See [the receiver section][Receivers] for details.
All context receiver parameters are available inside the scope of the function as implicit receivers and cannot be referenced using unlabeled `this`-expression syntax.
They are, however, available using labeled `this` syntax using the name of the receiver type classifier as the label.

Context receiver types of a particular function must all be different from each other and no pair of these types may be in a [subtyping relation][Subtyping].
They may, however, contain a type that is also used as the extension receiver of the function or a type in a subtyping relation with it.

For more information on how a particular receiver for each call is chosen, please refer to the [overloading section][Overload resolution].

TODO: Examples

#### Inlining

A function may be declared `inline` using a special `inline` modifier.
Expand Down Expand Up @@ -1486,6 +1502,23 @@ For all other purposes, extension properties are not different from non-extensio
> }
> ```

#### Contextual property declaration

A _contextual property declaration_ further extends the extension property declaration syntax with a number of additional special function parameters, the _context receiver parameters_, very much alike a [contextual function declaration], supplied using the `context` soft keyword.
As with extension receivers, these parameters are not named and must always be supplied.
Unlike extension receivers, these must always be provided implicitly at call site.
See [the receiver section][Receivers] for details.

A contextual property declaration may be extension or non-extension, but follows the same limitations as extension properties described in the [corresponding section][Extension property declaration].

All context receiver parameters can be accessed inside getter and setter scopes of the property as the implicit receiver or `this`.
It may also be accessed inside nested scopes using [labeled `this` syntax][This-expressions] using the type of the context receiver as the label.

Same as [contextual function declarations][contextual function declaration], context receiver types of a particular propery must all be different from each other and no pair of these types may be in a [subtyping relation][Subtyping].
They may, however, contain a type that is also used as the extension receiver of the function or a type in a subtyping relation with it.

TODO: Examples

#### Property initialization

All non-abstract properties must be definitely initialized before their first use.
Expand Down
97 changes: 69 additions & 28 deletions docs/src/md/kotlin.core/overload-resolution.md

Large diffs are not rendered by default.

36 changes: 31 additions & 5 deletions docs/src/md/kotlin.core/type-system.md
Original file line number Diff line number Diff line change
Expand Up @@ -827,14 +827,39 @@ $$\FTR(\RT, A_1, \ldots, A_n) \rightarrow R \equiv \FT(\RT, A_1, \ldots, A_n) \r

i.e., receiver is considered as yet another argument of its function type.

> Note: this means that, for example, these two types are equivalent w.r.t. type system
In addition to extension receiver, a function type (suspending or not) can additionally specify a number of **context receivers**.

A function type with context receivers

$$\mathtt{context}(T_1, \ldots, T_m)\quad\FTR(\RT, A_1, \ldots, A_n) \rightarrow R$$

or

$$\mathtt{context}(T_1, \ldots, T_m)\quad\FT(A_1, \ldots, A_n) \rightarrow R$$

consists of a number of **context receiver types** $T_1, \ldots, T_m$ and the base function type $\FTR$ or $\FT$ which may or may not have an extension receiver.
All context receivers can be considered as additional arguments to the corresponding function type, meaning that

$$
\begin{aligned}
&\mathtt{context}(T_1, \ldots, T_m)\quad\FTR(\RT, A_1, \ldots, A_n) \rightarrow R \\
&\quad{}\quad{}\quad{}\quad{}\equiv \FT(T_1, \ldots, T_m, \RT, A_1, \ldots, A_n, R) \\
&\mathtt{context}(T_1, \ldots, T_m)\quad\FT(A_1, \ldots, A_n) \rightarrow R \\
&\quad{}\quad{}\quad{}\quad{}\equiv \FT(T_1, \ldots, T_m, A_1, \ldots, A_n, R)
\end{aligned}
$$

> Note: this means that, for example, all these types are equivalent w.r.t. type system
>
> * `Int.(Int) -> String`
> * `(Int, Int) -> String`
> * `Int.(Double) -> String`
> * `(Int, Double) -> String`
> * `context(Int) (Double) -> String`
> * `context(Int) Double.() -> String`
> * `context(Int, Double) () -> String`
>
> However, these two types are **not** equivalent w.r.t. [overload resolution][Overload resolution], as it distinguishes between functions with and without receiver.
> However, these types are **not** equivalent w.r.t. [overload resolution][Overload resolution], as it distinguishes between functions with and without receiver.

TODO(Specify other cases when these two types are **not** equivalent)
TODO(Specify other cases when these types are **not** equivalent)

Furthermore, all function types $\FunctionN$ are subtypes of a general argument-agnostic type [$\Function$][`kotlin.Function`-typesystem] for the purpose of unification; this subtyping relation is also used in [overload resolution][Determining function applicability for a specific call].

Expand Down Expand Up @@ -862,6 +887,7 @@ Furthermore, all function types $\FunctionN$ are subtypes of a general argument-
> val barRef: (Int) -> Any = Number::bar
> ```


##### Suspending function types

Kotlin supports structured concurrency in the form of [coroutines] via [suspending functions].
Expand Down
4 changes: 4 additions & 0 deletions grammar/src/main/antlr/KotlinLexer.g4
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ INLINE: 'inline';
INFIX: 'infix';
EXTERNAL: 'external';
SUSPEND: 'suspend';
CONTEXT: 'context';
OVERRIDE: 'override';
ABSTRACT: 'abstract';
FINAL: 'final';
Expand Down Expand Up @@ -298,6 +299,7 @@ IdentifierOrSoftKey
| EXPECT
| ACTUAL
| VALUE
| CONTEXT
/* Strong keywords */
| CONST
| SUSPEND
Expand Down Expand Up @@ -506,6 +508,8 @@ Inside_REIFIED: REIFIED -> type(REIFIED);
Inside_EXPECT: EXPECT -> type(EXPECT);
Inside_ACTUAL: ACTUAL -> type(ACTUAL);

Inside_CONTEXT: CONTEXT -> type(CONTEXT);

Inside_BooleanLiteral: BooleanLiteral -> type(BooleanLiteral);
Inside_IntegerLiteral: IntegerLiteral -> type(IntegerLiteral);
Inside_HexLiteral: HexLiteral -> type(HexLiteral);
Expand Down
128 changes: 65 additions & 63 deletions grammar/src/main/antlr/KotlinLexer.tokens
Original file line number Diff line number Diff line change
Expand Up @@ -120,55 +120,56 @@ INLINE=119
INFIX=120
EXTERNAL=121
SUSPEND=122
OVERRIDE=123
ABSTRACT=124
FINAL=125
OPEN=126
CONST=127
LATEINIT=128
VARARG=129
NOINLINE=130
CROSSINLINE=131
REIFIED=132
EXPECT=133
ACTUAL=134
RealLiteral=135
FloatLiteral=136
DoubleLiteral=137
IntegerLiteral=138
HexLiteral=139
BinLiteral=140
UnsignedLiteral=141
LongLiteral=142
BooleanLiteral=143
NullLiteral=144
CharacterLiteral=145
Identifier=146
IdentifierOrSoftKey=147
FieldIdentifier=148
QUOTE_OPEN=149
TRIPLE_QUOTE_OPEN=150
UNICODE_CLASS_LL=151
UNICODE_CLASS_LM=152
UNICODE_CLASS_LO=153
UNICODE_CLASS_LT=154
UNICODE_CLASS_LU=155
UNICODE_CLASS_ND=156
UNICODE_CLASS_NL=157
QUOTE_CLOSE=158
LineStrRef=159
LineStrText=160
LineStrEscapedChar=161
LineStrExprStart=162
TRIPLE_QUOTE_CLOSE=163
MultiLineStringQuote=164
MultiLineStrRef=165
MultiLineStrText=166
MultiLineStrExprStart=167
Inside_Comment=168
Inside_WS=169
Inside_NL=170
ErrorCharacter=171
CONTEXT=123
OVERRIDE=124
ABSTRACT=125
FINAL=126
OPEN=127
CONST=128
LATEINIT=129
VARARG=130
NOINLINE=131
CROSSINLINE=132
REIFIED=133
EXPECT=134
ACTUAL=135
RealLiteral=136
FloatLiteral=137
DoubleLiteral=138
IntegerLiteral=139
HexLiteral=140
BinLiteral=141
UnsignedLiteral=142
LongLiteral=143
BooleanLiteral=144
NullLiteral=145
CharacterLiteral=146
Identifier=147
IdentifierOrSoftKey=148
FieldIdentifier=149
QUOTE_OPEN=150
TRIPLE_QUOTE_OPEN=151
UNICODE_CLASS_LL=152
UNICODE_CLASS_LM=153
UNICODE_CLASS_LO=154
UNICODE_CLASS_LT=155
UNICODE_CLASS_LU=156
UNICODE_CLASS_ND=157
UNICODE_CLASS_NL=158
QUOTE_CLOSE=159
LineStrRef=160
LineStrText=161
LineStrEscapedChar=162
LineStrExprStart=163
TRIPLE_QUOTE_CLOSE=164
MultiLineStringQuote=165
MultiLineStrRef=166
MultiLineStrText=167
MultiLineStrExprStart=168
Inside_Comment=169
Inside_WS=170
Inside_NL=171
ErrorCharacter=172
'...'=6
'.'=7
','=8
Expand Down Expand Up @@ -274,17 +275,18 @@ ErrorCharacter=171
'infix'=120
'external'=121
'suspend'=122
'override'=123
'abstract'=124
'final'=125
'open'=126
'const'=127
'lateinit'=128
'vararg'=129
'noinline'=130
'crossinline'=131
'reified'=132
'expect'=133
'actual'=134
'null'=144
'"""'=150
'context'=123
'override'=124
'abstract'=125
'final'=126
'open'=127
'const'=128
'lateinit'=129
'vararg'=130
'noinline'=131
'crossinline'=132
'reified'=133
'expect'=134
'actual'=135
'null'=145
'"""'=151
10 changes: 8 additions & 2 deletions grammar/src/main/antlr/KotlinParser.g4
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ typeProjectionModifier
;

functionType
: (receiverType NL* DOT NL*)? functionTypeParameters NL* ARROW NL* type
: (contextModifier NL*)? (receiverType NL* DOT NL*)? functionTypeParameters NL* ARROW NL* type
;

functionTypeParameters
Expand Down Expand Up @@ -760,7 +760,8 @@ modifier
| propertyModifier
| inheritanceModifier
| parameterModifier
| platformModifier) NL*
| platformModifier
| contextModifier) NL*
;

typeModifiers
Expand All @@ -770,6 +771,7 @@ typeModifiers
typeModifier
: annotation
| SUSPEND NL*
| contextModifier NL*
;

classModifier
Expand Down Expand Up @@ -842,6 +844,9 @@ platformModifier
| ACTUAL
;

contextModifier
: CONTEXT NL* LPAREN NL* type NL* (COMMA NL* type)* RPAREN;

// SECTION: annotations

annotation
Expand Down Expand Up @@ -916,6 +921,7 @@ simpleIdentifier
| CONST
| SUSPEND
| VALUE
| CONTEXT
;

identifier
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ File: propertyFromAbstractSuperClass.kt - e390474b6d27985868b418ca2233e4e6
PRIVATE("private")
VAL("val")
simpleIdentifier
Identifier("context")
CONTEXT("context")
COLON(":")
type
typeReference
Expand Down Expand Up @@ -410,7 +410,7 @@ File: propertyFromAbstractSuperClass.kt - e390474b6d27985868b418ca2233e4e6
COMMA(",")
classParameter
simpleIdentifier
Identifier("context")
CONTEXT("context")
COLON(":")
type
typeReference
Expand Down Expand Up @@ -538,7 +538,7 @@ File: propertyFromAbstractSuperClass.kt - e390474b6d27985868b418ca2233e4e6
postfixUnaryExpression
primaryExpression
simpleIdentifier
Identifier("context")
CONTEXT("context")
RPAREN(")")
NL("\n")
RCURL("}")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ File: multipleAreNull.kt - c1db05b9aed9b68bc78c8f7e6ca58e39
functionValueParameter
parameter
simpleIdentifier
Identifier("context")
CONTEXT("context")
COLON(":")
type
nullableType
Expand All @@ -59,7 +59,7 @@ File: multipleAreNull.kt - c1db05b9aed9b68bc78c8f7e6ca58e39
functionValueParameter
parameter
simpleIdentifier
Identifier("context")
CONTEXT("context")
COLON(":")
type
nullableType
Expand Down Expand Up @@ -92,7 +92,7 @@ File: multipleAreNull.kt - c1db05b9aed9b68bc78c8f7e6ca58e39
functionValueParameter
parameter
simpleIdentifier
Identifier("context")
CONTEXT("context")
COLON(":")
type
nullableType
Expand Down Expand Up @@ -137,7 +137,7 @@ File: multipleAreNull.kt - c1db05b9aed9b68bc78c8f7e6ca58e39
functionValueParameter
parameter
simpleIdentifier
Identifier("context")
CONTEXT("context")
COLON(":")
type
nullableType
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ File: kt2883.kt - 91abddac7c7af7dde8fc4557d2d1194f
functionValueParameter
parameter
simpleIdentifier
Identifier("context")
CONTEXT("context")
COLON(":")
type
typeReference
Expand Down