You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
*[Q\&A about design decisions](#qa-about-design-decisions)
45
47
*[Acknowledgments](#acknowledgments)
@@ -108,7 +110,21 @@ context(logger: Logger) fun User.doAction() {
108
110
* The type and order of context parameters must coincide.
109
111
* It is allowed (yet discouraged) to change the name of a context parameter.
110
112
111
-
It is a conflict to declare overloads which only differ in the number of context parameters. It is allowed to declare one overload with _no_ context parameters and one with _some_ of them (this is aligned with §7.8).
113
+
If is a conflict to declare overloads with the exact same set of context parameters.
114
+
115
+
It is allowed to declare multiple overloads if they differ in their set of context parameters. However, a warning should be reported if all of the set of context parameters of one overload are supertypes of those of another overload, since by §7.8 only the latter would be callable in a scope in which the more specific context is available.
116
+
117
+
```kotlin
118
+
openclassParent
119
+
classChild : Parent()
120
+
121
+
funfoo() { ... } // warning
122
+
context(x:Child) funfoo() { ... } // warning
123
+
context(x:Child, a:A) funfoo() { ... }
124
+
125
+
context(x:Parent) funbar() { ... } // warning
126
+
context(x:Child) funbar() { ... }
127
+
```
112
128
113
129
**§1.6***(naming ambiguity)*: We use the term **context** with two meanings:
114
130
@@ -165,16 +181,16 @@ fun foo(y: Int) {
165
181
166
182
**§1.8***(lambdas)*: If a lambda is assigned a function type with context parameters, those behave as if declared with `_` as its name.
167
183
168
-
* They participate in context resolution but are only accessible through the `implicit` function (defined below).
184
+
* They participate in context resolution but are only accessible through the `contextOf` function (defined below).
169
185
170
186
```kotlin
171
187
fun <A> withConsoleLogger(block: context(Logger) () ->A) =...
172
188
173
189
withConsoleLogger {
174
190
// you can call functions with Logger as context parameter
175
191
logWithTime("doing something")
176
-
// you can use 'implicit' to access the context parameter
177
-
implicit<Logger>().log("hello")
192
+
// you can use 'contextOf' to access the context parameter
[KEEP-448](./KEEP-0448-explicit-context-arguments.md) should be taken as an integral part of this design.
436
+
417
437
## Callable references
418
438
419
439
**§5.1***(callable references, eager resolution)*: References to callables declared with context parameters are resolved **eagerly**:
@@ -592,7 +612,7 @@ fun <A, T> withExampleReceiver(value: A, block: ExampleScope<A>.() -> T): T = ..
592
612
fun <A, T> withExampleContext(value:A, block: context(example: ExampleScope<A>) () ->T): T=
593
613
withExampleReceiver(value) { block() }
594
614
595
-
context(ExampleScope<A>) fun <A> similarExampleTo(other:A): A=...
615
+
context(example:ExampleScope<A>) fun <A> similarExampleTo(other:A): A=...
596
616
597
617
fundslMarkerExample() =
598
618
withExampleContext(3) { // (1)
@@ -618,42 +638,70 @@ fun dslMarkerExample() =
618
638
}
619
639
```
620
640
621
-
**§7.8***(most specific candidate)*: When choosing the **most specific candidate** we follow the [Kotlin specification](https://kotlinlang.org/spec/overload-resolution.html#choosing-the-most-specific-candidate-from-the-overload-candidate-set), with one addition:
622
-
623
-
* Candidates with context parameters are considered more specific than those without them.
624
-
* But there is no other prioritization coming from the length of the context parameter list or their types.
641
+
**§7.8***(most specific candidate)*: When choosing the **most specific candidate** we follow the [Kotlin specification](https://kotlinlang.org/spec/overload-resolution.html#choosing-the-most-specific-candidate-from-the-overload-candidate-set). Context parameters play **no role** in this choice, unless they are explicitly given (see [KEEP-448](./KEEP-0448-explicit-context-arguments.md) for details).
625
642
626
643
For example, the following call to `foo` is declared ambiguous, since `"hello"` may work both as `String` or `Any` context parameter.
627
644
628
645
```kotlin
629
-
context(Any) funfoo() {}
630
-
context(String) funfoo() {}
646
+
context(value:Any) funfoo() {}
647
+
context(string:String) funfoo() {}
631
648
632
-
funtest() =with("hello") {
649
+
funtest() =context("hello") {
633
650
foo()
634
651
}
635
652
```
636
653
637
654
The reasoning for this particular rule is that, since contexts are implicit, there is no way for the user to resolve to the other function if required. This implicitness also means that it's harder to figure out which overload is called from the program code -- once again, there's no value you can easily point to. In contrast, in the case of an explicit parameter, you can always use `f("hello" as Any)` to force using `(Any) -> R` over `(String) -> R`.
638
655
656
+
> [!NOTE]
657
+
> [Explicit context arguments](./KEEP-0448-explicit-context-arguments.md) provide a way to disambiguate between overloads if the name of the context parameter is different.
658
+
>
659
+
> ```kotlin
660
+
>funtest() = foo(value ="hello") // calls the 'Any' overload
661
+
> ```
662
+
639
663
### Extended type inference algorithm
640
664
641
665
**§7.9***(lambda literal inference)*: the type inference process in the [Kotlin specification](https://kotlinlang.org/spec/type-inference.html#statements-with-lambda-literals) should take context parameters into account. Note that unless a function type with context is "pushed" as a type for the lambda, context parameters are never inferred.
642
666
643
667
Context parameters take part in [builder-style type inference](https://kotlinlang.org/spec/type-inference.html#builder-style-type-inference), or any similar process defined by the implementation and whose goal is to infer better types for receivers.
644
668
669
+
### Extended scoping rules
670
+
671
+
**§7.10***(receiver shadowed by context)*: it is an error to call a function that binds to an implicit _receiver_in the context, whenever an implicit _context value_ of the same type is available in a more nested scope. The reasoning behind this error is that in many cases a function defined over the implicit receiver (either as member oras extension function) is chosen instead of a similar function using a context parameter; even if the context value isin a (lexically) nested scope. This leads to surprising behavior.
672
+
673
+
Note that this error should be reported even if there's no function defined with context parameters of that type in scope. For example, in the code below both calls to `moo` are marked as errors.
674
+
675
+
```kotlin
676
+
class Cow {
677
+
fun moo() { }
678
+
679
+
fun test1() = context(Cow()) {
680
+
moo() // error: receiver shadowed by context
681
+
}
682
+
}
683
+
684
+
fun test2() {
685
+
with(Cow()) {
686
+
context(Cow()) {
687
+
moo() // error: receiver shadowed by context
688
+
}
689
+
}
690
+
}
691
+
```
692
+
645
693
### ABI compatibility
646
694
647
-
**§7.10***(JVM and Java compatibility, functions)*: In the JVM a function with context parameters is represented as a function with additional parameters. In particular, the order is:
695
+
**§7.11** *(JVM and Java compatibility, functions)*: In the JVM a function with context parameters is represented as a function with additional parameters. In particular, the order is:
648
696
1. Context parameters, if present;
649
697
2. Extension receiver, if present;
650
698
3. Regular value parameters.
651
699
652
700
Note that parameter names do not impact JVM ABI compatibility, but we use the names given in parameter declarations as far as possible.
653
701
654
-
**§7.11***(JVM and Java compatibility, properties)*: In the JVM a property with context parameters is represented by its corresponding getter and/or setter. This representation follows the same argument order described in §7.10.
702
+
**§7.12** *(JVM and Java compatibility, properties)*: In the JVM a property with context parameters is represented by its corresponding getter and/or setter. This representation follows the same argument order described in §7.10.
655
703
656
-
**§7.12***(other targets)*: Targets may not follow the same ABI compatibility guarantees as those described for the JVM.
704
+
**§7.13** *(other targets)*: Targets may not follow the same ABI compatibility guarantees as those described for the JVM.
0 commit comments