Merge remote branch 'origin/master'
This commit is contained in:
+3
-3
@@ -25,12 +25,11 @@ public class SemanticWhitespaceAwarePsiBuilderImpl extends PsiBuilderAdapter imp
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean newlineBeforeCurrentToken() {
|
public boolean newlineBeforeCurrentToken() {
|
||||||
|
|
||||||
if (!newlinesEnabled.peek()) return false;
|
if (!newlinesEnabled.peek()) return false;
|
||||||
|
|
||||||
if (eof()) return true;
|
if (eof()) return true;
|
||||||
|
|
||||||
// TODO: maybe, memorize this somehow?
|
// TODO: maybe, memoize this somehow?
|
||||||
for (int i = 1; i <= getCurrentOffset(); i++) {
|
for (int i = 1; i <= getCurrentOffset(); i++) {
|
||||||
IElementType previousToken = rawLookup(-i);
|
IElementType previousToken = rawLookup(-i);
|
||||||
|
|
||||||
@@ -51,8 +50,9 @@ public class SemanticWhitespaceAwarePsiBuilderImpl extends PsiBuilderAdapter imp
|
|||||||
assert previousTokenEnd < getOriginalText().length();
|
assert previousTokenEnd < getOriginalText().length();
|
||||||
|
|
||||||
for (int j = previousTokenStart; j < previousTokenEnd; j++) {
|
for (int j = previousTokenStart; j < previousTokenEnd; j++) {
|
||||||
if (getOriginalText().charAt(j) == '\n')
|
if (getOriginalText().charAt(j) == '\n') {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+69
-66
@@ -651,7 +651,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
return DataFlowUtils.checkType(result, expression, context);
|
return DataFlowUtils.checkType(result, expression, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void checkLValue(BindingTrace trace, JetExpression expression) {
|
public void checkLValue(BindingTrace trace, JetExpression expression) {
|
||||||
checkLValue(trace, expression, false);
|
checkLValue(trace, expression, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -685,8 +685,8 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (OperatorConventions.BINARY_OPERATION_NAMES.containsKey(operationType)) {
|
else if (OperatorConventions.BINARY_OPERATION_NAMES.containsKey(operationType)) {
|
||||||
result = getTypeForBinaryCall(context.scope, OperatorConventions.BINARY_OPERATION_NAMES.get(operationType), context, expression);
|
result = getTypeForBinaryCall(context.scope, OperatorConventions.BINARY_OPERATION_NAMES.get(operationType), context, expression);
|
||||||
}
|
}
|
||||||
else if (operationType == JetTokens.EQ) {
|
else if (operationType == JetTokens.EQ) {
|
||||||
result = visitAssignment(expression, contextWithExpectedType);
|
result = visitAssignment(expression, contextWithExpectedType);
|
||||||
}
|
}
|
||||||
@@ -706,74 +706,77 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (OperatorConventions.EQUALS_OPERATIONS.contains(operationType)) {
|
else {
|
||||||
String name = "equals";
|
JetType booleanType = context.semanticServices.getStandardLibrary().getBooleanType();
|
||||||
if (right != null) {
|
if (OperatorConventions.EQUALS_OPERATIONS.contains(operationType)) {
|
||||||
ExpressionReceiver receiver = ExpressionTypingUtils.safeGetExpressionReceiver(facade, left, context.replaceScope(context.scope));
|
String name = "equals";
|
||||||
OverloadResolutionResults<FunctionDescriptor> resolutionResults = context.resolveExactSignature(
|
if (right != null) {
|
||||||
receiver, "equals",
|
ExpressionReceiver receiver = ExpressionTypingUtils.safeGetExpressionReceiver(facade, left, context.replaceScope(context.scope));
|
||||||
Collections.singletonList(JetStandardClasses.getNullableAnyType()));
|
OverloadResolutionResults<FunctionDescriptor> resolutionResults = context.resolveExactSignature(
|
||||||
if (resolutionResults.isSuccess()) {
|
receiver, "equals",
|
||||||
FunctionDescriptor equals = resolutionResults.getResult().getResultingDescriptor();
|
Collections.singletonList(JetStandardClasses.getNullableAnyType()));
|
||||||
context.trace.record(REFERENCE_TARGET, operationSign, equals);
|
if (resolutionResults.isSuccess()) {
|
||||||
if (ensureBooleanResult(operationSign, name, equals.getReturnType(), context)) {
|
FunctionDescriptor equals = resolutionResults.getResult().getResultingDescriptor();
|
||||||
ensureNonemptyIntersectionOfOperandTypes(expression, context);
|
context.trace.record(REFERENCE_TARGET, operationSign, equals);
|
||||||
}
|
if (ensureBooleanResult(operationSign, name, equals.getReturnType(), context)) {
|
||||||
}
|
ensureNonemptyIntersectionOfOperandTypes(expression, context);
|
||||||
else {
|
}
|
||||||
if (resolutionResults.isAmbiguity()) {
|
|
||||||
context.trace.report(OVERLOAD_RESOLUTION_AMBIGUITY.on(operationSign, resolutionResults.getResults()));
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
context.trace.report(EQUALS_MISSING.on(operationSign));
|
if (resolutionResults.isAmbiguity()) {
|
||||||
|
context.trace.report(OVERLOAD_RESOLUTION_AMBIGUITY.on(operationSign, resolutionResults.getResults()));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
context.trace.report(EQUALS_MISSING.on(operationSign));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = booleanType;
|
||||||
|
}
|
||||||
|
else if (operationType == JetTokens.EQEQEQ || operationType == JetTokens.EXCLEQEQEQ) {
|
||||||
|
ensureNonemptyIntersectionOfOperandTypes(expression, context);
|
||||||
|
|
||||||
|
// TODO : Check comparison pointlessness
|
||||||
|
result = booleanType;
|
||||||
|
}
|
||||||
|
else if (OperatorConventions.IN_OPERATIONS.contains(operationType)) {
|
||||||
|
if (right == null) {
|
||||||
|
result = ErrorUtils.createErrorType("No right argument"); // TODO
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
checkInExpression(expression, expression.getOperationReference(), expression.getLeft(), expression.getRight(), context);
|
||||||
|
result = booleanType;
|
||||||
|
}
|
||||||
|
else if (operationType == JetTokens.ANDAND || operationType == JetTokens.OROR) {
|
||||||
|
JetType leftType = facade.getType(left, context.replaceScope(context.scope));
|
||||||
|
WritableScopeImpl leftScope = newWritableScopeImpl(context).setDebugName("Left scope of && or ||");
|
||||||
|
DataFlowInfo flowInfoLeft = DataFlowUtils.extractDataFlowInfoFromCondition(left, operationType == JetTokens.ANDAND, leftScope, context); // TODO: This gets computed twice: here and in extractDataFlowInfoFromCondition() for the whole condition
|
||||||
|
WritableScopeImpl rightScope = operationType == JetTokens.ANDAND ? leftScope : newWritableScopeImpl(context).setDebugName("Right scope of && or ||");
|
||||||
|
JetType rightType = right == null ? null : facade.getType(right, context.replaceDataFlowInfo(flowInfoLeft).replaceScope(rightScope));
|
||||||
|
if (leftType != null && !isBoolean(context.semanticServices, leftType)) {
|
||||||
|
context.trace.report(TYPE_MISMATCH.on(left, booleanType, leftType));
|
||||||
|
}
|
||||||
|
if (rightType != null && !isBoolean(context.semanticServices, rightType)) {
|
||||||
|
context.trace.report(TYPE_MISMATCH.on(right, booleanType, rightType));
|
||||||
|
}
|
||||||
|
result = booleanType;
|
||||||
|
}
|
||||||
|
else if (operationType == JetTokens.ELVIS) {
|
||||||
|
JetType leftType = facade.getType(left, context.replaceScope(context.scope));
|
||||||
|
JetType rightType = right == null ? null : facade.getType(right, contextWithExpectedType.replaceScope(context.scope));
|
||||||
|
if (leftType != null) {
|
||||||
|
if (!leftType.isNullable()) {
|
||||||
|
context.trace.report(USELESS_ELVIS.on(expression, left, leftType));
|
||||||
|
}
|
||||||
|
if (rightType != null) {
|
||||||
|
DataFlowUtils.checkType(TypeUtils.makeNullableAsSpecified(leftType, rightType.isNullable()), left, contextWithExpectedType);
|
||||||
|
return TypeUtils.makeNullableAsSpecified(CommonSupertypes.commonSupertype(Arrays.asList(leftType, rightType)), rightType.isNullable());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result = context.semanticServices.getStandardLibrary().getBooleanType();
|
else {
|
||||||
}
|
context.trace.report(UNSUPPORTED.on(operationSign, "Unknown operation"));
|
||||||
else if (operationType == JetTokens.EQEQEQ || operationType == JetTokens.EXCLEQEQEQ) {
|
|
||||||
ensureNonemptyIntersectionOfOperandTypes(expression, context);
|
|
||||||
|
|
||||||
// TODO : Check comparison pointlessness
|
|
||||||
result = context.semanticServices.getStandardLibrary().getBooleanType();
|
|
||||||
}
|
|
||||||
else if (OperatorConventions.IN_OPERATIONS.contains(operationType)) {
|
|
||||||
if (right == null) {
|
|
||||||
result = ErrorUtils.createErrorType("No right argument"); // TODO
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
checkInExpression(expression, expression.getOperationReference(), expression.getLeft(), expression.getRight(), context);
|
|
||||||
result = context.semanticServices.getStandardLibrary().getBooleanType();
|
|
||||||
}
|
|
||||||
else if (operationType == JetTokens.ANDAND || operationType == JetTokens.OROR) {
|
|
||||||
JetType leftType = facade.getType(left, context.replaceScope(context.scope));
|
|
||||||
WritableScopeImpl leftScope = newWritableScopeImpl(context).setDebugName("Left scope of && or ||");
|
|
||||||
DataFlowInfo flowInfoLeft = DataFlowUtils.extractDataFlowInfoFromCondition(left, operationType == JetTokens.ANDAND, leftScope, context); // TODO: This gets computed twice: here and in extractDataFlowInfoFromCondition() for the whole condition
|
|
||||||
WritableScopeImpl rightScope = operationType == JetTokens.ANDAND ? leftScope : newWritableScopeImpl(context).setDebugName("Right scope of && or ||");
|
|
||||||
JetType rightType = right == null ? null : facade.getType(right, context.replaceDataFlowInfo(flowInfoLeft).replaceScope(rightScope));
|
|
||||||
if (leftType != null && !isBoolean(context.semanticServices, leftType)) {
|
|
||||||
context.trace.report(TYPE_MISMATCH.on(left, context.semanticServices.getStandardLibrary().getBooleanType(), leftType));
|
|
||||||
}
|
|
||||||
if (rightType != null && !isBoolean(context.semanticServices, rightType)) {
|
|
||||||
context.trace.report(TYPE_MISMATCH.on(right, context.semanticServices.getStandardLibrary().getBooleanType(), rightType));
|
|
||||||
}
|
|
||||||
result = context.semanticServices.getStandardLibrary().getBooleanType();
|
|
||||||
}
|
|
||||||
else if (operationType == JetTokens.ELVIS) {
|
|
||||||
JetType leftType = facade.getType(left, context.replaceScope(context.scope));
|
|
||||||
JetType rightType = right == null ? null : facade.getType(right, contextWithExpectedType.replaceScope(context.scope));
|
|
||||||
if (leftType != null) {
|
|
||||||
if (!leftType.isNullable()) {
|
|
||||||
context.trace.report(USELESS_ELVIS.on(expression, left, leftType));
|
|
||||||
}
|
|
||||||
if (rightType != null) {
|
|
||||||
DataFlowUtils.checkType(TypeUtils.makeNullableAsSpecified(leftType, rightType.isNullable()), left, contextWithExpectedType);
|
|
||||||
return TypeUtils.makeNullableAsSpecified(CommonSupertypes.commonSupertype(Arrays.asList(leftType, rightType)), rightType.isNullable());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
context.trace.report(UNSUPPORTED.on(operationSign, "Unknown operation"));
|
|
||||||
}
|
}
|
||||||
return DataFlowUtils.checkType(result, expression, contextWithExpectedType);
|
return DataFlowUtils.checkType(result, expression, contextWithExpectedType);
|
||||||
}
|
}
|
||||||
@@ -842,7 +845,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
protected JetType getTypeForBinaryCall(JetScope scope, String name, ExpressionTypingContext context, JetBinaryExpression binaryExpression) {
|
public JetType getTypeForBinaryCall(JetScope scope, String name, ExpressionTypingContext context, JetBinaryExpression binaryExpression) {
|
||||||
ExpressionReceiver receiver = safeGetExpressionReceiver(facade, binaryExpression.getLeft(), context.replaceScope(scope));
|
ExpressionReceiver receiver = safeGetExpressionReceiver(facade, binaryExpression.getLeft(), context.replaceScope(scope));
|
||||||
FunctionDescriptor functionDescriptor = context.replaceScope(scope).resolveCallWithGivenNameToDescriptor(
|
FunctionDescriptor functionDescriptor = context.replaceScope(scope).resolveCallWithGivenNameToDescriptor(
|
||||||
CallMaker.makeCall(receiver, binaryExpression),
|
CallMaker.makeCall(receiver, binaryExpression),
|
||||||
|
|||||||
+13
-15
@@ -10,10 +10,11 @@ import org.jetbrains.jet.lang.diagnostics.Errors;
|
|||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
||||||
|
import org.jetbrains.jet.lang.resolve.calls.OverloadResolutionResults;
|
||||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.TaskPrioritizers;
|
import org.jetbrains.jet.lang.resolve.calls.TaskPrioritizers;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
|
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.OverloadResolutionResults;
|
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
|
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
|
import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
|
||||||
@@ -21,7 +22,10 @@ import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
|
|||||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.TransientReceiver;
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.TransientReceiver;
|
||||||
import org.jetbrains.jet.lang.types.*;
|
import org.jetbrains.jet.lang.types.*;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
||||||
import static org.jetbrains.jet.lang.resolve.BindingContext.*;
|
import static org.jetbrains.jet.lang.resolve.BindingContext.*;
|
||||||
@@ -36,10 +40,6 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
super(facade);
|
super(facade);
|
||||||
}
|
}
|
||||||
|
|
||||||
private JetType getTypeWithNewScopeAndDataFlowInfo(@NotNull JetScope scope, @NotNull JetExpression expression, @NotNull DataFlowInfo newDataFlowInfo, @NotNull ExpressionTypingContext context) {
|
|
||||||
return facade.getType(expression, context.replaceScope(scope).replaceDataFlowInfo(newDataFlowInfo));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkCondition(@NotNull JetScope scope, @Nullable JetExpression condition, ExpressionTypingContext context) {
|
private void checkCondition(@NotNull JetScope scope, @Nullable JetExpression condition, ExpressionTypingContext context) {
|
||||||
if (condition != null) {
|
if (condition != null) {
|
||||||
JetType conditionType = facade.getType(condition, context.replaceScope(scope));
|
JetType conditionType = facade.getType(condition, context.replaceScope(scope));
|
||||||
@@ -63,30 +63,29 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
JetExpression thenBranch = expression.getThen();
|
JetExpression thenBranch = expression.getThen();
|
||||||
|
|
||||||
WritableScopeImpl thenScope = newWritableScopeImpl(context).setDebugName("Then scope");
|
WritableScopeImpl thenScope = newWritableScopeImpl(context).setDebugName("Then scope");
|
||||||
|
WritableScopeImpl elseScope = newWritableScopeImpl(context).setDebugName("Else scope");
|
||||||
DataFlowInfo thenInfo = DataFlowUtils.extractDataFlowInfoFromCondition(condition, true, thenScope, context);
|
DataFlowInfo thenInfo = DataFlowUtils.extractDataFlowInfoFromCondition(condition, true, thenScope, context);
|
||||||
DataFlowInfo elseInfo = DataFlowUtils.extractDataFlowInfoFromCondition(condition, false, null, context);
|
DataFlowInfo elseInfo = DataFlowUtils.extractDataFlowInfoFromCondition(condition, false, null, context);
|
||||||
|
|
||||||
if (elseBranch == null) {
|
if (elseBranch == null) {
|
||||||
if (thenBranch != null) {
|
if (thenBranch != null) {
|
||||||
JetType type = getTypeWithNewScopeAndDataFlowInfo(thenScope, thenBranch, thenInfo, context);
|
JetType type = context.getServices().getBlockReturnedTypeWithWritableScope(thenScope, Collections.singletonList(thenBranch), CoercionStrategy.NO_COERCION, context.replaceDataFlowInfo(thenInfo));
|
||||||
if (type != null && JetStandardClasses.isNothing(type)) {
|
if (type != null && JetStandardClasses.isNothing(type)) {
|
||||||
facade.setResultingDataFlowInfo(elseInfo);
|
facade.setResultingDataFlowInfo(elseInfo);
|
||||||
// resultScope = elseScope;
|
|
||||||
}
|
}
|
||||||
return DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType);
|
return DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (thenBranch == null) {
|
if (thenBranch == null) {
|
||||||
JetType type = getTypeWithNewScopeAndDataFlowInfo(context.scope, elseBranch, elseInfo, context);
|
JetType type = context.getServices().getBlockReturnedTypeWithWritableScope(elseScope, Collections.singletonList(elseBranch), CoercionStrategy.NO_COERCION, context.replaceDataFlowInfo(elseInfo));
|
||||||
if (type != null && JetStandardClasses.isNothing(type)) {
|
if (type != null && JetStandardClasses.isNothing(type)) {
|
||||||
facade.setResultingDataFlowInfo(thenInfo);
|
facade.setResultingDataFlowInfo(thenInfo);
|
||||||
// resultScope = thenScope;
|
|
||||||
}
|
}
|
||||||
return DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType);
|
return DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType);
|
||||||
}
|
}
|
||||||
JetType thenType = getTypeWithNewScopeAndDataFlowInfo(thenScope, thenBranch, thenInfo, contextWithExpectedType);
|
JetType thenType = context.getServices().getBlockReturnedTypeWithWritableScope(thenScope, Collections.singletonList(thenBranch), CoercionStrategy.NO_COERCION, contextWithExpectedType.replaceDataFlowInfo(thenInfo));
|
||||||
JetType elseType = getTypeWithNewScopeAndDataFlowInfo(context.scope, elseBranch, elseInfo, contextWithExpectedType);
|
JetType elseType = context.getServices().getBlockReturnedTypeWithWritableScope(elseScope, Collections.singletonList(elseBranch), CoercionStrategy.NO_COERCION, contextWithExpectedType.replaceDataFlowInfo(elseInfo));
|
||||||
|
|
||||||
JetType result;
|
JetType result;
|
||||||
if (thenType == null) {
|
if (thenType == null) {
|
||||||
@@ -120,7 +119,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
if (body != null) {
|
if (body != null) {
|
||||||
WritableScopeImpl scopeToExtend = newWritableScopeImpl(context).setDebugName("Scope extended in while's condition");
|
WritableScopeImpl scopeToExtend = newWritableScopeImpl(context).setDebugName("Scope extended in while's condition");
|
||||||
DataFlowInfo conditionInfo = condition == null ? context.dataFlowInfo : DataFlowUtils.extractDataFlowInfoFromCondition(condition, true, scopeToExtend, context);
|
DataFlowInfo conditionInfo = condition == null ? context.dataFlowInfo : DataFlowUtils.extractDataFlowInfoFromCondition(condition, true, scopeToExtend, context);
|
||||||
getTypeWithNewScopeAndDataFlowInfo(scopeToExtend, body, conditionInfo, context);
|
context.getServices().getBlockReturnedTypeWithWritableScope(scopeToExtend, Collections.singletonList(body), CoercionStrategy.NO_COERCION, context.replaceDataFlowInfo(conditionInfo));
|
||||||
}
|
}
|
||||||
if (!containsBreak(expression, context)) {
|
if (!containsBreak(expression, context)) {
|
||||||
facade.setResultingDataFlowInfo(DataFlowUtils.extractDataFlowInfoFromCondition(condition, false, null, context));
|
facade.setResultingDataFlowInfo(DataFlowUtils.extractDataFlowInfoFromCondition(condition, false, null, context));
|
||||||
@@ -229,8 +228,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
|
|
||||||
JetExpression body = expression.getBody();
|
JetExpression body = expression.getBody();
|
||||||
if (body != null) {
|
if (body != null) {
|
||||||
ExpressionTypingInternals blockLevelVisitor = ExpressionTypingVisitorDispatcher.createForBlock(loopScope);
|
context.getServices().getBlockReturnedTypeWithWritableScope(loopScope, Collections.singletonList(body), CoercionStrategy.NO_COERCION, context);
|
||||||
blockLevelVisitor.getType(body, context.replaceScope(loopScope));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType);
|
return DataFlowUtils.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType);
|
||||||
|
|||||||
+3
@@ -14,4 +14,7 @@ public interface ExpressionTypingFacade {
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
JetType getType(@NotNull JetExpression expression, ExpressionTypingContext context);
|
JetType getType(@NotNull JetExpression expression, ExpressionTypingContext context);
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
JetType getTypeForStatement(@NotNull JetExpression expression, ExpressionTypingContext context);
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-5
@@ -218,13 +218,13 @@ public class ExpressionTypingServices {
|
|||||||
final boolean[] mismatch = new boolean[1];
|
final boolean[] mismatch = new boolean[1];
|
||||||
ObservableBindingTrace errorInterceptingTrace = makeTraceInterceptingTypeMismatch(temporaryTraceExpectingUnit, statementExpression, mismatch);
|
ObservableBindingTrace errorInterceptingTrace = makeTraceInterceptingTypeMismatch(temporaryTraceExpectingUnit, statementExpression, mismatch);
|
||||||
newContext = createContext(newContext, errorInterceptingTrace, scope, newContext.dataFlowInfo, context.expectedType, context.expectedReturnType);
|
newContext = createContext(newContext, errorInterceptingTrace, scope, newContext.dataFlowInfo, context.expectedType, context.expectedReturnType);
|
||||||
result = blockLevelVisitor.getType(statementExpression, newContext);
|
result = blockLevelVisitor.getTypeForStatement(statementExpression, newContext);
|
||||||
if (mismatch[0]) {
|
if (mismatch[0]) {
|
||||||
TemporaryBindingTrace temporaryTraceNoExpectedType = TemporaryBindingTrace.create(trace);
|
TemporaryBindingTrace temporaryTraceNoExpectedType = TemporaryBindingTrace.create(trace);
|
||||||
mismatch[0] = false;
|
mismatch[0] = false;
|
||||||
ObservableBindingTrace interceptingTrace = makeTraceInterceptingTypeMismatch(temporaryTraceNoExpectedType, statementExpression, mismatch);
|
ObservableBindingTrace interceptingTrace = makeTraceInterceptingTypeMismatch(temporaryTraceNoExpectedType, statementExpression, mismatch);
|
||||||
newContext = createContext(newContext, interceptingTrace, scope, newContext.dataFlowInfo, NO_EXPECTED_TYPE, context.expectedReturnType);
|
newContext = createContext(newContext, interceptingTrace, scope, newContext.dataFlowInfo, NO_EXPECTED_TYPE, context.expectedReturnType);
|
||||||
result = blockLevelVisitor.getType(statementExpression, newContext);
|
result = blockLevelVisitor.getTypeForStatement(statementExpression, newContext);
|
||||||
if (mismatch[0]) {
|
if (mismatch[0]) {
|
||||||
temporaryTraceExpectingUnit.commit();
|
temporaryTraceExpectingUnit.commit();
|
||||||
}
|
}
|
||||||
@@ -238,11 +238,11 @@ public class ExpressionTypingServices {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
newContext = createContext(newContext, trace, scope, newContext.dataFlowInfo, context.expectedType, context.expectedReturnType);
|
newContext = createContext(newContext, trace, scope, newContext.dataFlowInfo, context.expectedType, context.expectedReturnType);
|
||||||
result = blockLevelVisitor.getType(statementExpression, newContext);
|
result = blockLevelVisitor.getTypeForStatement(statementExpression, newContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
result = blockLevelVisitor.getType(statementExpression, newContext);
|
result = blockLevelVisitor.getTypeForStatement(statementExpression, newContext);
|
||||||
if (coercionStrategyForLastExpression == CoercionStrategy.COERCION_TO_UNIT) {
|
if (coercionStrategyForLastExpression == CoercionStrategy.COERCION_TO_UNIT) {
|
||||||
boolean mightBeUnit = false;
|
boolean mightBeUnit = false;
|
||||||
if (statementExpression instanceof JetDeclaration) {
|
if (statementExpression instanceof JetDeclaration) {
|
||||||
@@ -264,7 +264,7 @@ public class ExpressionTypingServices {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
result = blockLevelVisitor.getType(statementExpression, newContext);
|
result = blockLevelVisitor.getTypeForStatement(statementExpression, newContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
DataFlowInfo newDataFlowInfo = blockLevelVisitor.getResultingDataFlowInfo();
|
DataFlowInfo newDataFlowInfo = blockLevelVisitor.getResultingDataFlowInfo();
|
||||||
|
|||||||
+28
-19
@@ -14,6 +14,7 @@ import org.jetbrains.jet.lang.types.ErrorUtils;
|
|||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
import org.jetbrains.jet.util.lazy.ReenteringLazyValueComputationException;
|
import org.jetbrains.jet.util.lazy.ReenteringLazyValueComputationException;
|
||||||
|
|
||||||
|
import static org.jetbrains.jet.lang.diagnostics.Errors.ELSE_MISPLACED_IN_WHEN;
|
||||||
import static org.jetbrains.jet.lang.diagnostics.Errors.TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM;
|
import static org.jetbrains.jet.lang.diagnostics.Errors.TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -21,36 +22,33 @@ import static org.jetbrains.jet.lang.diagnostics.Errors.TYPECHECKER_HAS_RUN_INTO
|
|||||||
*/
|
*/
|
||||||
public class ExpressionTypingVisitorDispatcher extends JetVisitor<JetType, ExpressionTypingContext> implements ExpressionTypingInternals {
|
public class ExpressionTypingVisitorDispatcher extends JetVisitor<JetType, ExpressionTypingContext> implements ExpressionTypingInternals {
|
||||||
|
|
||||||
private static Function<ExpressionTypingInternals, BasicExpressionTypingVisitor> BASIC_FACTORY = new Function<ExpressionTypingInternals, BasicExpressionTypingVisitor>() {
|
private static ExpressionTypingVisitorDispatcher BASIC_DISPATCHER = new ExpressionTypingVisitorDispatcher(null);
|
||||||
@Override
|
|
||||||
public BasicExpressionTypingVisitor fun(ExpressionTypingInternals facade) {
|
|
||||||
return new BasicExpressionTypingVisitor(facade);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static ExpressionTypingFacade create() {
|
public static ExpressionTypingFacade create() {
|
||||||
return new ExpressionTypingVisitorDispatcher(BASIC_FACTORY);
|
return BASIC_DISPATCHER;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static ExpressionTypingInternals createForBlock(final WritableScope writableScope) {
|
public static ExpressionTypingInternals createForBlock(final WritableScope writableScope) {
|
||||||
return new ExpressionTypingVisitorDispatcher(new Function<ExpressionTypingInternals, BasicExpressionTypingVisitor>() {
|
return new ExpressionTypingVisitorDispatcher(writableScope);
|
||||||
@Override
|
|
||||||
public BasicExpressionTypingVisitor fun(ExpressionTypingInternals facade) {
|
|
||||||
return new ExpressionTypingVisitorForStatements(facade, writableScope);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private final BasicExpressionTypingVisitor basic;
|
private final BasicExpressionTypingVisitor basic;
|
||||||
|
private final ExpressionTypingVisitorForStatements statements;
|
||||||
private final ClosureExpressionsTypingVisitor closures = new ClosureExpressionsTypingVisitor(this);
|
private final ClosureExpressionsTypingVisitor closures = new ClosureExpressionsTypingVisitor(this);
|
||||||
private final ControlStructureTypingVisitor controlStructures = new ControlStructureTypingVisitor(this);
|
private final ControlStructureTypingVisitor controlStructures = new ControlStructureTypingVisitor(this);
|
||||||
private final PatternMatchingTypingVisitor patterns = new PatternMatchingTypingVisitor(this);
|
private final PatternMatchingTypingVisitor patterns = new PatternMatchingTypingVisitor(this);
|
||||||
protected DataFlowInfo resultDataFlowInfo;
|
protected DataFlowInfo resultDataFlowInfo;
|
||||||
|
|
||||||
private ExpressionTypingVisitorDispatcher(Function<ExpressionTypingInternals, BasicExpressionTypingVisitor> factoryForBasic) {
|
private ExpressionTypingVisitorDispatcher(WritableScope writableScope) {
|
||||||
this.basic = factoryForBasic.fun(this);
|
this.basic = new BasicExpressionTypingVisitor(this);
|
||||||
|
if (writableScope != null) {
|
||||||
|
this.statements = new ExpressionTypingVisitorForStatements(this, writableScope, basic);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.statements = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -87,12 +85,23 @@ public class ExpressionTypingVisitorDispatcher extends JetVisitor<JetType, Expre
|
|||||||
@Override
|
@Override
|
||||||
@Nullable
|
@Nullable
|
||||||
public final JetType getType(@NotNull JetExpression expression, ExpressionTypingContext context) {
|
public final JetType getType(@NotNull JetExpression expression, ExpressionTypingContext context) {
|
||||||
|
return getType(expression, context, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public final JetType getTypeForStatement(@NotNull JetExpression expression, ExpressionTypingContext context) {
|
||||||
|
return getType(expression, context, statements);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private JetType getType(@NotNull JetExpression expression, ExpressionTypingContext context, JetVisitor<JetType, ExpressionTypingContext> visitor) {
|
||||||
if (context.trace.get(BindingContext.PROCESSED, expression)) {
|
if (context.trace.get(BindingContext.PROCESSED, expression)) {
|
||||||
return context.trace.getBindingContext().get(BindingContext.EXPRESSION_TYPE, expression);
|
return context.trace.getBindingContext().get(BindingContext.EXPRESSION_TYPE, expression);
|
||||||
}
|
}
|
||||||
JetType result;
|
JetType result;
|
||||||
try {
|
try {
|
||||||
result = expression.accept(this, context);
|
result = expression.accept(visitor, context);
|
||||||
// Some recursive definitions (object expressions) must put their types in the cache manually:
|
// Some recursive definitions (object expressions) must put their types in the cache manually:
|
||||||
if (context.trace.get(BindingContext.PROCESSED, expression)) {
|
if (context.trace.get(BindingContext.PROCESSED, expression)) {
|
||||||
return context.trace.getBindingContext().get(BindingContext.EXPRESSION_TYPE, expression);
|
return context.trace.getBindingContext().get(BindingContext.EXPRESSION_TYPE, expression);
|
||||||
@@ -115,10 +124,10 @@ public class ExpressionTypingVisitorDispatcher extends JetVisitor<JetType, Expre
|
|||||||
context.trace.record(BindingContext.RESOLUTION_SCOPE, expression, context.scope);
|
context.trace.record(BindingContext.RESOLUTION_SCOPE, expression, context.scope);
|
||||||
}
|
}
|
||||||
context.trace.record(BindingContext.PROCESSED, expression);
|
context.trace.record(BindingContext.PROCESSED, expression);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JetType visitFunctionLiteralExpression(JetFunctionLiteralExpression expression, ExpressionTypingContext data) {
|
public JetType visitFunctionLiteralExpression(JetFunctionLiteralExpression expression, ExpressionTypingContext data) {
|
||||||
|
|||||||
+31
-8
@@ -27,12 +27,14 @@ import static org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils.get
|
|||||||
/**
|
/**
|
||||||
* @author abreslav
|
* @author abreslav
|
||||||
*/
|
*/
|
||||||
public class ExpressionTypingVisitorForStatements extends BasicExpressionTypingVisitor {
|
public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisitor {
|
||||||
private final WritableScope scope;
|
private final WritableScope scope;
|
||||||
|
private final BasicExpressionTypingVisitor basic;
|
||||||
|
|
||||||
public ExpressionTypingVisitorForStatements(@NotNull ExpressionTypingInternals facade, @NotNull WritableScope scope) {
|
public ExpressionTypingVisitorForStatements(@NotNull ExpressionTypingInternals facade, @NotNull WritableScope scope, BasicExpressionTypingVisitor basic) {
|
||||||
super(facade);
|
super(facade);
|
||||||
this.scope = scope;
|
this.scope = scope;
|
||||||
|
this.basic = basic;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -126,6 +128,22 @@ public class ExpressionTypingVisitorForStatements extends BasicExpressionTypingV
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
public JetType visitBinaryExpression(JetBinaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
|
||||||
|
JetSimpleNameExpression operationSign = expression.getOperationReference();
|
||||||
|
IElementType operationType = operationSign.getReferencedNameElementType();
|
||||||
|
JetType result;
|
||||||
|
if (operationType == JetTokens.EQ) {
|
||||||
|
result = visitAssignment(expression, contextWithExpectedType);
|
||||||
|
}
|
||||||
|
else if (OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(operationType)) {
|
||||||
|
result = visitAssignmentOperation(expression, contextWithExpectedType);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return facade.getType(expression, contextWithExpectedType);
|
||||||
|
}
|
||||||
|
return DataFlowUtils.checkType(result, expression, contextWithExpectedType);
|
||||||
|
}
|
||||||
|
|
||||||
protected JetType visitAssignmentOperation(JetBinaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
|
protected JetType visitAssignmentOperation(JetBinaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
|
||||||
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).replaceExpectedReturnType(TypeUtils.NO_EXPECTED_TYPE);
|
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).replaceExpectedReturnType(TypeUtils.NO_EXPECTED_TYPE);
|
||||||
// If there's += (or similar op) defined as such, we just call it.
|
// If there's += (or similar op) defined as such, we just call it.
|
||||||
@@ -134,7 +152,7 @@ public class ExpressionTypingVisitorForStatements extends BasicExpressionTypingV
|
|||||||
String name = OperatorConventions.ASSIGNMENT_OPERATIONS.get(operationType);
|
String name = OperatorConventions.ASSIGNMENT_OPERATIONS.get(operationType);
|
||||||
|
|
||||||
TemporaryBindingTrace temporaryBindingTrace = TemporaryBindingTrace.create(context.trace);
|
TemporaryBindingTrace temporaryBindingTrace = TemporaryBindingTrace.create(context.trace);
|
||||||
JetType assignmentOperationType = getTypeForBinaryCall(scope, name, context.replaceBindingTrace(temporaryBindingTrace), expression);
|
JetType assignmentOperationType = basic.getTypeForBinaryCall(scope, name, context.replaceBindingTrace(temporaryBindingTrace), expression);
|
||||||
|
|
||||||
JetExpression left = JetPsiUtil.deparenthesize(expression.getLeft());
|
JetExpression left = JetPsiUtil.deparenthesize(expression.getLeft());
|
||||||
// If there isn't, we call plus (or like) and then assign
|
// If there isn't, we call plus (or like) and then assign
|
||||||
@@ -145,7 +163,7 @@ public class ExpressionTypingVisitorForStatements extends BasicExpressionTypingV
|
|||||||
JetArrayAccessExpression arrayAccessExpression = (JetArrayAccessExpression) left;
|
JetArrayAccessExpression arrayAccessExpression = (JetArrayAccessExpression) left;
|
||||||
resolveArrayAccessToLValue(arrayAccessExpression, expression.getRight(), operationSign, context);
|
resolveArrayAccessToLValue(arrayAccessExpression, expression.getRight(), operationSign, context);
|
||||||
}
|
}
|
||||||
assignmentOperationType = getTypeForBinaryCall(scope, counterpartName, context, expression);
|
assignmentOperationType = basic.getTypeForBinaryCall(scope, counterpartName, context, expression);
|
||||||
if (assignmentOperationType != null) {
|
if (assignmentOperationType != null) {
|
||||||
context.trace.record(VARIABLE_REASSIGNMENT, expression);
|
context.trace.record(VARIABLE_REASSIGNMENT, expression);
|
||||||
ExpressionTypingUtils.checkWrappingInRef(expression.getLeft(), context);
|
ExpressionTypingUtils.checkWrappingInRef(expression.getLeft(), context);
|
||||||
@@ -155,7 +173,7 @@ public class ExpressionTypingVisitorForStatements extends BasicExpressionTypingV
|
|||||||
temporaryBindingTrace.commit();
|
temporaryBindingTrace.commit();
|
||||||
checkReassignment(expression, context, assignmentOperationType, left);
|
checkReassignment(expression, context, assignmentOperationType, left);
|
||||||
}
|
}
|
||||||
checkLValue(context.trace, expression.getLeft());
|
basic.checkLValue(context.trace, expression.getLeft());
|
||||||
return checkAssignmentType(assignmentOperationType, expression, contextWithExpectedType);
|
return checkAssignmentType(assignmentOperationType, expression, contextWithExpectedType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,7 +194,7 @@ public class ExpressionTypingVisitorForStatements extends BasicExpressionTypingV
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected JetType visitAssignment(JetBinaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
|
protected JetType visitAssignment(JetBinaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
|
||||||
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).replaceExpectedReturnType(TypeUtils.NO_EXPECTED_TYPE);
|
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).replaceExpectedReturnType(TypeUtils.NO_EXPECTED_TYPE);
|
||||||
JetExpression left = JetPsiUtil.deparenthesize(expression.getLeft());
|
JetExpression left = JetPsiUtil.deparenthesize(expression.getLeft());
|
||||||
@@ -184,7 +202,7 @@ public class ExpressionTypingVisitorForStatements extends BasicExpressionTypingV
|
|||||||
if (left instanceof JetArrayAccessExpression) {
|
if (left instanceof JetArrayAccessExpression) {
|
||||||
JetArrayAccessExpression arrayAccessExpression = (JetArrayAccessExpression) left;
|
JetArrayAccessExpression arrayAccessExpression = (JetArrayAccessExpression) left;
|
||||||
JetType assignmentType = resolveArrayAccessToLValue(arrayAccessExpression, right, expression.getOperationReference(), context);
|
JetType assignmentType = resolveArrayAccessToLValue(arrayAccessExpression, right, expression.getOperationReference(), context);
|
||||||
checkLValue(context.trace, arrayAccessExpression);
|
basic.checkLValue(context.trace, arrayAccessExpression);
|
||||||
return checkAssignmentType(assignmentType, expression, contextWithExpectedType);
|
return checkAssignmentType(assignmentType, expression, contextWithExpectedType);
|
||||||
}
|
}
|
||||||
JetType leftType = facade.getType(expression.getLeft(), context.replaceScope(scope));
|
JetType leftType = facade.getType(expression.getLeft(), context.replaceScope(scope));
|
||||||
@@ -192,7 +210,7 @@ public class ExpressionTypingVisitorForStatements extends BasicExpressionTypingV
|
|||||||
JetType rightType = facade.getType(right, context.replaceExpectedType(leftType).replaceScope(scope));
|
JetType rightType = facade.getType(right, context.replaceExpectedType(leftType).replaceScope(scope));
|
||||||
}
|
}
|
||||||
if (leftType != null) { //if leftType == null, some another error has been generated
|
if (leftType != null) { //if leftType == null, some another error has been generated
|
||||||
checkLValue(context.trace, expression.getLeft());
|
basic.checkLValue(context.trace, expression.getLeft());
|
||||||
}
|
}
|
||||||
if (left instanceof JetSimpleNameExpression) {
|
if (left instanceof JetSimpleNameExpression) {
|
||||||
JetSimpleNameExpression simpleName = (JetSimpleNameExpression) left;
|
JetSimpleNameExpression simpleName = (JetSimpleNameExpression) left;
|
||||||
@@ -237,6 +255,11 @@ public class ExpressionTypingVisitorForStatements extends BasicExpressionTypingV
|
|||||||
return setFunctionDescriptor.getReturnType();
|
return setFunctionDescriptor.getReturnType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JetType visitExpression(JetExpression expression, ExpressionTypingContext context) {
|
||||||
|
return facade.getType(expression, context);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JetType visitJetElement(JetElement element, ExpressionTypingContext context) {
|
public JetType visitJetElement(JetElement element, ExpressionTypingContext context) {
|
||||||
context.trace.report(UNSUPPORTED.on(element, "in a block"));
|
context.trace.report(UNSUPPORTED.on(element, "in a block"));
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
//KT-629 Assignments are parsed as expressions.
|
||||||
|
|
||||||
|
namespace kt629
|
||||||
|
|
||||||
|
class A() {
|
||||||
|
var p = "yeah"
|
||||||
|
fun mod(other : A) : A {
|
||||||
|
return A();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box() : Boolean {
|
||||||
|
var c = A()
|
||||||
|
val d = c;
|
||||||
|
c %= A();
|
||||||
|
return (c != d) && (<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>c.p = "yeah"<!>)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun box2() : Boolean {
|
||||||
|
var <!UNUSED_VARIABLE!>c<!> = A()
|
||||||
|
return (<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>c.p = "yeah"<!>) && true
|
||||||
|
}
|
||||||
@@ -113,7 +113,7 @@ public class JetTypeCheckerTest extends JetLiteFixture {
|
|||||||
assertType("if (true) 1 else '1'", "Any");
|
assertType("if (true) 1 else '1'", "Any");
|
||||||
|
|
||||||
assertType("if (true) else '1'", "Unit");
|
assertType("if (true) else '1'", "Unit");
|
||||||
assertType("if (true) else a = 0", "Unit");
|
assertType("if (true) else { var a = 0; a = 1 }", "Unit");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testWhen() throws Exception {
|
public void testWhen() throws Exception {
|
||||||
|
|||||||
Reference in New Issue
Block a user