From 5f9f01fe4ea8f19eb75c4ea932695e752c63cd76 Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Fri, 20 Mar 2020 15:20:09 +0300 Subject: [PATCH] [FIR] Implement new completion mode calculator Note that `testDelegates` now fails due to KT-37638 and `testSimpleIn` fails due to problems with type parameters of inner classes --- .../definetelyNotNullForTypeParameter.kt | 2 +- .../definetelyNotNullForTypeParameter.txt | 7 +- .../kotlin/fir/resolve/calls/Candidate.kt | 5 +- .../inference/CompletionModeCalculator.kt | 231 ++++++++++++++++++ .../resolve/inference/InferenceCompletion.kt | 75 +----- .../box/elvis/genericElvisWithNullLHS.kt | 1 - .../codegen/box/regressions/kt33638.kt | 1 - .../generics/innerClasses/simpleIn.fir.fail | 2 + .../inference/regressions/kt32250.fir.kt | 30 --- .../tests/inference/regressions/kt32250.kt | 1 + .../testsWithStdLib/kt7585/delegate.fir.fail | 17 ++ .../testsWithStdLib/kt7585/delegate.fir.kt | 76 ++++++ .../testsWithStdLib/kt7585/delegate.kt | 1 - .../expressions/whenUnusedExpression.fir.txt | 2 +- 14 files changed, 340 insertions(+), 111 deletions(-) create mode 100644 compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/CompletionModeCalculator.kt create mode 100644 compiler/testData/diagnostics/tests/generics/innerClasses/simpleIn.fir.fail delete mode 100644 compiler/testData/diagnostics/tests/inference/regressions/kt32250.fir.kt create mode 100644 compiler/testData/diagnostics/testsWithStdLib/kt7585/delegate.fir.fail create mode 100644 compiler/testData/diagnostics/testsWithStdLib/kt7585/delegate.fir.kt diff --git a/compiler/fir/analysis-tests/testData/resolve/arguments/definetelyNotNullForTypeParameter.kt b/compiler/fir/analysis-tests/testData/resolve/arguments/definetelyNotNullForTypeParameter.kt index ce312e56336..580d7b0c6bb 100644 --- a/compiler/fir/analysis-tests/testData/resolve/arguments/definetelyNotNullForTypeParameter.kt +++ b/compiler/fir/analysis-tests/testData/resolve/arguments/definetelyNotNullForTypeParameter.kt @@ -2,7 +2,7 @@ interface Out fun id(x: Out): Out = TODO() -fun foo(computable: Out) +fun foo(computable: Out) {} fun bar(computable: Out) { foo(id(computable)) diff --git a/compiler/fir/analysis-tests/testData/resolve/arguments/definetelyNotNullForTypeParameter.txt b/compiler/fir/analysis-tests/testData/resolve/arguments/definetelyNotNullForTypeParameter.txt index f659d303353..465f220857f 100644 --- a/compiler/fir/analysis-tests/testData/resolve/arguments/definetelyNotNullForTypeParameter.txt +++ b/compiler/fir/analysis-tests/testData/resolve/arguments/definetelyNotNullForTypeParameter.txt @@ -4,7 +4,8 @@ FILE: definetelyNotNullForTypeParameter.kt public final fun id(x: R|Out|): R|Out| { ^id R|kotlin/TODO|() } - public final fun foo(computable: R|Out|): R|kotlin/Unit| - public final fun bar(computable: R|Out|): R|kotlin/Unit| { - R|/foo|(R|/id|(R|/computable|)) + public final fun foo(computable: R|Out|): R|kotlin/Unit| { + } + public final fun bar(computable: R|Out|): R|kotlin/Unit| { + R|/foo|(R|/id|(R|/computable|)) } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Candidate.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Candidate.kt index b50d049f445..9fcfb19b65e 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Candidate.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Candidate.kt @@ -7,7 +7,6 @@ package org.jetbrains.kotlin.fir.resolve.calls import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.FirFile -import org.jetbrains.kotlin.fir.declarations.FirTypeParameter import org.jetbrains.kotlin.fir.declarations.FirValueParameter import org.jetbrains.kotlin.fir.expressions.FirArgumentList import org.jetbrains.kotlin.fir.expressions.FirEmptyArgumentList @@ -17,6 +16,7 @@ import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents import org.jetbrains.kotlin.fir.resolve.DoubleColonLHS import org.jetbrains.kotlin.fir.resolve.ImplicitReceiverStack +import org.jetbrains.kotlin.fir.resolve.inference.PostponedResolvedAtom import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol import org.jetbrains.kotlin.fir.types.ConeKotlinType @@ -27,7 +27,6 @@ import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemOperation import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImpl -import org.jetbrains.kotlin.resolve.calls.model.PostponedResolvedAtomMarker import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind data class CallInfo( @@ -114,7 +113,7 @@ class Candidate( var argumentMapping: Map? = null lateinit var typeArgumentMapping: TypeArgumentMapping - val postponedAtoms = mutableListOf() + val postponedAtoms = mutableListOf() val diagnostics: MutableList = mutableListOf() diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/CompletionModeCalculator.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/CompletionModeCalculator.kt new file mode 100644 index 00000000000..bf75cdec2e2 --- /dev/null +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/CompletionModeCalculator.kt @@ -0,0 +1,231 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.fir.resolve.inference + +import org.jetbrains.kotlin.fir.resolve.calls.Candidate +import org.jetbrains.kotlin.fir.types.ConeIntegerLiteralType +import org.jetbrains.kotlin.fir.types.ConeKotlinType +import org.jetbrains.kotlin.fir.types.FirTypeRef +import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode +import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter.Context +import org.jetbrains.kotlin.resolve.calls.inference.components.TrivialConstraintTypeInferenceOracle +import org.jetbrains.kotlin.resolve.calls.inference.model.Constraint +import org.jetbrains.kotlin.resolve.calls.inference.model.VariableWithConstraints +import org.jetbrains.kotlin.types.AbstractTypeChecker +import org.jetbrains.kotlin.types.model.* +import org.jetbrains.kotlin.utils.newLinkedHashMapWithExpectedSize +import java.util.* + +fun Candidate.computeCompletionMode( + components: InferenceComponents, + expectedType: FirTypeRef?, + currentReturnType: ConeKotlinType? +): ConstraintSystemCompletionMode { + return when { + // Presence of expected type means that we are trying to complete outermost call => completion mode should be full + expectedType != null -> ConstraintSystemCompletionMode.FULL + + // This is questionable as null return type can be only for error call + currentReturnType == null || currentReturnType is ConeIntegerLiteralType -> ConstraintSystemCompletionMode.PARTIAL + + // Full if return type for call has no type variables + csBuilder.isProperType(currentReturnType) -> ConstraintSystemCompletionMode.FULL + + else -> CalculatorForNestedCall( + this, currentReturnType, csBuilder, components.trivialConstraintTypeInferenceOracle + ).computeCompletionMode() + } +} + +private typealias CsCompleterContext = Context + +private class CalculatorForNestedCall( + private val candidate: Candidate, + private val returnType: ConeKotlinType?, + private val context: CsCompleterContext, + private val oracle: TrivialConstraintTypeInferenceOracle +) { + private enum class FixationDirection { + TO_SUBTYPE, EQUALITY + } + + private val fixationDirectionsForVariables: MutableMap = + newLinkedHashMapWithExpectedSize(context.notFixedTypeVariables.size) + private val variablesWithQueuedConstraints = mutableSetOf() + private val typesToProcess: Queue = ArrayDeque() + + private val postponedAtoms: List by lazy { + candidate.postponedAtoms.filterNot { it.analyzed } + } + + fun computeCompletionMode(): ConstraintSystemCompletionMode = with(context) { + // Add fixation directions for variables based on effective variance in type + typesToProcess.add(returnType) + computeDirections() + + // If all variables have required proper constraint, run full completion + if (directionRequirementsForVariablesHold()) + return ConstraintSystemCompletionMode.FULL + + return ConstraintSystemCompletionMode.PARTIAL + } + + private fun CsCompleterContext.computeDirections() { + while (typesToProcess.isNotEmpty()) { + val type = typesToProcess.poll() ?: break + + if (!type.contains { it.typeConstructor() in notFixedTypeVariables }) + continue + + val fixationDirectionsFromType = mutableSetOf() + collectRequiredDirectionsForVariables(type, TypeVariance.OUT, fixationDirectionsFromType) + + for (directionForVariable in fixationDirectionsFromType) { + updateDirection(directionForVariable) + enqueueTypesFromConstraints(directionForVariable.variable) + } + } + } + + private fun enqueueTypesFromConstraints(variableWithConstraints: VariableWithConstraints) { + val variable = variableWithConstraints.typeVariable + if (variable !in variablesWithQueuedConstraints) { + for (constraint in variableWithConstraints.constraints) { + typesToProcess.add(constraint.type) + } + + variablesWithQueuedConstraints.add(variable) + } + } + + private fun CsCompleterContext.directionRequirementsForVariablesHold(): Boolean { + for ((variable, fixationDirection) in fixationDirectionsForVariables) { + if (!hasProperConstraint(variable, fixationDirection)) + return false + } + return true + } + + private fun updateDirection(directionForVariable: FixationDirectionForVariable) { + val (variable, newDirection) = directionForVariable + fixationDirectionsForVariables[variable]?.let { oldDirection -> + if (oldDirection != FixationDirection.EQUALITY && oldDirection != newDirection) + fixationDirectionsForVariables[variable] = FixationDirection.EQUALITY + } ?: run { + fixationDirectionsForVariables[variable] = newDirection + } + } + + private data class FixationDirectionForVariable(val variable: VariableWithConstraints, val direction: FixationDirection) + + private fun CsCompleterContext.collectRequiredDirectionsForVariables( + type: KotlinTypeMarker, outerVariance: TypeVariance, + fixationDirectionsCollector: MutableSet + ) { + val typeArgumentsCount = type.argumentsCount() + if (typeArgumentsCount > 0) { + for (position in 0 until typeArgumentsCount) { + val argument = type.getArgument(position) + val parameter = type.typeConstructor().getParameter(position) + + if (argument.isStarProjection()) + continue + + collectRequiredDirectionsForVariables( + argument.getType(), + compositeVariance(outerVariance, argument, parameter), + fixationDirectionsCollector + ) + } + } else { + processTypeWithoutParameters(type, outerVariance, fixationDirectionsCollector) + } + } + + private fun CsCompleterContext.compositeVariance( + outerVariance: TypeVariance, + argument: TypeArgumentMarker, + parameter: TypeParameterMarker + ): TypeVariance { + val effectiveArgumentVariance = AbstractTypeChecker.effectiveVariance(parameter.getVariance(), argument.getVariance()) + ?: TypeVariance.INV // conflicting variance + return when (outerVariance) { + TypeVariance.INV -> TypeVariance.INV + TypeVariance.OUT -> effectiveArgumentVariance + TypeVariance.IN -> effectiveArgumentVariance.reversed() + } + } + + private fun TypeVariance.reversed(): TypeVariance = when (this) { + TypeVariance.IN -> TypeVariance.OUT + TypeVariance.OUT -> TypeVariance.IN + TypeVariance.INV -> TypeVariance.INV + } + + private fun CsCompleterContext.processTypeWithoutParameters( + type: KotlinTypeMarker, compositeVariance: TypeVariance, + newRequirementsCollector: MutableSet + ) { + val variableWithConstraints = notFixedTypeVariables[type.typeConstructor()] ?: return + val direction = when (compositeVariance) { + TypeVariance.IN -> FixationDirection.EQUALITY // Assuming that variables in contravariant positions are fixed to subtype + TypeVariance.OUT -> FixationDirection.TO_SUBTYPE + TypeVariance.INV -> FixationDirection.EQUALITY + } + val requirement = FixationDirectionForVariable(variableWithConstraints, direction) + newRequirementsCollector.add(requirement) + } + + private fun CsCompleterContext.hasProperConstraint( + variableWithConstraints: VariableWithConstraints, + direction: FixationDirection + ): Boolean { + val constraints = variableWithConstraints.constraints + val variable = variableWithConstraints.typeVariable + + // ILT constraint tracking is necessary to prevent incorrect full completion from Nothing constraint + // Consider ILT <: T; Nothing <: T for T requiring lower constraint + // Nothing would trigger full completion, but resulting type would be Int + // Possible restrictions on integer constant from outer calls would be ignored + + var iltConstraintPresent = false + var properConstraintPresent = false + var nonNothingProperConstraintPresent = false + + for (constraint in constraints) { + if (!constraint.hasRequiredKind(direction) || !isProperType(constraint.type)) + continue + + if (constraint.type.typeConstructor().isIntegerLiteralTypeConstructor()) { + iltConstraintPresent = true + } else if (oracle.isSuitableResultedType(constraint.type)) { + properConstraintPresent = true + nonNothingProperConstraintPresent = true + } else if (!isLowerConstraintForPartiallyAnalyzedVariable(constraint, variable)) { + properConstraintPresent = true + } + } + + if (!properConstraintPresent) return false + + return !iltConstraintPresent || nonNothingProperConstraintPresent + } + + private fun Constraint.hasRequiredKind(direction: FixationDirection) = when (direction) { + FixationDirection.TO_SUBTYPE -> kind.isLower() || kind.isEqual() + FixationDirection.EQUALITY -> kind.isEqual() + } + + private fun CsCompleterContext.isLowerConstraintForPartiallyAnalyzedVariable( + constraint: Constraint, + variable: TypeVariableMarker + ): Boolean { + val defaultType = variable.defaultType() + return constraint.kind.isLower() && postponedAtoms.any { atom -> + atom.expectedType?.contains { type -> defaultType == type } ?: false + } + } +} diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/InferenceCompletion.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/InferenceCompletion.kt index 6169a4147d7..c9133d783ac 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/InferenceCompletion.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/inference/InferenceCompletion.kt @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter +import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode import org.jetbrains.kotlin.resolve.calls.inference.components.TypeVariableDirectionCalculator import org.jetbrains.kotlin.resolve.calls.inference.components.VariableFixationFinder import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImpl @@ -22,85 +23,19 @@ import org.jetbrains.kotlin.resolve.calls.inference.model.VariableWithConstraint import org.jetbrains.kotlin.resolve.calls.model.PostponedResolvedAtomMarker import org.jetbrains.kotlin.types.model.KotlinTypeMarker import org.jetbrains.kotlin.types.model.TypeConstructorMarker -import org.jetbrains.kotlin.types.model.isIntegerLiteralTypeConstructor import org.jetbrains.kotlin.types.model.typeConstructor import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.addToStdlib.safeAs - -fun Candidate.computeCompletionMode( - components: InferenceComponents, - expectedType: FirTypeRef?, - currentReturnType: ConeKotlinType? -): KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode { - // Presence of expected type means that we trying to complete outermost call => completion mode should be full - if (expectedType != null) return KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode.FULL - - // This is questionable as null return type can be only for error call - if (currentReturnType == null || currentReturnType is ConeIntegerLiteralType) - return KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode.PARTIAL - - return when { - // Consider call foo(bar(x)), if return type of bar is a proper one, then we can complete resolve for bar => full completion mode - // Otherwise, we shouldn't complete bar until we process call foo - csBuilder.isProperType(currentReturnType) -> KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode.FULL - - // Nested call is connected with the outer one through the UPPER constraint (returnType <: expectedOuterType) - // This means that there will be no new LOWER constraints => - // it's possible to complete call now if there are proper LOWER constraints - csBuilder.isTypeVariable(currentReturnType) -> - if (hasProperNonTrivialLowerConstraints(components, currentReturnType)) - KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode.FULL - else - KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode.PARTIAL - - // Return type has proper equal constraints => there is no need in the outer call - containsTypeVariablesWithProperEqualConstraints(components, currentReturnType) -> KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode.FULL - - else -> KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode.PARTIAL - } -} - val Candidate.csBuilder: NewConstraintSystemImpl get() = system.getBuilder() -private fun Candidate.containsTypeVariablesWithProperEqualConstraints(components: InferenceComponents, type: ConeKotlinType): Boolean = - with(components.ctx){ - for ((variableConstructor, variableWithConstraints) in csBuilder.currentStorage().notFixedTypeVariables) { - if (!type.contains { it.typeConstructor() == variableConstructor }) continue - - val constraints = variableWithConstraints.constraints - val onlyProperEqualConstraints = - constraints.isNotEmpty() && constraints.any { it.kind.isEqual() && csBuilder.isProperType(it.type) } - - if (!onlyProperEqualConstraints) return false - } - - return true - } - -private fun Candidate.hasProperNonTrivialLowerConstraints(components: InferenceComponents, typeVariable: ConeKotlinType): Boolean { - assert(csBuilder.isTypeVariable(typeVariable)) { "$typeVariable is not a type variable" } - - val context = components.ctx - val constructor = typeVariable.typeConstructor(context) - val variableWithConstraints = csBuilder.currentStorage().notFixedTypeVariables[constructor] ?: return false - val constraints = variableWithConstraints.constraints - // TODO: support Exact annotation - // see KotlinCallCompleter:244 - return constraints.isNotEmpty() && constraints.any { - !it.type.typeConstructor(context).isIntegerLiteralTypeConstructor(context) && - (it.kind.isLower() || it.kind.isEqual()) && csBuilder.isProperType(it.type) - } - -} - class ConstraintSystemCompleter(private val components: BodyResolveComponents) { private val variableFixationFinder = VariableFixationFinder(components.inferenceComponents.trivialConstraintTypeInferenceOracle) fun complete( c: KotlinConstraintSystemCompleter.Context, - completionMode: KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode, + completionMode: ConstraintSystemCompletionMode, topLevelAtoms: List, candidateReturnType: ConeKotlinType, analyze: (PostponedResolvedAtom) -> Unit @@ -117,13 +52,13 @@ class ConstraintSystemCompleter(private val components: BodyResolveComponents) { ) ?: break if ( - completionMode == KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode.FULL && + completionMode == ConstraintSystemCompletionMode.FULL && resolveLambdaOrCallableReferenceWithTypeVariableAsExpectedType(c, variableForFixation, postponedAtoms, analyze) ) { continue } - if (variableForFixation.hasProperConstraint || completionMode == KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode.FULL) { + if (variableForFixation.hasProperConstraint || completionMode == ConstraintSystemCompletionMode.FULL) { val variableWithConstraints = c.notFixedTypeVariables.getValue(variableForFixation.variable) fixVariable(c, candidateReturnType, variableWithConstraints, emptyList()) @@ -137,7 +72,7 @@ class ConstraintSystemCompleter(private val components: BodyResolveComponents) { break } - if (completionMode == KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode.FULL) { + if (completionMode == ConstraintSystemCompletionMode.FULL) { // force resolution for all not-analyzed argument's getOrderedNotAnalyzedPostponedArguments(topLevelAtoms).forEach(analyze) // diff --git a/compiler/testData/codegen/box/elvis/genericElvisWithNullLHS.kt b/compiler/testData/codegen/box/elvis/genericElvisWithNullLHS.kt index 6f8a18afbff..17981e5031e 100644 --- a/compiler/testData/codegen/box/elvis/genericElvisWithNullLHS.kt +++ b/compiler/testData/codegen/box/elvis/genericElvisWithNullLHS.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND_FIR: JVM_IR // WITH_RUNTIME // KJS_WITH_FULL_RUNTIME diff --git a/compiler/testData/codegen/box/regressions/kt33638.kt b/compiler/testData/codegen/box/regressions/kt33638.kt index 463dbdbb9b9..7570c86435e 100644 --- a/compiler/testData/codegen/box/regressions/kt33638.kt +++ b/compiler/testData/codegen/box/regressions/kt33638.kt @@ -1,7 +1,6 @@ // !LANGUAGE: +NewInference // WITH_RUNTIME // KJS_WITH_FULL_RUNTIME -// IGNORE_BACKEND_FIR: JVM_IR class Holder(val list: List?) diff --git a/compiler/testData/diagnostics/tests/generics/innerClasses/simpleIn.fir.fail b/compiler/testData/diagnostics/tests/generics/innerClasses/simpleIn.fir.fail new file mode 100644 index 00000000000..4f77a424ff8 --- /dev/null +++ b/compiler/testData/diagnostics/tests/generics/innerClasses/simpleIn.fir.fail @@ -0,0 +1,2 @@ +Failures detected in FirBodyResolveTransformerAdapter, file: /simpleIn.fir.kt +Cause: java.lang.RuntimeException: While resolving call R|/outer|.set#(R?C|/infer|(String())) diff --git a/compiler/testData/diagnostics/tests/inference/regressions/kt32250.fir.kt b/compiler/testData/diagnostics/tests/inference/regressions/kt32250.fir.kt deleted file mode 100644 index bf32f159b54..00000000000 --- a/compiler/testData/diagnostics/tests/inference/regressions/kt32250.fir.kt +++ /dev/null @@ -1,30 +0,0 @@ -// !LANGUAGE: +NewInference -// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE - -interface I { - fun foo() -} - -data class Pair(val fst: X, val snd: Y) - -class A(f: Pair Unit>? = null) - -class B(f: ((I) -> Unit)? = null) - -fun main() { - val cond = true - A( - if (cond) { - Pair(1, { baz -> baz.foo() }) - } else { - null - } - ) - B( - if (cond) { - { baz -> baz.foo() } - } else { - null - } - ) -} diff --git a/compiler/testData/diagnostics/tests/inference/regressions/kt32250.kt b/compiler/testData/diagnostics/tests/inference/regressions/kt32250.kt index 47302f2ca75..ae4d1393b61 100644 --- a/compiler/testData/diagnostics/tests/inference/regressions/kt32250.kt +++ b/compiler/testData/diagnostics/tests/inference/regressions/kt32250.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !LANGUAGE: +NewInference // !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE diff --git a/compiler/testData/diagnostics/testsWithStdLib/kt7585/delegate.fir.fail b/compiler/testData/diagnostics/testsWithStdLib/kt7585/delegate.fir.fail new file mode 100644 index 00000000000..b1cc486f92a --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/kt7585/delegate.fir.fail @@ -0,0 +1,17 @@ +Failures detected in FirImplicitTypeBodyResolveTransformerAdapter, file: /My.kt +Cause: java.lang.RuntimeException: While resolving call Q|Properties|.R?C|/Properties.calcVal|( = calcVal@fun .(): { + lval y: = x#.plus#(IntegerLiteral(1)) + when () { + CMP(>, y#.compareTo#(IntegerLiteral(0))) -> { + MyBase#.derivedWrapper#() + } + CMP(<, x#.compareTo#(IntegerLiteral(0))) -> { + MyBase#.exoticWrapper#(x#) + } + else -> { + throw java#.lang#.NullPointerException#(String()) + } + } + +} +) diff --git a/compiler/testData/diagnostics/testsWithStdLib/kt7585/delegate.fir.kt b/compiler/testData/diagnostics/testsWithStdLib/kt7585/delegate.fir.kt new file mode 100644 index 00000000000..557e9ba6a6b --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/kt7585/delegate.fir.kt @@ -0,0 +1,76 @@ +// !WITH_NEW_INFERENCE +// NI_EXPECTED_FILE +// JAVAC_EXPECTED_FILE +// FILE: Base.java + +public interface Base {} + +// FILE: Other.java + +public interface Other {} + +// FILE: Derived.java + +public final class Derived implements Base, Other {} + +// FILE: Exotic.java + +public final class Exotic implements Base, Other { + + int x; + + Exotic(int x) { + this.x = x; + } +} + +// FILE: Properties.java + +import kotlin.jvm.functions.Function0; + +class Val { + + Function0 initializer; + + Val(Function0 initializer) { + this.initializer = initializer; + } + + T getValue(Object instance, Object metadata) { + return initializer.invoke(); + } +} + +class Properties { + static Val calcVal(Function0 initializer) { + return new Val(initializer); + } +} + +// FILE: My.kt + +open class Wrapper(val v: T) + +class DerivedWrapper(v: Derived<*>): Wrapper>(v) + +class ExoticWrapper(v: Exotic): Wrapper(v) + +object MyBase { + + fun derived() = Derived() + fun exotic(x: Int) = Exotic(x) + + fun derivedWrapper() = DerivedWrapper(derived()) + fun exoticWrapper(x: Int) = ExoticWrapper(exotic(x)) +} + +class My(val x: Int) { + val wrapper/*: Wrapper<*>*/ by Properties.calcVal { + val y = x + 1 + when { + y > 0 -> MyBase.derivedWrapper() + x < 0 -> MyBase.exoticWrapper(x) + else -> throw java.lang.NullPointerException("") + } + } +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/kt7585/delegate.kt b/compiler/testData/diagnostics/testsWithStdLib/kt7585/delegate.kt index 96207a9379a..557e9ba6a6b 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/kt7585/delegate.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/kt7585/delegate.kt @@ -1,4 +1,3 @@ -// FIR_IDENTICAL // !WITH_NEW_INFERENCE // NI_EXPECTED_FILE // JAVAC_EXPECTED_FILE diff --git a/compiler/testData/ir/irText/expressions/whenUnusedExpression.fir.txt b/compiler/testData/ir/irText/expressions/whenUnusedExpression.fir.txt index 645e254491f..72b8ef480c9 100644 --- a/compiler/testData/ir/irText/expressions/whenUnusedExpression.fir.txt +++ b/compiler/testData/ir/irText/expressions/whenUnusedExpression.fir.txt @@ -3,7 +3,7 @@ FILE fqName: fileName:/whenUnusedExpression.kt VALUE_PARAMETER name:b index:0 type:kotlin.Boolean VALUE_PARAMETER name:i index:1 type:kotlin.Int BLOCK_BODY - WHEN type=kotlin.Int? origin=IF + WHEN type=kotlin.Int origin=IF BRANCH if: GET_VAR 'b: kotlin.Boolean declared in .test' type=kotlin.Boolean origin=null then: BLOCK type=kotlin.Int origin=WHEN