Merge remote branch 'origin/master'
This commit is contained in:
@@ -49,8 +49,10 @@ public interface JetControlFlowBuilder {
|
||||
|
||||
void exitSubroutine(@NotNull JetDeclaration subroutine);
|
||||
|
||||
@Nullable
|
||||
@NotNull
|
||||
JetElement getCurrentSubroutine();
|
||||
@Nullable
|
||||
JetElement getReturnSubroutine();
|
||||
void returnValue(@NotNull JetExpression returnExpression, @NotNull JetElement subroutine);
|
||||
|
||||
void returnNoValue(@NotNull JetElement returnExpression, @NotNull JetElement subroutine);
|
||||
|
||||
@@ -140,13 +140,20 @@ public class JetControlFlowBuilderAdapter implements JetControlFlowBuilder {
|
||||
builder.exitSubroutine(subroutine);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
@Nullable
|
||||
public JetElement getCurrentSubroutine() {
|
||||
assert builder != null;
|
||||
return builder.getCurrentSubroutine();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public JetElement getReturnSubroutine() {
|
||||
assert builder != null;
|
||||
return builder.getReturnSubroutine();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void returnValue(@NotNull JetExpression returnExpression, @NotNull JetElement subroutine) {
|
||||
assert builder != null;
|
||||
|
||||
@@ -528,8 +528,8 @@ public class JetControlFlowProcessor {
|
||||
}
|
||||
JetSimpleNameExpression labelElement = expression.getTargetLabel();
|
||||
JetElement subroutine;
|
||||
String labelName = expression.getLabelName();
|
||||
if (labelElement != null) {
|
||||
String labelName = expression.getLabelName();
|
||||
assert labelName != null;
|
||||
PsiElement labeledElement = BindingContextUtils.resolveToDeclarationPsiElement(trace.getBindingContext(), labelElement);
|
||||
if (labeledElement != null) {
|
||||
@@ -541,13 +541,18 @@ public class JetControlFlowProcessor {
|
||||
}
|
||||
}
|
||||
else {
|
||||
subroutine = builder.getCurrentSubroutine();
|
||||
subroutine = builder.getReturnSubroutine();
|
||||
// TODO : a context check
|
||||
}
|
||||
//todo cache JetFunctionLiteral instead
|
||||
if (subroutine instanceof JetFunctionLiteralExpression) {
|
||||
subroutine = ((JetFunctionLiteralExpression) subroutine).getFunctionLiteral();
|
||||
}
|
||||
boolean error = false;
|
||||
if (builder.getCurrentSubroutine() != subroutine) {
|
||||
trace.report(RETURN_NOT_ALLOWED.on(expression));
|
||||
error = true;
|
||||
}
|
||||
if (subroutine instanceof JetFunction || subroutine instanceof JetPropertyAccessor || subroutine instanceof JetConstructor) {
|
||||
if (returnedExpression == null) {
|
||||
builder.returnNoValue(expression, subroutine);
|
||||
@@ -556,9 +561,9 @@ public class JetControlFlowProcessor {
|
||||
builder.returnValue(expression, subroutine);
|
||||
}
|
||||
}
|
||||
else {
|
||||
else if (!error) {
|
||||
if (labelElement != null) {
|
||||
trace.report(NOT_A_RETURN_LABEL.on(expression, expression.getLabelName()));
|
||||
trace.report(NOT_A_RETURN_LABEL.on(expression, labelName));
|
||||
}
|
||||
else {
|
||||
trace.report(RETURN_NOT_ALLOWED.on(expression));
|
||||
|
||||
@@ -75,17 +75,22 @@ public class JetFlowInformationProvider {
|
||||
Pseudocode pseudocode = pseudocodeMap.get(subroutine);
|
||||
assert pseudocode != null;
|
||||
|
||||
final Set<Instruction> instructions = Sets.newHashSet(pseudocode.getInstructions());
|
||||
SubroutineExitInstruction exitInstruction = pseudocode.getExitInstruction();
|
||||
for (Instruction previousInstruction : exitInstruction.getPreviousInstructions()) {
|
||||
previousInstruction.accept(new InstructionVisitor() {
|
||||
@Override
|
||||
public void visitReturnValue(ReturnValueInstruction instruction) {
|
||||
returnedExpressions.add((JetExpression) instruction.getElement());
|
||||
if (instructions.contains(instruction)) { //exclude non-local return expressions
|
||||
returnedExpressions.add((JetExpression) instruction.getElement());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitReturnNoValue(ReturnNoValueInstruction instruction) {
|
||||
returnedExpressions.add((JetExpression) instruction.getElement());
|
||||
if (instructions.contains(instruction)) {
|
||||
returnedExpressions.add((JetExpression) instruction.getElement());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
+16
-5
@@ -45,7 +45,12 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
|
||||
|
||||
@Override
|
||||
public void enterSubroutine(@NotNull JetDeclaration subroutine) {
|
||||
pushBuilder(subroutine, subroutine);
|
||||
if (builder != null && subroutine instanceof JetFunctionLiteral) {
|
||||
pushBuilder(subroutine, builder.getReturnSubroutine());
|
||||
}
|
||||
else {
|
||||
pushBuilder(subroutine, subroutine);
|
||||
}
|
||||
assert builder != null;
|
||||
builder.enterSubroutine(subroutine);
|
||||
}
|
||||
@@ -66,13 +71,13 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
|
||||
private final Pseudocode pseudocode;
|
||||
private final Label error;
|
||||
private final Label sink;
|
||||
private final JetElement currentSubroutine;
|
||||
private final JetElement returnSubroutine;
|
||||
|
||||
private JetControlFlowInstructionsGeneratorWorker(@NotNull JetElement scopingElement, @NotNull JetElement currentSubroutine) {
|
||||
private JetControlFlowInstructionsGeneratorWorker(@NotNull JetElement scopingElement, @NotNull JetElement returnSubroutine) {
|
||||
this.pseudocode = new Pseudocode(scopingElement);
|
||||
this.error = pseudocode.createLabel("error");
|
||||
this.sink = pseudocode.createLabel("sink");
|
||||
this.currentSubroutine = currentSubroutine;
|
||||
this.returnSubroutine = returnSubroutine;
|
||||
}
|
||||
|
||||
public Pseudocode getPseudocode() {
|
||||
@@ -134,9 +139,15 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
|
||||
add(new SubroutineEnterInstruction(subroutine));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JetElement getCurrentSubroutine() {
|
||||
return currentSubroutine;// subroutineInfo.empty() ? null : subroutineInfo.peek().getElement();
|
||||
return pseudocode.getCorrespondingElement();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetElement getReturnSubroutine() {
|
||||
return returnSubroutine;// subroutineInfo.empty() ? null : subroutineInfo.peek().getElement();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -89,7 +89,7 @@ public class FunctionDescriptorUtil {
|
||||
ReceiverDescriptor.NO_RECEIVER,
|
||||
Collections.<TypeParameterDescriptor>emptyList(),
|
||||
JetStandardClasses.getValueParameters(functionDescriptor, functionType),
|
||||
JetStandardClasses.getReturnType(functionType),
|
||||
JetStandardClasses.obtainReturnTypeFromFunctionType(functionType),
|
||||
Modality.FINAL, Visibility.LOCAL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.jetbrains.jet.lang.psi;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
@@ -62,4 +63,14 @@ public class JetPsiUtil {
|
||||
}
|
||||
return rootElements;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static JetNamedFunction getSurroundingFunction(@Nullable PsiElement element) {
|
||||
while (element != null) {
|
||||
if (element instanceof JetNamedFunction) return (JetNamedFunction) element;
|
||||
if (element instanceof JetClassOrObject || element instanceof JetNamespace) return null;
|
||||
element = element.getParent();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,8 +4,12 @@ import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.DECLARATION_TO_DESCRIPTOR;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
@@ -40,4 +44,12 @@ public class BindingContextUtils {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static JetType getFunctionReturnType(@NotNull BindingContext bindingContext, @NotNull JetFunction function) {
|
||||
DeclarationDescriptor descriptor = bindingContext.get(DECLARATION_TO_DESCRIPTOR, function);
|
||||
assert descriptor instanceof FunctionDescriptor;
|
||||
FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor;
|
||||
return functionDescriptor.getReturnType();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -385,7 +385,7 @@ public class JetStandardClasses {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JetType getReturnType(@NotNull JetType type) {
|
||||
public static JetType obtainReturnTypeFromFunctionType(@NotNull JetType type) {
|
||||
assert isFunctionType(type);
|
||||
List<TypeProjection> arguments = type.getArguments();
|
||||
return arguments.get(arguments.size() - 1).getType();
|
||||
|
||||
+8
-4
@@ -61,6 +61,7 @@ public class ClosureExpressionsTypingVisitor extends ExpressionTypingVisitor {
|
||||
@Override
|
||||
public JetType visitFunctionLiteralExpression(JetFunctionLiteralExpression expression, ExpressionTypingContext context) {
|
||||
JetFunctionLiteral functionLiteral = expression.getFunctionLiteral();
|
||||
if (functionLiteral.getBodyExpression() == null) return null;
|
||||
|
||||
JetTypeReference receiverTypeRef = functionLiteral.getReceiverTypeRef();
|
||||
final JetType receiverType;
|
||||
@@ -137,19 +138,22 @@ public class ClosureExpressionsTypingVisitor extends ExpressionTypingVisitor {
|
||||
JetTypeReference returnTypeRef = functionLiteral.getReturnTypeRef();
|
||||
if (returnTypeRef != null) {
|
||||
returnType = context.getTypeResolver().resolveType(context.scope, returnTypeRef);
|
||||
context.getServices().checkFunctionReturnType(expression, context.replaceScope(functionInnerScope).replaceExpectedReturnType(returnType).replaceDataFlowInfo(context.dataFlowInfo));
|
||||
context.getServices().checkFunctionReturnType(expression, context.replaceScope(functionInnerScope).
|
||||
replaceExpectedType(returnType).replaceExpectedReturnType(returnType).replaceDataFlowInfo(context.dataFlowInfo));
|
||||
}
|
||||
else {
|
||||
if (functionTypeExpected) {
|
||||
returnType = JetStandardClasses.getReturnType(expectedType);
|
||||
returnType = JetStandardClasses.obtainReturnTypeFromFunctionType(expectedType);
|
||||
}
|
||||
returnType = context.getServices().getBlockReturnedType(functionInnerScope, functionLiteral.getBodyExpression(), CoercionStrategy.COERCION_TO_UNIT, context.replaceExpectedType(returnType).replaceExpectedReturnType(returnType));
|
||||
// }
|
||||
returnType = context.getServices().getBlockReturnedType(functionInnerScope, functionLiteral.getBodyExpression(), CoercionStrategy.COERCION_TO_UNIT,
|
||||
context.replaceExpectedType(returnType).replaceExpectedReturnType(returnType));
|
||||
}
|
||||
JetType safeReturnType = returnType == null ? ErrorUtils.createErrorType("<return type>") : returnType;
|
||||
functionDescriptor.setReturnType(safeReturnType);
|
||||
|
||||
if (functionTypeExpected) {
|
||||
JetType expectedReturnType = JetStandardClasses.getReturnType(expectedType);
|
||||
JetType expectedReturnType = JetStandardClasses.obtainReturnTypeFromFunctionType(expectedType);
|
||||
if (JetStandardClasses.isUnit(expectedReturnType)) {
|
||||
functionDescriptor.setReturnType(expectedReturnType);
|
||||
return DataFlowUtils.checkType(JetStandardClasses.getFunctionType(Collections.<AnnotationDescriptor>emptyList(), effectiveReceiverType, parameterTypes, expectedReturnType), expression, context);
|
||||
|
||||
+22
-18
@@ -1,12 +1,14 @@
|
||||
package org.jetbrains.jet.lang.types.expressions;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
||||
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
|
||||
import org.jetbrains.jet.lang.resolve.calls.OverloadResolutionResults;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
@@ -40,7 +42,6 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
JetType conditionType = facade.getType(condition, context.replaceScope(scope));
|
||||
|
||||
if (conditionType != null && !isBoolean(context.semanticServices, conditionType)) {
|
||||
// context.trace.getErrorHandler().genericError(condition.getNode(), "Condition must be of type Boolean, but was of type " + conditionType);
|
||||
context.trace.report(TYPE_MISMATCH_IN_CONDITION.on(condition, conditionType));
|
||||
}
|
||||
}
|
||||
@@ -201,7 +202,6 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
if (expectedParameterType != null &&
|
||||
actualParameterType != null &&
|
||||
!context.semanticServices.getTypeChecker().isSubtypeOf(expectedParameterType, actualParameterType)) {
|
||||
// context.trace.getErrorHandler().genericError(typeReference.getNode(), "The loop iterates over values of type " + expectedParameterType + " but the parameter is declared to be " + actualParameterType);
|
||||
context.trace.report(TYPE_MISMATCH_IN_FOR_LOOP.on(typeReference, expectedParameterType, actualParameterType));
|
||||
}
|
||||
}
|
||||
@@ -238,11 +238,9 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
boolean hasNextPropertySupported = hasNextProperty != null;
|
||||
if (hasNextFunctionSupported && hasNextPropertySupported && !ErrorUtils.isErrorType(iteratorType)) {
|
||||
// TODO : overload resolution rules impose priorities here???
|
||||
// context.trace.getErrorHandler().genericError(reportErrorsOn, "An ambiguity between 'iterator().hasNext()' function and 'iterator().hasNext' property");
|
||||
context.trace.report(HAS_NEXT_PROPERTY_AND_FUNCTION_AMBIGUITY.on(loopRangeExpression));
|
||||
}
|
||||
else if (!hasNextFunctionSupported && !hasNextPropertySupported) {
|
||||
// context.trace.getErrorHandler().genericError(reportErrorsOn, "Loop range must have an 'iterator().hasNext()' function or an 'iterator().hasNext' property");
|
||||
context.trace.report(HAS_NEXT_MISSING.on(loopRangeExpression));
|
||||
}
|
||||
else {
|
||||
@@ -251,10 +249,8 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
|
||||
OverloadResolutionResults<FunctionDescriptor> nextResolutionResults = context.resolveExactSignature(new TransientReceiver(iteratorType), "next", Collections.<JetType>emptyList());
|
||||
if (nextResolutionResults.isAmbiguity()) {
|
||||
// context.trace.getErrorHandler().genericError(reportErrorsOn, "Method 'iterator().next()' is ambiguous for this expression");
|
||||
context.trace.report(NEXT_AMBIGUITY.on(loopRangeExpression));
|
||||
} else if (nextResolutionResults.isNothing()) {
|
||||
// context.trace.getErrorHandler().genericError(reportErrorsOn, "Loop range must have an 'iterator().next()' method");
|
||||
context.trace.report(NEXT_MISSING.on(loopRangeExpression));
|
||||
} else {
|
||||
FunctionDescriptor nextFunction = nextResolutionResults.getResult().getResultingDescriptor();
|
||||
@@ -272,7 +268,6 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
context.trace.report(ITERATOR_AMBIGUITY.on(loopRangeExpression, iteratorResolutionResults.getResults()));
|
||||
}
|
||||
else {
|
||||
// context.trace.getErrorHandler().genericError(reportErrorsOn, errorMessage);
|
||||
context.trace.report(ITERATOR_MISSING.on(loopRangeExpression));
|
||||
}
|
||||
}
|
||||
@@ -283,7 +278,6 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
private FunctionDescriptor checkHasNextFunctionSupport(@NotNull JetExpression loopRange, @NotNull JetType iteratorType, ExpressionTypingContext context) {
|
||||
OverloadResolutionResults<FunctionDescriptor> hasNextResolutionResults = context.resolveExactSignature(new TransientReceiver(iteratorType), "hasNext", Collections.<JetType>emptyList());
|
||||
if (hasNextResolutionResults.isAmbiguity()) {
|
||||
// context.trace.getErrorHandler().genericError(loopRange.getNode(), "Method 'iterator().hasNext()' is ambiguous for this expression");
|
||||
context.trace.report(HAS_NEXT_FUNCTION_AMBIGUITY.on(loopRange));
|
||||
} else if (hasNextResolutionResults.isNothing()) {
|
||||
return null;
|
||||
@@ -291,7 +285,6 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
assert hasNextResolutionResults.isSuccess();
|
||||
JetType hasNextReturnType = hasNextResolutionResults.getResult().getResultingDescriptor().getReturnType();
|
||||
if (!isBoolean(context.semanticServices, hasNextReturnType)) {
|
||||
// context.trace.getErrorHandler().genericError(loopRange.getNode(), "The 'iterator().hasNext()' method of the loop range must return Boolean, but returns " + hasNextReturnType);
|
||||
context.trace.report(HAS_NEXT_FUNCTION_TYPE_MISMATCH.on(loopRange, hasNextReturnType));
|
||||
}
|
||||
}
|
||||
@@ -308,11 +301,9 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
JetType hasNextReturnType = hasNextProperty.getOutType();
|
||||
if (hasNextReturnType == null) {
|
||||
// TODO : accessibility
|
||||
// context.trace.getErrorHandler().genericError(loopRange.getNode(), "The 'iterator().hasNext' property of the loop range must be readable");
|
||||
context.trace.report(HAS_NEXT_MUST_BE_READABLE.on(loopRange));
|
||||
}
|
||||
else if (!isBoolean(context.semanticServices, hasNextReturnType)) {
|
||||
// context.trace.getErrorHandler().genericError(loopRange.getNode(), "The 'iterator().hasNext' property of the loop range must return Boolean, but returns " + hasNextReturnType);
|
||||
context.trace.report(HAS_NEXT_PROPERTY_TYPE_MISMATCH.on(loopRange, hasNextReturnType));
|
||||
}
|
||||
}
|
||||
@@ -373,20 +364,33 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
|
||||
public JetType visitReturnExpression(JetReturnExpression expression, ExpressionTypingContext context) {
|
||||
context.labelResolver.recordLabel(expression, context);
|
||||
if (context.expectedReturnType == TypeUtils.FORBIDDEN) {
|
||||
// context.trace.getErrorHandler().genericError(expression.getNode(), "'return' is not allowed here");
|
||||
context.trace.report(RETURN_NOT_ALLOWED.on(expression));
|
||||
return null;
|
||||
}
|
||||
JetExpression returnedExpression = expression.getReturnedExpression();
|
||||
|
||||
JetType returnedType = JetStandardClasses.getUnitType();
|
||||
if (returnedExpression != null) {
|
||||
facade.getType(returnedExpression, context.replaceExpectedType(context.expectedReturnType).replaceScope(context.scope));
|
||||
JetType expectedType = context.expectedReturnType;
|
||||
if (expression.getTargetLabel() == null) {
|
||||
if (PsiTreeUtil.getParentOfType(expression, JetFunctionLiteral.class) ==
|
||||
PsiTreeUtil.getParentOfType(expression, JetDeclaration.class)) { // expression is located in function literal
|
||||
JetNamedFunction function = JetPsiUtil.getSurroundingFunction(expression);
|
||||
if (function != null && function.getReturnTypeRef() != null) {
|
||||
expectedType = BindingContextUtils.getFunctionReturnType(context.trace.getBindingContext(), function);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (context.expectedReturnType != TypeUtils.NO_EXPECTED_TYPE && !JetStandardClasses.isUnit(context.expectedReturnType)) {
|
||||
// context.trace.getErrorHandler().genericError(expression.getNode(), "This function must return a value of type " + context.expectedReturnType);
|
||||
context.trace.report(RETURN_TYPE_MISMATCH.on(expression, context.expectedReturnType));
|
||||
PsiElement element = context.trace.get(LABEL_TARGET, expression.getTargetLabel());
|
||||
if (element instanceof JetFunction && ((JetFunction) element).getReturnTypeRef() != null) {
|
||||
expectedType = BindingContextUtils.getFunctionReturnType(context.trace.getBindingContext(), (JetFunction) element);
|
||||
}
|
||||
}
|
||||
if (returnedExpression != null) {
|
||||
facade.getType(returnedExpression, context.replaceExpectedType(expectedType).replaceScope(context.scope));
|
||||
}
|
||||
else {
|
||||
if (expectedType != TypeUtils.NO_EXPECTED_TYPE && expectedType != null && !JetStandardClasses.isUnit(expectedType)) {
|
||||
context.trace.report(RETURN_TYPE_MISMATCH.on(expression, expectedType));
|
||||
}
|
||||
}
|
||||
return DataFlowUtils.checkType(JetStandardClasses.getNothingType(), expression, context);
|
||||
|
||||
+3
-1
@@ -122,7 +122,9 @@ public class ExpressionTypingServices {
|
||||
|
||||
if (function instanceof JetFunctionLiteralExpression) {
|
||||
JetFunctionLiteralExpression functionLiteralExpression = (JetFunctionLiteralExpression) function;
|
||||
getBlockReturnedType(newContext.scope, functionLiteralExpression.getBodyExpression(), CoercionStrategy.COERCION_TO_UNIT, newContext);
|
||||
JetBlockExpression blockExpression = functionLiteralExpression.getBodyExpression();
|
||||
assert blockExpression != null;
|
||||
getBlockReturnedType(newContext.scope, blockExpression, CoercionStrategy.COERCION_TO_UNIT, context);
|
||||
}
|
||||
else {
|
||||
expressionTypingFacade.getType(bodyExpression, newContext);
|
||||
|
||||
@@ -5,9 +5,12 @@ fun unitEmpty() : Unit {}
|
||||
fun unitEmptyReturn() : Unit {return}
|
||||
fun unitIntReturn() : Unit {return <!TYPE_MISMATCH!>1<!>}
|
||||
fun unitUnitReturn() : Unit {return ()}
|
||||
fun test1() : Any = {return}
|
||||
fun test1() : Any = {<!RETURN_TYPE_MISMATCH, RETURN_NOT_ALLOWED!>return<!>}
|
||||
fun test2() : Any = @a {return@a 1}
|
||||
fun test3() : Any { <!RETURN_TYPE_MISMATCH!>return<!> }
|
||||
fun test4(): fun(): Unit = { <!RETURN_TYPE_MISMATCH, RETURN_NOT_ALLOWED!>return@test4<!> }
|
||||
fun test5(): Any = @{ return@ }
|
||||
fun test5(): Any = {<!RETURN_NOT_ALLOWED!>return 1<!>}
|
||||
|
||||
fun bbb() {
|
||||
return <!TYPE_MISMATCH!>1<!>
|
||||
|
||||
@@ -6,12 +6,12 @@ class A {
|
||||
if (1 < 2)
|
||||
return@inner
|
||||
else
|
||||
return@outer
|
||||
<!RETURN_NOT_ALLOWED!>return@outer<!>
|
||||
}
|
||||
if (1 < 2)
|
||||
<!NOT_A_RETURN_LABEL!>return@A<!>
|
||||
<!RETURN_NOT_ALLOWED!>return@A<!>
|
||||
else if (2 < 3)
|
||||
<!NOT_A_RETURN_LABEL!>return<!UNRESOLVED_REFERENCE!>@inner<!><!>
|
||||
<!RETURN_NOT_ALLOWED!>return<!UNRESOLVED_REFERENCE!>@inner<!><!>
|
||||
return@outer
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
//kt-411 Wrong type expected when returning from a function literal
|
||||
|
||||
namespace kt411
|
||||
|
||||
fun f() {
|
||||
invoker(
|
||||
@{
|
||||
return@ 11 // expects Function, but should expect Int
|
||||
}
|
||||
)
|
||||
}
|
||||
fun invoker(gen : fun() : Int) : Int = 0
|
||||
|
||||
//more tests
|
||||
fun t1() {
|
||||
val v = @{ () : Int =>
|
||||
return@ 111
|
||||
}
|
||||
}
|
||||
|
||||
fun t2() : String {
|
||||
val g : fun(): Int = @{
|
||||
if (true) {
|
||||
return@ 1
|
||||
}
|
||||
<!RETURN_NOT_ALLOWED!>return "s"<!>
|
||||
}
|
||||
return "s"
|
||||
}
|
||||
|
||||
fun t3() : String {
|
||||
invoker(
|
||||
@{
|
||||
if (true) {
|
||||
<!RETURN_NOT_ALLOWED!>return@t3 "1"<!>
|
||||
}
|
||||
else {
|
||||
<!RETURN_NOT_ALLOWED!>return <!ERROR_COMPILE_TIME_VALUE!>2<!><!>
|
||||
}
|
||||
return@ 0
|
||||
}
|
||||
)
|
||||
invoker(
|
||||
@{ (): Int =>
|
||||
return@ 1
|
||||
}
|
||||
)
|
||||
invoker(
|
||||
{
|
||||
<!RETURN_NOT_ALLOWED!>return "0"<!>
|
||||
}
|
||||
)
|
||||
return "2"
|
||||
}
|
||||
|
||||
fun t4() : Int {
|
||||
val h : fun (): String = @l{
|
||||
return@l "a"
|
||||
}
|
||||
val g : fun (): String = @{ () : String =>
|
||||
return@ "a"
|
||||
}
|
||||
|
||||
fun inner(): String {
|
||||
return "2"
|
||||
}
|
||||
|
||||
return 12
|
||||
}
|
||||
@@ -5,7 +5,7 @@ fun unitEmpty() : Unit {}
|
||||
fun unitEmptyReturn() : Unit {return}
|
||||
fun unitIntReturn() : Unit {return <error>1</error>}
|
||||
fun unitUnitReturn() : Unit {return ()}
|
||||
fun test1() : Any = {return}
|
||||
fun test1() : Any = { <error>return</error> }
|
||||
fun test2() : Any = @a {return@a 1}
|
||||
fun test3() : Any { <error>return</error> }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user