[FIR] Implement deprecation for calls to overrides of hidden

#KT-65438
This commit is contained in:
Kirill Rakhman
2024-02-06 11:02:37 +01:00
committed by Space Team
parent e16f80c578
commit c6b2675089
12 changed files with 173 additions and 59 deletions
@@ -20,19 +20,15 @@ import org.jetbrains.kotlin.fir.declarations.FutureApiDeprecationInfo
import org.jetbrains.kotlin.fir.declarations.RequireKotlinDeprecationInfo import org.jetbrains.kotlin.fir.declarations.RequireKotlinDeprecationInfo
import org.jetbrains.kotlin.fir.declarations.getDeprecation import org.jetbrains.kotlin.fir.declarations.getDeprecation
import org.jetbrains.kotlin.fir.declarations.getOwnDeprecation import org.jetbrains.kotlin.fir.declarations.getOwnDeprecation
import org.jetbrains.kotlin.fir.expressions.FirAnnotation import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.FirDelegatedConstructorCall
import org.jetbrains.kotlin.fir.expressions.FirStatement
import org.jetbrains.kotlin.fir.expressions.toReference
import org.jetbrains.kotlin.fir.languageVersionSettings import org.jetbrains.kotlin.fir.languageVersionSettings
import org.jetbrains.kotlin.fir.references.resolved import org.jetbrains.kotlin.fir.references.resolved
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeCallToDeprecatedOverrideOfHidden
import org.jetbrains.kotlin.fir.resolve.firClassLike import org.jetbrains.kotlin.fir.resolve.firClassLike
import org.jetbrains.kotlin.fir.scopes.impl.typeAliasForConstructor import org.jetbrains.kotlin.fir.scopes.impl.typeAliasForConstructor
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.SymbolInternals import org.jetbrains.kotlin.fir.symbols.SymbolInternals
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol
import org.jetbrains.kotlin.metadata.ProtoBuf import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.resolve.deprecation.DeprecationInfo import org.jetbrains.kotlin.resolve.deprecation.DeprecationInfo
import org.jetbrains.kotlin.resolve.deprecation.DeprecationLevelValue import org.jetbrains.kotlin.resolve.deprecation.DeprecationLevelValue
@@ -69,6 +65,39 @@ object FirDeprecationChecker : FirBasicExpressionChecker(MppCheckerKind.Common)
} else { } else {
reportApiStatusIfNeeded(source, referencedSymbol, context, reporter, callSite = expression) reportApiStatusIfNeeded(source, referencedSymbol, context, reporter, callSite = expression)
} }
reportCallToDeprecatedOverrideOfHidden(expression, source, referencedSymbol, reporter, context)
}
private fun reportCallToDeprecatedOverrideOfHidden(
expression: FirStatement,
source: KtSourceElement?,
referencedSymbol: FirBasedSymbol<*>,
reporter: DiagnosticReporter,
context: CheckerContext,
) {
if (expression !is FirQualifiedAccessExpression) return
if (ConeCallToDeprecatedOverrideOfHidden in expression.nonFatalDiagnostics) {
val unwrappedSymbol = (referencedSymbol as? FirSyntheticPropertySymbol)?.getterSymbol?.delegateFunctionSymbol
?: referencedSymbol as? FirCallableSymbol
val callableName = unwrappedSymbol?.callableId?.callableName?.asString()
val message = getDeprecatedOverrideOfHiddenMessage(callableName)
reporter.reportOn(source, FirErrors.DEPRECATION, referencedSymbol, message, context)
}
}
internal val DeprecatedOverrideOfHiddenReplacements = mapOf(
"getFirst" to "first()",
"getLast" to "last()",
)
internal fun getDeprecatedOverrideOfHiddenMessage(callableName: String?): String {
val getFirstOrLastReplacement = DeprecatedOverrideOfHiddenReplacements[callableName]
return if (getFirstOrLastReplacement != null) {
"This declaration will be renamed in a future version of Kotlin. Please consider using the '$getFirstOrLastReplacement' stdlib extension if the collection supports fast random access."
} else {
"This declaration is redundant in Kotlin and might be removed soon."
}
} }
/** Checks if this is an access to a delegated property inside the delegated property itself. /** Checks if this is an access to a delegated property inside the delegated property itself.
@@ -330,8 +330,8 @@ var FirCallableDeclaration.isHiddenEverywhereBesideSuperCalls: HiddenEverywhereB
IsHiddenEverywhereBesideSuperCalls IsHiddenEverywhereBesideSuperCalls
) )
enum class HiddenEverywhereBesideSuperCallsStatus(val affectsOverrides: Boolean) { enum class HiddenEverywhereBesideSuperCallsStatus {
HIDDEN(true), HIDDEN_IN_DECLARING_CLASS_ONLY(false) HIDDEN, HIDDEN_IN_DECLARING_CLASS_ONLY
} }
private object IsHiddenToOvercomeSignatureClash : FirDeclarationDataKey() private object IsHiddenToOvercomeSignatureClash : FirDeclarationDataKey()
@@ -340,11 +340,25 @@ var FirCallableDeclaration.isHiddenToOvercomeSignatureClash: Boolean? by FirDecl
IsHiddenToOvercomeSignatureClash IsHiddenToOvercomeSignatureClash
) )
fun FirCallableSymbol<*>.isHidden(isSuperCall: Boolean, isOverridden: Boolean): Boolean { enum class CallToPotentiallyHiddenSymbolResult {
Hidden, Visible, VisibleWithDeprecation,
}
fun FirCallableSymbol<*>.isHidden(isSuperCall: Boolean, isOverridden: Boolean): CallToPotentiallyHiddenSymbolResult {
val fir = fir val fir = fir
return when { if (fir.isHiddenToOvercomeSignatureClash == true) {
fir.isHiddenToOvercomeSignatureClash == true -> true return CallToPotentiallyHiddenSymbolResult.Hidden
!isSuperCall && fir.isHiddenEverywhereBesideSuperCalls?.let { it.affectsOverrides || !isOverridden } == true -> true }
else -> false
val status = fir.isHiddenEverywhereBesideSuperCalls ?: return CallToPotentiallyHiddenSymbolResult.Visible
return when (status) {
// If the declaration is HIDDEN, we don't need a deprecation on supercalls because what are we warning the user about?
// The declaration can't get any more hidden.
HiddenEverywhereBesideSuperCallsStatus.HIDDEN -> if (isSuperCall) CallToPotentiallyHiddenSymbolResult.Visible else CallToPotentiallyHiddenSymbolResult.Hidden
// However, on HIDDEN_IN_DECLARING_CLASS_ONLY,
// we report a deprecation warning on super calls because we might want to rename the method in the future
// (getFirst -> first).
HiddenEverywhereBesideSuperCallsStatus.HIDDEN_IN_DECLARING_CLASS_ONLY -> if (isSuperCall || isOverridden) CallToPotentiallyHiddenSymbolResult.VisibleWithDeprecation else CallToPotentiallyHiddenSymbolResult.Hidden
} }
} }
@@ -124,7 +124,7 @@ class FirSyntheticPropertiesScope private constructor(
if (getterReturnType?.isUnit == true && CompilerConeAttributes.EnhancedNullability !in getterReturnType.attributes) return if (getterReturnType?.isUnit == true && CompilerConeAttributes.EnhancedNullability !in getterReturnType.attributes) return
// Should have Java among overridden _and_ don't have isHiddenEverywhereBesideSuperCalls among them // Should have Java among overridden _and_ don't have isHiddenEverywhereBesideSuperCalls among them
val getterCompatibility = getterSymbol.computeGetterCompatibility() val (getterCompatibility, deprecatedOverrideOfHidden) = getterSymbol.computeGetterCompatibility()
if (getterCompatibility == Incompatible) return if (getterCompatibility == Incompatible) return
var matchingSetter: FirSimpleFunction? = null var matchingSetter: FirSimpleFunction? = null
@@ -143,13 +143,14 @@ class FirSyntheticPropertiesScope private constructor(
}) })
} }
val property = buildSyntheticProperty(propertyName, getter, matchingSetter, getterCompatibility) val property = buildSyntheticProperty(propertyName, getter, matchingSetter, getterCompatibility, deprecatedOverrideOfHidden)
getter.originalForSubstitutionOverride?.let { getter.originalForSubstitutionOverride?.let {
property.originalForSubstitutionOverrideAttr = buildSyntheticProperty( property.originalForSubstitutionOverrideAttr = buildSyntheticProperty(
propertyName, propertyName,
it, it,
matchingSetter?.originalForSubstitutionOverride ?: matchingSetter, matchingSetter?.originalForSubstitutionOverride ?: matchingSetter,
getterCompatibility getterCompatibility,
deprecatedOverrideOfHidden,
) )
} }
val syntheticSymbol = property.symbol val syntheticSymbol = property.symbol
@@ -166,6 +167,7 @@ class FirSyntheticPropertiesScope private constructor(
getter: FirSimpleFunction, getter: FirSimpleFunction,
setter: FirSimpleFunction?, setter: FirSimpleFunction?,
getterCompatibility: SyntheticGetterCompatibility, getterCompatibility: SyntheticGetterCompatibility,
deprecatedOverrideOfHidden: Boolean,
): FirSyntheticProperty { ): FirSyntheticProperty {
val classLookupTag = getter.symbol.originalOrSelf().dispatchReceiverClassLookupTagOrNull() val classLookupTag = getter.symbol.originalOrSelf().dispatchReceiverClassLookupTagOrNull()
val packageName = classLookupTag?.classId?.packageFqName ?: getter.symbol.callableId.packageName val packageName = classLookupTag?.classId?.packageFqName ?: getter.symbol.callableId.packageName
@@ -185,6 +187,9 @@ class FirSyntheticPropertiesScope private constructor(
if (getterCompatibility != HasJavaOrigin) { if (getterCompatibility != HasJavaOrigin) {
noJavaOrigin = true noJavaOrigin = true
} }
if (deprecatedOverrideOfHidden) {
this.deprecatedOverrideOfHidden = true
}
} }
} }
@@ -250,6 +255,7 @@ class FirSyntheticPropertiesScope private constructor(
HasJavaOrigin HasJavaOrigin
} }
private data class GetterCompatibilityResult(val compatibility: SyntheticGetterCompatibility, val deprecatedOverrideOfHidden: Boolean)
/** /**
* This method computes if getter method can be used as base for synthetic property based on overridden hierarchy * This method computes if getter method can be used as base for synthetic property based on overridden hierarchy
* There are three kinds of compatibility: * There are three kinds of compatibility:
@@ -257,16 +263,20 @@ class FirSyntheticPropertiesScope private constructor(
* - `HasJavaOrigin` indicates that this getter is based on root java function (ok to create property) * - `HasJavaOrigin` indicates that this getter is based on root java function (ok to create property)
* - `HasKotlinOrigin` shows that there is no base java getter overridden. Property will be created only with some LV (KT-64358) * - `HasKotlinOrigin` shows that there is no base java getter overridden. Property will be created only with some LV (KT-64358)
*/ */
private fun FirNamedFunctionSymbol.computeGetterCompatibility(): SyntheticGetterCompatibility { private fun FirNamedFunctionSymbol.computeGetterCompatibility(): GetterCompatibilityResult {
val kotlinBaseAllowed = !session.languageVersionSettings.supportsFeature(ForbidSyntheticPropertiesWithoutBaseJavaGetter) val kotlinBaseAllowed = !session.languageVersionSettings.supportsFeature(ForbidSyntheticPropertiesWithoutBaseJavaGetter)
var isHiddenEverywhereBesideSuperCalls = false var isHiddenEverywhereBesideSuperCalls = false
var isDeprecatedOverrideOfHidden = false
var result = Incompatible var result = Incompatible
val visited = mutableSetOf<MemberWithBaseScope<FirNamedFunctionSymbol>>() val visited = mutableSetOf<MemberWithBaseScope<FirNamedFunctionSymbol>>()
fun checkJavaOrigin(symbol: FirNamedFunctionSymbol, scope: FirTypeScope, isOverridden: Boolean) { fun checkJavaOrigin(symbol: FirNamedFunctionSymbol, scope: FirTypeScope, isOverridden: Boolean) {
if (symbol.isHidden(isSuperCall = false, isOverridden = isOverridden)) { val hidden = symbol.isHidden(isSuperCall = false, isOverridden = isOverridden)
isHiddenEverywhereBesideSuperCalls = true when (hidden) {
CallToPotentiallyHiddenSymbolResult.Hidden -> isHiddenEverywhereBesideSuperCalls = true
CallToPotentiallyHiddenSymbolResult.VisibleWithDeprecation -> isDeprecatedOverrideOfHidden = true
CallToPotentiallyHiddenSymbolResult.Visible -> {}
} }
val overriddenWithScope = scope.getDirectOverriddenFunctionsWithBaseScope(symbol) val overriddenWithScope = scope.getDirectOverriddenFunctionsWithBaseScope(symbol)
@@ -292,7 +302,7 @@ class FirSyntheticPropertiesScope private constructor(
checkJavaOrigin(this, baseScope, isOverridden = false) checkJavaOrigin(this, baseScope, isOverridden = false)
return when { val syntheticGetterCompatibility = when {
isHiddenEverywhereBesideSuperCalls -> Incompatible isHiddenEverywhereBesideSuperCalls -> Incompatible
result != Incompatible -> result result != Incompatible -> result
!kotlinBaseAllowed -> Incompatible !kotlinBaseAllowed -> Incompatible
@@ -300,6 +310,7 @@ class FirSyntheticPropertiesScope private constructor(
isJavaTypeOnThePath(this.dispatchReceiverType) -> HasKotlinOrigin isJavaTypeOnThePath(this.dispatchReceiverType) -> HasKotlinOrigin
else -> Incompatible else -> Incompatible
} }
return GetterCompatibilityResult(syntheticGetterCompatibility, isDeprecatedOverrideOfHidden)
} }
/* /*
@@ -365,3 +376,9 @@ private var FirSyntheticProperty.noJavaOrigin: Boolean? by FirDeclarationDataReg
val FirSimpleSyntheticPropertySymbol.noJavaOrigin: Boolean val FirSimpleSyntheticPropertySymbol.noJavaOrigin: Boolean
get() = (fir as FirSyntheticProperty).noJavaOrigin == true get() = (fir as FirSyntheticProperty).noJavaOrigin == true
private object DeprecatedOverrideOfHidden : FirDeclarationDataKey()
private var FirSyntheticProperty.deprecatedOverrideOfHidden: Boolean? by FirDeclarationDataRegistry.data(DeprecatedOverrideOfHidden)
val FirSimpleSyntheticPropertySymbol.deprecatedOverrideOfHidden: Boolean
get() = (fir as FirSyntheticProperty).deprecatedOverrideOfHidden == true
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.fir.resolve.inference.ResolvedCallableReferenceAtom
import org.jetbrains.kotlin.fir.resolve.inference.csBuilder import org.jetbrains.kotlin.fir.resolve.inference.csBuilder
import org.jetbrains.kotlin.fir.resolve.inference.inferenceComponents import org.jetbrains.kotlin.fir.resolve.inference.inferenceComponents
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.transformers.addNonFatalDiagnostic
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirAbstractBodyResolveTransformer import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirAbstractBodyResolveTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirExpressionsResolveTransformer import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirExpressionsResolveTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
@@ -391,6 +392,10 @@ class FirCallResolver(
replaceDispatchReceiver(candidate.dispatchReceiverExpression()) replaceDispatchReceiver(candidate.dispatchReceiverExpression())
replaceExtensionReceiver(candidate.chosenExtensionReceiverExpression()) replaceExtensionReceiver(candidate.chosenExtensionReceiverExpression())
replaceContextReceiverArguments(candidate.contextReceiverArguments()) replaceContextReceiverArguments(candidate.contextReceiverArguments())
if (CallToDeprecatedOverrideOfHidden in candidate.diagnostics) {
addNonFatalDiagnostic(ConeCallToDeprecatedOverrideOfHidden)
}
} }
} }
transformer.storeTypeFromCallee(qualifiedAccess, isLhsOfAssignment = callSite is FirVariableAssignment) transformer.storeTypeFromCallee(qualifiedAccess, isLhsOfAssignment = callSite is FirVariableAssignment)
@@ -755,7 +755,7 @@ internal object CheckHiddenDeclaration : ResolutionStage() {
/** Actual declarations are checked by [FirDeprecationChecker] */ /** Actual declarations are checked by [FirDeprecationChecker] */
if (symbol.isActual) return if (symbol.isActual) return
val deprecation = symbol.getDeprecation(context.session, callInfo.callSite) val deprecation = symbol.getDeprecation(context.session, callInfo.callSite)
if (deprecation?.deprecationLevel == DeprecationLevelValue.HIDDEN || isHiddenForThisCallSite(symbol, callInfo, candidate, context.session)) { if (deprecation?.deprecationLevel == DeprecationLevelValue.HIDDEN || isHiddenForThisCallSite(symbol, callInfo, candidate, context.session, sink)) {
sink.yieldDiagnostic(HiddenCandidate) sink.yieldDiagnostic(HiddenCandidate)
} }
} }
@@ -764,25 +764,43 @@ internal object CheckHiddenDeclaration : ResolutionStage() {
symbol: FirCallableSymbol<*>, symbol: FirCallableSymbol<*>,
callInfo: CallInfo, callInfo: CallInfo,
candidate: Candidate, candidate: Candidate,
session: FirSession session: FirSession,
sink: CheckerSink,
): Boolean { ): Boolean {
val isSuperCall = callInfo.callSite.isSuperCall(session) /**
* The logic for synthetic properties itself is in [FirSyntheticPropertiesScope.computeGetterCompatibility].
*/
if (symbol is FirSimpleSyntheticPropertySymbol && symbol.deprecatedOverrideOfHidden) {
sink.reportDiagnostic(CallToDeprecatedOverrideOfHidden)
}
if (symbol.fir.dispatchReceiverType == null || symbol !is FirNamedFunctionSymbol) return false if (symbol.fir.dispatchReceiverType == null || symbol !is FirNamedFunctionSymbol) return false
if (symbol.isHidden(isSuperCall, isOverridden = false)) return true val isSuperCall = callInfo.callSite.isSuperCall(session)
if (symbol.isHidden(isSuperCall, isOverridden = false) == CallToPotentiallyHiddenSymbolResult.Hidden) return true
val scope = candidate.originScope as? FirTypeScope ?: return false val scope = candidate.originScope as? FirTypeScope ?: return false
var result = false var hidden = false
var deprecated = false
scope.processOverriddenFunctions(symbol) { scope.processOverriddenFunctions(symbol) {
if (it.isHidden(isSuperCall, isOverridden = true)) { val result = it.isHidden(isSuperCall, isOverridden = true)
result = true if (result != CallToPotentiallyHiddenSymbolResult.Visible) {
if (result == CallToPotentiallyHiddenSymbolResult.Hidden) {
hidden = true
} else if (result == CallToPotentiallyHiddenSymbolResult.VisibleWithDeprecation) {
deprecated = true
}
ProcessorAction.STOP ProcessorAction.STOP
} else { } else {
ProcessorAction.NEXT ProcessorAction.NEXT
} }
} }
return result if (deprecated) {
sink.reportDiagnostic(CallToDeprecatedOverrideOfHidden)
}
return hidden
} }
private fun FirElement.isSuperCall(session: FirSession): Boolean = private fun FirElement.isSuperCall(session: FirSession): Boolean =
@@ -328,9 +328,7 @@ class FirCallCompletionResultsWriterTransformer(
result.replaceConeTypeOrNull(resultType) result.replaceConeTypeOrNull(resultType)
session.lookupTracker?.recordTypeResolveAsLookup(resultType, qualifiedAccessExpression.source, context.file.source) session.lookupTracker?.recordTypeResolveAsLookup(resultType, qualifiedAccessExpression.source, context.file.source)
if (calleeReference.candidate.doesResolutionResultOverrideOtherToPreserveCompatibility()) { result.addNonFatalDiagnostics(calleeReference)
result.addNonFatalDiagnostic(ConeResolutionResultOverridesOtherToPreserveCompatibility)
}
return result return result
} }
@@ -384,12 +382,20 @@ class FirCallCompletionResultsWriterTransformer(
return arrayOfCallTransformer.transformFunctionCall(result, session) return arrayOfCallTransformer.transformFunctionCall(result, session)
} }
if (calleeReference.candidate.doesResolutionResultOverrideOtherToPreserveCompatibility()) { result.addNonFatalDiagnostics(calleeReference)
result.addNonFatalDiagnostic(ConeResolutionResultOverridesOtherToPreserveCompatibility)
}
return result return result
} }
private fun FirQualifiedAccessExpression.addNonFatalDiagnostics(calleeReference: FirNamedReferenceWithCandidate) {
if (calleeReference.candidate.doesResolutionResultOverrideOtherToPreserveCompatibility()) {
addNonFatalDiagnostic(ConeResolutionResultOverridesOtherToPreserveCompatibility)
}
if (CallToDeprecatedOverrideOfHidden in calleeReference.candidate.diagnostics) {
addNonFatalDiagnostic(ConeCallToDeprecatedOverrideOfHidden)
}
}
private fun FirCall.transformWithExpectedTypes(expectedArgumentsTypeMapping: ExpectedArgumentType.ArgumentsMap?) { private fun FirCall.transformWithExpectedTypes(expectedArgumentsTypeMapping: ExpectedArgumentType.ArgumentsMap?) {
class SamConversionInsertionTransformer : FirTransformer<Nothing?>() { class SamConversionInsertionTransformer : FirTransformer<Nothing?>() {
override fun <E : FirElement> transformElement(element: E, data: Nothing?): E { override fun <E : FirElement> transformElement(element: E, data: Nothing?): E {
@@ -579,9 +585,7 @@ class FirCallCompletionResultsWriterTransformer(
replaceCalleeReference(resolvedReference) replaceCalleeReference(resolvedReference)
replaceDispatchReceiver(dispatchReceiver) replaceDispatchReceiver(dispatchReceiver)
replaceExtensionReceiver(extensionReceiver) replaceExtensionReceiver(extensionReceiver)
if (calleeReference.candidate.doesResolutionResultOverrideOtherToPreserveCompatibility()) { addNonFatalDiagnostics(calleeReference)
addNonFatalDiagnostic(ConeResolutionResultOverridesOtherToPreserveCompatibility)
}
} }
} }
@@ -163,4 +163,6 @@ object TypeParameterAsExpression : ResolutionDiagnostic(INAPPLICABLE)
class TypeVariableAsExplicitReceiver( class TypeVariableAsExplicitReceiver(
val explicitReceiver: FirExpression, val explicitReceiver: FirExpression,
val typeParameter: FirTypeParameter, val typeParameter: FirTypeParameter,
) : ResolutionDiagnostic(RESOLVED_WITH_ERROR) ) : ResolutionDiagnostic(RESOLVED_WITH_ERROR)
object CallToDeprecatedOverrideOfHidden : ResolutionDiagnostic(RESOLVED)
@@ -404,3 +404,8 @@ object ConeResolutionResultOverridesOtherToPreserveCompatibility : ConeDiagnosti
get() = "Resolution result overrides another result to preserve compatibility, result maybe changed in future versions" get() = "Resolution result overrides another result to preserve compatibility, result maybe changed in future versions"
} }
object ConeCallToDeprecatedOverrideOfHidden : ConeDiagnostic {
override val reason: String
get() = "Call to deprecated override of hidden"
}
@@ -9,5 +9,5 @@ interface A : MutableCollection<String> {
fun foo(x: MutableCollection<Int>, y: Collection<String>, z: A) { fun foo(x: MutableCollection<Int>, y: Collection<String>, z: A) {
x.<!UNRESOLVED_REFERENCE!>nonExistingMethod<!>(1).<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><<!CANNOT_INFER_PARAMETER_TYPE!>String<!>>() } x.<!UNRESOLVED_REFERENCE!>nonExistingMethod<!>(1).<!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>checkType<!> { <!INAPPLICABLE_CANDIDATE!>_<!><<!CANNOT_INFER_PARAMETER_TYPE!>String<!>>() }
y.<!UNRESOLVED_REFERENCE!>nonExistingMethod<!>("") y.<!UNRESOLVED_REFERENCE!>nonExistingMethod<!>("")
z.<!UNRESOLVED_REFERENCE!>nonExistingMethod<!>("") z.<!DEPRECATION!>nonExistingMethod<!>("")
} }
@@ -1,11 +1,11 @@
fun foo(ll: java.util.LinkedList<String>, al: ArrayList<String>, ad: ArrayDeque<String>, jad: java.util.ArrayDeque<String>) { fun foo(ll: java.util.LinkedList<String>, al: ArrayList<String>, ad: ArrayDeque<String>, jad: java.util.ArrayDeque<String>) {
ll.addFirst("") ll.addFirst("")
ll.addLast("") ll.addLast("")
ll.getFirst() ll.<!DEPRECATION!>getFirst<!>()
ll.first // synthetic property for getFirst() ll.<!DEPRECATION!>first<!> // synthetic property for getFirst()
ll.first() // stdlib extension on List ll.first() // stdlib extension on List
ll.getLast() ll.<!DEPRECATION!>getLast<!>()
ll.last ll.<!DEPRECATION!>last<!>
ll.last() ll.last()
ll.removeFirst() ll.removeFirst()
ll.removeLast() ll.removeLast()
@@ -13,11 +13,11 @@ fun foo(ll: java.util.LinkedList<String>, al: ArrayList<String>, ad: ArrayDeque<
al.addFirst("") al.addFirst("")
al.addLast("") al.addLast("")
al.getFirst() al.<!DEPRECATION!>getFirst<!>()
al.first al.<!DEPRECATION!>first<!>
al.first() al.first()
al.getLast() al.<!DEPRECATION!>getLast<!>()
al.last al.<!DEPRECATION!>last<!>
al.last() al.last()
al.removeFirst() al.removeFirst()
al.removeLast() al.removeLast()
@@ -46,4 +46,4 @@ fun foo(ll: java.util.LinkedList<String>, al: ArrayList<String>, ad: ArrayDeque<
jad.removeFirst() jad.removeFirst()
jad.removeLast() jad.removeLast()
jad.reversed() jad.reversed()
} }
@@ -1,3 +1,7 @@
/newListMethods.fir.kt:(253,261): warning: 'fun getFirst(): T!' is deprecated. This declaration will be renamed in a future version of Kotlin. Please consider using the 'first()' stdlib extension if the collection supports fast random access.
/newListMethods.fir.kt:(302,309): warning: 'fun getLast(): T!' is deprecated. This declaration will be renamed in a future version of Kotlin. Please consider using the 'last()' stdlib extension if the collection supports fast random access.
/newListMethods.fir.kt:(596,604): error: Unresolved reference 'getFirst'. /newListMethods.fir.kt:(596,604): error: Unresolved reference 'getFirst'.
/newListMethods.fir.kt:(613,618): error: Function invocation 'first()' expected. /newListMethods.fir.kt:(613,618): error: Function invocation 'first()' expected.
@@ -5,3 +9,19 @@
/newListMethods.fir.kt:(704,711): error: Unresolved reference 'getLast'. /newListMethods.fir.kt:(704,711): error: Unresolved reference 'getLast'.
/newListMethods.fir.kt:(720,724): error: Function invocation 'last()' expected. /newListMethods.fir.kt:(720,724): error: Function invocation 'last()' expected.
/newListMethods.fir.kt:(838,846): warning: 'fun getFirst(): String!' is deprecated. This declaration will be renamed in a future version of Kotlin. Please consider using the 'first()' stdlib extension if the collection supports fast random access.
/newListMethods.fir.kt:(855,860): warning: 'val first: String!' is deprecated. This declaration will be renamed in a future version of Kotlin. Please consider using the 'first()' stdlib extension if the collection supports fast random access.
/newListMethods.fir.kt:(881,888): warning: 'fun getLast(): String!' is deprecated. This declaration will be renamed in a future version of Kotlin. Please consider using the 'last()' stdlib extension if the collection supports fast random access.
/newListMethods.fir.kt:(897,901): warning: 'val last: String!' is deprecated. This declaration will be renamed in a future version of Kotlin. Please consider using the 'last()' stdlib extension if the collection supports fast random access.
/newListMethods.fir.kt:(1015,1023): warning: 'fun getFirst(): String' is deprecated. This declaration will be renamed in a future version of Kotlin. Please consider using the 'first()' stdlib extension if the collection supports fast random access.
/newListMethods.fir.kt:(1032,1037): warning: 'val first: String' is deprecated. This declaration will be renamed in a future version of Kotlin. Please consider using the 'first()' stdlib extension if the collection supports fast random access.
/newListMethods.fir.kt:(1058,1065): warning: 'fun getLast(): String' is deprecated. This declaration will be renamed in a future version of Kotlin. Please consider using the 'last()' stdlib extension if the collection supports fast random access.
/newListMethods.fir.kt:(1074,1078): warning: 'val last: String' is deprecated. This declaration will be renamed in a future version of Kotlin. Please consider using the 'last()' stdlib extension if the collection supports fast random access.
@@ -10,8 +10,8 @@ class A<T> : ArrayList<T>() {
super.addLast(t) super.addLast(t)
} }
override fun getFirst(): T = super.getFirst() override fun getFirst(): T = super.<!DEPRECATION!>getFirst<!>()
override fun getLast(): T = super.getLast() override fun getLast(): T = super.<!DEPRECATION!>getLast<!>()
override fun removeFirst(): T = super.removeFirst() override fun removeFirst(): T = super.removeFirst()
override fun removeLast(): T = super.removeLast() override fun removeLast(): T = super.removeLast()
@@ -34,11 +34,11 @@ fun foo(x: MutableList<String>, y: ArrayList<String>, z: A<String>) {
y.addFirst("") y.addFirst("")
y.addLast("") y.addLast("")
y.getFirst() y.<!DEPRECATION!>getFirst<!>()
y.first y.<!DEPRECATION!>first<!>
y.first() y.first()
y.getLast() y.<!DEPRECATION!>getLast<!>()
y.last y.<!DEPRECATION!>last<!>
y.last() y.last()
y.<!DEBUG_INFO_CALL("fqName: java.util.ArrayList.removeFirst; typeCall: function")!>removeFirst()<!> y.<!DEBUG_INFO_CALL("fqName: java.util.ArrayList.removeFirst; typeCall: function")!>removeFirst()<!>
y.<!DEBUG_INFO_CALL("fqName: java.util.ArrayList.removeLast; typeCall: function")!>removeLast()<!> y.<!DEBUG_INFO_CALL("fqName: java.util.ArrayList.removeLast; typeCall: function")!>removeLast()<!>
@@ -46,11 +46,11 @@ fun foo(x: MutableList<String>, y: ArrayList<String>, z: A<String>) {
z.addFirst("") z.addFirst("")
z.addLast("") z.addLast("")
z.getFirst() z.<!DEPRECATION!>getFirst<!>()
z.first z.<!DEPRECATION!>first<!>
z.first() z.first()
z.getLast() z.<!DEPRECATION!>getLast<!>()
z.last z.<!DEPRECATION!>last<!>
z.last() z.last()
z.<!DEBUG_INFO_CALL("fqName: A.removeFirst; typeCall: function")!>removeFirst()<!> z.<!DEBUG_INFO_CALL("fqName: A.removeFirst; typeCall: function")!>removeFirst()<!>
z.<!DEBUG_INFO_CALL("fqName: A.removeLast; typeCall: function")!>removeLast()<!> z.<!DEBUG_INFO_CALL("fqName: A.removeLast; typeCall: function")!>removeLast()<!>