Allow use reference to reified type parameters in contracts since 1.4
This commit is contained in:
+5
@@ -1385,6 +1385,11 @@ public class FirOldFrontendDiagnosticsTestWithStdlibGenerated extends AbstractFi
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/receiver.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("reifiedGeneric.kt")
|
||||
public void testReifiedGeneric() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/reifiedGeneric.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("safecallAndReturnsNull.kt")
|
||||
public void testSafecallAndReturnsNull() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/safecallAndReturnsNull.kt");
|
||||
|
||||
@@ -20,10 +20,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.contracts.description.ContractProviderKey
|
||||
import org.jetbrains.kotlin.contracts.model.Computation
|
||||
import org.jetbrains.kotlin.contracts.model.ConditionalEffect
|
||||
import org.jetbrains.kotlin.contracts.model.ESEffect
|
||||
import org.jetbrains.kotlin.contracts.model.Functor
|
||||
import org.jetbrains.kotlin.contracts.model.*
|
||||
import org.jetbrains.kotlin.contracts.model.functors.*
|
||||
import org.jetbrains.kotlin.contracts.model.structure.*
|
||||
import org.jetbrains.kotlin.contracts.model.visitors.Reducer
|
||||
@@ -71,12 +68,13 @@ class EffectsExtractingVisitor(
|
||||
if (resolvedCall.isCallWithUnsupportedReceiver()) return UNKNOWN_COMPUTATION
|
||||
|
||||
val arguments = resolvedCall.getCallArgumentsAsComputations() ?: return UNKNOWN_COMPUTATION
|
||||
val typeSubstitution = resolvedCall.getTypeSubstitution()
|
||||
|
||||
val descriptor = resolvedCall.resultingDescriptor
|
||||
return when {
|
||||
descriptor.isEqualsDescriptor() -> CallComputation(
|
||||
ESBooleanType,
|
||||
EqualsFunctor(false).invokeWithArguments(arguments, reducer)
|
||||
EqualsFunctor(false).invokeWithArguments(arguments, typeSubstitution, reducer)
|
||||
)
|
||||
descriptor is ValueDescriptor -> ESVariableWithDataFlowValue(
|
||||
descriptor,
|
||||
@@ -86,7 +84,7 @@ class EffectsExtractingVisitor(
|
||||
val esType = descriptor.returnType?.toESType()
|
||||
CallComputation(
|
||||
esType,
|
||||
descriptor.getFunctor()?.invokeWithArguments(arguments, reducer) ?: emptyList()
|
||||
descriptor.getFunctor()?.invokeWithArguments(arguments, typeSubstitution, reducer) ?: emptyList()
|
||||
)
|
||||
}
|
||||
else -> UNKNOWN_COMPUTATION
|
||||
@@ -123,7 +121,7 @@ class EffectsExtractingVisitor(
|
||||
val arg = extractOrGetCached(expression.leftHandSide)
|
||||
return CallComputation(
|
||||
ESBooleanType,
|
||||
IsFunctor(rightType, expression.isNegated).invokeWithArguments(listOf(arg), reducer)
|
||||
IsFunctor(rightType, expression.isNegated).invokeWithArguments(listOf(arg), emptyMap(), reducer)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -148,10 +146,10 @@ class EffectsExtractingVisitor(
|
||||
val args = listOf(left, right)
|
||||
|
||||
return when (expression.operationToken) {
|
||||
KtTokens.EXCLEQ -> CallComputation(ESBooleanType, EqualsFunctor(true).invokeWithArguments(args, reducer))
|
||||
KtTokens.EQEQ -> CallComputation(ESBooleanType, EqualsFunctor(false).invokeWithArguments(args, reducer))
|
||||
KtTokens.ANDAND -> CallComputation(ESBooleanType, AndFunctor().invokeWithArguments(args, reducer))
|
||||
KtTokens.OROR -> CallComputation(ESBooleanType, OrFunctor().invokeWithArguments(args, reducer))
|
||||
KtTokens.EXCLEQ -> CallComputation(ESBooleanType, EqualsFunctor(true).invokeWithArguments(args, emptyMap(), reducer))
|
||||
KtTokens.EQEQ -> CallComputation(ESBooleanType, EqualsFunctor(false).invokeWithArguments(args, emptyMap(), reducer))
|
||||
KtTokens.ANDAND -> CallComputation(ESBooleanType, AndFunctor().invokeWithArguments(args, emptyMap(), reducer))
|
||||
KtTokens.OROR -> CallComputation(ESBooleanType, OrFunctor().invokeWithArguments(args, emptyMap(), reducer))
|
||||
else -> UNKNOWN_COMPUTATION
|
||||
}
|
||||
}
|
||||
@@ -215,6 +213,14 @@ class EffectsExtractingVisitor(
|
||||
return arguments
|
||||
}
|
||||
|
||||
private fun ResolvedCall<*>.getTypeSubstitution(): ESTypeSubstitution {
|
||||
val result = mutableMapOf<ESKotlinType, ESKotlinType>()
|
||||
for ((typeParameter, typeArgument) in typeArguments) {
|
||||
result[ESKotlinType(typeParameter.defaultType)] = ESKotlinType(typeArgument)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private fun ResolvedValueArgument.toComputation(): Computation? {
|
||||
return when (this) {
|
||||
// Assume that we don't know anything about default arguments
|
||||
|
||||
+6
-5
@@ -16,14 +16,14 @@
|
||||
|
||||
package org.jetbrains.kotlin.contracts.parsing
|
||||
|
||||
import org.jetbrains.kotlin.config.AnalysisFlags
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.contracts.description.ContractDescription
|
||||
import org.jetbrains.kotlin.contracts.description.ContractProviderKey
|
||||
import org.jetbrains.kotlin.contracts.description.LazyContractProvider
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isContractDescriptionCallPsiCheck
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
@@ -46,7 +46,7 @@ class ContractParsingServices(val languageVersionSettings: LanguageVersionSettin
|
||||
// is a *necessary* (but not sufficient, actually) condition for presence of 'LazyContractProvider'
|
||||
if (!expression.isContractDescriptionCallPsiCheck()) return
|
||||
|
||||
val callContext = ContractCallContext(expression, scope, trace)
|
||||
val callContext = ContractCallContext(expression, scope, trace, languageVersionSettings)
|
||||
val contractProviderIfAny =
|
||||
(scope.ownerDescriptor as? FunctionDescriptor)?.getUserData(ContractProviderKey) as? LazyContractProvider?
|
||||
var resultingContractDescription: ContractDescription? = null
|
||||
@@ -104,7 +104,8 @@ class ContractParsingServices(val languageVersionSettings: LanguageVersionSettin
|
||||
class ContractCallContext(
|
||||
val contractCallExpression: KtExpression,
|
||||
val scope: LexicalScope,
|
||||
val trace: BindingTrace
|
||||
val trace: BindingTrace,
|
||||
val languageVersionSettings: LanguageVersionSettings
|
||||
) {
|
||||
val ownerDescriptor: DeclarationDescriptor = scope.ownerDescriptor
|
||||
val functionDescriptor: FunctionDescriptor = ownerDescriptor as FunctionDescriptor
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
|
||||
package org.jetbrains.kotlin.contracts.parsing
|
||||
|
||||
import org.jetbrains.kotlin.contracts.description.*
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.contracts.description.BooleanExpression
|
||||
import org.jetbrains.kotlin.contracts.description.expressions.*
|
||||
import org.jetbrains.kotlin.descriptors.ValueDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.AbstractTypeParameterDescriptor
|
||||
@@ -47,8 +48,16 @@ internal class PsiConditionParser(
|
||||
}
|
||||
|
||||
if (descriptor is AbstractTypeParameterDescriptor) {
|
||||
collector.badDescription("references to type parameters are forbidden in contracts", typeReference)
|
||||
return null
|
||||
val reifiedGenericsAllowed = callContext.languageVersionSettings.supportsFeature(LanguageFeature.AllowReifiedGenericsInContracts)
|
||||
if (!reifiedGenericsAllowed || !descriptor.isReified) {
|
||||
val message = if (reifiedGenericsAllowed) {
|
||||
"references to not reified type parameters are forbidden in contracts"
|
||||
} else {
|
||||
"references to type parameters are forbidden in contracts"
|
||||
}
|
||||
collector.badDescription(message, typeReference)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
// This should be reported as "Can't check for erased" error, but we explicitly abort contract parsing. Just in case.
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.contracts.model
|
||||
|
||||
import org.jetbrains.kotlin.contracts.model.structure.ESKotlinType
|
||||
import org.jetbrains.kotlin.contracts.model.visitors.Reducer
|
||||
|
||||
/**
|
||||
@@ -27,13 +28,19 @@ import org.jetbrains.kotlin.contracts.model.visitors.Reducer
|
||||
* values, it takes effects and returns effects.
|
||||
*/
|
||||
interface Functor {
|
||||
fun invokeWithArguments(arguments: List<Computation>, reducer: Reducer): List<ESEffect>
|
||||
fun invokeWithArguments(arguments: List<Computation>, typeSubstitution: ESTypeSubstitution, reducer: Reducer): List<ESEffect>
|
||||
}
|
||||
|
||||
|
||||
abstract class AbstractFunctor : Functor {
|
||||
override fun invokeWithArguments(arguments: List<Computation>, reducer: Reducer): List<ESEffect> =
|
||||
reducer.reduceEffects(doInvocation(arguments, reducer))
|
||||
override fun invokeWithArguments(arguments: List<Computation>, typeSubstitution: ESTypeSubstitution, reducer: Reducer): List<ESEffect> =
|
||||
reducer.reduceEffects(doInvocation(arguments, typeSubstitution, reducer))
|
||||
|
||||
protected abstract fun doInvocation(arguments: List<Computation>, reducer: Reducer): List<ESEffect>
|
||||
}
|
||||
protected abstract fun doInvocation(
|
||||
arguments: List<Computation>,
|
||||
typeSubstitution: ESTypeSubstitution,
|
||||
reducer: Reducer
|
||||
): List<ESEffect>
|
||||
}
|
||||
|
||||
typealias ESTypeSubstitution = Map<ESKotlinType, ESKotlinType>
|
||||
+5
-2
@@ -17,11 +17,14 @@
|
||||
package org.jetbrains.kotlin.contracts.model.functors
|
||||
|
||||
import org.jetbrains.kotlin.contracts.model.*
|
||||
import org.jetbrains.kotlin.contracts.model.structure.*
|
||||
import org.jetbrains.kotlin.contracts.model.structure.ESConstant
|
||||
import org.jetbrains.kotlin.contracts.model.structure.ESOr
|
||||
import org.jetbrains.kotlin.contracts.model.structure.isReturns
|
||||
import org.jetbrains.kotlin.contracts.model.structure.isWildcard
|
||||
import org.jetbrains.kotlin.contracts.model.visitors.Reducer
|
||||
|
||||
abstract class AbstractBinaryFunctor : AbstractFunctor() {
|
||||
override fun doInvocation(arguments: List<Computation>, reducer: Reducer): List<ESEffect> {
|
||||
override fun doInvocation(arguments: List<Computation>, typeSubstitution: ESTypeSubstitution, reducer: Reducer): List<ESEffect> {
|
||||
assert(arguments.size == 2) { "Wrong size of arguments list for Binary functor: expected 2, got ${arguments.size}" }
|
||||
return invokeWithArguments(arguments[0], arguments[1])
|
||||
}
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ import org.jetbrains.kotlin.contracts.model.visitors.Reducer
|
||||
* be called only on clauses that haven't failed before reaching functor transformation.
|
||||
*/
|
||||
abstract class AbstractUnaryFunctor : AbstractFunctor() {
|
||||
override fun doInvocation(arguments: List<Computation>, reducer: Reducer): List<ESEffect> {
|
||||
override fun doInvocation(arguments: List<Computation>, typeSubstitution: ESTypeSubstitution, reducer: Reducer): List<ESEffect> {
|
||||
assert(arguments.size == 1) { "Wrong size of arguments list for Unary operator: expected 1, got ${arguments.size}" }
|
||||
return invokeWithArguments(arguments[0])
|
||||
}
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@ class EqualsFunctor(val isNegated: Boolean) : AbstractFunctor() {
|
||||
We don't want to code here fair analysis for general cases, because it's too complex. Instead, we just
|
||||
check some specific cases, which are useful enough in practice
|
||||
*/
|
||||
override fun doInvocation(arguments: List<Computation>, reducer: Reducer): List<ESEffect> {
|
||||
override fun doInvocation(arguments: List<Computation>, typeSubstitution: ESTypeSubstitution, reducer: Reducer): List<ESEffect> {
|
||||
assert(arguments.size == 2) { "Equals functor expected 2 arguments, got ${arguments.size}" }
|
||||
|
||||
// TODO: AnnotationConstructorCaller kills this with implicit receiver. Investigate, how.
|
||||
|
||||
@@ -24,21 +24,23 @@ import org.jetbrains.kotlin.contracts.model.structure.ESType
|
||||
import org.jetbrains.kotlin.contracts.model.visitors.Reducer
|
||||
|
||||
class IsFunctor(val type: ESType, val isNegated: Boolean) : AbstractFunctor() {
|
||||
override fun doInvocation(arguments: List<Computation>, reducer: Reducer): List<ESEffect> {
|
||||
override fun doInvocation(arguments: List<Computation>, typeSubstitution: ESTypeSubstitution, reducer: Reducer): List<ESEffect> {
|
||||
assert(arguments.size == 1) { "Wrong size of arguments list for Unary operator: expected 1, got ${arguments.size}" }
|
||||
return invokeWithArguments(arguments[0])
|
||||
return invokeWithArguments(arguments[0], typeSubstitution)
|
||||
}
|
||||
|
||||
fun invokeWithArguments(arg: Computation): List<ESEffect> {
|
||||
fun invokeWithArguments(arg: Computation, typeSubstitution: ESTypeSubstitution): List<ESEffect> {
|
||||
return if (arg is ESValue)
|
||||
invokeWithValue(arg)
|
||||
invokeWithValue(arg, typeSubstitution)
|
||||
else
|
||||
emptyList()
|
||||
}
|
||||
|
||||
private fun invokeWithValue(value: ESValue): List<ConditionalEffect> {
|
||||
val trueIs = ESIs(value, this)
|
||||
val falseIs = ESIs(value, IsFunctor(type, isNegated.not()))
|
||||
private fun invokeWithValue(value: ESValue, typeSubstitution: ESTypeSubstitution): List<ConditionalEffect> {
|
||||
val substitutedType = typeSubstitution[type] ?: type
|
||||
|
||||
val trueIs = ESIs(value, IsFunctor(substitutedType, isNegated))
|
||||
val falseIs = ESIs(value, IsFunctor(substitutedType, isNegated.not()))
|
||||
|
||||
val trueResult = ConditionalEffect(trueIs, ESReturns(ESConstants.trueValue))
|
||||
val falseResult = ConditionalEffect(falseIs, ESReturns(ESConstants.falseValue))
|
||||
|
||||
+2
-2
@@ -28,7 +28,7 @@ class SubstitutingFunctor(
|
||||
private val basicEffects: List<ESEffect>,
|
||||
private val ownerFunction: FunctionDescriptor
|
||||
) : AbstractFunctor() {
|
||||
override fun doInvocation(arguments: List<Computation>, reducer: Reducer): List<ESEffect> {
|
||||
override fun doInvocation(arguments: List<Computation>, typeSubstitution: ESTypeSubstitution, reducer: Reducer): List<ESEffect> {
|
||||
if (basicEffects.isEmpty()) return emptyList()
|
||||
|
||||
val receiver =
|
||||
@@ -40,7 +40,7 @@ class SubstitutingFunctor(
|
||||
}
|
||||
|
||||
val substitutions = parameters.zip(arguments).toMap()
|
||||
val substitutor = Substitutor(substitutions, reducer)
|
||||
val substitutor = Substitutor(substitutions, typeSubstitution, reducer)
|
||||
val substitutedClauses = mutableListOf<ESEffect>()
|
||||
|
||||
effectsLoop@ for (effect in basicEffects) {
|
||||
|
||||
@@ -36,6 +36,20 @@ object ESBooleanType : ESType() {
|
||||
|
||||
class ESKotlinType(val type: KotlinType) : ESType() {
|
||||
override fun toKotlinType(builtIns: KotlinBuiltIns): KotlinType = type
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as ESKotlinType
|
||||
|
||||
if (type != other.type) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return type.hashCode()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
+4
-2
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.contracts.model.visitors
|
||||
import org.jetbrains.kotlin.contracts.model.Computation
|
||||
import org.jetbrains.kotlin.contracts.model.ESExpression
|
||||
import org.jetbrains.kotlin.contracts.model.ESExpressionVisitor
|
||||
import org.jetbrains.kotlin.contracts.model.ESTypeSubstitution
|
||||
import org.jetbrains.kotlin.contracts.model.structure.*
|
||||
|
||||
/**
|
||||
@@ -28,11 +29,12 @@ import org.jetbrains.kotlin.contracts.model.structure.*
|
||||
*/
|
||||
class Substitutor(
|
||||
private val substitutions: Map<ESVariable, Computation>,
|
||||
private val typeSubstitution: ESTypeSubstitution,
|
||||
private val reducer: Reducer
|
||||
) : ESExpressionVisitor<Computation?> {
|
||||
override fun visitIs(isOperator: ESIs): Computation? {
|
||||
val arg = isOperator.left.accept(this) ?: return null
|
||||
return CallComputation(ESBooleanType, isOperator.functor.invokeWithArguments(arg))
|
||||
return CallComputation(ESBooleanType, isOperator.functor.invokeWithArguments(arg, typeSubstitution))
|
||||
}
|
||||
|
||||
override fun visitNot(not: ESNot): Computation? {
|
||||
@@ -43,7 +45,7 @@ class Substitutor(
|
||||
override fun visitEqual(equal: ESEqual): Computation? {
|
||||
val left = equal.left.accept(this) ?: return null
|
||||
val right = equal.right.accept(this) ?: return null
|
||||
return CallComputation(ESBooleanType, equal.functor.invokeWithArguments(listOf(left, right), reducer))
|
||||
return CallComputation(ESBooleanType, equal.functor.invokeWithArguments(listOf(left, right), typeSubstitution, reducer))
|
||||
}
|
||||
|
||||
override fun visitAnd(and: ESAnd): Computation? {
|
||||
|
||||
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect +AllowContractsForNonOverridableMembers
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect +AllowContractsForNonOverridableMembers +AllowReifiedGenericsInContracts
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER -NOTHING_TO_INLINE -ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS -ABSTRACT_FUNCTION_WITH_BODY -UNUSED_PARAMETER -UNUSED_VARIABLE -EXPERIMENTAL_FEATURE_WARNING
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect +AllowContractsForNonOverridableMembers
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect +AllowContractsForNonOverridableMembers +AllowReifiedGenericsInContracts
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER -NOTHING_TO_INLINE -ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS -ABSTRACT_FUNCTION_WITH_BODY -UNUSED_PARAMETER -UNUSED_VARIABLE -EXPERIMENTAL_FEATURE_WARNING
|
||||
|
||||
|
||||
Vendored
+6
@@ -21,9 +21,15 @@ public open class Class {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public final inline fun inlineMember(/*0*/ x: kotlin.Boolean): kotlin.Unit
|
||||
Returns(WILDCARD) -> x
|
||||
|
||||
public final fun member(/*0*/ x: kotlin.Boolean): kotlin.Unit
|
||||
Returns(WILDCARD) -> x
|
||||
|
||||
public open fun openMemeber(/*0*/ x: kotlin.Boolean): kotlin.Unit
|
||||
public final suspend fun suspendMember(/*0*/ x: kotlin.Boolean): kotlin.Unit
|
||||
Returns(WILDCARD) -> x
|
||||
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect -AllowContractsForNonOverridableMembers
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect -AllowContractsForNonOverridableMembers -AllowReifiedGenericsInContracts
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect -AllowContractsForNonOverridableMembers
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect -AllowContractsForNonOverridableMembers -AllowReifiedGenericsInContracts
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect +AllowContractsForNonOverridableMembers
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect +AllowContractsForNonOverridableMembers +AllowReifiedGenericsInContracts
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect +AllowContractsForNonOverridableMembers
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect +AllowContractsForNonOverridableMembers +AllowReifiedGenericsInContracts
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
|
||||
|
||||
@@ -6,7 +6,7 @@ import kotlin.contracts.*
|
||||
|
||||
inline fun <reified T> referToReifiedGeneric(x: Any?) {
|
||||
contract {
|
||||
returns() implies (x is <!ERROR_IN_CONTRACT_DESCRIPTION("references to type parameters are forbidden in contracts")!>T<!>)
|
||||
returns() implies (x is T)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
@@ -6,6 +6,8 @@ public fun referToAliasedSimpleType(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
Returns(WILDCARD) -> x is Int
|
||||
|
||||
public inline fun </*0*/ reified T> referToReifiedGeneric(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
Returns(WILDCARD) -> x is T
|
||||
|
||||
public fun referToSubstituted(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
public fun referToSubstitutedWithStar(/*0*/ x: kotlin.Any?): kotlin.Unit
|
||||
Returns(WILDCARD) -> x is Generic<*>
|
||||
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect +AllowReifiedGenericsInContracts
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER -UNUSED_VARIABLE
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
inline fun <reified T> requireIsInstance(value: Any?) {
|
||||
contract {
|
||||
returns() implies (value is T)
|
||||
}
|
||||
if (value !is T) {
|
||||
throw IllegalArgumentException()
|
||||
}
|
||||
}
|
||||
|
||||
inline fun <reified T> cast(value: Any?): T {
|
||||
contract {
|
||||
returns() implies (value is T)
|
||||
}
|
||||
return value as T
|
||||
}
|
||||
|
||||
fun test_1(x: Any) {
|
||||
requireIsInstance<String>(x)
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
|
||||
fun test_2(x: Any) {
|
||||
val s: String = cast(x)
|
||||
x.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect +AllowReifiedGenericsInContracts
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER -UNUSED_VARIABLE
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
inline fun <reified T> requireIsInstance(value: Any?) {
|
||||
contract {
|
||||
returns() implies (value is T)
|
||||
}
|
||||
if (value !is T) {
|
||||
throw IllegalArgumentException()
|
||||
}
|
||||
}
|
||||
|
||||
inline fun <reified T> cast(value: Any?): T {
|
||||
contract {
|
||||
returns() implies (value is T)
|
||||
}
|
||||
return value as T
|
||||
}
|
||||
|
||||
fun test_1(x: Any) {
|
||||
requireIsInstance<String>(x)
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
}
|
||||
|
||||
fun test_2(x: Any) {
|
||||
val s: String = cast(x)
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!>.length
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
package
|
||||
|
||||
public inline fun </*0*/ reified T> cast(/*0*/ value: kotlin.Any?): T
|
||||
Returns(WILDCARD) -> value is T
|
||||
|
||||
public inline fun </*0*/ reified T> requireIsInstance(/*0*/ value: kotlin.Any?): kotlin.Unit
|
||||
Returns(WILDCARD) -> value is T
|
||||
|
||||
public fun test_1(/*0*/ x: kotlin.Any): kotlin.Unit
|
||||
public fun test_2(/*0*/ x: kotlin.Any): kotlin.Unit
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
// !LANGUAGE: +AllowContractsForCustomFunctions +ReadDeserializedContracts +AllowContractsForNonOverridableMembers +AllowReifiedGenericsInContracts
|
||||
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
|
||||
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||
|
||||
package test
|
||||
|
||||
import kotlin.contracts.*
|
||||
|
||||
inline fun <reified T> requireIsInstance(value: Any?) {
|
||||
contract {
|
||||
returns() implies (value is T)
|
||||
}
|
||||
if (value !is T) {
|
||||
throw IllegalArgumentException()
|
||||
}
|
||||
}
|
||||
|
||||
inline fun <reified T, reified U> cast(value: Any?, z: U): T {
|
||||
contract {
|
||||
returns() implies (value is T)
|
||||
}
|
||||
return value as T
|
||||
}
|
||||
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
package test
|
||||
|
||||
public inline fun </*0*/ reified T, /*1*/ reified U> cast(/*0*/ value: kotlin.Any?, /*1*/ z: U): T
|
||||
Returns(WILDCARD) -> value is T
|
||||
|
||||
public inline fun </*0*/ reified T> requireIsInstance(/*0*/ value: kotlin.Any?): kotlin.Unit
|
||||
Returns(WILDCARD) -> value is T
|
||||
+5
@@ -1386,6 +1386,11 @@ public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestW
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/receiver.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("reifiedGeneric.kt")
|
||||
public void testReifiedGeneric() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/reifiedGeneric.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("safecallAndReturnsNull.kt")
|
||||
public void testSafecallAndReturnsNull() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/safecallAndReturnsNull.kt");
|
||||
|
||||
compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsTestWithStdLibUsingJavacGenerated.java
Generated
+5
@@ -1386,6 +1386,11 @@ public class DiagnosticsTestWithStdLibUsingJavacGenerated extends AbstractDiagno
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/receiver.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("reifiedGeneric.kt")
|
||||
public void testReifiedGeneric() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/reifiedGeneric.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("safecallAndReturnsNull.kt")
|
||||
public void testSafecallAndReturnsNull() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts/safecallAndReturnsNull.kt");
|
||||
|
||||
@@ -4650,6 +4650,11 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest {
|
||||
runTest("compiler/testData/loadJava/compiledKotlinWithStdlib/contracts/callsEffect.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("contractWithRefiedGeneric.kt")
|
||||
public void testContractWithRefiedGeneric() throws Exception {
|
||||
runTest("compiler/testData/loadJava/compiledKotlinWithStdlib/contracts/contractWithRefiedGeneric.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("contractsOnMembers.kt")
|
||||
public void testContractsOnMembers() throws Exception {
|
||||
runTest("compiler/testData/loadJava/compiledKotlinWithStdlib/contracts/contractsOnMembers.kt");
|
||||
|
||||
+5
@@ -4651,6 +4651,11 @@ public class IrLoadJavaTestGenerated extends AbstractIrLoadJavaTest {
|
||||
runTest("compiler/testData/loadJava/compiledKotlinWithStdlib/contracts/callsEffect.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("contractWithRefiedGeneric.kt")
|
||||
public void testContractWithRefiedGeneric() throws Exception {
|
||||
runTest("compiler/testData/loadJava/compiledKotlinWithStdlib/contracts/contractWithRefiedGeneric.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("contractsOnMembers.kt")
|
||||
public void testContractsOnMembers() throws Exception {
|
||||
runTest("compiler/testData/loadJava/compiledKotlinWithStdlib/contracts/contractsOnMembers.kt");
|
||||
|
||||
Generated
+5
@@ -4650,6 +4650,11 @@ public class LoadJavaUsingJavacTestGenerated extends AbstractLoadJavaUsingJavacT
|
||||
runTest("compiler/testData/loadJava/compiledKotlinWithStdlib/contracts/callsEffect.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("contractWithRefiedGeneric.kt")
|
||||
public void testContractWithRefiedGeneric() throws Exception {
|
||||
runTest("compiler/testData/loadJava/compiledKotlinWithStdlib/contracts/contractWithRefiedGeneric.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("contractsOnMembers.kt")
|
||||
public void testContractsOnMembers() throws Exception {
|
||||
runTest("compiler/testData/loadJava/compiledKotlinWithStdlib/contracts/contractsOnMembers.kt");
|
||||
|
||||
@@ -122,6 +122,7 @@ enum class LanguageFeature(
|
||||
AllowResultInReturnType(KOTLIN_1_4),
|
||||
PreferJavaFieldOverload(KOTLIN_1_4),
|
||||
AllowContractsForNonOverridableMembers(KOTLIN_1_4),
|
||||
AllowReifiedGenericsInContracts(KOTLIN_1_4),
|
||||
|
||||
ProperVisibilityForCompanionObjectInstanceField(sinceVersion = null, kind = BUG_FIX),
|
||||
// Temporarily disabled, see KT-27084/KT-22379
|
||||
|
||||
+1
-1
@@ -296,7 +296,7 @@ class MemberDeserializer(private val c: DeserializationContext) {
|
||||
function.isExpect = Flags.IS_EXPECT_FUNCTION.get(flags)
|
||||
|
||||
val mapValueForContract =
|
||||
c.components.contractDeserializer.deserializeContractFromFunction(proto, function, c.typeTable, c.typeDeserializer)
|
||||
c.components.contractDeserializer.deserializeContractFromFunction(proto, function, c.typeTable, local.typeDeserializer)
|
||||
if (mapValueForContract != null) {
|
||||
function.putInUserDataMap(mapValueForContract.first, mapValueForContract.second)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user