JS backend: fixed smartcast when a call have implicit this or receiver.
This commit is contained in:
@@ -31,4 +31,12 @@ public final class CastTest extends AbstractExpressionTest {
|
|||||||
public void testCastToNotNullType() throws Exception {
|
public void testCastToNotNullType() throws Exception {
|
||||||
checkFooBoxIsOk();
|
checkFooBoxIsOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testSmartCastInExtensionFunction() throws Exception {
|
||||||
|
checkFooBoxIsOk();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSmartCastInFunction() throws Exception {
|
||||||
|
checkFooBoxIsOk();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,8 +24,10 @@ import org.jetbrains.jet.lang.descriptors.*;
|
|||||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||||
|
import org.jetbrains.jet.lang.resolve.calls.autocasts.AutoCastReceiver;
|
||||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
|
||||||
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ThisReceiver;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
|
import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
|
||||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
||||||
@@ -112,12 +114,20 @@ public final class JsDescriptorUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static DeclarationDescriptor getDeclarationDescriptorForReceiver
|
public static DeclarationDescriptor getDeclarationDescriptorForReceiver(@NotNull ReceiverValue receiverParameter) {
|
||||||
(@NotNull ReceiverValue receiverParameter) {
|
DeclarationDescriptor declarationDescriptor;
|
||||||
DeclarationDescriptor declarationDescriptor =
|
|
||||||
receiverParameter.getType().getConstructor().getDeclarationDescriptor();
|
if (receiverParameter instanceof ThisReceiver) {
|
||||||
//TODO: WHY assert?
|
declarationDescriptor = ((ThisReceiver) receiverParameter).getDeclarationDescriptor();
|
||||||
assert declarationDescriptor != null;
|
}
|
||||||
|
else if (receiverParameter instanceof AutoCastReceiver) {
|
||||||
|
AutoCastReceiver autoCastReceiver = ((AutoCastReceiver) receiverParameter);
|
||||||
|
declarationDescriptor = getDeclarationDescriptorForReceiver(autoCastReceiver.getOriginal());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new UnsupportedOperationException("Unsupported receiver type: " + receiverParameter);
|
||||||
|
}
|
||||||
|
|
||||||
return declarationDescriptor.getOriginal();
|
return declarationDescriptor.getOriginal();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
package foo
|
||||||
|
|
||||||
|
class A {
|
||||||
|
fun foo(a: Int) = "A.foo($a)"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Any.bar() = "Any.bar()"
|
||||||
|
fun A.bar() = "A.bar()"
|
||||||
|
|
||||||
|
fun boo(a: Any) = "boo(Any)"
|
||||||
|
fun boo(a: A) = "boo(A)"
|
||||||
|
|
||||||
|
fun assert<T>(expected: T, actual: T, caseName: String) {
|
||||||
|
if (expected != actual) throw Exception("Filed on $caseName, expected: $expected, actual: $actual")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Any.testInTopLevel() {
|
||||||
|
assert(bar(), "Any.bar()", "bar()")
|
||||||
|
assert(this.bar(), "Any.bar()", "this.bar()")
|
||||||
|
assert(boo(this), "boo(Any)", "boo(this)")
|
||||||
|
|
||||||
|
if (this is A) {
|
||||||
|
assert(foo(47), "A.foo(47)", "foo(47)")
|
||||||
|
assert(bar(), "A.bar()", "bar()")
|
||||||
|
|
||||||
|
assert(this.foo(47), "A.foo(47)", "this.foo(47)")
|
||||||
|
assert(this.bar(), "A.bar()", "this.bar()")
|
||||||
|
|
||||||
|
assert(boo(this), "boo(A)", "boo(this: A)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class B {
|
||||||
|
fun Any.test() {
|
||||||
|
assert(bar(), "Any.bar()", "bar()")
|
||||||
|
assert(this.bar(), "Any.bar()", "this.bar()")
|
||||||
|
assert(boo(this), "boo(Any)", "boo(this)")
|
||||||
|
|
||||||
|
if (this is A) {
|
||||||
|
assert(foo(47), "A.foo(47)", "foo(47)")
|
||||||
|
assert(bar(), "A.bar()", "bar()")
|
||||||
|
|
||||||
|
assert(this.foo(47), "A.foo(47)", "this.foo(47)")
|
||||||
|
assert(this.bar(), "A.bar()", "this.bar()")
|
||||||
|
|
||||||
|
assert(boo(this), "boo(A)", "boo(this: A)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testInClass() {
|
||||||
|
A().test()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
A().testInTopLevel()
|
||||||
|
B().testInClass()
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package foo
|
||||||
|
|
||||||
|
class A {
|
||||||
|
fun foo(a: Int) = "A.foo($a)"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Any.bar() = "Any.bar()"
|
||||||
|
fun A.bar() = "A.bar()"
|
||||||
|
|
||||||
|
fun boo(a: Any) = "boo(Any)"
|
||||||
|
fun boo(a: A) = "boo(A)"
|
||||||
|
|
||||||
|
fun assert<T>(expected: T, actual: T, caseName: String) {
|
||||||
|
if (expected != actual) throw Exception("Filed on $caseName, expected: $expected, actual: $actual")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testInTopLevel(a: Any) {
|
||||||
|
assert(a.bar(), "Any.bar()", "bar()")
|
||||||
|
assert(a.bar(), "Any.bar()", "this.bar()")
|
||||||
|
assert(boo(a), "boo(Any)", "boo(this)")
|
||||||
|
|
||||||
|
if (a is A) {
|
||||||
|
assert(a.foo(47), "A.foo(47)", "a.foo(47)")
|
||||||
|
assert(a.bar(), "A.bar()", "a.bar()")
|
||||||
|
assert(boo(a), "boo(A)", "boo(a: A)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class B {
|
||||||
|
fun testInClass(a: Any) {
|
||||||
|
assert(a.bar(), "Any.bar()", "bar()")
|
||||||
|
assert(a.bar(), "Any.bar()", "this.bar()")
|
||||||
|
assert(boo(a), "boo(Any)", "boo(this)")
|
||||||
|
|
||||||
|
if (a is A) {
|
||||||
|
assert(a.foo(47), "A.foo(47)", "a.foo(47)")
|
||||||
|
assert(a.bar(), "A.bar()", "a.bar()")
|
||||||
|
assert(boo(a), "boo(A)", "boo(a: A)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
testInTopLevel(A())
|
||||||
|
B().testInClass(A())
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user