diff --git a/annotations/com/intellij/util/annotations.xml b/annotations/com/intellij/util/annotations.xml
index b6951be234c..3aa90806ee8 100644
--- a/annotations/com/intellij/util/annotations.xml
+++ b/annotations/com/intellij/util/annotations.xml
@@ -14,4 +14,10 @@
-
+ -
+
+
+ -
+
+
\ No newline at end of file
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilder.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilder.java
index 1c37511288e..b2f168f55c3 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilder.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilder.java
@@ -20,6 +20,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.cfg.pseudocode.PseudoValue;
import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode;
+import org.jetbrains.jet.lang.cfg.pseudocode.TypePredicate;
import org.jetbrains.jet.lang.cfg.pseudocode.instructions.eval.AccessTarget;
import org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
@@ -115,6 +116,7 @@ public interface JetControlFlowBuilder {
@NotNull JetElement instructionElement,
@Nullable JetElement valueElement,
@NotNull List inputValues,
+ @NotNull Map expectedTypes,
boolean synthetic
);
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilderAdapter.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilderAdapter.java
index acd15845357..ce21685711b 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilderAdapter.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowBuilderAdapter.java
@@ -20,6 +20,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.cfg.pseudocode.PseudoValue;
import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode;
+import org.jetbrains.jet.lang.cfg.pseudocode.TypePredicate;
import org.jetbrains.jet.lang.cfg.pseudocode.instructions.eval.AccessTarget;
import org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
@@ -71,9 +72,10 @@ public abstract class JetControlFlowBuilderAdapter implements JetControlFlowBuil
@NotNull JetElement instructionElement,
@Nullable JetElement valueElement,
@NotNull List inputValues,
+ @NotNull Map expectedTypes,
boolean synthetic
) {
- return getDelegateBuilder().magic(instructionElement, valueElement, inputValues, synthetic);
+ return getDelegateBuilder().magic(instructionElement, valueElement, inputValues, expectedTypes, synthetic);
}
@NotNull
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 679f9bd2487..38108fe0e50 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java
@@ -22,16 +22,12 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.SmartFMap;
-import com.intellij.util.containers.ContainerUtil;
import kotlin.Function0;
import kotlin.Function1;
import kotlin.KotlinPackage;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowInstructionsGenerator;
-import org.jetbrains.jet.lang.cfg.pseudocode.PseudoValue;
-import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode;
-import org.jetbrains.jet.lang.cfg.pseudocode.PseudocodeImpl;
+import org.jetbrains.jet.lang.cfg.pseudocode.*;
import org.jetbrains.jet.lang.cfg.pseudocode.instructions.eval.AccessTarget;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
@@ -188,12 +184,24 @@ public class JetControlFlowProcessor {
@NotNull
private PseudoValue createSyntheticValue(@NotNull JetElement instructionElement) {
- return builder.magic(instructionElement, null, Collections.emptyList(), true);
+ return createSyntheticValue(instructionElement, Collections.emptyList());
+ }
+
+ @NotNull
+ private PseudoValue createSyntheticValue(@NotNull JetElement instructionElement, @NotNull List extends JetElement> from) {
+ List values = elementsToValues(from);
+ return builder.magic(instructionElement, null, values, defaultTypeMap(values), true);
}
@NotNull
private PseudoValue createNonSyntheticValue(@NotNull List extends JetElement> from, @NotNull JetElement to) {
- return builder.magic(to, to, elementsToValues(from), false);
+ List values = elementsToValues(from);
+ return builder.magic(to, to, values, defaultTypeMap(values), false);
+ }
+
+ @NotNull
+ private Map defaultTypeMap(List values) {
+ return PseudocodePackage.expectedTypeFor(AllTypes.instance$, values);
}
private void mergeValues(@NotNull List from, @NotNull JetExpression to) {
@@ -218,10 +226,10 @@ public class JetControlFlowProcessor {
}
private List elementsToValues(List extends JetElement> from) {
+ if (from.isEmpty()) return Collections.emptyList();
return KotlinPackage.filterNotNull(
- KotlinPackage.mapTo(
+ KotlinPackage.map(
from,
- new LinkedHashSet(),
new Function1() {
@Override
public PseudoValue invoke(JetElement element) {
@@ -862,12 +870,17 @@ public class JetControlFlowProcessor {
private void writeLoopParameterAssignment(JetForExpression expression) {
JetParameter loopParameter = expression.getLoopParameter();
JetMultiDeclaration multiDeclaration = expression.getMultiParameter();
-
JetExpression loopRange = expression.getLoopRange();
+
+ JetType loopRangeType = trace.get(BindingContext.EXPRESSION_TYPE, loopRange);
+ TypePredicate loopRangeTypeSet = loopRangeType != null ? new SingleType(loopRangeType) : AllTypes.instance$;
+ PseudoValue loopRangeValue = builder.getBoundValue(loopRange);
+
PseudoValue value = builder.magic(
loopRange != null ? loopRange : expression,
null,
- Collections.singletonList(builder.getBoundValue(loopRange)),
+ Collections.singletonList(loopRangeValue),
+ Collections.singletonMap(loopRangeValue, loopRangeTypeSet),
true
);
@@ -1058,7 +1071,10 @@ public class JetControlFlowProcessor {
inputExpressions.add(calleeExpression);
inputExpressions.add(generateAndGetReceiverIfAny(expression));
- createNonSyntheticValue(inputExpressions, calleeExpression != null ? calleeExpression : expression);
+ createNonSyntheticValue(
+ inputExpressions,
+ calleeExpression != null ? calleeExpression : expression
+ );
}
copyValue(calleeExpression, expression);
@@ -1106,16 +1122,16 @@ public class JetControlFlowProcessor {
generateInstructions(initializer, NOT_IN_CONDITION);
for (JetMultiDeclarationEntry entry : declaration.getEntries()) {
builder.declareVariable(entry);
+
ResolvedCall resolvedCall = trace.get(BindingContext.COMPONENT_RESOLVED_CALL, entry);
PseudoValue writtenValue = resolvedCall != null
? builder.call(
- entry,
- resolvedCall,
- getReceiverValues(resolvedCall, false),
- Collections.emptyMap()
- )
- : builder.magic(entry, null,
- ContainerUtil.createMaybeSingletonList(builder.getBoundValue(initializer)), true);
+ entry,
+ resolvedCall,
+ getReceiverValues(resolvedCall, false),
+ Collections.emptyMap()
+ )
+ : createSyntheticValue(entry, Collections.singletonList(initializer));
if (generateWriteForEntries) {
generateInitializer(entry, writtenValue != null ? writtenValue : createSyntheticValue(entry));
}
@@ -1209,9 +1225,7 @@ public class JetControlFlowProcessor {
JetWhenCondition condition = conditions[i];
condition.accept(conditionVisitor, context);
if (i + 1 < conditions.length) {
- PseudoValue conditionValue = builder.magic(
- condition, null, elementsToValues(Arrays.asList(subjectExpression, condition)), true
- );
+ PseudoValue conditionValue = createSyntheticValue(condition, Arrays.asList(subjectExpression, condition));
builder.nondeterministicJump(bodyLabel, expression, conditionValue);
}
}
@@ -1221,9 +1235,7 @@ public class JetControlFlowProcessor {
PseudoValue conditionValue = null;
JetWhenCondition lastCondition = KotlinPackage.lastOrNull(conditions);
if (lastCondition != null) {
- conditionValue = builder.magic(
- lastCondition, null, elementsToValues(Arrays.asList(subjectExpression, lastCondition)), true
- );
+ conditionValue = createSyntheticValue(lastCondition, Arrays.asList(subjectExpression, lastCondition));
}
builder.nondeterministicJump(nextLabel, expression, conditionValue);
}
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/JetControlFlowInstructionsGenerator.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/JetControlFlowInstructionsGenerator.java
index ba1eee9dc8e..21878b53024 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/JetControlFlowInstructionsGenerator.java
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/JetControlFlowInstructionsGenerator.java
@@ -420,7 +420,8 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
@NotNull
@Override
public PseudoValue loadStringTemplate(@NotNull JetStringTemplateExpression expression, @NotNull List inputValues) {
- return inputValues.isEmpty() ? read(expression) : magic(expression, expression, inputValues, false);
+ if (inputValues.isEmpty()) return read(expression);
+ return magic(expression, expression, inputValues, PseudocodePackage.expectedTypeFor(AllTypes.instance$, inputValues), false);
}
@NotNull
@@ -429,10 +430,12 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
@NotNull JetElement instructionElement,
@Nullable JetElement valueElement,
@NotNull List inputValues,
+ @NotNull Map expectedTypes,
boolean synthetic
) {
- MagicInstruction instruction =
- MagicInstruction.object$.create(instructionElement, valueElement, getCurrentScope(), synthetic, inputValues, valueFactory);
+ MagicInstruction instruction = MagicInstruction.object$.create(
+ instructionElement, valueElement, getCurrentScope(), synthetic, inputValues, expectedTypes, valueFactory
+ );
add(instruction);
return instruction.getOutputValue();
}
@@ -489,7 +492,21 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
@NotNull PredefinedOperation operation,
@NotNull List inputValues
) {
- return magic(expression, expression, inputValues, false);
+ Map expectedTypes;
+ switch(operation) {
+ case AND:
+ case OR:
+ SingleType onlyBoolean = new SingleType(KotlinBuiltIns.getInstance().getBooleanType());
+ expectedTypes = PseudocodePackage.expectedTypeFor(onlyBoolean, inputValues);
+ break;
+ case NOT_NULL_ASSERTION:
+ expectedTypes = PseudocodePackage.expectedTypeFor(AllTypes.instance$, inputValues);
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid operation: " + operation);
+ }
+
+ return magic(expression, expression, inputValues, expectedTypes, false);
}
@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
new file mode 100644
index 00000000000..ac4bd2030cb
--- /dev/null
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/TypePredicate.kt
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2010-2014 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jetbrains.jet.lang.cfg.pseudocode
+
+import org.jetbrains.jet.lang.types.JetType
+import org.jetbrains.jet.lang.types.checker.JetTypeChecker
+import org.jetbrains.jet.renderer.DescriptorRenderer
+import com.intellij.util.SmartFMap
+import org.jetbrains.jet.lang.types.TypeUtils
+
+public trait TypePredicate: (JetType) -> Boolean {
+ [suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE")]
+ override fun invoke(typeToCheck: JetType): Boolean
+}
+
+public data class SingleType(val targetType: JetType): TypePredicate {
+ override fun invoke(typeToCheck: JetType): Boolean = JetTypeChecker.INSTANCE.equalTypes(typeToCheck, targetType)
+ override fun toString(): String = targetType.render()
+}
+
+public object AllTypes : TypePredicate {
+ override fun invoke(typeToCheck: JetType): Boolean = true
+
+ override fun toString(): String = ""
+}
+
+private fun JetType.render(): String = DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(this)
+
+public fun TypePredicate.expectedTypeFor(keys: Iterable): Map =
+ keys.fold(SmartFMap.emptyMap()) { (map, key) -> map.plus(key, this) }
diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/instructions/eval/operationInstructions.kt b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/instructions/eval/operationInstructions.kt
index 1696f9013c3..a5d704c3da4 100644
--- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/instructions/eval/operationInstructions.kt
+++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/pseudocode/instructions/eval/operationInstructions.kt
@@ -26,6 +26,7 @@ import org.jetbrains.jet.lang.cfg.pseudocode.instructions.InstructionVisitor
import org.jetbrains.jet.lang.cfg.pseudocode.instructions.InstructionVisitorWithResult
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor
+import org.jetbrains.jet.lang.cfg.pseudocode.TypePredicate
public abstract class OperationInstruction protected(
element: JetElement,
@@ -102,8 +103,13 @@ public class MagicInstruction(
element: JetElement,
lexicalScope: LexicalScope,
val synthetic: Boolean,
- inputValues: List
+ inputValues: List,
+ val expectedTypes: Map
) : OperationInstruction(element, lexicalScope, inputValues), StrictlyValuedOperationInstruction {
+ protected fun setResult(valueElement: JetElement?, factory: PseudoValueFactory?): OperationInstruction {
+ return setResult(factory?.newValue(valueElement, this))
+ }
+
override fun accept(visitor: InstructionVisitor) {
visitor.visitMagic(this)
}
@@ -113,7 +119,7 @@ public class MagicInstruction(
}
override fun createCopy() =
- MagicInstruction(element, lexicalScope, synthetic, inputValues).setResult(resultValue)
+ MagicInstruction(element, lexicalScope, synthetic, inputValues, expectedTypes).setResult(resultValue)
override fun toString() = renderInstruction("magic", render(element))
@@ -124,8 +130,11 @@ public class MagicInstruction(
lexicalScope: LexicalScope,
synthetic: Boolean,
inputValues: List,
+ expectedTypes: Map,
factory: PseudoValueFactory
- ): MagicInstruction = MagicInstruction(element, lexicalScope, synthetic, inputValues).setResult(factory, valueElement) as MagicInstruction
+ ): MagicInstruction = MagicInstruction(
+ element, lexicalScope, synthetic, inputValues, expectedTypes
+ ).setResult(factory, valueElement) as MagicInstruction
}
}