f12a4e08cf
Otherwise, it leads to branches inference run fully independent,
while there are cases when it's necessary to flow type information from
one of the branch to another (see the new test).
NB. In K1, it worked differently: if branches were inferred altogether
only for Any/Any? expect types (otherwise they're analyzed independently)
See foo2/foo4 in the test.
To avoid breaking change we need to support foo1/foo3, but we're trying
not to have some special rule for Any, so we've got a new resolution mode
that provides expect type, but doesn't require full completion.
^KT-45989 Fixed
^KT-56563 Fixed
^KT-54709 Related
For change in specialCallWithMaterializeAndExpectedType.kt
At first, see at KT-36776
Long time ago, it's been decided that if/when resolution
should look similar to similar "select()" calls,
but it's a breaking change (see KT-36776), and we were ready for that back then.
But then, there were too many broken cases found, thus we reverted it at
100a6f70ca
But probably, it would be better to try to infer `String?`
instead of `Nothing?` (see next commits)
Note that change in specialCallWithMaterializeAndExpectedType.kt
will be addressed in later commits, too
55 lines
1.2 KiB
Kotlin
Vendored
55 lines
1.2 KiB
Kotlin
Vendored
// !CHECK_TYPE
|
|
// See also KT-10896: Wrong inference of if / else result type
|
|
|
|
interface Option<T>
|
|
class Some<T> : Option<T>
|
|
class None<T> : Option<T>
|
|
|
|
fun <T> bind(r: Option<T>): Option<T> {
|
|
return if (r is Some) {
|
|
// Ideally we should infer Option<T> here (see KT-10896)
|
|
(if (true) None() else r) checkType { _<Option<T>>() }
|
|
// Works correctly
|
|
if (true) None() else r
|
|
}
|
|
else r
|
|
}
|
|
|
|
fun <T> bind2(r: Option<T>): Option<T> {
|
|
return if (r is Some) {
|
|
// Works correctly
|
|
if (true) None<T>() else r
|
|
}
|
|
else r
|
|
}
|
|
|
|
fun <T, R> bind3(r: Option<T>): Option<T> {
|
|
return <!RETURN_TYPE_MISMATCH!>if (r is Some) {
|
|
// Diagnoses an error correctly
|
|
if (true) None<R>() else r
|
|
}
|
|
else r<!>
|
|
}
|
|
|
|
fun <T> bindWhen(r: Option<T>): Option<T> {
|
|
return when (r) {
|
|
is Some -> {
|
|
// Works correctly
|
|
if (true) None() else r
|
|
}
|
|
else -> r
|
|
}
|
|
}
|
|
|
|
interface SimpleOption
|
|
class SimpleSome : SimpleOption
|
|
class SimpleNone : SimpleOption
|
|
|
|
fun bindNoGeneric(r: SimpleOption): SimpleOption {
|
|
return if (r is SimpleSome) {
|
|
(if (true) SimpleNone() else r) checkType { _<SimpleOption>() }
|
|
if (true) SimpleNone() else r
|
|
}
|
|
else r
|
|
}
|