From 2d3ac9109bed6f50029d9cadbdea9a7a9bd61cd6 Mon Sep 17 00:00:00 2001 From: Alexey Sedunov Date: Mon, 21 Jul 2014 17:08:06 +0400 Subject: [PATCH] Pseudocode: Generate synthetic VALUE_CONSUMER for both property and class delegates --- .../jet/lang/cfg/JetControlFlowProcessor.java | 54 +++++++++++++------ .../jet/lang/cfg/pseudocode/TypePredicate.kt | 2 +- .../delegationByExpression.values | 20 +++---- .../local/ObjectExpression.values | 6 +-- .../properties/DelegatedProperty.instructions | 15 +++--- .../properties/DelegatedProperty.kt | 2 +- .../properties/DelegatedProperty.values | 9 ++-- 7 files changed, 67 insertions(+), 41 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java index d03c95f07f1..ee9b72f2926 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java @@ -22,6 +22,7 @@ import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.SmartFMap; import com.intellij.util.containers.ContainerUtil; +import jet.runtime.typeinfo.JetValueParameter; import kotlin.Function0; import kotlin.Function1; import kotlin.KotlinPackage; @@ -548,7 +549,7 @@ public class JetControlFlowProcessor { @NotNull Map receiverValues, @NotNull JetExpression parentExpression ) { - if (target == AccessTarget.BlackBox.instance$) { + if (target == AccessTarget.BlackBox.INSTANCE$) { List values = ContainerUtil.createMaybeSingletonList(rightValue); builder.magic(parentExpression, parentExpression, values, defaultTypeMap(values), MagicKind.UNSUPPORTED_ELEMENT); } @@ -893,14 +894,8 @@ public class JetControlFlowProcessor { JetMultiDeclaration multiDeclaration = expression.getMultiParameter(); JetExpression loopRange = expression.getLoopRange(); - TypePredicate loopRangeTypePredicate = AllTypes.INSTANCE$; - ResolvedCall iteratorResolvedCall = trace.get(BindingContext.LOOP_RANGE_ITERATOR_RESOLVED_CALL, loopRange); - if (iteratorResolvedCall != null) { - ReceiverValue iteratorReceiver = getExplicitReceiverValue(iteratorResolvedCall); - if (iteratorReceiver.exists()) { - loopRangeTypePredicate = PseudocodePackage.getReceiverTypePredicate(iteratorResolvedCall, iteratorReceiver); - } - } + TypePredicate loopRangeTypePredicate = + getTypePredicateByReceiverValue(trace.get(BindingContext.LOOP_RANGE_ITERATOR_RESOLVED_CALL, loopRange)); PseudoValue loopRangeValue = builder.getBoundValue(loopRange); PseudoValue value = builder.magic( @@ -1154,7 +1149,9 @@ public class JetControlFlowProcessor { JetExpression delegate = property.getDelegateExpression(); if (delegate != null) { generateInstructions(delegate); + generateDelegateConsumer(property, delegate); } + if (JetPsiUtil.isLocal(property)) { for (JetPropertyAccessor accessor : property.getAccessors()) { generateInstructions(accessor); @@ -1162,6 +1159,36 @@ public class JetControlFlowProcessor { } } + private void generateDelegateConsumer(@NotNull JetProperty property, @NotNull JetExpression delegate) { + DeclarationDescriptor descriptor = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, property); + if (!(descriptor instanceof PropertyDescriptor)) return; + + List values = Collections.singletonList(builder.getBoundValue(delegate)); + List typePredicates = KotlinPackage.map( + ((PropertyDescriptor) descriptor).getAccessors(), + new Function1() { + @Override + public TypePredicate invoke(PropertyAccessorDescriptor descriptor) { + return getTypePredicateByReceiverValue(trace.get(BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, descriptor)); + } + } + ); + Map valuesToTypePredicates = + PseudocodePackage.expectedTypeFor(PseudocodePackage.and(typePredicates), values); + builder.magic(property, null, values, valuesToTypePredicates, MagicKind.VALUE_CONSUMER); + } + + private TypePredicate getTypePredicateByReceiverValue(@Nullable ResolvedCall resolvedCall) { + if (resolvedCall == null) return AllTypes.INSTANCE$; + + ReceiverValue receiverValue = getExplicitReceiverValue(resolvedCall); + if (receiverValue.exists()) { + return PseudocodePackage.getReceiverTypePredicate(resolvedCall, receiverValue); + } + + return AllTypes.INSTANCE$; + } + @Override public void visitMultiDeclaration(@NotNull JetMultiDeclaration declaration) { visitMultiDeclaration(declaration, true); @@ -1399,12 +1426,9 @@ public class JetControlFlowProcessor { generateInstructions(specifier.getDelegateExpression()); List arguments = ContainerUtil.createMaybeSingletonList(builder.getBoundValue(specifier.getDelegateExpression())); - TypePredicate expectedTypePredicate = - PseudocodePackage.getSubtypesPredicate(trace.get(BindingContext.TYPE, specifier.getTypeReference())); - if (expectedTypePredicate == null) { - expectedTypePredicate = AllTypes.INSTANCE$; - } - builder.magic(specifier, specifier, arguments, PseudocodePackage.expectedTypeFor(expectedTypePredicate, arguments), MagicKind.VALUE_CONSUMER); + JetType jetType = trace.get(BindingContext.TYPE, specifier.getTypeReference()); + TypePredicate expectedTypePredicate = jetType != null ? PseudocodePackage.getSubtypesPredicate(jetType) : AllTypes.INSTANCE$; + builder.magic(specifier, null, arguments, PseudocodePackage.expectedTypeFor(expectedTypePredicate, arguments), MagicKind.VALUE_CONSUMER); } @Override diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/TypePredicate.kt b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/TypePredicate.kt index bd201338487..e52501b7a4e 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/TypePredicate.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/TypePredicate.kt @@ -72,7 +72,7 @@ fun or(predicates: Collection): TypePredicate? = else -> ForSomeType(predicates.toList()) } -fun JetType.getSubtypesPredicate(): TypePredicate? { +fun JetType.getSubtypesPredicate(): TypePredicate { return when { KotlinBuiltIns.getInstance().isAnyOrNullableAny(this) && isNullable() -> AllTypes TypeUtils.canHaveSubtypes(JetTypeChecker.DEFAULT, this) -> AllSubtypes(this) diff --git a/compiler/testData/cfg/declarations/classesAndObjects/delegationByExpression.values b/compiler/testData/cfg/declarations/classesAndObjects/delegationByExpression.values index 6d4a8f4528c..c5f4dbea26c 100644 --- a/compiler/testData/cfg/declarations/classesAndObjects/delegationByExpression.values +++ b/compiler/testData/cfg/declarations/classesAndObjects/delegationByExpression.values @@ -11,14 +11,14 @@ class A(a: Int, b: Int): T == B == class B(a: Int, b: Int): T by A(a + b, a - b) --------------------- - : Int NEW: magic[FAKE_INITIALIZER](a: Int) -> - : Int NEW: magic[FAKE_INITIALIZER](b: Int) -> -a : Int NEW: r(a) -> -b : Int NEW: r(b) -> -a + b : Int NEW: call(a + b, plus|, ) -> -a : Int NEW: r(a) -> -b : Int NEW: r(b) -> -a - b : Int NEW: call(a - b, minus|, ) -> -A(a + b, a - b) : {<: T} NEW: call(A(a + b, a - b), |, ) -> -T by A(a + b, a - b) : * NEW: magic[VALUE_CONSUMER](T by A(a + b, a - b)|) -> + : Int NEW: magic[FAKE_INITIALIZER](a: Int) -> + : Int NEW: magic[FAKE_INITIALIZER](b: Int) -> + : * NEW: magic[VALUE_CONSUMER](T by A(a + b, a - b)|) -> +a : Int NEW: r(a) -> +b : Int NEW: r(b) -> +a + b : Int NEW: call(a + b, plus|, ) -> +a : Int NEW: r(a) -> +b : Int NEW: r(b) -> +a - b : Int NEW: call(a - b, minus|, ) -> +A(a + b, a - b) : {<: T} NEW: call(A(a + b, a - b), |, ) -> ===================== diff --git a/compiler/testData/cfg/declarations/local/ObjectExpression.values b/compiler/testData/cfg/declarations/local/ObjectExpression.values index 4523e7363ea..d4fa5d403d2 100644 --- a/compiler/testData/cfg/declarations/local/ObjectExpression.values +++ b/compiler/testData/cfg/declarations/local/ObjectExpression.values @@ -26,9 +26,9 @@ fun foo(b: B) : Int { } --------------------- : B NEW: magic[FAKE_INITIALIZER](b: B) -> -b : {<: A} NEW: r(b) -> -A by b : * NEW: magic[VALUE_CONSUMER](A by b|) -> -object : A by b {} : NEW: r(object : A by b {}) -> + : * NEW: magic[VALUE_CONSUMER](A by b|) -> +b : {<: A} NEW: r(b) -> +object : A by b {} : NEW: r(object : A by b {}) -> o : {<: A} NEW: r(o) -> foo() : Int NEW: call(foo(), foo|) -> o.foo() : Int COPY diff --git a/compiler/testData/cfg/declarations/properties/DelegatedProperty.instructions b/compiler/testData/cfg/declarations/properties/DelegatedProperty.instructions index e305af3e212..c113a2ea28a 100644 --- a/compiler/testData/cfg/declarations/properties/DelegatedProperty.instructions +++ b/compiler/testData/cfg/declarations/properties/DelegatedProperty.instructions @@ -1,6 +1,6 @@ == Delegate == class Delegate { - fun get(_this: Any, p: PropertyMetadata): Int = 0 + fun get(_this: Nothing?, p: PropertyMetadata): Int = 0 } --------------------- L0: @@ -13,12 +13,12 @@ sink: PREV:[, ] ===================== == get == -fun get(_this: Any, p: PropertyMetadata): Int = 0 +fun get(_this: Nothing?, p: PropertyMetadata): Int = 0 --------------------- L0: 1 - v(_this: Any) - magic[FAKE_INITIALIZER](_this: Any) -> + v(_this: Nothing?) + magic[FAKE_INITIALIZER](_this: Nothing?) -> w(_this|) v(p: PropertyMetadata) magic[FAKE_INITIALIZER](p: PropertyMetadata) -> @@ -55,10 +55,11 @@ L0: 1 v(val b by a) r(a) -> + magic[VALUE_CONSUMER](val b by a|) -> L1: - NEXT:[] + NEXT:[] error: - PREV:[] + PREV:[] sink: - PREV:[, ] + PREV:[, ] ===================== diff --git a/compiler/testData/cfg/declarations/properties/DelegatedProperty.kt b/compiler/testData/cfg/declarations/properties/DelegatedProperty.kt index 69dd88733f3..d0f6e621021 100644 --- a/compiler/testData/cfg/declarations/properties/DelegatedProperty.kt +++ b/compiler/testData/cfg/declarations/properties/DelegatedProperty.kt @@ -1,5 +1,5 @@ class Delegate { - fun get(_this: Any, p: PropertyMetadata): Int = 0 + fun get(_this: Nothing?, p: PropertyMetadata): Int = 0 } val a = Delegate() diff --git a/compiler/testData/cfg/declarations/properties/DelegatedProperty.values b/compiler/testData/cfg/declarations/properties/DelegatedProperty.values index eea35c4faa8..b4aff3f3a6c 100644 --- a/compiler/testData/cfg/declarations/properties/DelegatedProperty.values +++ b/compiler/testData/cfg/declarations/properties/DelegatedProperty.values @@ -1,13 +1,13 @@ == Delegate == class Delegate { - fun get(_this: Any, p: PropertyMetadata): Int = 0 + fun get(_this: Nothing?, p: PropertyMetadata): Int = 0 } --------------------- ===================== == get == -fun get(_this: Any, p: PropertyMetadata): Int = 0 +fun get(_this: Nothing?, p: PropertyMetadata): Int = 0 --------------------- - : {<: Any} NEW: magic[FAKE_INITIALIZER](_this: Any) -> + : {<: Nothing?} NEW: magic[FAKE_INITIALIZER](_this: Nothing?) -> : {<: PropertyMetadata} NEW: magic[FAKE_INITIALIZER](p: PropertyMetadata) -> 0 : Int NEW: r(0) -> ===================== @@ -19,5 +19,6 @@ Delegate() : Delegate NEW: call(Delegate(), ) -> == b == val b by a --------------------- -a : * NEW: r(a) -> + : * NEW: magic[VALUE_CONSUMER](val b by a|) -> +a : Delegate NEW: r(a) -> =====================