FIR: Support adding expect type to calls in foo() as R position
See https://kotlinlang.org/docs/whatsnew12.html#support-for-foo-as-a-shorthand-for-this-foo
This commit is contained in:
committed by
TeamCityServer
parent
6136526a3a
commit
d932d5b0a5
+6
@@ -12197,6 +12197,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
|||||||
runTest("compiler/testData/diagnostics/tests/inference/expectedTypeWithGenerics.kt");
|
runTest("compiler/testData/diagnostics/tests/inference/expectedTypeWithGenerics.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("expectedTypeWithGenericsSafeCalls.kt")
|
||||||
|
public void testExpectedTypeWithGenericsSafeCalls() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/inference/expectedTypeWithGenericsSafeCalls.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("extensionLambdasAndArrow.kt")
|
@TestMetadata("extensionLambdasAndArrow.kt")
|
||||||
public void testExtensionLambdasAndArrow() throws Exception {
|
public void testExtensionLambdasAndArrow() throws Exception {
|
||||||
|
|||||||
+6
@@ -12197,6 +12197,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
|||||||
runTest("compiler/testData/diagnostics/tests/inference/expectedTypeWithGenerics.kt");
|
runTest("compiler/testData/diagnostics/tests/inference/expectedTypeWithGenerics.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("expectedTypeWithGenericsSafeCalls.kt")
|
||||||
|
public void testExpectedTypeWithGenericsSafeCalls() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/inference/expectedTypeWithGenericsSafeCalls.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("extensionLambdasAndArrow.kt")
|
@TestMetadata("extensionLambdasAndArrow.kt")
|
||||||
public void testExtensionLambdasAndArrow() throws Exception {
|
public void testExtensionLambdasAndArrow() throws Exception {
|
||||||
|
|||||||
+9
-1
@@ -9,8 +9,10 @@ import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirFunction
|
||||||
import org.jetbrains.kotlin.fir.expressions.*
|
import org.jetbrains.kotlin.fir.expressions.*
|
||||||
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.inference.isFunctionForExpectTypeFromCastFeature
|
||||||
import org.jetbrains.kotlin.fir.typeContext
|
import org.jetbrains.kotlin.fir.typeContext
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
||||||
@@ -34,7 +36,7 @@ object FirUselessTypeOperationCallChecker : FirTypeOperatorCallChecker() {
|
|||||||
} else {
|
} else {
|
||||||
targetType
|
targetType
|
||||||
}
|
}
|
||||||
if (isRefinementUseless(context, candidateType, refinedTargetType, shouldCheckForExactType(expression, context))) {
|
if (isRefinementUseless(context, candidateType, refinedTargetType, shouldCheckForExactType(expression, context), arg)) {
|
||||||
when (expression.operation) {
|
when (expression.operation) {
|
||||||
FirOperation.IS -> reporter.reportOn(expression.source, FirErrors.USELESS_IS_CHECK, true, context)
|
FirOperation.IS -> reporter.reportOn(expression.source, FirErrors.USELESS_IS_CHECK, true, context)
|
||||||
FirOperation.NOT_IS -> reporter.reportOn(expression.source, FirErrors.USELESS_IS_CHECK, false, context)
|
FirOperation.NOT_IS -> reporter.reportOn(expression.source, FirErrors.USELESS_IS_CHECK, false, context)
|
||||||
@@ -62,8 +64,14 @@ object FirUselessTypeOperationCallChecker : FirTypeOperatorCallChecker() {
|
|||||||
candidateType: ConeKotlinType,
|
candidateType: ConeKotlinType,
|
||||||
targetType: ConeKotlinType,
|
targetType: ConeKotlinType,
|
||||||
shouldCheckForExactType: Boolean,
|
shouldCheckForExactType: Boolean,
|
||||||
|
arg: FirExpression,
|
||||||
): Boolean {
|
): Boolean {
|
||||||
return if (shouldCheckForExactType) {
|
return if (shouldCheckForExactType) {
|
||||||
|
if (arg is FirFunctionCall) {
|
||||||
|
val function = arg.toResolvedCallableSymbol()?.fir as? FirFunction
|
||||||
|
if (function != null && function.isFunctionForExpectTypeFromCastFeature()) return false
|
||||||
|
}
|
||||||
|
|
||||||
isExactTypeCast(context, candidateType, targetType)
|
isExactTypeCast(context, candidateType, targetType)
|
||||||
} else {
|
} else {
|
||||||
isUpcast(context, candidateType, targetType)
|
isUpcast(context, candidateType, targetType)
|
||||||
|
|||||||
@@ -26,11 +26,16 @@ sealed class ResolutionMode {
|
|||||||
class WithStatus(val status: FirDeclarationStatus) : ResolutionMode()
|
class WithStatus(val status: FirDeclarationStatus) : ResolutionMode()
|
||||||
|
|
||||||
class LambdaResolution(val expectedReturnTypeRef: FirResolvedTypeRef?) : ResolutionMode()
|
class LambdaResolution(val expectedReturnTypeRef: FirResolvedTypeRef?) : ResolutionMode()
|
||||||
|
|
||||||
|
class WithExpectedTypeFromCast(
|
||||||
|
val expectedTypeRef: FirTypeRef,
|
||||||
|
) : ResolutionMode()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ResolutionMode.expectedType(components: BodyResolveComponents): FirTypeRef? = when (this) {
|
fun ResolutionMode.expectedType(components: BodyResolveComponents, allowFromCast: Boolean = false): FirTypeRef? = when (this) {
|
||||||
is ResolutionMode.WithExpectedType -> expectedTypeRef
|
is ResolutionMode.WithExpectedType -> expectedTypeRef
|
||||||
is ResolutionMode.ContextIndependent -> components.noExpectedType
|
is ResolutionMode.ContextIndependent -> components.noExpectedType
|
||||||
|
is ResolutionMode.WithExpectedTypeFromCast -> expectedTypeRef.takeIf { allowFromCast }
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+48
-12
@@ -8,16 +8,14 @@ package org.jetbrains.kotlin.fir.resolve.inference
|
|||||||
import org.jetbrains.kotlin.fir.*
|
import org.jetbrains.kotlin.fir.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
|
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
|
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirFunction
|
||||||
import org.jetbrains.kotlin.fir.declarations.builder.buildValueParameter
|
import org.jetbrains.kotlin.fir.declarations.builder.buildValueParameter
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirResolvable
|
import org.jetbrains.kotlin.fir.expressions.FirResolvable
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
|
import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
|
||||||
import org.jetbrains.kotlin.fir.resolve.ResolutionMode
|
import org.jetbrains.kotlin.fir.resolve.ResolutionMode
|
||||||
import org.jetbrains.kotlin.fir.resolve.calls.Candidate
|
import org.jetbrains.kotlin.fir.resolve.calls.*
|
||||||
import org.jetbrains.kotlin.fir.resolve.calls.FirNamedReferenceWithCandidate
|
|
||||||
import org.jetbrains.kotlin.fir.resolve.calls.ResolutionContext
|
|
||||||
import org.jetbrains.kotlin.fir.resolve.calls.isUnitOrFlexibleUnit
|
|
||||||
import org.jetbrains.kotlin.fir.resolve.expectedType
|
import org.jetbrains.kotlin.fir.resolve.expectedType
|
||||||
import org.jetbrains.kotlin.fir.resolve.inference.model.ConeArgumentConstraintPosition
|
import org.jetbrains.kotlin.fir.resolve.inference.model.ConeArgumentConstraintPosition
|
||||||
import org.jetbrains.kotlin.fir.resolve.inference.model.ConeExpectedTypeConstraintPosition
|
import org.jetbrains.kotlin.fir.resolve.inference.model.ConeExpectedTypeConstraintPosition
|
||||||
@@ -59,20 +57,22 @@ class FirCallCompleter(
|
|||||||
expectedTypeRef: FirTypeRef?,
|
expectedTypeRef: FirTypeRef?,
|
||||||
expectedTypeMismatchIsReportedInChecker: Boolean = false,
|
expectedTypeMismatchIsReportedInChecker: Boolean = false,
|
||||||
): CompletionResult<T> where T : FirResolvable, T : FirStatement =
|
): CompletionResult<T> where T : FirResolvable, T : FirStatement =
|
||||||
completeCall(call, expectedTypeRef, mayBeCoercionToUnitApplied = false, expectedTypeMismatchIsReportedInChecker)
|
completeCall(call, expectedTypeRef, mayBeCoercionToUnitApplied = false, expectedTypeMismatchIsReportedInChecker, isFromCast = false)
|
||||||
|
|
||||||
fun <T> completeCall(call: T, data: ResolutionMode): CompletionResult<T> where T : FirResolvable, T : FirStatement =
|
fun <T> completeCall(call: T, data: ResolutionMode): CompletionResult<T> where T : FirResolvable, T : FirStatement =
|
||||||
completeCall(
|
completeCall(
|
||||||
call,
|
call,
|
||||||
data.expectedType(components),
|
data.expectedType(components, allowFromCast = true),
|
||||||
(data as? ResolutionMode.WithExpectedType)?.mayBeCoercionToUnitApplied == true,
|
(data as? ResolutionMode.WithExpectedType)?.mayBeCoercionToUnitApplied == true,
|
||||||
(data as? ResolutionMode.WithExpectedType)?.expectedTypeMismatchIsReportedInChecker == true,
|
(data as? ResolutionMode.WithExpectedType)?.expectedTypeMismatchIsReportedInChecker == true,
|
||||||
|
isFromCast = data is ResolutionMode.WithExpectedTypeFromCast,
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun <T> completeCall(
|
private fun <T> completeCall(
|
||||||
call: T, expectedTypeRef: FirTypeRef?,
|
call: T, expectedTypeRef: FirTypeRef?,
|
||||||
mayBeCoercionToUnitApplied: Boolean,
|
mayBeCoercionToUnitApplied: Boolean,
|
||||||
expectedTypeMismatchIsReportedInChecker: Boolean,
|
expectedTypeMismatchIsReportedInChecker: Boolean,
|
||||||
|
isFromCast: Boolean,
|
||||||
): CompletionResult<T>
|
): CompletionResult<T>
|
||||||
where T : FirResolvable, T : FirStatement {
|
where T : FirResolvable, T : FirStatement {
|
||||||
val typeRef = components.typeFromCallee(call)
|
val typeRef = components.typeFromCallee(call)
|
||||||
@@ -93,15 +93,24 @@ class FirCallCompleter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (expectedTypeRef is FirResolvedTypeRef) {
|
if (expectedTypeRef is FirResolvedTypeRef) {
|
||||||
val expectedTypeConstraintPosition = ConeExpectedTypeConstraintPosition(expectedTypeMismatchIsReportedInChecker)
|
if (isFromCast) {
|
||||||
if (expectedTypeRef.coneType.isUnitOrFlexibleUnit && mayBeCoercionToUnitApplied) {
|
if (candidate.isFunctionForExpectTypeFromCastFeature()) {
|
||||||
if (candidate.system.notFixedTypeVariables.isNotEmpty()) {
|
candidate.system.addSubtypeConstraint(
|
||||||
candidate.system.addSubtypeConstraintIfCompatible(
|
initialType, expectedTypeRef.type,
|
||||||
initialType, expectedTypeRef.type, expectedTypeConstraintPosition
|
ConeExpectedTypeConstraintPosition(expectedTypeMismatchIsReportedInChecker = false),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
candidate.system.addSubtypeConstraint(initialType, expectedTypeRef.type, expectedTypeConstraintPosition)
|
val expectedTypeConstraintPosition = ConeExpectedTypeConstraintPosition(expectedTypeMismatchIsReportedInChecker)
|
||||||
|
if (expectedTypeRef.coneType.isUnitOrFlexibleUnit && mayBeCoercionToUnitApplied) {
|
||||||
|
if (candidate.system.notFixedTypeVariables.isNotEmpty()) {
|
||||||
|
candidate.system.addSubtypeConstraintIfCompatible(
|
||||||
|
initialType, expectedTypeRef.type, expectedTypeConstraintPosition
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
candidate.system.addSubtypeConstraint(initialType, expectedTypeRef.type, expectedTypeConstraintPosition)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -288,3 +297,30 @@ class FirCallCompleter(
|
|||||||
this, TypeApproximatorConfiguration.FinalApproximationAfterResolutionAndInference
|
this, TypeApproximatorConfiguration.FinalApproximationAfterResolutionAndInference
|
||||||
) ?: this
|
) ?: this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun Candidate.isFunctionForExpectTypeFromCastFeature(): Boolean {
|
||||||
|
if (typeArgumentMapping != TypeArgumentMapping.NoExplicitArguments) return false
|
||||||
|
val fir = symbol.fir as? FirFunction ?: return false
|
||||||
|
|
||||||
|
return fir.isFunctionForExpectTypeFromCastFeature()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expect type is only being added to calls in a position of cast argument: foo() as R
|
||||||
|
// And that call should be resolved to something materialize()-like: it returns its single generic parameter and doesn't have value parameters
|
||||||
|
// fun <T> materialize(): T
|
||||||
|
fun FirFunction<*>.isFunctionForExpectTypeFromCastFeature(): Boolean {
|
||||||
|
val typeParameter = typeParameters.singleOrNull() ?: return false
|
||||||
|
|
||||||
|
val returnType = returnTypeRef.coneTypeSafe<ConeKotlinType>() ?: return false
|
||||||
|
|
||||||
|
if ((returnType.lowerBoundIfFlexible() as? ConeTypeParameterType)?.lookupTag != typeParameter.symbol.toLookupTag()) return false
|
||||||
|
|
||||||
|
fun FirTypeRef.isBadType() =
|
||||||
|
coneTypeSafe<ConeKotlinType>()
|
||||||
|
?.contains { (it.lowerBoundIfFlexible() as? ConeTypeParameterType)?.lookupTag == typeParameter.symbol.toLookupTag() } != false
|
||||||
|
|
||||||
|
if (valueParameters.any { it.returnTypeRef.isBadType() } || receiverTypeRef?.isBadType() == true) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -760,8 +760,8 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
|
|||||||
)
|
)
|
||||||
lambda.addReturn()
|
lambda.addReturn()
|
||||||
}
|
}
|
||||||
is ResolutionMode.WithStatus -> {
|
is ResolutionMode.WithStatus, is ResolutionMode.WithExpectedTypeFromCast -> {
|
||||||
throw AssertionError("Should not be here in WithStatus mode")
|
throw AssertionError("Should not be here in WithStatus/WithExpectedTypeFromCast mode")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+32
-1
@@ -594,7 +594,7 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform
|
|||||||
): FirStatement {
|
): FirStatement {
|
||||||
val resolved = components.typeResolverTransformer.withAllowedBareTypes {
|
val resolved = components.typeResolverTransformer.withAllowedBareTypes {
|
||||||
typeOperatorCall.transformConversionTypeRef(transformer, ResolutionMode.ContextIndependent)
|
typeOperatorCall.transformConversionTypeRef(transformer, ResolutionMode.ContextIndependent)
|
||||||
}.transformOtherChildren(transformer, ResolutionMode.ContextIndependent)
|
}.transformTypeOperatorCallChildren()
|
||||||
|
|
||||||
val conversionTypeRef = resolved.conversionTypeRef.withTypeArgumentsForBareType(resolved.argument)
|
val conversionTypeRef = resolved.conversionTypeRef.withTypeArgumentsForBareType(resolved.argument)
|
||||||
resolved.transformChildren(object : FirDefaultTransformer<Any?>() {
|
resolved.transformChildren(object : FirDefaultTransformer<Any?>() {
|
||||||
@@ -636,6 +636,37 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform
|
|||||||
return resolved
|
return resolved
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun FirTypeOperatorCall.transformTypeOperatorCallChildren(): FirTypeOperatorCall {
|
||||||
|
if (operation == FirOperation.AS || operation == FirOperation.SAFE_AS) {
|
||||||
|
val argument = argumentList.arguments.singleOrNull() ?: error("Not a single argument: ${this.render()}")
|
||||||
|
|
||||||
|
// For calls in the form of (materialize() as MyClass) we've got a special rule that adds expect type to the `materialize()` call
|
||||||
|
// AS operator doesn't add expected type to any other expressions
|
||||||
|
// See https://kotlinlang.org/docs/whatsnew12.html#support-for-foo-as-a-shorthand-for-this-foo
|
||||||
|
// And limitations at org.jetbrains.kotlin.fir.resolve.inference.FirCallCompleterKt.isFunctionForExpectTypeFromCastFeature(org.jetbrains.kotlin.fir.declarations.FirFunction<?>)
|
||||||
|
if (argument is FirFunctionCall || (argument is FirSafeCallExpression && argument.regularQualifiedAccess is FirFunctionCall)) {
|
||||||
|
val expectedType = conversionTypeRef.coneTypeSafe<ConeKotlinType>()?.takeIf {
|
||||||
|
// is not bare type
|
||||||
|
it !is ConeClassLikeType ||
|
||||||
|
it.typeArguments.isNotEmpty() ||
|
||||||
|
(it.lookupTag.toSymbol(session)?.fir as? FirTypeParameterRefsOwner)?.typeParameters?.isEmpty() == true
|
||||||
|
}?.let {
|
||||||
|
if (operation == FirOperation.SAFE_AS)
|
||||||
|
it.withNullability(ConeNullability.NULLABLE, session.typeContext)
|
||||||
|
else
|
||||||
|
it
|
||||||
|
}
|
||||||
|
|
||||||
|
if (expectedType != null) {
|
||||||
|
val newMode = ResolutionMode.WithExpectedTypeFromCast(conversionTypeRef.withReplacedConeType(expectedType))
|
||||||
|
return transformOtherChildren(transformer, newMode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return transformOtherChildren(transformer, ResolutionMode.ContextIndependent)
|
||||||
|
}
|
||||||
|
|
||||||
override fun transformCheckNotNullCall(
|
override fun transformCheckNotNullCall(
|
||||||
checkNotNullCall: FirCheckNotNullCall,
|
checkNotNullCall: FirCheckNotNullCall,
|
||||||
data: ResolutionMode,
|
data: ResolutionMode,
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
|||||||
Vendored
+1
-1
@@ -8,6 +8,6 @@ object CommonCase {
|
|||||||
operator fun <D, E, R> Fas<D, E, R>.provideDelegate(host: D, p: Any?): Fas<D, E, R> = TODO()
|
operator fun <D, E, R> Fas<D, E, R>.provideDelegate(host: D, p: Any?): Fas<D, E, R> = TODO()
|
||||||
operator fun <D, E, R> Fas<D, E, R>.getValue(receiver: E, p: Any?): R = TODO()
|
operator fun <D, E, R> Fas<D, E, R>.getValue(receiver: E, p: Any?): R = TODO()
|
||||||
|
|
||||||
val Long.test1: String by <!TYPE_MISMATCH!>delegate()<!> // common test, not working because of Inference1
|
val Long.test1: String by <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER, NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER, NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>delegate<!>() // common test, not working because of Inference1
|
||||||
val Long.test2: String by delegate<CommonCase, Long, String>() // should work
|
val Long.test2: String by delegate<CommonCase, Long, String>() // should work
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -13,6 +13,6 @@ val asA = <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo<!>().<!UNRESOLVED_RE
|
|||||||
val receiverParenthesized = (<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo<!>()).<!UNRESOLVED_REFERENCE!>fooA<!>() as A
|
val receiverParenthesized = (<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo<!>()).<!UNRESOLVED_REFERENCE!>fooA<!>() as A
|
||||||
val no2A = A().<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>fooA<!>().<!UNRESOLVED_REFERENCE!>fooA<!>() as A
|
val no2A = A().<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>fooA<!>().<!UNRESOLVED_REFERENCE!>fooA<!>() as A
|
||||||
|
|
||||||
val correct1 = A().<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>fooA<!>() as A
|
val correct1 = A().fooA() as A
|
||||||
val correct2 = foo<A>().<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>fooA<!>() as A
|
val correct2 = foo<A>().fooA() as A
|
||||||
val correct3 = A().fooA<A>().<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>fooA<!>() as A
|
val correct3 = A().fooA<A>().fooA() as A
|
||||||
|
|||||||
@@ -4,17 +4,17 @@ fun <T> foo(): T = TODO()
|
|||||||
|
|
||||||
fun <V> id(value: V) = value
|
fun <V> id(value: V) = value
|
||||||
|
|
||||||
val asString = <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo<!>() as String
|
val asString = foo() as String
|
||||||
|
|
||||||
val viaId = <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER, NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>id<!>(foo()) as String
|
val viaId = <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER, NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>id<!>(foo()) as String
|
||||||
|
|
||||||
val insideId = id(<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo<!>() as String)
|
val insideId = id(foo() as String)
|
||||||
|
|
||||||
val asList = <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo<!>() as List<String>
|
val asList = foo() as List<String>
|
||||||
|
|
||||||
val asStarList = <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo<!>() as List<*>
|
val asStarList = foo() as List<*>
|
||||||
|
|
||||||
val safeAs = <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo<!>() as? String
|
val safeAs = foo() as? String
|
||||||
|
|
||||||
val fromIs = <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo<!>() is String
|
val fromIs = <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo<!>() is String
|
||||||
val fromNoIs = <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo<!>() !is String
|
val fromNoIs = <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo<!>() !is String
|
||||||
|
|||||||
+3
-3
@@ -11,6 +11,6 @@ class A {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val x = A().<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo<!>() as String
|
val x = A().foo() as String
|
||||||
val y = A.<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo2<!>() as String
|
val y = A.foo2() as String
|
||||||
val z = pp.A.<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo2<!>() as String
|
val z = pp.A.foo2() as String
|
||||||
|
|||||||
+5
-5
@@ -8,15 +8,15 @@ fun <T> foo(): T = TODO()
|
|||||||
|
|
||||||
fun <V> id(value: V) = value
|
fun <V> id(value: V) = value
|
||||||
|
|
||||||
val par1 = (<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo<!>()) as String
|
val par1 = (foo()) as String
|
||||||
val par2 = ((<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo<!>())) as String
|
val par2 = ((foo())) as String
|
||||||
|
|
||||||
val par3 = (dd@ (<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo<!>())) as String
|
val par3 = (dd@ (foo())) as String
|
||||||
|
|
||||||
val par4 = ( @bar() (<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo<!>())) as String
|
val par4 = ( @bar() (foo())) as String
|
||||||
|
|
||||||
object X {
|
object X {
|
||||||
fun <T> foo(): T = TODO()
|
fun <T> foo(): T = TODO()
|
||||||
}
|
}
|
||||||
|
|
||||||
val par5 = ( @bar() X.<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo<!>()) as String
|
val par5 = ( @bar() X.foo()) as String
|
||||||
|
|||||||
+3
-3
@@ -5,13 +5,13 @@ class X<S> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun test(x: X<Number>) {
|
fun test(x: X<Number>) {
|
||||||
val y = x.<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo<!>() as Int
|
val y = x.foo() as Int
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <S, D: S> g() {
|
fun <S, D: S> g() {
|
||||||
fun <T : S> foo(): T = TODO()
|
fun <T : S> foo(): T = TODO()
|
||||||
|
|
||||||
val y = <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo<!>() as Int
|
val y = <!NEW_INFERENCE_ERROR!>foo()<!> as Int
|
||||||
|
|
||||||
val y2 = <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo<!>() as D
|
val y2 = foo() as D
|
||||||
}
|
}
|
||||||
|
|||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
|
// SKIP_TXT
|
||||||
|
// !LANGUAGE: +ExpectedTypeFromCast
|
||||||
|
|
||||||
|
class X {
|
||||||
|
fun <T> foo(): T = TODO()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test(x: X?) {
|
||||||
|
val y = x?.foo() as Int
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
// !LANGUAGE: +ExpectedTypeFromCast
|
||||||
|
// !DIAGNOSTICS: -UNUSED_VARIABLE -DEBUG_INFO_LEAKING_THIS
|
||||||
|
|
||||||
|
// FILE: a/View.java
|
||||||
|
package a;
|
||||||
|
|
||||||
|
public class View {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: a/Test.java
|
||||||
|
package a;
|
||||||
|
|
||||||
|
public class Test {
|
||||||
|
public <T extends View> T findViewById(int id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: 1.kt
|
||||||
|
package a
|
||||||
|
|
||||||
|
|
||||||
|
class X : View()
|
||||||
|
|
||||||
|
class Y<T> : View()
|
||||||
|
|
||||||
|
val xExplicit: X = Test().findViewById(0)
|
||||||
|
val xCast = Test().findViewById(0) as X
|
||||||
|
|
||||||
|
val xCastExplicitType = Test().findViewById<X>(0) as X
|
||||||
|
val xSafeCastExplicitType = Test().findViewById<X>(0) as? X
|
||||||
|
|
||||||
|
val yExplicit: Y<String> = Test().findViewById(0)
|
||||||
|
val yCast = Test().findViewById(0) as Y<String>
|
||||||
|
|
||||||
|
|
||||||
|
class TestChild : Test() {
|
||||||
|
val xExplicit: X = findViewById(0)
|
||||||
|
val xCast = findViewById(0) as X
|
||||||
|
|
||||||
|
val yExplicit: Y<String> = findViewById(0)
|
||||||
|
val yCast = findViewById(0) as Y<String>
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test(t: Test) {
|
||||||
|
val xExplicit: X = t.findViewById(0)
|
||||||
|
val xCast = t.findViewById(0) as X
|
||||||
|
|
||||||
|
val yExplicit: Y<String> = t.findViewById(0)
|
||||||
|
val yCast = t.findViewById(0) as Y<String>
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test2(t: Test?) {
|
||||||
|
val xSafeCallSafeCast = t?.findViewById(0) <!USELESS_CAST!>as? X<!>
|
||||||
|
val xSafeCallSafeCastExplicitType = t?.findViewById<X>(0) <!USELESS_CAST!>as? X<!>
|
||||||
|
|
||||||
|
val xSafeCallCast = t?.findViewById(0) as X
|
||||||
|
val xSafeCallCastExplicitType = t<!UNNECESSARY_SAFE_CALL!>?.<!>findViewById<X>(0) as X
|
||||||
|
}
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
// FIR_IDENTICAL
|
|
||||||
// !LANGUAGE: +ExpectedTypeFromCast
|
// !LANGUAGE: +ExpectedTypeFromCast
|
||||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -DEBUG_INFO_LEAKING_THIS
|
// !DIAGNOSTICS: -UNUSED_VARIABLE -DEBUG_INFO_LEAKING_THIS
|
||||||
|
|
||||||
@@ -25,35 +24,35 @@ class X : View()
|
|||||||
class Y<T> : View()
|
class Y<T> : View()
|
||||||
|
|
||||||
val xExplicit: X = Test().findViewById(0)
|
val xExplicit: X = Test().findViewById(0)
|
||||||
val xCast = Test().<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>findViewById<!>(0) as X
|
val xCast = Test().findViewById(0) as X
|
||||||
|
|
||||||
val xCastExplicitType = Test().findViewById<X>(0) as X
|
val xCastExplicitType = Test().findViewById<X>(0) as X
|
||||||
val xSafeCastExplicitType = Test().findViewById<X>(0) <!USELESS_CAST!>as? X<!>
|
val xSafeCastExplicitType = Test().findViewById<X>(0) <!USELESS_CAST!>as? X<!>
|
||||||
|
|
||||||
val yExplicit: Y<String> = Test().findViewById(0)
|
val yExplicit: Y<String> = Test().findViewById(0)
|
||||||
val yCast = Test().<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>findViewById<!>(0) as Y<String>
|
val yCast = Test().findViewById(0) as Y<String>
|
||||||
|
|
||||||
|
|
||||||
class TestChild : Test() {
|
class TestChild : Test() {
|
||||||
val xExplicit: X = findViewById(0)
|
val xExplicit: X = findViewById(0)
|
||||||
val xCast = <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>findViewById<!>(0) as X
|
val xCast = findViewById(0) as X
|
||||||
|
|
||||||
val yExplicit: Y<String> = findViewById(0)
|
val yExplicit: Y<String> = findViewById(0)
|
||||||
val yCast = <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>findViewById<!>(0) as Y<String>
|
val yCast = findViewById(0) as Y<String>
|
||||||
}
|
}
|
||||||
|
|
||||||
fun test(t: Test) {
|
fun test(t: Test) {
|
||||||
val xExplicit: X = t.findViewById(0)
|
val xExplicit: X = t.findViewById(0)
|
||||||
val xCast = t.<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>findViewById<!>(0) as X
|
val xCast = t.findViewById(0) as X
|
||||||
|
|
||||||
val yExplicit: Y<String> = t.findViewById(0)
|
val yExplicit: Y<String> = t.findViewById(0)
|
||||||
val yCast = t.<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>findViewById<!>(0) as Y<String>
|
val yCast = t.findViewById(0) as Y<String>
|
||||||
}
|
}
|
||||||
|
|
||||||
fun test2(t: Test?) {
|
fun test2(t: Test?) {
|
||||||
val xSafeCallSafeCast = t?.<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>findViewById<!>(0) as? X
|
val xSafeCallSafeCast = t?.findViewById(0) as? X
|
||||||
val xSafeCallSafeCastExplicitType = t?.findViewById<X>(0) <!USELESS_CAST!>as? X<!>
|
val xSafeCallSafeCastExplicitType = t?.findViewById<X>(0) <!USELESS_CAST!>as? X<!>
|
||||||
|
|
||||||
val xSafeCallCast = t?.<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>findViewById<!>(0) as X
|
val xSafeCallCast = t?.findViewById(0) as X
|
||||||
val xSafeCallCastExplicitType = t<!UNNECESSARY_SAFE_CALL!>?.<!>findViewById<X>(0) as X
|
val xSafeCallCastExplicitType = t<!UNNECESSARY_SAFE_CALL!>?.<!>findViewById<X>(0) as X
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ inline fun <reified T> foo(): T {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
val fooCall = <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo<!>() as String // T in foo should be inferred to String
|
val fooCall = foo() as String // T in foo should be inferred to String
|
||||||
fooCall checkType { _<String>() }
|
fooCall checkType { _<String>() }
|
||||||
|
|
||||||
val safeFooCall = <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo<!>() as? String
|
val safeFooCall = foo() as? String
|
||||||
safeFooCall checkType { _<String?>() }
|
safeFooCall checkType { _<String?>() }
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+6
@@ -12203,6 +12203,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
|||||||
runTest("compiler/testData/diagnostics/tests/inference/expectedTypeWithGenerics.kt");
|
runTest("compiler/testData/diagnostics/tests/inference/expectedTypeWithGenerics.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("expectedTypeWithGenericsSafeCalls.kt")
|
||||||
|
public void testExpectedTypeWithGenericsSafeCalls() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/inference/expectedTypeWithGenericsSafeCalls.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("extensionLambdasAndArrow.kt")
|
@TestMetadata("extensionLambdasAndArrow.kt")
|
||||||
public void testExtensionLambdasAndArrow() throws Exception {
|
public void testExtensionLambdasAndArrow() throws Exception {
|
||||||
|
|||||||
+5
@@ -10626,6 +10626,11 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
|
|||||||
runTest("compiler/testData/diagnostics/tests/inference/expectedTypeWithGenerics.kt");
|
runTest("compiler/testData/diagnostics/tests/inference/expectedTypeWithGenerics.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("expectedTypeWithGenericsSafeCalls.kt")
|
||||||
|
public void testExpectedTypeWithGenericsSafeCalls() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/inference/expectedTypeWithGenericsSafeCalls.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("extensionLambdasAndArrow.kt")
|
@TestMetadata("extensionLambdasAndArrow.kt")
|
||||||
public void testExtensionLambdasAndArrow() throws Exception {
|
public void testExtensionLambdasAndArrow() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/inference/extensionLambdasAndArrow.kt");
|
runTest("compiler/testData/diagnostics/tests/inference/extensionLambdasAndArrow.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user