diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/DelegatedPropertiesCodegenHelper.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/DelegatedPropertiesCodegenHelper.kt new file mode 100644 index 00000000000..11cf6c63aed --- /dev/null +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/DelegatedPropertiesCodegenHelper.kt @@ -0,0 +1,110 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.codegen + +import org.jetbrains.kotlin.codegen.binding.CodegenBinding +import org.jetbrains.kotlin.codegen.inline.InlineCodegen +import org.jetbrains.kotlin.codegen.optimization.nullCheck.isCheckParameterIsNotNull +import org.jetbrains.kotlin.codegen.state.GenerationState +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.descriptors.VariableDescriptorWithAccessors +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.FunctionImportedFromObject +import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall +import org.jetbrains.kotlin.serialization.deserialization.descriptors.DescriptorWithContainerSource +import org.jetbrains.org.objectweb.asm.Opcodes +import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode +import org.jetbrains.org.objectweb.asm.tree.MethodNode +import org.jetbrains.org.objectweb.asm.tree.VarInsnNode + +class DelegatedPropertiesCodegenHelper(private val state: GenerationState) { + + private val bindingContext = state.bindingContext + private val bindingTrace = state.bindingTrace + private val typeMapper = state.typeMapper + + fun isDelegatedPropertyMetadataRequired(descriptor: VariableDescriptorWithAccessors): Boolean { + val provideDelegateResolvedCall = bindingContext[BindingContext.PROVIDE_DELEGATE_RESOLVED_CALL, descriptor] + val getValueResolvedCall = descriptor.getter?.let { bindingContext[BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, it] } + val setValueResolvedCall = descriptor.setter?.let { bindingContext[BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, it] } + + return provideDelegateResolvedCall != null && isDelegatedPropertyMetadataRequired(provideDelegateResolvedCall) || + getValueResolvedCall != null && isDelegatedPropertyMetadataRequired(getValueResolvedCall) || + setValueResolvedCall != null && isDelegatedPropertyMetadataRequired(setValueResolvedCall) + } + + private fun isDelegatedPropertyMetadataRequired(operatorCall: ResolvedCall): Boolean { + val calleeDescriptor = operatorCall.resultingDescriptor.getActualCallee().original + + if (!calleeDescriptor.isInline) return true + + val metadataParameter = calleeDescriptor.valueParameters[1] + if (true == bindingContext[BindingContext.UNUSED_DELEGATED_PROPERTY_OPERATOR_PARAMETER, metadataParameter]) { + return false + } + + if (calleeDescriptor !is DescriptorWithContainerSource) return true + + val cachedResult = bindingTrace[CodegenBinding.PROPERTY_METADATA_REQUIRED_FOR_OPERATOR_CALL, calleeDescriptor] + if (cachedResult != null) { + return cachedResult + } + + return isDelegatedPropertyMetadataRequiredForFunctionFromBinaries(calleeDescriptor).also { + bindingTrace.record(CodegenBinding.PROPERTY_METADATA_REQUIRED_FOR_OPERATOR_CALL, calleeDescriptor, it) + } + } + + private fun FunctionDescriptor.getActualCallee(): FunctionDescriptor = + if (this is FunctionImportedFromObject) + callableFromObject + else + this + + private fun isDelegatedPropertyMetadataRequiredForFunctionFromBinaries(calleeDescriptor: FunctionDescriptor): Boolean { + assert(calleeDescriptor is DescriptorWithContainerSource) { + "Function descriptor from binaries expected: $calleeDescriptor" + } + + val metadataParameterIndex = getMetadataParameterIndex(calleeDescriptor) + val methodNode = InlineCodegen.createSpecialInlineMethodNodeFromBinaries(calleeDescriptor, state) + + return isMetadataParameterUsedInCompiledMethodBody(metadataParameterIndex, methodNode) + } + + private fun isMetadataParameterUsedInCompiledMethodBody(metadataParameterIndex: Int, methodNode: MethodNode): Boolean = + methodNode.instructions.toArray().any { insn -> + insn is VarInsnNode && insn.opcode == Opcodes.ALOAD && insn.`var` == metadataParameterIndex && + !isParameterNullCheckArgument(insn) + } + + private fun isParameterNullCheckArgument(insn: AbstractInsnNode): Boolean { + val next1 = insn.next + val next2 = next1.next + return next1 != null && next2 != null && + next1.opcode == Opcodes.LDC && next2.isCheckParameterIsNotNull() + } + + private fun getMetadataParameterIndex(calleeDescriptor: FunctionDescriptor): Int { + assert(calleeDescriptor.valueParameters.size >= 2) { + "Unexpected delegated property operator (should have at least 2 value parameters): $calleeDescriptor" + } + + var index = 0 + + calleeDescriptor.dispatchReceiverParameter?.let { + index += typeMapper.mapType(it.type).size + } + + calleeDescriptor.extensionReceiverParameter?.let { + index += typeMapper.mapType(it.type).size + } + + index += typeMapper.mapType(calleeDescriptor.valueParameters[0].type).size + + return index + } +} diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyCodegen.java index 51a1a6b5923..ed916230a59 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/PropertyCodegen.java @@ -49,8 +49,7 @@ import static org.jetbrains.kotlin.codegen.AsmUtil.getVisibilityForBackingField; import static org.jetbrains.kotlin.codegen.FunctionCodegen.processInterfaceMethod; import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isConstOrHasJvmFieldAnnotation; import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvmInterface; -import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.DELEGATED_PROPERTIES_WITH_METADATA; -import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.DELEGATED_PROPERTY_METADATA_OWNER; +import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.*; import static org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings.*; import static org.jetbrains.kotlin.diagnostics.Errors.EXPECTED_FUNCTION_SOURCE_WITH_DEFAULT_ARGUMENTS_NOT_FOUND; import static org.jetbrains.kotlin.resolve.DescriptorUtils.isCompanionObject; @@ -569,6 +568,10 @@ public class PropertyCodegen { @NotNull VariableDescriptorWithAccessors descriptor, @NotNull BindingContext bindingContext ) { + if (Boolean.TRUE == bindingContext.get(DELEGATED_PROPERTY_WITH_OPTIMIZED_METADATA, descriptor)) { + return StackValue.constant(null, K_PROPERTY_TYPE); + } + Type owner = bindingContext.get(DELEGATED_PROPERTY_METADATA_OWNER, descriptor); assert owner != null : "Delegated property owner not found: " + descriptor; diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenAnnotatingVisitor.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenAnnotatingVisitor.java index cebc54d638a..2ba7191e535 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenAnnotatingVisitor.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenAnnotatingVisitor.java @@ -88,6 +88,7 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid { private final SwitchCodegenProvider switchCodegenProvider; private final LanguageVersionSettings languageVersionSettings; private final ClassBuilderMode classBuilderMode; + private final DelegatedPropertiesCodegenHelper delegatedPropertiesCodegenHelper; public CodegenAnnotatingVisitor(@NotNull GenerationState state) { this.bindingTrace = state.getBindingTrace(); @@ -97,6 +98,7 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid { this.switchCodegenProvider = new SwitchCodegenProvider(state); this.languageVersionSettings = state.getLanguageVersionSettings(); this.classBuilderMode = state.getClassBuilderMode(); + this.delegatedPropertiesCodegenHelper = new DelegatedPropertiesCodegenHelper(state); } @NotNull @@ -509,15 +511,20 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid { ClassDescriptor classDescriptor = recordClassForCallable(delegate, variableDescriptor, Collections.singleton(supertype), name); recordClosure(classDescriptor, name); - Type containerType = getMetadataOwner(property); - List descriptors = bindingTrace.get(DELEGATED_PROPERTIES_WITH_METADATA, containerType); - if (descriptors == null) { - descriptors = new ArrayList<>(1); - bindingTrace.record(DELEGATED_PROPERTIES_WITH_METADATA, containerType, descriptors); - } - descriptors.add(variableDescriptor); + if (delegatedPropertiesCodegenHelper.isDelegatedPropertyMetadataRequired(variableDescriptor)) { + Type containerType = getMetadataOwner(property); + List descriptors = bindingTrace.get(DELEGATED_PROPERTIES_WITH_METADATA, containerType); + if (descriptors == null) { + descriptors = new ArrayList<>(1); + bindingTrace.record(DELEGATED_PROPERTIES_WITH_METADATA, containerType, descriptors); + } + descriptors.add(variableDescriptor); - bindingTrace.record(DELEGATED_PROPERTY_METADATA_OWNER, variableDescriptor, containerType); + bindingTrace.record(DELEGATED_PROPERTY_METADATA_OWNER, variableDescriptor, containerType); + } + else { + bindingTrace.record(DELEGATED_PROPERTY_WITH_OPTIMIZED_METADATA, variableDescriptor); + } } super.visitProperty(property); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenBinding.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenBinding.java index bc50cc161f0..46d9bc288b7 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenBinding.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/binding/CodegenBinding.java @@ -75,6 +75,10 @@ public class CodegenBinding { Slices.createSimpleSlice(); public static final WritableSlice LOCAL_VARIABLE_PROPERTY_METADATA = Slices.createSimpleSlice(); + public static final WritableSlice PROPERTY_METADATA_REQUIRED_FOR_OPERATOR_CALL = + Slices.createSimpleSlice(); + public static final WritableSlice DELEGATED_PROPERTY_WITH_OPTIMIZED_METADATA = + Slices.createSimpleSlice(); public static final WritableSlice CALL_LABEL_FOR_LAMBDA_ARGUMENT = Slices.createSimpleSlice(); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt index 29667d45830..2308c3774ee 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.kt @@ -534,12 +534,41 @@ abstract class InlineCodegen( else mangleSuspendInlineFunctionAsmMethodIfNeeded(functionDescriptor, jvmSignature.asmMethod) - val methodId = MethodId(methodOwner.internalName, asmMethod) val directMember = getDirectMemberAndCallableFromObject(functionDescriptor) if (!isBuiltInArrayIntrinsic(functionDescriptor) && directMember !is DescriptorWithContainerSource) { return sourceCompilerForInline.doCreateMethodNodeFromSource(functionDescriptor, jvmSignature, callDefault, asmMethod) } + return getCompiledMethodNodeInner(functionDescriptor, directMember, asmMethod, methodOwner, state, jvmSignature) + } + + internal fun createSpecialInlineMethodNodeFromBinaries(functionDescriptor: FunctionDescriptor, state: GenerationState): MethodNode { + val directMember = getDirectMemberAndCallableFromObject(functionDescriptor) + assert(directMember is DescriptorWithContainerSource) { + "Function is not in binaries: $functionDescriptor" + } + assert(directMember is FunctionDescriptor && directMember.isOperator) { + "Operator function expected: $directMember" + } + + val methodOwner = state.typeMapper.mapImplementationOwner(functionDescriptor) + val jvmSignature = state.typeMapper.mapSignatureWithGeneric(functionDescriptor, OwnerKind.IMPLEMENTATION) + + val asmMethod = mangleSuspendInlineFunctionAsmMethodIfNeeded(functionDescriptor, jvmSignature.asmMethod) + + return getCompiledMethodNodeInner(functionDescriptor, directMember, asmMethod, methodOwner, state, jvmSignature).node + } + + private fun getCompiledMethodNodeInner( + functionDescriptor: FunctionDescriptor, + directMember: CallableMemberDescriptor, + asmMethod: Method, + methodOwner: Type, + state: GenerationState, + jvmSignature: JvmMethodSignature + ): SMAPAndMethodNode { + val methodId = MethodId(methodOwner.internalName, asmMethod) + val resultInCache = state.inlineCache.methodNodeById.getOrPut(methodId) { val result = doCreateMethodNodeFromCompiled(directMember, state, asmMethod) ?: if (functionDescriptor.isSuspend) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProvider.kt b/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProvider.kt index bb42f06a0d3..480b75696f5 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProvider.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProvider.kt @@ -33,8 +33,11 @@ import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantOfType -import org.jetbrains.kotlin.resolve.* +import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext.* +import org.jetbrains.kotlin.resolve.BindingTrace +import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils +import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.bindingContextUtil.getEnclosingDescriptor import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsResultOfLambda @@ -744,12 +747,11 @@ class ControlFlowInformationProvider private constructor( } } } - if (functionDescriptor.isOverridableOrOverrides - || owner.hasModifier(KtTokens.OVERRIDE_KEYWORD) - || OperatorNameConventions.GET_VALUE == functionName - || OperatorNameConventions.SET_VALUE == functionName - || OperatorNameConventions.PROVIDE_DELEGATE == functionName - ) { + if (functionDescriptor.isOperator && functionName in OperatorNameConventions.DELEGATED_PROPERTY_OPERATORS) { + trace.record(UNUSED_DELEGATED_PROPERTY_OPERATOR_PARAMETER, variableDescriptor, true) + return + } + if (functionDescriptor.isOverridableOrOverrides || owner.hasModifier(KtTokens.OVERRIDE_KEYWORD)) { return } if (anonymous) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java index ac5a6eeb7fa..6ea918ff734 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java @@ -107,6 +107,8 @@ public interface BindingContext { WritableSlice LEAKING_THIS = Slices.createSimpleSlice(); WritableSlice UNUSED_MAIN_PARAMETER = Slices.createSimpleSlice(); + WritableSlice UNUSED_DELEGATED_PROPERTY_OPERATOR_PARAMETER = Slices.createSimpleSlice(); + /** * A qualifier corresponds to a receiver expression (if any). For 'A.B' qualifier is recorded for 'A'. */ diff --git a/compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/definedInSources.kt b/compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/definedInSources.kt new file mode 100644 index 00000000000..073c1676afb --- /dev/null +++ b/compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/definedInSources.kt @@ -0,0 +1,65 @@ +class Provider(val _value: T) { + inline operator fun provideDelegate(thisRef: Any?, kProperty: Any?) = + Mut(_value) +} + +class Mut(var _value: T) { + + inline operator fun getValue(thisRef: Any?, kProperty: Any?) = _value + + inline operator fun setValue(thisRef: Any?, kProperty: Any?, newValue: T) { + _value = newValue + } +} + +class C { + val delegatedVal by Mut(1) + var delegatedVar by Mut(2) + val delegatedValByProvider by Provider(1) + var delegatedVarByProvider by Provider(2) +} + +val topLevelDelegatedVal by Mut(1) +var topLevelDelegatedVar by Mut(2) +val topLevelDelegatedValByProvider by Provider(1) +var topLevelDelegatedVarByProvider by Provider(2) + +fun box(): String { + val localDelegatedVal by Mut(1) + var localDelegatedVar by Mut(2) + val localDelegatedValByProvider by Provider(1) + var localDelegatedVarByProvider by Provider(2) + + val x = C() + if (x.delegatedVal != 1) throw AssertionError() + if (x.delegatedVar != 2) throw AssertionError() + x.delegatedVar = 3 + if (x.delegatedVar != 3) throw AssertionError() + + if (x.delegatedValByProvider != 1) throw AssertionError() + if (x.delegatedVarByProvider != 2) throw AssertionError() + x.delegatedVarByProvider = 3 + if (x.delegatedVarByProvider != 3) throw AssertionError() + + if (topLevelDelegatedVal != 1) throw AssertionError() + if (topLevelDelegatedVar != 2) throw AssertionError() + topLevelDelegatedVar = 3 + if (topLevelDelegatedVar != 3) throw AssertionError() + + if (topLevelDelegatedValByProvider != 1) throw AssertionError() + if (topLevelDelegatedVarByProvider != 2) throw AssertionError() + topLevelDelegatedVarByProvider = 3 + if (topLevelDelegatedVarByProvider != 3) throw AssertionError() + + if (localDelegatedVal != 1) throw AssertionError() + if (localDelegatedVar != 2) throw AssertionError() + localDelegatedVar = 3 + if (localDelegatedVar != 3) throw AssertionError() + + if (localDelegatedValByProvider != 1) throw AssertionError() + if (localDelegatedVarByProvider != 2) throw AssertionError() + localDelegatedVarByProvider = 3 + if (localDelegatedVarByProvider != 3) throw AssertionError() + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/definedInSourcesWithNonNullParameter.kt b/compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/definedInSourcesWithNonNullParameter.kt new file mode 100644 index 00000000000..590afc160bc --- /dev/null +++ b/compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/definedInSourcesWithNonNullParameter.kt @@ -0,0 +1,65 @@ +class Provider(val _value: T) { + inline operator fun provideDelegate(thisRef: Any?, kProperty: Any) = + Mut(_value) +} + +class Mut(var _value: T) { + + inline operator fun getValue(thisRef: Any?, kProperty: Any) = _value + + inline operator fun setValue(thisRef: Any?, kProperty: Any, newValue: T) { + _value = newValue + } +} + +class C { + val delegatedVal by Mut(1) + var delegatedVar by Mut(2) + val delegatedValByProvider by Provider(1) + var delegatedVarByProvider by Provider(2) +} + +val topLevelDelegatedVal by Mut(1) +var topLevelDelegatedVar by Mut(2) +val topLevelDelegatedValByProvider by Provider(1) +var topLevelDelegatedVarByProvider by Provider(2) + +fun box(): String { + val localDelegatedVal by Mut(1) + var localDelegatedVar by Mut(2) + val localDelegatedValByProvider by Provider(1) + var localDelegatedVarByProvider by Provider(2) + + val x = C() + if (x.delegatedVal != 1) throw AssertionError() + if (x.delegatedVar != 2) throw AssertionError() + x.delegatedVar = 3 + if (x.delegatedVar != 3) throw AssertionError() + + if (x.delegatedValByProvider != 1) throw AssertionError() + if (x.delegatedVarByProvider != 2) throw AssertionError() + x.delegatedVarByProvider = 3 + if (x.delegatedVarByProvider != 3) throw AssertionError() + + if (topLevelDelegatedVal != 1) throw AssertionError() + if (topLevelDelegatedVar != 2) throw AssertionError() + topLevelDelegatedVar = 3 + if (topLevelDelegatedVar != 3) throw AssertionError() + + if (topLevelDelegatedValByProvider != 1) throw AssertionError() + if (topLevelDelegatedVarByProvider != 2) throw AssertionError() + topLevelDelegatedVarByProvider = 3 + if (topLevelDelegatedVarByProvider != 3) throw AssertionError() + + if (localDelegatedVal != 1) throw AssertionError() + if (localDelegatedVar != 2) throw AssertionError() + localDelegatedVar = 3 + if (localDelegatedVar != 3) throw AssertionError() + + if (localDelegatedValByProvider != 1) throw AssertionError() + if (localDelegatedVarByProvider != 2) throw AssertionError() + localDelegatedVarByProvider = 3 + if (localDelegatedVarByProvider != 3) throw AssertionError() + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/inSeparateModule.kt b/compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/inSeparateModule.kt new file mode 100644 index 00000000000..a0e2d564484 --- /dev/null +++ b/compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/inSeparateModule.kt @@ -0,0 +1,76 @@ +// MODULE: lib +// FILE: lib.kt +package lib + +class Provider(val _value: T) { + inline operator fun provideDelegate(thisRef: Any?, kProperty: Any?) = + Mut(_value) +} + +class Mut(var _value: T) { + + inline operator fun getValue(thisRef: Any?, kProperty: Any?) = _value + + inline operator fun setValue(thisRef: Any?, kProperty: Any?, newValue: T) { + _value = newValue + } +} + +// MODULE: main(lib)(lib) +// FILE: main.kt +import lib.* + +class C { + val delegatedVal by Mut(1) + var delegatedVar by Mut(2) + + val delegatedValByProvider by Provider(1) + var delegatedVarByProvider by Provider(2) +} + +val topLevelDelegatedVal by Mut(1) +var topLevelDelegatedVar by Mut(2) + +val topLevelDelegatedValByProvider by Provider(1) +var topLevelDelegatedVarByProvider by Provider(2) + +fun box(): String { + val localDelegatedVal by Mut(1) + var localDelegatedVar by Mut(2) + + val localDelegatedValByProvider by Provider(1) + var localDelegatedVarByProvider by Provider(2) + + val x = C() + if (x.delegatedVal != 1) throw AssertionError() + if (x.delegatedVar != 2) throw AssertionError() + x.delegatedVar = 3 + if (x.delegatedVar != 3) throw AssertionError() + + if (x.delegatedValByProvider != 1) throw AssertionError() + if (x.delegatedVarByProvider != 2) throw AssertionError() + x.delegatedVarByProvider = 3 + if (x.delegatedVarByProvider != 3) throw AssertionError() + + if (topLevelDelegatedVal != 1) throw AssertionError() + if (topLevelDelegatedVar != 2) throw AssertionError() + topLevelDelegatedVar = 3 + if (topLevelDelegatedVar != 3) throw AssertionError() + + if (topLevelDelegatedValByProvider != 1) throw AssertionError() + if (topLevelDelegatedVarByProvider != 2) throw AssertionError() + topLevelDelegatedVarByProvider = 3 + if (topLevelDelegatedVarByProvider != 3) throw AssertionError() + + if (localDelegatedVal != 1) throw AssertionError() + if (localDelegatedVar != 2) throw AssertionError() + localDelegatedVar = 3 + if (localDelegatedVar != 3) throw AssertionError() + + if (localDelegatedValByProvider != 1) throw AssertionError() + if (localDelegatedVarByProvider != 2) throw AssertionError() + localDelegatedVarByProvider = 3 + if (localDelegatedVarByProvider != 3) throw AssertionError() + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/inSeparateModuleWithNonNullParameter.kt b/compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/inSeparateModuleWithNonNullParameter.kt new file mode 100644 index 00000000000..b6ee79d4b73 --- /dev/null +++ b/compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/inSeparateModuleWithNonNullParameter.kt @@ -0,0 +1,76 @@ +// MODULE: lib +// FILE: lib.kt +package lib + +class Provider(val _value: T) { + inline operator fun provideDelegate(thisRef: Any?, kProperty: Any) = + Mut(_value) +} + +class Mut(var _value: T) { + + inline operator fun getValue(thisRef: Any?, kProperty: Any) = _value + + inline operator fun setValue(thisRef: Any?, kProperty: Any, newValue: T) { + _value = newValue + } +} + +// MODULE: main(lib)(lib) +// FILE: main.kt +import lib.* + +class C { + val delegatedVal by Mut(1) + var delegatedVar by Mut(2) + + val delegatedValByProvider by Provider(1) + var delegatedVarByProvider by Provider(2) +} + +val topLevelDelegatedVal by Mut(1) +var topLevelDelegatedVar by Mut(2) + +val topLevelDelegatedValByProvider by Provider(1) +var topLevelDelegatedVarByProvider by Provider(2) + +fun box(): String { + val localDelegatedVal by Mut(1) + var localDelegatedVar by Mut(2) + + val localDelegatedValByProvider by Provider(1) + var localDelegatedVarByProvider by Provider(2) + + val x = C() + if (x.delegatedVal != 1) throw AssertionError() + if (x.delegatedVar != 2) throw AssertionError() + x.delegatedVar = 3 + if (x.delegatedVar != 3) throw AssertionError() + + if (x.delegatedValByProvider != 1) throw AssertionError() + if (x.delegatedVarByProvider != 2) throw AssertionError() + x.delegatedVarByProvider = 3 + if (x.delegatedVarByProvider != 3) throw AssertionError() + + if (topLevelDelegatedVal != 1) throw AssertionError() + if (topLevelDelegatedVar != 2) throw AssertionError() + topLevelDelegatedVar = 3 + if (topLevelDelegatedVar != 3) throw AssertionError() + + if (topLevelDelegatedValByProvider != 1) throw AssertionError() + if (topLevelDelegatedVarByProvider != 2) throw AssertionError() + topLevelDelegatedVarByProvider = 3 + if (topLevelDelegatedVarByProvider != 3) throw AssertionError() + + if (localDelegatedVal != 1) throw AssertionError() + if (localDelegatedVar != 2) throw AssertionError() + localDelegatedVar = 3 + if (localDelegatedVar != 3) throw AssertionError() + + if (localDelegatedValByProvider != 1) throw AssertionError() + if (localDelegatedVarByProvider != 2) throw AssertionError() + localDelegatedVarByProvider = 3 + if (localDelegatedVarByProvider != 3) throw AssertionError() + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/lazy.kt b/compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/lazy.kt new file mode 100644 index 00000000000..d4e1d498861 --- /dev/null +++ b/compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/lazy.kt @@ -0,0 +1,17 @@ +// WITH_RUNTIME + +val topLevelLazyVal by lazy { 1 } + +class C { + val memberLazyVal by lazy { 2 } +} + +fun box(): String { + val localLazyVal by lazy { 3 } + + if (topLevelLazyVal != 1) throw AssertionError() + if (C().memberLazyVal != 2) throw AssertionError() + if (localLazyVal != 3) throw AssertionError() + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/mixedArgumentSizes.kt b/compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/mixedArgumentSizes.kt new file mode 100644 index 00000000000..dad20517a99 --- /dev/null +++ b/compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/mixedArgumentSizes.kt @@ -0,0 +1,59 @@ +inline operator fun Double.provideDelegate(thisRef: Any?, kProp: Any?) = this.toLong() + +inline operator fun Long.getValue(thisRef: Any?, kProp: Any?) = this.toInt() + +inline operator fun Long.getValue(thisRef: Long, kProp: Any?) = this.toInt() + thisRef.toInt() + +inline operator fun Long.getValue(thisRef: IntArray, kProp: Any?) = thisRef[this.toInt()] + +inline operator fun Long.setValue(thisRef: IntArray, kProp: Any?, newValue: Int) { + thisRef[this.toInt()] = newValue +} + +val magic1 by 42.0 + +val magic2 by 42L + +var IntArray.firstElement by 0L + +val Long.plus3 by 3L + +class C { + inline operator fun Long.getValue(thisRef: IntArray, kProp: Any?) = thisRef[this.toInt()] * 10 + + inline operator fun Long.setValue(thisRef: IntArray, kProp: Any?, newValue: Int) { + thisRef[this.toInt()] = newValue * 10 + } + + inline operator fun Long.getValue(thisRef: Long, kProp: Any?) = this.toInt() + thisRef.toInt() * 10 + + var IntArray.secondElementX10 by 1L + + val Long.appendDigit1 by 1L + + fun test(intArray: IntArray) { + if (intArray.secondElementX10 != 220) throw AssertionError() + intArray.secondElementX10 = 42 + if (intArray.secondElementX10 != 4200) throw AssertionError() + + if (42L.appendDigit1 != 421) throw AssertionError() + } +} + +fun box(): String { + if (magic1 != 42) throw AssertionError() + if (magic2 != 42) throw AssertionError() + + val intArray = IntArray(9) { (it + 1) * 10 + it + 1 } // [ 11, 22, 33, ..., 99 ] + + if (10L.plus3 != 13) throw AssertionError() + + if (intArray.firstElement != 11) throw AssertionError() + intArray.firstElement = 42 + if (intArray.firstElement != 42) throw AssertionError() + + val x = C() + x.test(intArray) + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/optimizedDelegatedProperties/definedInSources.kt b/compiler/testData/codegen/bytecodeText/optimizedDelegatedProperties/definedInSources.kt new file mode 100644 index 00000000000..9fd18f214c4 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/optimizedDelegatedProperties/definedInSources.kt @@ -0,0 +1,55 @@ +// IGNORE_BACKEND: JVM_IR + +class Provider(val _value: T) { + inline operator fun provideDelegate(thisRef: Any?, kProperty: Any?) = + Mut(_value) +} + +class Mut(var _value: T) { + + inline operator fun getValue(thisRef: Any?, kProperty: Any?) = _value + + inline operator fun setValue(thisRef: Any?, kProperty: Any?, newValue: T) { + _value = newValue + } +} + +class C { + val delegatedVal by Mut(1) + var delegatedVar by Mut(2) + + val delegatedValByProvider by Provider(1) + var delegatedVarByProvider by Provider(2) +} + +val topLevelDelegatedVal by Mut(1) +var topLevelDelegatedVar by Mut(2) + +val topLevelDelegatedValByProvider by Provider(1) +var topLevelDelegatedVarByProvider by Provider(2) + +fun box(): String { + val localDelegatedVal by Mut(1) + var localDelegatedVar by Mut(2) + + val localDelegatedValByProvider by Provider(1) + var localDelegatedVarByProvider by Provider(2) + + if (localDelegatedVal != 1) throw AssertionError() + if (localDelegatedVar != 2) throw AssertionError() + localDelegatedVar = 3 + if (localDelegatedVar != 3) throw AssertionError() + + if (localDelegatedValByProvider != 1) throw AssertionError() + if (localDelegatedVarByProvider != 2) throw AssertionError() + localDelegatedVarByProvider = 3 + if (localDelegatedVarByProvider != 3) throw AssertionError() + + return "OK" +} + +// 0 \$\$delegatedProperties +// 0 ANEWARRAY +// 0 kotlin/reflect/KProperty +// 0 kotlin/jvm/internal/PropertyReference0Impl\.\ +// 0 kotlin/jvm/internal/MutablePropertyReference0Impl\.\ \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/optimizedDelegatedProperties/inSeparateModule.kt b/compiler/testData/codegen/bytecodeText/optimizedDelegatedProperties/inSeparateModule.kt new file mode 100644 index 00000000000..7e1baf51cff --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/optimizedDelegatedProperties/inSeparateModule.kt @@ -0,0 +1,91 @@ +// IGNORE_BACKEND: JVM_IR + +// MODULE: lib +// FILE: lib.kt +package lib + +class Provider(val _value: T) { + inline operator fun provideDelegate(thisRef: Any?, kProperty: Any?) = + Mut(_value) +} + +class Mut(var _value: T) { + + inline operator fun getValue(thisRef: Any?, kProperty: Any?) = _value + + inline operator fun setValue(thisRef: Any?, kProperty: Any?, newValue: T) { + _value = newValue + } +} + +// MODULE: main(lib)(lib) +// FILE: main.kt +import lib.* + +class C { + val delegatedVal by Mut(1) + var delegatedVar by Mut(2) + val delegatedValByProvider by Provider(1) + var delegatedVarByProvider by Provider(2) +} + +val topLevelDelegatedVal by Mut(1) +var topLevelDelegatedVar by Mut(2) +val topLevelDelegatedValByProvider by Provider(1) +var topLevelDelegatedVarByProvider by Provider(2) + +fun box(): String { + val localDelegatedVal by Mut(1) + var localDelegatedVar by Mut(2) + val localDelegatedValByProvider by Provider(1) + var localDelegatedVarByProvider by Provider(1) + + val x = C() + if (x.delegatedVal != 1) throw AssertionError() + if (x.delegatedVar != 2) throw AssertionError() + x.delegatedVar = 3 + if (x.delegatedVar != 3) throw AssertionError() + + if (x.delegatedValByProvider != 1) throw AssertionError() + if (x.delegatedVarByProvider != 2) throw AssertionError() + x.delegatedVarByProvider = 3 + if (x.delegatedVarByProvider != 3) throw AssertionError() + + if (topLevelDelegatedVal != 1) throw AssertionError() + if (topLevelDelegatedVar != 2) throw AssertionError() + topLevelDelegatedVar = 3 + if (topLevelDelegatedVar != 3) throw AssertionError() + + if (topLevelDelegatedValByProvider != 1) throw AssertionError() + if (topLevelDelegatedVarByProvider != 2) throw AssertionError() + topLevelDelegatedVarByProvider = 3 + if (topLevelDelegatedVarByProvider != 3) throw AssertionError() + + if (localDelegatedVal != 1) throw AssertionError() + if (localDelegatedVar != 2) throw AssertionError() + localDelegatedVar = 3 + if (localDelegatedVar != 3) throw AssertionError() + + if (localDelegatedValByProvider != 1) throw AssertionError() + if (localDelegatedVarByProvider != 2) throw AssertionError() + localDelegatedVarByProvider = 3 + if (localDelegatedVarByProvider != 3) throw AssertionError() + + return "OK" +} + +// @MainKt.class: +// 0 \$\$delegatedProperties +// 0 ANEWARRAY +// 0 kotlin/reflect/KProperty +// 0 final static synthetic \[Lkotlin/reflect/KProperty; \$\$delegatedProperties +// 0 kotlin/jvm/internal/PropertyReference0Impl\.\ +// 0 kotlin/jvm/internal/MutablePropertyReference0Impl\.\ + +// @C.class: +// 0 \$\$delegatedProperties +// 0 ANEWARRAY +// 0 kotlin/reflect/KProperty +// 0 final static synthetic \[Lkotlin/reflect/KProperty; \$\$delegatedProperties +// 0 kotlin/jvm/internal/PropertyReference0Impl\.\ +// 0 kotlin/jvm/internal/MutablePropertyReference0Impl\.\ diff --git a/compiler/testData/codegen/bytecodeText/optimizedDelegatedProperties/lazy.kt b/compiler/testData/codegen/bytecodeText/optimizedDelegatedProperties/lazy.kt new file mode 100644 index 00000000000..06e0b33c9dc --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/optimizedDelegatedProperties/lazy.kt @@ -0,0 +1,22 @@ +// IGNORE_BACKEND: JVM_IR +// WITH_RUNTIME + +val topLevelLazyVal by lazy { 1 } + +class C { + val memberLazyVal by lazy { 2 } +} + +fun box(): String { + val localLazyVal by lazy { 3 } + + if (topLevelLazyVal != 1) throw AssertionError() + if (C().memberLazyVal != 2) throw AssertionError() + if (localLazyVal != 3) throw AssertionError() + + return "OK" +} + +// 0 \$\$delegatedProperties +// 0 kotlin/jvm/internal/PropertyReference0Impl\.\ +// 0 kotlin/jvm/internal/MutablePropertyReference0Impl\.\ \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/optimizedDelegatedProperties/withNonNullMetadataParameter.kt b/compiler/testData/codegen/bytecodeText/optimizedDelegatedProperties/withNonNullMetadataParameter.kt new file mode 100644 index 00000000000..674142655cf --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/optimizedDelegatedProperties/withNonNullMetadataParameter.kt @@ -0,0 +1,53 @@ +// IGNORE_BACKEND: JVM_IR + +class Provider(val _value: T) { + inline operator fun provideDelegate(thisRef: Any?, kProperty: Any) = + Mut(_value) +} + +class Mut(var _value: T) { + + inline operator fun getValue(thisRef: Any?, kProperty: Any) = _value + + inline operator fun setValue(thisRef: Any?, kProperty: Any, newValue: T) { + _value = newValue + } +} + +class C { + val delegatedVal by Mut(1) + var delegatedVar by Mut(2) + + val delegatedValByProvider by Provider(1) + var delegatedVarByProvider by Provider(2) +} + +val topLevelDelegatedVal by Mut(1) +var topLevelDelegatedVar by Mut(2) + +val topLevelDelegatedValByProvider by Provider(1) +var topLevelDelegatedVarByProvider by Provider(2) + +fun box(): String { + val localDelegatedVal by Mut(1) + var localDelegatedVar by Mut(2) + + val localDelegatedValByProvider by Provider(1) + var localDelegatedVarByProvider by Provider(2) + + if (localDelegatedVal != 1) throw AssertionError() + if (localDelegatedVar != 2) throw AssertionError() + localDelegatedVar = 3 + if (localDelegatedVar != 3) throw AssertionError() + + if (localDelegatedValByProvider != 1) throw AssertionError() + if (localDelegatedVarByProvider != 2) throw AssertionError() + localDelegatedVarByProvider = 3 + if (localDelegatedVarByProvider != 3) throw AssertionError() + + return "OK" +} + +// 0 final static synthetic \[Lkotlin/reflect/KProperty; \$\$delegatedProperties +// 0 kotlin/jvm/internal/PropertyReference0Impl\.\ +// 0 kotlin/jvm/internal/MutablePropertyReference0Impl\.\ \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/UnusedParameters.kt b/compiler/testData/diagnostics/tests/UnusedParameters.kt index 6d9d36d4454..40a91f87c52 100644 --- a/compiler/testData/diagnostics/tests/UnusedParameters.kt +++ b/compiler/testData/diagnostics/tests/UnusedParameters.kt @@ -16,13 +16,22 @@ fun f(a: Int, b: Int, c: Int = b) { a + a } -fun Any.getValue(thisRef: Any?, prop: KProperty<*>): String = ":)" -fun Any.setValue(thisRef: Any?, prop: KProperty<*>, value: String) { +fun Any.getValue(thisRef: Any?, prop: KProperty<*>): String = ":)" +fun Any.setValue(thisRef: Any?, prop: KProperty<*>, value: String) { } -fun Any.provideDelegate(thisRef: Any?, prop: KProperty<*>) { +fun Any.provideDelegate(thisRef: Any?, prop: KProperty<*>) { } +operator fun Int.getValue(thisRef: Any?, prop: KProperty<*>): String = ":)" + +operator fun Int.setValue(thisRef: Any?, prop: KProperty<*>, value: String) { +} + +operator fun Int.provideDelegate(thisRef: Any?, prop: KProperty<*>) { +} + + fun get(p: Any) { } diff --git a/compiler/testData/diagnostics/tests/UnusedParameters.txt b/compiler/testData/diagnostics/tests/UnusedParameters.txt index 422af376f3b..91a8e2f01eb 100644 --- a/compiler/testData/diagnostics/tests/UnusedParameters.txt +++ b/compiler/testData/diagnostics/tests/UnusedParameters.txt @@ -5,8 +5,11 @@ public fun foo(/*0*/ s: kotlin.String): kotlin.Unit public fun get(/*0*/ p: kotlin.Any): kotlin.Unit public fun set(/*0*/ p: kotlin.Any): kotlin.Unit public fun kotlin.Any.getValue(/*0*/ thisRef: kotlin.Any?, /*1*/ prop: kotlin.reflect.KProperty<*>): kotlin.String +public operator fun kotlin.Int.getValue(/*0*/ thisRef: kotlin.Any?, /*1*/ prop: kotlin.reflect.KProperty<*>): kotlin.String public fun kotlin.Any.provideDelegate(/*0*/ thisRef: kotlin.Any?, /*1*/ prop: kotlin.reflect.KProperty<*>): kotlin.Unit +public operator fun kotlin.Int.provideDelegate(/*0*/ thisRef: kotlin.Any?, /*1*/ prop: kotlin.reflect.KProperty<*>): kotlin.Unit public fun kotlin.Any.setValue(/*0*/ thisRef: kotlin.Any?, /*1*/ prop: kotlin.reflect.KProperty<*>, /*2*/ value: kotlin.String): kotlin.Unit +public operator fun kotlin.Int.setValue(/*0*/ thisRef: kotlin.Any?, /*1*/ prop: kotlin.reflect.KProperty<*>, /*2*/ value: kotlin.String): kotlin.Unit public final class C { public constructor C(/*0*/ a: kotlin.Int, /*1*/ b: kotlin.Int, /*2*/ c: kotlin.Int, /*3*/ d: kotlin.Int, /*4*/ e: kotlin.Int = ..., /*5*/ f: kotlin.String) diff --git a/compiler/testData/diagnostics/tests/delegatedProperty/disallowImplInTypeParameter.kt b/compiler/testData/diagnostics/tests/delegatedProperty/disallowImplInTypeParameter.kt index 9b320bd7f82..ec70b1aa791 100644 --- a/compiler/testData/diagnostics/tests/delegatedProperty/disallowImplInTypeParameter.kt +++ b/compiler/testData/diagnostics/tests/delegatedProperty/disallowImplInTypeParameter.kt @@ -3,5 +3,5 @@ import kotlin.reflect.KProperty0 val a: Int by A() class A { - fun getValue(t: Any?, p: KProperty0<*>): Int = 1 + fun getValue(t: Any?, p: KProperty0<*>): Int = 1 } diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/checkers/AbstractDiagnosticsTest.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/checkers/AbstractDiagnosticsTest.kt index 9e622c4b2a0..a5e77c783e9 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/checkers/AbstractDiagnosticsTest.kt +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/checkers/AbstractDiagnosticsTest.kt @@ -39,11 +39,8 @@ import org.jetbrains.kotlin.load.java.lazy.SingleModuleClassResolver import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.SpecialNames -import org.jetbrains.kotlin.platform.CommonPlatforms import org.jetbrains.kotlin.platform.isCommon -import org.jetbrains.kotlin.platform.js.JsPlatforms import org.jetbrains.kotlin.platform.jvm.JvmPlatforms -import org.jetbrains.kotlin.platform.konan.KonanPlatforms import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.resolve.* import org.jetbrains.kotlin.resolve.calls.model.MutableResolvedCall diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index bc1f23ace75..9600473b301 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -9608,6 +9608,49 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { } } + @TestMetadata("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class OptimizedDelegatedProperties extends AbstractBlackBoxCodegenTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath); + } + + public void testAllFilesPresentInOptimizedDelegatedProperties() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); + } + + @TestMetadata("definedInSources.kt") + public void testDefinedInSources() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/definedInSources.kt"); + } + + @TestMetadata("definedInSourcesWithNonNullParameter.kt") + public void testDefinedInSourcesWithNonNullParameter() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/definedInSourcesWithNonNullParameter.kt"); + } + + @TestMetadata("inSeparateModule.kt") + public void testInSeparateModule() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/inSeparateModule.kt"); + } + + @TestMetadata("inSeparateModuleWithNonNullParameter.kt") + public void testInSeparateModuleWithNonNullParameter() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/inSeparateModuleWithNonNullParameter.kt"); + } + + @TestMetadata("lazy.kt") + public void testLazy() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/lazy.kt"); + } + + @TestMetadata("mixedArgumentSizes.kt") + public void testMixedArgumentSizes() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/mixedArgumentSizes.kt"); + } + } + @TestMetadata("compiler/testData/codegen/box/delegatedProperty/provideDelegate") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java index 5ab24da7713..485b6ab3c0a 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java @@ -3400,6 +3400,39 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest { } } + @TestMetadata("compiler/testData/codegen/bytecodeText/optimizedDelegatedProperties") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class OptimizedDelegatedProperties extends AbstractBytecodeTextTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath); + } + + public void testAllFilesPresentInOptimizedDelegatedProperties() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/bytecodeText/optimizedDelegatedProperties"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); + } + + @TestMetadata("definedInSources.kt") + public void testDefinedInSources() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/optimizedDelegatedProperties/definedInSources.kt"); + } + + @TestMetadata("inSeparateModule.kt") + public void testInSeparateModule() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/optimizedDelegatedProperties/inSeparateModule.kt"); + } + + @TestMetadata("lazy.kt") + public void testLazy() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/optimizedDelegatedProperties/lazy.kt"); + } + + @TestMetadata("withNonNullMetadataParameter.kt") + public void testWithNonNullMetadataParameter() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/optimizedDelegatedProperties/withNonNullMetadataParameter.kt"); + } + } + @TestMetadata("compiler/testData/codegen/bytecodeText/properties") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index cd41d7f3c6c..6c33a8a5520 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -9608,6 +9608,49 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes } } + @TestMetadata("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class OptimizedDelegatedProperties extends AbstractLightAnalysisModeTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath); + } + + public void testAllFilesPresentInOptimizedDelegatedProperties() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); + } + + @TestMetadata("definedInSources.kt") + public void testDefinedInSources() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/definedInSources.kt"); + } + + @TestMetadata("definedInSourcesWithNonNullParameter.kt") + public void testDefinedInSourcesWithNonNullParameter() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/definedInSourcesWithNonNullParameter.kt"); + } + + @TestMetadata("inSeparateModule.kt") + public void testInSeparateModule() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/inSeparateModule.kt"); + } + + @TestMetadata("inSeparateModuleWithNonNullParameter.kt") + public void testInSeparateModuleWithNonNullParameter() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/inSeparateModuleWithNonNullParameter.kt"); + } + + @TestMetadata("lazy.kt") + public void testLazy() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/lazy.kt"); + } + + @TestMetadata("mixedArgumentSizes.kt") + public void testMixedArgumentSizes() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/mixedArgumentSizes.kt"); + } + } + @TestMetadata("compiler/testData/codegen/box/delegatedProperty/provideDelegate") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 0dec818837b..8d5d3d8b6e6 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -8493,6 +8493,49 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes } } + @TestMetadata("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class OptimizedDelegatedProperties extends AbstractIrBlackBoxCodegenTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM_IR, testDataFilePath); + } + + public void testAllFilesPresentInOptimizedDelegatedProperties() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true); + } + + @TestMetadata("definedInSources.kt") + public void testDefinedInSources() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/definedInSources.kt"); + } + + @TestMetadata("definedInSourcesWithNonNullParameter.kt") + public void testDefinedInSourcesWithNonNullParameter() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/definedInSourcesWithNonNullParameter.kt"); + } + + @TestMetadata("inSeparateModule.kt") + public void testInSeparateModule() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/inSeparateModule.kt"); + } + + @TestMetadata("inSeparateModuleWithNonNullParameter.kt") + public void testInSeparateModuleWithNonNullParameter() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/inSeparateModuleWithNonNullParameter.kt"); + } + + @TestMetadata("lazy.kt") + public void testLazy() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/lazy.kt"); + } + + @TestMetadata("mixedArgumentSizes.kt") + public void testMixedArgumentSizes() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/mixedArgumentSizes.kt"); + } + } + @TestMetadata("compiler/testData/codegen/box/delegatedProperty/provideDelegate") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java index 77cc3f96811..b4529e45eb4 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java @@ -3370,6 +3370,39 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest { } } + @TestMetadata("compiler/testData/codegen/bytecodeText/optimizedDelegatedProperties") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class OptimizedDelegatedProperties extends AbstractIrBytecodeTextTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM_IR, testDataFilePath); + } + + public void testAllFilesPresentInOptimizedDelegatedProperties() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/bytecodeText/optimizedDelegatedProperties"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true); + } + + @TestMetadata("definedInSources.kt") + public void testDefinedInSources() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/optimizedDelegatedProperties/definedInSources.kt"); + } + + @TestMetadata("inSeparateModule.kt") + public void testInSeparateModule() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/optimizedDelegatedProperties/inSeparateModule.kt"); + } + + @TestMetadata("lazy.kt") + public void testLazy() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/optimizedDelegatedProperties/lazy.kt"); + } + + @TestMetadata("withNonNullMetadataParameter.kt") + public void testWithNonNullMetadataParameter() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/optimizedDelegatedProperties/withNonNullMetadataParameter.kt"); + } + } + @TestMetadata("compiler/testData/codegen/bytecodeText/properties") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/core/descriptors/src/org/jetbrains/kotlin/util/OperatorNameConventions.kt b/core/descriptors/src/org/jetbrains/kotlin/util/OperatorNameConventions.kt index f8bc8d171d9..e257951db31 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/util/OperatorNameConventions.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/util/OperatorNameConventions.kt @@ -73,4 +73,7 @@ object OperatorNameConventions { @JvmField internal val ASSIGNMENT_OPERATIONS = setOf(TIMES_ASSIGN, DIV_ASSIGN, MOD_ASSIGN, REM_ASSIGN, PLUS_ASSIGN, MINUS_ASSIGN) + + @JvmField + val DELEGATED_PROPERTY_OPERATORS = setOf(GET_VALUE, SET_VALUE, PROVIDE_DELEGATE) } diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index 1d13dab1935..46f217ec046 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -7313,6 +7313,49 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { } } + @TestMetadata("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class OptimizedDelegatedProperties extends AbstractIrJsCodegenBoxTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath); + } + + public void testAllFilesPresentInOptimizedDelegatedProperties() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS_IR, true); + } + + @TestMetadata("definedInSources.kt") + public void testDefinedInSources() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/definedInSources.kt"); + } + + @TestMetadata("definedInSourcesWithNonNullParameter.kt") + public void testDefinedInSourcesWithNonNullParameter() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/definedInSourcesWithNonNullParameter.kt"); + } + + @TestMetadata("inSeparateModule.kt") + public void testInSeparateModule() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/inSeparateModule.kt"); + } + + @TestMetadata("inSeparateModuleWithNonNullParameter.kt") + public void testInSeparateModuleWithNonNullParameter() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/inSeparateModuleWithNonNullParameter.kt"); + } + + @TestMetadata("lazy.kt") + public void testLazy() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/lazy.kt"); + } + + @TestMetadata("mixedArgumentSizes.kt") + public void testMixedArgumentSizes() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/mixedArgumentSizes.kt"); + } + } + @TestMetadata("compiler/testData/codegen/box/delegatedProperty/provideDelegate") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 1bef4b8218c..64a718efc6b 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -8398,6 +8398,49 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { } } + @TestMetadata("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class OptimizedDelegatedProperties extends AbstractJsCodegenBoxTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath); + } + + public void testAllFilesPresentInOptimizedDelegatedProperties() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true); + } + + @TestMetadata("definedInSources.kt") + public void testDefinedInSources() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/definedInSources.kt"); + } + + @TestMetadata("definedInSourcesWithNonNullParameter.kt") + public void testDefinedInSourcesWithNonNullParameter() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/definedInSourcesWithNonNullParameter.kt"); + } + + @TestMetadata("inSeparateModule.kt") + public void testInSeparateModule() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/inSeparateModule.kt"); + } + + @TestMetadata("inSeparateModuleWithNonNullParameter.kt") + public void testInSeparateModuleWithNonNullParameter() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/inSeparateModuleWithNonNullParameter.kt"); + } + + @TestMetadata("lazy.kt") + public void testLazy() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/lazy.kt"); + } + + @TestMetadata("mixedArgumentSizes.kt") + public void testMixedArgumentSizes() throws Exception { + runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/mixedArgumentSizes.kt"); + } + } + @TestMetadata("compiler/testData/codegen/box/delegatedProperty/provideDelegate") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)