[NI] Fix trace manipulations for builder inference and ::-expressions

For a class literal Type::class we are resolving Type as a constructor,
 getting all diagnostics (about missing arguments, for example) and then
 just not committing this trace with errors

 #KT-37626 Fixed
This commit is contained in:
Mikhail Zarechenskiy
2020-03-24 02:44:00 +03:00
parent 6213680604
commit 38a719cb22
13 changed files with 181 additions and 4 deletions
@@ -6140,6 +6140,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/dispatchResume.kt", "kotlin.coroutines");
}
@TestMetadata("doubleColonExpressionsGenerationInBuilderInference.kt")
public void testDoubleColonExpressionsGenerationInBuilderInference() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/doubleColonExpressionsGenerationInBuilderInference.kt");
}
@TestMetadata("emptyClosure.kt")
public void testEmptyClosure_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/emptyClosure.kt", "kotlin.coroutines");
@@ -9,7 +9,13 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
import org.jetbrains.kotlin.psi.KtDotQualifiedExpression
import org.jetbrains.kotlin.psi.KtDoubleColonExpression
import org.jetbrains.kotlin.psi.KtReferenceExpression
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.MissingSupertypesResolver
import org.jetbrains.kotlin.resolve.TemporaryBindingTrace
import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver
@@ -25,7 +31,10 @@ import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.tower.*
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.StubType
import org.jetbrains.kotlin.types.TypeApproximator
import org.jetbrains.kotlin.types.TypeConstructor
import org.jetbrains.kotlin.types.UnwrappedType
import org.jetbrains.kotlin.types.expressions.DoubleColonExpressionResolver
import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices
import org.jetbrains.kotlin.types.typeUtil.contains
@@ -110,10 +119,24 @@ class CoroutineInferenceSession(
}
private fun skipCall(callInfo: SingleCallResolutionResult): Boolean {
val descriptor = callInfo.resultCallAtom.candidateDescriptor
// FakeCallableDescriptorForObject can't introduce new information for inference,
// so it's safe to complete it fully
val descriptor = callInfo.resultCallAtom.candidateDescriptor
return descriptor is FakeCallableDescriptorForObject
if (descriptor is FakeCallableDescriptorForObject) return true
// In this case temporary trace isn't committed during resolve of expressions like A::class, see resolveDoubleColonLHS
if (!DescriptorUtils.isObject(descriptor) && isInLHSOfDoubleColonExpression(callInfo)) return true
return false
}
private fun isInLHSOfDoubleColonExpression(callInfo: SingleCallResolutionResult): Boolean {
val callElement = callInfo.resultCallAtom.atom.psiKotlinCall.psiCall.callElement
val lhs = callElement.getParentOfType<KtDoubleColonExpression>(strict = false)?.lhs
if (lhs !is KtReferenceExpression && lhs !is KtDotQualifiedExpression) return false
return lhs.isAncestor(callElement)
}
override fun currentConstraintSystem(): ConstraintStorage {
@@ -38,13 +38,16 @@ abstract class KtDoubleColonExpression(node: ASTNode) : KtExpressionImpl(node) {
val doubleColonTokenReference: PsiElement
get() = findChildByType(KtTokens.COLONCOLON)!!
val lhs: PsiElement?
get() = doubleColonTokenReference.prevSibling
fun setReceiverExpression(newReceiverExpression: KtExpression) {
val oldReceiverExpression = this.receiverExpression
oldReceiverExpression?.replace(newReceiverExpression) ?: addBefore(newReceiverExpression, doubleColonTokenReference)
}
val isEmptyLHS: Boolean
get() = doubleColonTokenReference.prevSibling == null
get() = lhs == null
override fun <R, D> accept(visitor: KtVisitor<R, D>, data: D): R {
return visitor.visitDoubleColonExpression(this, data)
@@ -0,0 +1,32 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS, JS_IR
// WITH_RUNTIME
// KJS_WITH_FULL_RUNTIME
package a.b
class BatchInfo1(val batchSize: Int)
class BatchInfo2<T>(val data: T)
object Obj
fun test() {
val a: Sequence<String> = sequence {
val x = BatchInfo1::class
val y = a.b.BatchInfo1::class
val z = Obj::class
val x1 = BatchInfo1::batchSize
val y1 = a.b.BatchInfo1::class
yieldAll(listOf(x, y, z, x1, y1).map { it.toString() })
}
val size = a.toList().size
assert(size == 5) { "actual size: $size"}
}
fun box(): String {
test()
return "OK"
}
@@ -0,0 +1,38 @@
// !USE_EXPERIMENTAL: kotlin.RequiresOptIn
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER -UNUSED_EXPRESSION
@file:OptIn(ExperimentalTypeInference::class)
package a.b
import kotlin.experimental.ExperimentalTypeInference
class BatchInfo1(val batchSize: Int)
class BatchInfo2<T>(val data: T)
object Obj
fun test1() {
val a: Sequence<String> = sequence {
val x = BatchInfo1::class
val y = a.b.BatchInfo1::class
val z = Obj::class
val x1 = BatchInfo1::batchSize
val y1 = a.b.BatchInfo1::class
}
}
interface Scope<T> {
fun yield(t: T) {}
}
fun <S> generate(@BuilderInference g: Scope<S>.() -> Unit): S = TODO()
val test2 = generate {
{ yield("foo") }::class
}
val test3 = generate {
({ yield("foo") })::class
}
@@ -0,0 +1,41 @@
package
package a {
package a.b {
public val test2: kotlin.String
public val test3: kotlin.String
public fun </*0*/ S> generate(/*0*/ @kotlin.BuilderInference g: a.b.Scope<S>.() -> kotlin.Unit): S
public fun test1(): kotlin.Unit
public final class BatchInfo1 {
public constructor BatchInfo1(/*0*/ batchSize: kotlin.Int)
public final val batchSize: kotlin.Int
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class BatchInfo2</*0*/ T> {
public constructor BatchInfo2</*0*/ T>(/*0*/ data: T)
public final val data: T
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public object Obj {
private constructor Obj()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface Scope</*0*/ T> {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public open fun yield(/*0*/ t: T): kotlin.Unit
}
}
}
@@ -1922,6 +1922,11 @@ public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestW
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/correctMember.kt");
}
@TestMetadata("doubleColonExpressionToClassWithParameters.kt")
public void testDoubleColonExpressionToClassWithParameters() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/doubleColonExpressionToClassWithParameters.kt");
}
@TestMetadata("elvisOperatorAgainstFlexibleType.kt")
public void testElvisOperatorAgainstFlexibleType() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/elvisOperatorAgainstFlexibleType.kt");
@@ -1922,6 +1922,11 @@ public class DiagnosticsTestWithStdLibUsingJavacGenerated extends AbstractDiagno
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/correctMember.kt");
}
@TestMetadata("doubleColonExpressionToClassWithParameters.kt")
public void testDoubleColonExpressionToClassWithParameters() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/doubleColonExpressionToClassWithParameters.kt");
}
@TestMetadata("elvisOperatorAgainstFlexibleType.kt")
public void testElvisOperatorAgainstFlexibleType() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/elvisOperatorAgainstFlexibleType.kt");
@@ -6260,6 +6260,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/dispatchResume.kt", "kotlin.coroutines");
}
@TestMetadata("doubleColonExpressionsGenerationInBuilderInference.kt")
public void testDoubleColonExpressionsGenerationInBuilderInference() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/doubleColonExpressionsGenerationInBuilderInference.kt");
}
@TestMetadata("emptyClosure.kt")
public void testEmptyClosure_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/emptyClosure.kt", "kotlin.coroutines.experimental");
@@ -6260,6 +6260,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/dispatchResume.kt", "kotlin.coroutines");
}
@TestMetadata("doubleColonExpressionsGenerationInBuilderInference.kt")
public void testDoubleColonExpressionsGenerationInBuilderInference() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/doubleColonExpressionsGenerationInBuilderInference.kt");
}
@TestMetadata("emptyClosure.kt")
public void testEmptyClosure_1_2() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/emptyClosure.kt", "kotlin.coroutines.experimental");
@@ -6140,6 +6140,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/dispatchResume.kt", "kotlin.coroutines");
}
@TestMetadata("doubleColonExpressionsGenerationInBuilderInference.kt")
public void testDoubleColonExpressionsGenerationInBuilderInference() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/doubleColonExpressionsGenerationInBuilderInference.kt");
}
@TestMetadata("emptyClosure.kt")
public void testEmptyClosure_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/emptyClosure.kt", "kotlin.coroutines");
@@ -5160,6 +5160,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/dispatchResume.kt", "kotlin.coroutines");
}
@TestMetadata("doubleColonExpressionsGenerationInBuilderInference.kt")
public void testDoubleColonExpressionsGenerationInBuilderInference() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/doubleColonExpressionsGenerationInBuilderInference.kt");
}
@TestMetadata("emptyClosure.kt")
public void testEmptyClosure_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/emptyClosure.kt", "kotlin.coroutines");
@@ -5160,6 +5160,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/dispatchResume.kt", "kotlin.coroutines");
}
@TestMetadata("doubleColonExpressionsGenerationInBuilderInference.kt")
public void testDoubleColonExpressionsGenerationInBuilderInference() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/doubleColonExpressionsGenerationInBuilderInference.kt");
}
@TestMetadata("emptyClosure.kt")
public void testEmptyClosure_1_3() throws Exception {
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/emptyClosure.kt", "kotlin.coroutines");