For-related descriptors stored
This commit is contained in:
@@ -20,6 +20,8 @@ public interface BindingContext {
|
|||||||
WritableSlice<JetTypeReference, JetType> TYPE = ManyMapSlices.createSimpleSlice("TYPE");
|
WritableSlice<JetTypeReference, JetType> TYPE = ManyMapSlices.createSimpleSlice("TYPE");
|
||||||
WritableSlice<JetExpression, JetType> EXPRESSION_TYPE = new BasicWritableSlice<JetExpression, JetType>("EXPRESSION_TYPE", RewritePolicy.DO_NOTHING);
|
WritableSlice<JetExpression, JetType> EXPRESSION_TYPE = new BasicWritableSlice<JetExpression, JetType>("EXPRESSION_TYPE", RewritePolicy.DO_NOTHING);
|
||||||
WritableSlice<JetReferenceExpression, DeclarationDescriptor> REFERENCE_TARGET = new BasicWritableSlice<JetReferenceExpression, DeclarationDescriptor>("REFERENCE_TARGET", RewritePolicy.DO_NOTHING);
|
WritableSlice<JetReferenceExpression, DeclarationDescriptor> REFERENCE_TARGET = new BasicWritableSlice<JetReferenceExpression, DeclarationDescriptor>("REFERENCE_TARGET", RewritePolicy.DO_NOTHING);
|
||||||
|
WritableSlice<JetExpression, FunctionDescriptor> LOOP_RANGE_ITERATOR = ManyMapSlices.createSimpleSlice("LOOP_RANGE_ITERATOR");
|
||||||
|
WritableSlice<JetExpression, DeclarationDescriptor> LOOP_RANGE_HAS_NEXT = ManyMapSlices.createSimpleSlice("LOOP_RANGE_HAS_NEXT");
|
||||||
WritableSlice<JetExpression, JetType> AUTOCAST = ManyMapSlices.createSimpleSlice("AUTOCAST");
|
WritableSlice<JetExpression, JetType> AUTOCAST = ManyMapSlices.createSimpleSlice("AUTOCAST");
|
||||||
WritableSlice<JetExpression, JetScope> RESOLUTION_SCOPE = ManyMapSlices.createSimpleSlice("RESOLUTION_SCOPE");
|
WritableSlice<JetExpression, JetScope> RESOLUTION_SCOPE = ManyMapSlices.createSimpleSlice("RESOLUTION_SCOPE");
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ import org.jetbrains.jet.util.WritableSlice;
|
|||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
import static org.jetbrains.jet.lang.resolve.BindingContext.LOOP_RANGE_HAS_NEXT;
|
||||||
|
import static org.jetbrains.jet.lang.resolve.BindingContext.LOOP_RANGE_ITERATOR;
|
||||||
import static org.jetbrains.jet.lang.resolve.BindingContext.STATEMENT;
|
import static org.jetbrains.jet.lang.resolve.BindingContext.STATEMENT;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2028,7 +2030,7 @@ public class JetTypeInferrer {
|
|||||||
}
|
}
|
||||||
JetType expectedParameterType = null;
|
JetType expectedParameterType = null;
|
||||||
if (loopRangeType != null) {
|
if (loopRangeType != null) {
|
||||||
expectedParameterType = checkIterableConvention(loopRangeType, loopRange.getNode(), context);
|
expectedParameterType = checkIterableConvention(loopRangeType, loopRange, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
WritableScope loopScope = newWritableScopeImpl(context.scope, context.trace).setDebugName("Scope with for-loop index");
|
WritableScope loopScope = newWritableScopeImpl(context.scope, context.trace).setDebugName("Scope with for-loop index");
|
||||||
@@ -2063,12 +2065,19 @@ public class JetTypeInferrer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private JetType checkIterableConvention(@NotNull JetType type, @NotNull ASTNode reportErrorsOn, TypeInferenceContext context) {
|
private JetType checkIterableConvention(@NotNull JetType type, @NotNull JetExpression loopRange, TypeInferenceContext context) {
|
||||||
|
ASTNode reportErrorsOn = loopRange.getNode();
|
||||||
OverloadResolutionResult iteratorResolutionResult = context.services.resolveNoParametersFunction(type, context.scope, "iterator");
|
OverloadResolutionResult iteratorResolutionResult = context.services.resolveNoParametersFunction(type, context.scope, "iterator");
|
||||||
if (iteratorResolutionResult.isSuccess()) {
|
if (iteratorResolutionResult.isSuccess()) {
|
||||||
JetType iteratorType = iteratorResolutionResult.getFunctionDescriptor().getReturnType();
|
FunctionDescriptor iteratorFunction = iteratorResolutionResult.getFunctionDescriptor();
|
||||||
boolean hasNextFunctionSupported = checkHasNextFunctionSupport(reportErrorsOn, iteratorType, context);
|
|
||||||
boolean hasNextPropertySupported = checkHasNextPropertySupport(reportErrorsOn, iteratorType, context);
|
context.trace.record(LOOP_RANGE_ITERATOR, loopRange, iteratorFunction);
|
||||||
|
|
||||||
|
JetType iteratorType = iteratorFunction.getReturnType();
|
||||||
|
FunctionDescriptor hasNextFunction = checkHasNextFunctionSupport(loopRange, iteratorType, context);
|
||||||
|
boolean hasNextFunctionSupported = hasNextFunction != null;
|
||||||
|
VariableDescriptor hasNextProperty = checkHasNextPropertySupport(loopRange, iteratorType, context);
|
||||||
|
boolean hasNextPropertySupported = hasNextProperty != null;
|
||||||
if (hasNextFunctionSupported && hasNextPropertySupported && !ErrorUtils.isErrorType(iteratorType)) {
|
if (hasNextFunctionSupported && hasNextPropertySupported && !ErrorUtils.isErrorType(iteratorType)) {
|
||||||
// TODO : overload resolution rules impose priorities here???
|
// TODO : overload resolution rules impose priorities here???
|
||||||
context.trace.getErrorHandler().genericError(reportErrorsOn, "An ambiguity between 'iterator().hasNext()' function and 'iterator().hasNext()' property");
|
context.trace.getErrorHandler().genericError(reportErrorsOn, "An ambiguity between 'iterator().hasNext()' function and 'iterator().hasNext()' property");
|
||||||
@@ -2076,6 +2085,9 @@ public class JetTypeInferrer {
|
|||||||
else if (!hasNextFunctionSupported && !hasNextPropertySupported) {
|
else if (!hasNextFunctionSupported && !hasNextPropertySupported) {
|
||||||
context.trace.getErrorHandler().genericError(reportErrorsOn, "Loop range must have an 'iterator().hasNext()' function or an 'iterator().hasNext' property");
|
context.trace.getErrorHandler().genericError(reportErrorsOn, "Loop range must have an 'iterator().hasNext()' function or an 'iterator().hasNext' property");
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
context.trace.record(LOOP_RANGE_HAS_NEXT, loopRange, hasNextFunctionSupported ? hasNextFunction : hasNextProperty);
|
||||||
|
}
|
||||||
|
|
||||||
OverloadResolutionResult nextResolutionResult = context.services.resolveNoParametersFunction(iteratorType, context.scope, "next");
|
OverloadResolutionResult nextResolutionResult = context.services.resolveNoParametersFunction(iteratorType, context.scope, "next");
|
||||||
if (nextResolutionResult.isAmbiguity()) {
|
if (nextResolutionResult.isAmbiguity()) {
|
||||||
@@ -2096,122 +2108,42 @@ public class JetTypeInferrer {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkHasNextFunctionSupport(@NotNull ASTNode reportErrorsOn, @NotNull JetType iteratorType, TypeInferenceContext context) {
|
@Nullable
|
||||||
|
private FunctionDescriptor checkHasNextFunctionSupport(@NotNull JetExpression loopRange, @NotNull JetType iteratorType, TypeInferenceContext context) {
|
||||||
OverloadResolutionResult hasNextResolutionResult = context.services.resolveNoParametersFunction(iteratorType, context.scope, "hasNext");
|
OverloadResolutionResult hasNextResolutionResult = context.services.resolveNoParametersFunction(iteratorType, context.scope, "hasNext");
|
||||||
if (hasNextResolutionResult.isAmbiguity()) {
|
if (hasNextResolutionResult.isAmbiguity()) {
|
||||||
context.trace.getErrorHandler().genericError(reportErrorsOn, "Method 'iterator().hasNext()' is ambiguous for this expression");
|
context.trace.getErrorHandler().genericError(loopRange.getNode(), "Method 'iterator().hasNext()' is ambiguous for this expression");
|
||||||
} else if (hasNextResolutionResult.isNothing()) {
|
} else if (hasNextResolutionResult.isNothing()) {
|
||||||
return false;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
|
assert hasNextResolutionResult.isSuccess();
|
||||||
JetType hasNextReturnType = hasNextResolutionResult.getFunctionDescriptor().getReturnType();
|
JetType hasNextReturnType = hasNextResolutionResult.getFunctionDescriptor().getReturnType();
|
||||||
if (!isBoolean(hasNextReturnType)) {
|
if (!isBoolean(hasNextReturnType)) {
|
||||||
context.trace.getErrorHandler().genericError(reportErrorsOn, "The 'iterator().hasNext()' method of the loop range must return Boolean, but returns " + hasNextReturnType);
|
context.trace.getErrorHandler().genericError(loopRange.getNode(), "The 'iterator().hasNext()' method of the loop range must return Boolean, but returns " + hasNextReturnType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return hasNextResolutionResult.getFunctionDescriptor();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkHasNextPropertySupport(@NotNull ASTNode reportErrorsOn, @NotNull JetType iteratorType, TypeInferenceContext context) {
|
@Nullable
|
||||||
|
private VariableDescriptor checkHasNextPropertySupport(@NotNull JetExpression loopRange, @NotNull JetType iteratorType, TypeInferenceContext context) {
|
||||||
VariableDescriptor hasNextProperty = iteratorType.getMemberScope().getVariable("hasNext");
|
VariableDescriptor hasNextProperty = iteratorType.getMemberScope().getVariable("hasNext");
|
||||||
// TODO :extension properties
|
// TODO :extension properties
|
||||||
if (hasNextProperty == null) {
|
if (hasNextProperty == null) {
|
||||||
return false;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
JetType hasNextReturnType = hasNextProperty.getOutType();
|
JetType hasNextReturnType = hasNextProperty.getOutType();
|
||||||
if (hasNextReturnType == null) {
|
if (hasNextReturnType == null) {
|
||||||
// TODO : accessibility
|
// TODO : accessibility
|
||||||
context.trace.getErrorHandler().genericError(reportErrorsOn, "The 'iterator().hasNext' property of the loop range must be readable");
|
context.trace.getErrorHandler().genericError(loopRange.getNode(), "The 'iterator().hasNext' property of the loop range must be readable");
|
||||||
}
|
}
|
||||||
else if (!isBoolean(hasNextReturnType)) {
|
else if (!isBoolean(hasNextReturnType)) {
|
||||||
context.trace.getErrorHandler().genericError(reportErrorsOn, "The 'iterator().hasNext' property of the loop range must return Boolean, but returns " + hasNextReturnType);
|
context.trace.getErrorHandler().genericError(loopRange.getNode(), "The 'iterator().hasNext' property of the loop range must return Boolean, but returns " + hasNextReturnType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return hasNextProperty;
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Override
|
|
||||||
// public void visitNewExpression(JetNewExpression expression) {
|
|
||||||
// // TODO : type argument inference
|
|
||||||
// JetTypeReference typeReference = expression.getTypeReference();
|
|
||||||
// if (typeReference != null) {
|
|
||||||
// result = checkTypeInitializerCall(scope, typeReference, expression);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// private void resolveCallWithExplicitName(@NotNull JetScope scope, JetExpression receiver, String functionName, List<JetType> resolvedTypeArguments, List<ValueArgumentPsi> valueArguments) {
|
|
||||||
//
|
|
||||||
// boolean someNamed = false;
|
|
||||||
// boolean allNamed = true;
|
|
||||||
// for (ValueArgumentPsi valueArgument : valueArguments) {
|
|
||||||
// if (valueArgument.isNamed()) {
|
|
||||||
// context.trace.getErrorHandler().genericError(valueArgument.asElement().getNode(), "Named arguments are not supported");
|
|
||||||
// someNamed = true;
|
|
||||||
// }
|
|
||||||
// else {
|
|
||||||
// allNamed = false;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if (someNamed) {
|
|
||||||
// return; // TODO
|
|
||||||
// }
|
|
||||||
// if (someNamed && !allNamed) {
|
|
||||||
// // TODO function literals outside parentheses
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// ErrorHandlerWithRegions errorHandler = context.trace.getErrorHandler();
|
|
||||||
//
|
|
||||||
// // 1. resolve 'receiver' in 'scope' with expected type 'NO_EXPECTED_TYPE'
|
|
||||||
// errorHandler.openRegion();
|
|
||||||
// JetType receiverType = JetTypeInferrer.this.getType(scope, receiver, false, NO_EXPECTED_TYPE);
|
|
||||||
// // for each applicable function in 'receiverType'
|
|
||||||
// Set<FunctionDescriptor> allFunctions = receiverType.getMemberScope().getFunctionGroup(functionName).getFunctionDescriptors();
|
|
||||||
// Map<FunctionDescriptor, List<JetType>> applicableFunctions = Maps.newHashMap();
|
|
||||||
// int typeArgCount = resolvedTypeArguments.size();
|
|
||||||
// int valueArgCount = valueArguments.size();
|
|
||||||
// for (FunctionDescriptor functionDescriptor : allFunctions) {
|
|
||||||
// if (typeArgCount == 0 || functionDescriptor.getTypeParameters().size() == typeArgCount) {
|
|
||||||
// if (FunctionDescriptorUtil.getMinimumArity(functionDescriptor) <= valueArgCount &&
|
|
||||||
// valueArgCount <= FunctionDescriptorUtil.getMaximumArity(functionDescriptor)) {
|
|
||||||
// // get expected types for value parameters
|
|
||||||
// if (typeArgCount > 0) {
|
|
||||||
// FunctionDescriptor substitutedFunctionDescriptor = FunctionDescriptorUtil.substituteFunctionDescriptor(resolvedTypeArguments, functionDescriptor);
|
|
||||||
// }
|
|
||||||
// else {
|
|
||||||
// FunctionDescriptor substitutedFunctionDescriptor = FunctionDescriptorUtil.substituteFunctionDescriptor(TypeUtils.getDefaultTypes(functionDescriptor.getTypeParameters()), functionDescriptor);
|
|
||||||
// List<JetType> valueArgumentTypes = getArgumentTypes(substitutedFunctionDescriptor, valueArguments);
|
|
||||||
// if (valueArgumentTypes == null) {
|
|
||||||
// Map<TypeConstructor, TypeProjection> noExpectedTypes = Maps.newHashMap();
|
|
||||||
// for (TypeParameterDescriptor typeParameterDescriptor : functionDescriptor.getTypeParameters()) {
|
|
||||||
// noExpectedTypes.put(typeParameterDescriptor.getTypeConstructor(), new TypeProjection(NO_EXPECTED_TYPE));
|
|
||||||
// }
|
|
||||||
// substitutedFunctionDescriptor = functionDescriptor.substitute(TypeSubstitutor.create(noExpectedTypes));
|
|
||||||
// valueArgumentTypes = getArgumentTypes(substitutedFunctionDescriptor, valueArguments);
|
|
||||||
// }
|
|
||||||
// if (valueArgumentTypes != null) {
|
|
||||||
// List<JetType> typeArguments = solveConstraintSystem(functionDescriptor, valueArgumentTypes, expectedReturnType);
|
|
||||||
// if (typeArguments != null) {
|
|
||||||
// applicableFunctions.put(functionDescriptor, typeArguments);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// // type-check the parameters
|
|
||||||
// // if something was found (one or many options
|
|
||||||
// errorHandler.closeAndCommitCurrentRegion();
|
|
||||||
// // otherwise
|
|
||||||
// errorHandler.closeAndReturnCurrentRegion();
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// // get expected types for value parameters
|
|
||||||
// // type-check the parameters
|
|
||||||
// // if something was found (one or many options
|
|
||||||
// errorHandler.closeAndCommitCurrentRegion();
|
|
||||||
// // otherwise
|
|
||||||
// errorHandler.closeAndReturnCurrentRegion();
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JetType visitHashQualifiedExpression(JetHashQualifiedExpression expression, TypeInferenceContext context) {
|
public JetType visitHashQualifiedExpression(JetHashQualifiedExpression expression, TypeInferenceContext context) {
|
||||||
context.trace.getErrorHandler().genericError(expression.getOperationTokenNode(), "Unsupported");
|
context.trace.getErrorHandler().genericError(expression.getOperationTokenNode(), "Unsupported");
|
||||||
|
|||||||
Reference in New Issue
Block a user