KT-1550 Cannot use parenthesized array access expression.
This commit is contained in:
+37
-19
@@ -57,8 +57,8 @@ import static org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils.*;
|
|||||||
import static org.jetbrains.jet.lang.types.expressions.OperatorConventions.*;
|
import static org.jetbrains.jet.lang.types.expressions.OperatorConventions.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author abreslav
|
* @author abreslav
|
||||||
*/
|
*/
|
||||||
public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||||
protected BasicExpressionTypingVisitor(@NotNull ExpressionTypingInternals facade) {
|
protected BasicExpressionTypingVisitor(@NotNull ExpressionTypingInternals facade) {
|
||||||
super(facade);
|
super(facade);
|
||||||
@@ -255,7 +255,8 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
else {
|
else {
|
||||||
if (typeChecker.isSubtypeOf(actualType, targetType)) {
|
if (typeChecker.isSubtypeOf(actualType, targetType)) {
|
||||||
context.trace.report(USELESS_CAST.on(expression.getOperationSign()));
|
context.trace.report(USELESS_CAST.on(expression.getOperationSign()));
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
if (isCastErased(actualType, targetType, typeChecker)) {
|
if (isCastErased(actualType, targetType, typeChecker)) {
|
||||||
context.trace.report(Errors.UNCHECKED_CAST.on(expression, actualType, targetType));
|
context.trace.report(Errors.UNCHECKED_CAST.on(expression, actualType, targetType));
|
||||||
}
|
}
|
||||||
@@ -459,7 +460,9 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// supertypes may be empty when all the supertypes are error types (are not resolved, for example)
|
// supertypes may be empty when all the supertypes are error types (are not resolved, for example)
|
||||||
JetType type = supertypes.isEmpty() ? JetStandardClasses.getAnyType() : supertypes.iterator().next();
|
JetType type = supertypes.isEmpty()
|
||||||
|
? JetStandardClasses.getAnyType()
|
||||||
|
: supertypes.iterator().next();
|
||||||
result = substitutor.substitute(type, Variance.INVARIANT);
|
result = substitutor.substitute(type, Variance.INVARIANT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -607,7 +610,9 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
temporaryTrace.commit();
|
temporaryTrace.commit();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
ExpressionTypingContext newContext = receiver.exists() ? context.replaceScope(receiver.getType().getMemberScope()) : context;
|
ExpressionTypingContext newContext = receiver.exists()
|
||||||
|
? context.replaceScope(receiver.getType().getMemberScope())
|
||||||
|
: context;
|
||||||
JetType jetType = lookupNamespaceOrClassObject(nameExpression, nameExpression.getReferencedName(), newContext);
|
JetType jetType = lookupNamespaceOrClassObject(nameExpression, nameExpression.getReferencedName(), newContext);
|
||||||
if (jetType == null) {
|
if (jetType == null) {
|
||||||
context.trace.report(UNRESOLVED_REFERENCE.on(nameExpression));
|
context.trace.report(UNRESOLVED_REFERENCE.on(nameExpression));
|
||||||
@@ -628,7 +633,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void checkSuper(@NotNull ReceiverDescriptor receiverDescriptor, @Nullable DeclarationDescriptor member, @NotNull BindingTrace trace, @NotNull JetExpression expression) {
|
private static void checkSuper(@NotNull ReceiverDescriptor receiverDescriptor, @Nullable DeclarationDescriptor member, @NotNull BindingTrace trace, @NotNull JetExpression expression) {
|
||||||
if (!(receiverDescriptor instanceof ExpressionReceiver)) return;
|
if (!(receiverDescriptor instanceof ExpressionReceiver)) return;
|
||||||
JetExpression receiver = ((ExpressionReceiver) receiverDescriptor).getExpression();
|
JetExpression receiver = ((ExpressionReceiver) receiverDescriptor).getExpression();
|
||||||
@@ -732,7 +737,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
private void checkLValue(BindingTrace trace, JetExpression expressionWithParenthesis, boolean canBeThis) {
|
private void checkLValue(BindingTrace trace, JetExpression expressionWithParenthesis, boolean canBeThis) {
|
||||||
JetExpression expression = JetPsiUtil.deparenthesize(expressionWithParenthesis);
|
JetExpression expression = JetPsiUtil.deparenthesize(expressionWithParenthesis);
|
||||||
if (expression instanceof JetArrayAccessExpression) {
|
if (expression instanceof JetArrayAccessExpression) {
|
||||||
checkLValue(trace, ((JetArrayAccessExpression) expressionWithParenthesis).getArrayExpression(), true);
|
checkLValue(trace, ((JetArrayAccessExpression) expression).getArrayExpression(), true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (canBeThis && expression instanceof JetThisExpression) return;
|
if (canBeThis && expression instanceof JetThisExpression) return;
|
||||||
@@ -765,8 +770,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);
|
||||||
}
|
}
|
||||||
@@ -781,7 +786,8 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
TypeConstructor intTypeConstructor = standardLibrary.getInt().getTypeConstructor();
|
TypeConstructor intTypeConstructor = standardLibrary.getInt().getTypeConstructor();
|
||||||
if (constructor.equals(intTypeConstructor)) {
|
if (constructor.equals(intTypeConstructor)) {
|
||||||
result = standardLibrary.getBooleanType();
|
result = standardLibrary.getBooleanType();
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
context.trace.report(COMPARE_TO_TYPE_MISMATCH.on(operationSign, compareToReturnType));
|
context.trace.report(COMPARE_TO_TYPE_MISMATCH.on(operationSign, compareToReturnType));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -831,8 +837,12 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
JetType leftType = facade.getType(left, context.replaceScope(context.scope));
|
JetType leftType = facade.getType(left, context.replaceScope(context.scope));
|
||||||
WritableScopeImpl leftScope = newWritableScopeImpl(context).setDebugName("Left scope of && or ||");
|
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
|
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 ||");
|
WritableScopeImpl rightScope = operationType == JetTokens.ANDAND
|
||||||
JetType rightType = right == null ? null : facade.getType(right, context.replaceDataFlowInfo(flowInfoLeft).replaceScope(rightScope));
|
? 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(leftType)) {
|
if (leftType != null && !isBoolean(leftType)) {
|
||||||
context.trace.report(TYPE_MISMATCH.on(left, booleanType, leftType));
|
context.trace.report(TYPE_MISMATCH.on(left, booleanType, leftType));
|
||||||
}
|
}
|
||||||
@@ -843,7 +853,9 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
}
|
}
|
||||||
else if (operationType == JetTokens.ELVIS) {
|
else if (operationType == JetTokens.ELVIS) {
|
||||||
JetType leftType = facade.getType(left, context.replaceScope(context.scope));
|
JetType leftType = facade.getType(left, context.replaceScope(context.scope));
|
||||||
JetType rightType = right == null ? null : facade.getType(right, contextWithExpectedType.replaceScope(context.scope));
|
JetType rightType = right == null
|
||||||
|
? null
|
||||||
|
: facade.getType(right, contextWithExpectedType.replaceScope(context.scope));
|
||||||
if (leftType != null) {
|
if (leftType != null) {
|
||||||
if (!leftType.isNullable()) {
|
if (!leftType.isNullable()) {
|
||||||
context.trace.report(USELESS_ELVIS.on(left, leftType));
|
context.trace.report(USELESS_ELVIS.on(left, leftType));
|
||||||
@@ -920,7 +932,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
/*package*/ OverloadResolutionResults<FunctionDescriptor> getResolutionResultsForBinaryCall(JetScope scope, String name, ExpressionTypingContext context, JetBinaryExpression binaryExpression, ExpressionReceiver receiver) {
|
/*package*/ OverloadResolutionResults<FunctionDescriptor> getResolutionResultsForBinaryCall(JetScope scope, String name, ExpressionTypingContext context, JetBinaryExpression binaryExpression, ExpressionReceiver receiver) {
|
||||||
// ExpressionReceiver receiver = safeGetExpressionReceiver(facade, binaryExpression.getLeft(), context.replaceScope(scope));
|
// ExpressionReceiver receiver = safeGetExpressionReceiver(facade, binaryExpression.getLeft(), context.replaceScope(scope));
|
||||||
return context.replaceScope(scope).resolveCallWithGivenNameToDescriptor(
|
return context.replaceScope(scope).resolveCallWithGivenNameToDescriptor(
|
||||||
CallMaker.makeCall(receiver, binaryExpression),
|
CallMaker.makeCall(receiver, binaryExpression),
|
||||||
@@ -1004,12 +1016,12 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
/*package*/ JetType resolveArrayAccessSetMethod(@NotNull JetArrayAccessExpression arrayAccessExpression, @NotNull JetExpression rightHandSide, @NotNull ExpressionTypingContext context, @NotNull BindingTrace traceForResolveResult) {
|
/*package*/ JetType resolveArrayAccessSetMethod(@NotNull JetArrayAccessExpression arrayAccessExpression, @NotNull JetExpression rightHandSide, @NotNull ExpressionTypingContext context, @NotNull BindingTrace traceForResolveResult) {
|
||||||
return resolveArrayAccessSpecialMethod(arrayAccessExpression, rightHandSide, context, traceForResolveResult, false);
|
return resolveArrayAccessSpecialMethod(arrayAccessExpression, rightHandSide, context, traceForResolveResult, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
/*package*/ JetType resolveArrayAccessGetMethod(@NotNull JetArrayAccessExpression arrayAccessExpression, @NotNull ExpressionTypingContext context) {
|
/*package*/ JetType resolveArrayAccessGetMethod(@NotNull JetArrayAccessExpression arrayAccessExpression, @NotNull ExpressionTypingContext context) {
|
||||||
return resolveArrayAccessSpecialMethod(arrayAccessExpression, null, context, context.trace, true);
|
return resolveArrayAccessSpecialMethod(arrayAccessExpression, null, context, context.trace, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1025,14 +1037,20 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
ExpressionReceiver receiver = new ExpressionReceiver(arrayAccessExpression.getArrayExpression(), arrayType);
|
ExpressionReceiver receiver = new ExpressionReceiver(arrayAccessExpression.getArrayExpression(), arrayType);
|
||||||
if (!isGet) assert rightHandSide != null;
|
if (!isGet) assert rightHandSide != null;
|
||||||
OverloadResolutionResults<FunctionDescriptor> functionResults = context.resolveCallWithGivenName(
|
OverloadResolutionResults<FunctionDescriptor> functionResults = context.resolveCallWithGivenName(
|
||||||
isGet ? CallMaker.makeArrayGetCall(receiver, arrayAccessExpression) : CallMaker.makeArraySetCall(receiver, arrayAccessExpression, rightHandSide),
|
isGet
|
||||||
|
? CallMaker.makeArrayGetCall(receiver, arrayAccessExpression)
|
||||||
|
: CallMaker.makeArraySetCall(receiver, arrayAccessExpression, rightHandSide),
|
||||||
arrayAccessExpression,
|
arrayAccessExpression,
|
||||||
isGet ? "get" : "set");
|
isGet ? "get" : "set");
|
||||||
if (!functionResults.isSuccess()) {
|
if (!functionResults.isSuccess()) {
|
||||||
traceForResolveResult.report(isGet ? NO_GET_METHOD.on(arrayAccessExpression) : NO_SET_METHOD.on(arrayAccessExpression));
|
traceForResolveResult.report(isGet
|
||||||
|
? NO_GET_METHOD.on(arrayAccessExpression)
|
||||||
|
: NO_SET_METHOD.on(arrayAccessExpression));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
traceForResolveResult.record(isGet ? INDEXED_LVALUE_GET : INDEXED_LVALUE_SET, arrayAccessExpression, functionResults.getResultingCall());
|
traceForResolveResult.record(isGet
|
||||||
|
? INDEXED_LVALUE_GET
|
||||||
|
: INDEXED_LVALUE_SET, arrayAccessExpression, functionResults.getResultingCall());
|
||||||
return functionResults.getResultingDescriptor().getReturnType();
|
return functionResults.getResultingDescriptor().getReturnType();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package foo
|
||||||
|
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
fun main(args : Array<String>)
|
||||||
|
{
|
||||||
|
val c = ArrayList<Int>()
|
||||||
|
c.add(3)
|
||||||
|
System.out?.println(++(c[0]))
|
||||||
|
System.out?.println((c[1])--)
|
||||||
|
System.out?.println(-(c[2]))
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user