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");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("expectedTypeWithGenericsSafeCalls.kt")
|
||||
public void testExpectedTypeWithGenericsSafeCalls() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/expectedTypeWithGenericsSafeCalls.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("extensionLambdasAndArrow.kt")
|
||||
public void testExtensionLambdasAndArrow() throws Exception {
|
||||
|
||||
+6
@@ -12197,6 +12197,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
||||
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
|
||||
@TestMetadata("extensionLambdasAndArrow.kt")
|
||||
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.FirErrors
|
||||
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.resolve.fullyExpandedType
|
||||
import org.jetbrains.kotlin.fir.resolve.inference.isFunctionForExpectTypeFromCastFeature
|
||||
import org.jetbrains.kotlin.fir.typeContext
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
||||
@@ -34,7 +36,7 @@ object FirUselessTypeOperationCallChecker : FirTypeOperatorCallChecker() {
|
||||
} else {
|
||||
targetType
|
||||
}
|
||||
if (isRefinementUseless(context, candidateType, refinedTargetType, shouldCheckForExactType(expression, context))) {
|
||||
if (isRefinementUseless(context, candidateType, refinedTargetType, shouldCheckForExactType(expression, context), arg)) {
|
||||
when (expression.operation) {
|
||||
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)
|
||||
@@ -62,8 +64,14 @@ object FirUselessTypeOperationCallChecker : FirTypeOperatorCallChecker() {
|
||||
candidateType: ConeKotlinType,
|
||||
targetType: ConeKotlinType,
|
||||
shouldCheckForExactType: Boolean,
|
||||
arg: FirExpression,
|
||||
): Boolean {
|
||||
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)
|
||||
} else {
|
||||
isUpcast(context, candidateType, targetType)
|
||||
|
||||
@@ -26,11 +26,16 @@ sealed class ResolutionMode {
|
||||
class WithStatus(val status: FirDeclarationStatus) : 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.ContextIndependent -> components.noExpectedType
|
||||
is ResolutionMode.WithExpectedTypeFromCast -> expectedTypeRef.takeIf { allowFromCast }
|
||||
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.declarations.FirAnonymousFunction
|
||||
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.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirResolvable
|
||||
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
||||
import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
|
||||
import org.jetbrains.kotlin.fir.resolve.ResolutionMode
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.Candidate
|
||||
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.calls.*
|
||||
import org.jetbrains.kotlin.fir.resolve.expectedType
|
||||
import org.jetbrains.kotlin.fir.resolve.inference.model.ConeArgumentConstraintPosition
|
||||
import org.jetbrains.kotlin.fir.resolve.inference.model.ConeExpectedTypeConstraintPosition
|
||||
@@ -59,20 +57,22 @@ class FirCallCompleter(
|
||||
expectedTypeRef: FirTypeRef?,
|
||||
expectedTypeMismatchIsReportedInChecker: Boolean = false,
|
||||
): 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 =
|
||||
completeCall(
|
||||
call,
|
||||
data.expectedType(components),
|
||||
data.expectedType(components, allowFromCast = true),
|
||||
(data as? ResolutionMode.WithExpectedType)?.mayBeCoercionToUnitApplied == true,
|
||||
(data as? ResolutionMode.WithExpectedType)?.expectedTypeMismatchIsReportedInChecker == true,
|
||||
isFromCast = data is ResolutionMode.WithExpectedTypeFromCast,
|
||||
)
|
||||
|
||||
private fun <T> completeCall(
|
||||
call: T, expectedTypeRef: FirTypeRef?,
|
||||
mayBeCoercionToUnitApplied: Boolean,
|
||||
expectedTypeMismatchIsReportedInChecker: Boolean,
|
||||
isFromCast: Boolean,
|
||||
): CompletionResult<T>
|
||||
where T : FirResolvable, T : FirStatement {
|
||||
val typeRef = components.typeFromCallee(call)
|
||||
@@ -93,15 +93,24 @@ class FirCallCompleter(
|
||||
}
|
||||
|
||||
if (expectedTypeRef is FirResolvedTypeRef) {
|
||||
val expectedTypeConstraintPosition = ConeExpectedTypeConstraintPosition(expectedTypeMismatchIsReportedInChecker)
|
||||
if (expectedTypeRef.coneType.isUnitOrFlexibleUnit && mayBeCoercionToUnitApplied) {
|
||||
if (candidate.system.notFixedTypeVariables.isNotEmpty()) {
|
||||
candidate.system.addSubtypeConstraintIfCompatible(
|
||||
initialType, expectedTypeRef.type, expectedTypeConstraintPosition
|
||||
if (isFromCast) {
|
||||
if (candidate.isFunctionForExpectTypeFromCastFeature()) {
|
||||
candidate.system.addSubtypeConstraint(
|
||||
initialType, expectedTypeRef.type,
|
||||
ConeExpectedTypeConstraintPosition(expectedTypeMismatchIsReportedInChecker = false),
|
||||
)
|
||||
}
|
||||
} 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
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
is ResolutionMode.WithStatus -> {
|
||||
throw AssertionError("Should not be here in WithStatus mode")
|
||||
is ResolutionMode.WithStatus, is ResolutionMode.WithExpectedTypeFromCast -> {
|
||||
throw AssertionError("Should not be here in WithStatus/WithExpectedTypeFromCast mode")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+32
-1
@@ -594,7 +594,7 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform
|
||||
): FirStatement {
|
||||
val resolved = components.typeResolverTransformer.withAllowedBareTypes {
|
||||
typeOperatorCall.transformConversionTypeRef(transformer, ResolutionMode.ContextIndependent)
|
||||
}.transformOtherChildren(transformer, ResolutionMode.ContextIndependent)
|
||||
}.transformTypeOperatorCallChildren()
|
||||
|
||||
val conversionTypeRef = resolved.conversionTypeRef.withTypeArgumentsForBareType(resolved.argument)
|
||||
resolved.transformChildren(object : FirDefaultTransformer<Any?>() {
|
||||
@@ -636,6 +636,37 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform
|
||||
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(
|
||||
checkNotNullCall: FirCheckNotNullCall,
|
||||
data: ResolutionMode,
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// 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>.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
|
||||
}
|
||||
|
||||
+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 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 correct2 = foo<A>().<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>fooA<!>() as A
|
||||
val correct3 = A().fooA<A>().<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>fooA<!>() as A
|
||||
val correct1 = A().fooA() as A
|
||||
val correct2 = foo<A>().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
|
||||
|
||||
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 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 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 y = A.<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo2<!>() as String
|
||||
val z = pp.A.<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo2<!>() as String
|
||||
val x = A().foo() as String
|
||||
val y = A.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
|
||||
|
||||
val par1 = (<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo<!>()) as String
|
||||
val par2 = ((<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo<!>())) as String
|
||||
val par1 = (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 {
|
||||
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>) {
|
||||
val y = x.<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo<!>() as Int
|
||||
val y = x.foo() as Int
|
||||
}
|
||||
|
||||
fun <S, D: S> g() {
|
||||
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
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -DEBUG_INFO_LEAKING_THIS
|
||||
|
||||
@@ -25,35 +24,35 @@ class X : View()
|
||||
class Y<T> : View()
|
||||
|
||||
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 xSafeCastExplicitType = Test().findViewById<X>(0) <!USELESS_CAST!>as? X<!>
|
||||
|
||||
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() {
|
||||
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 yCast = <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>findViewById<!>(0) as Y<String>
|
||||
val yCast = findViewById(0) as Y<String>
|
||||
}
|
||||
|
||||
fun test(t: Test) {
|
||||
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 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?) {
|
||||
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 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
|
||||
}
|
||||
|
||||
@@ -8,9 +8,9 @@ inline fun <reified T> foo(): T {
|
||||
}
|
||||
|
||||
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>() }
|
||||
|
||||
val safeFooCall = <!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo<!>() as? String
|
||||
val safeFooCall = foo() as? String
|
||||
safeFooCall checkType { _<String?>() }
|
||||
}
|
||||
|
||||
Generated
+6
@@ -12203,6 +12203,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
||||
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
|
||||
@TestMetadata("extensionLambdasAndArrow.kt")
|
||||
public void testExtensionLambdasAndArrow() throws Exception {
|
||||
|
||||
+5
@@ -10626,6 +10626,11 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
|
||||
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")
|
||||
public void testExtensionLambdasAndArrow() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/extensionLambdasAndArrow.kt");
|
||||
|
||||
Reference in New Issue
Block a user