JET-113 Check returns in secondary constructors
This commit is contained in:
@@ -11,6 +11,7 @@ import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider;
|
|||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.types.ErrorUtils;
|
import org.jetbrains.jet.lang.types.ErrorUtils;
|
||||||
|
import org.jetbrains.jet.lang.types.JetStandardClasses;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
import org.jetbrains.jet.lang.types.JetTypeInferrer;
|
import org.jetbrains.jet.lang.types.JetTypeInferrer;
|
||||||
import org.jetbrains.jet.lexer.JetTokens;
|
import org.jetbrains.jet.lexer.JetTokens;
|
||||||
@@ -727,7 +728,7 @@ public class TopDownAnalyzer {
|
|||||||
JetFlowInformationProvider flowInformationProvider = classDescriptorResolver.computeFlowData(declaration, bodyExpression);
|
JetFlowInformationProvider flowInformationProvider = classDescriptorResolver.computeFlowData(declaration, bodyExpression);
|
||||||
JetTypeInferrer typeInferrer = semanticServices.getTypeInferrer(traceForConstructors, flowInformationProvider);
|
JetTypeInferrer typeInferrer = semanticServices.getTypeInferrer(traceForConstructors, flowInformationProvider);
|
||||||
|
|
||||||
typeInferrer.getType(functionInnerScope, bodyExpression, true, null);
|
typeInferrer.checkFunctionReturnType(functionInnerScope, declaration, descriptor, JetStandardClasses.getUnitType());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -308,9 +308,44 @@ public class JetTypeInferrer {
|
|||||||
|
|
||||||
public void checkFunctionReturnType(@NotNull JetScope outerScope, @NotNull JetDeclarationWithBody function, @NotNull FunctionDescriptor functionDescriptor) {
|
public void checkFunctionReturnType(@NotNull JetScope outerScope, @NotNull JetDeclarationWithBody function, @NotNull FunctionDescriptor functionDescriptor) {
|
||||||
final JetType expectedReturnType = functionDescriptor.getUnsubstitutedReturnType();
|
final JetType expectedReturnType = functionDescriptor.getUnsubstitutedReturnType();
|
||||||
|
JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(outerScope, functionDescriptor, trace);
|
||||||
|
checkFunctionReturnType(functionInnerScope, function, functionDescriptor, expectedReturnType);
|
||||||
|
// Map<JetElement, JetType> typeMap = collectReturnedExpressionsWithTypes(outerScope, function, functionDescriptor, expectedReturnType);
|
||||||
|
// if (typeMap.isEmpty()) {
|
||||||
|
// return; // The function returns Nothing
|
||||||
|
// }
|
||||||
|
// for (Map.Entry<JetElement, JetType> entry : typeMap.entrySet()) {
|
||||||
|
// JetType actualType = entry.getValue();
|
||||||
|
// JetElement element = entry.getKey();
|
||||||
|
// JetTypeChecker typeChecker = semanticServices.getTypeChecker();
|
||||||
|
// if (!typeChecker.isSubtypeOf(actualType, expectedReturnType)) {
|
||||||
|
// if (typeChecker.isConvertibleBySpecialConversion(actualType, expectedReturnType)) {
|
||||||
|
// if (expectedReturnType.getConstructor().equals(JetStandardClasses.getUnitType().getConstructor())
|
||||||
|
// && element.getParent() instanceof JetReturnExpression) {
|
||||||
|
// trace.getErrorHandler().genericError(element.getNode(), "This function must return a value of type Unit");
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// else {
|
||||||
|
// if (element == function) {
|
||||||
|
// JetExpression bodyExpression = function.getBodyExpression();
|
||||||
|
// assert bodyExpression != null;
|
||||||
|
// trace.getErrorHandler().genericError(bodyExpression.getNode(), "This function must return a value of type " + expectedReturnType);
|
||||||
|
// }
|
||||||
|
// else if (element instanceof JetExpression) {
|
||||||
|
// JetExpression expression = (JetExpression) element;
|
||||||
|
// trace.getErrorHandler().typeMismatch(expression, expectedReturnType, actualType);
|
||||||
|
// }
|
||||||
|
// else {
|
||||||
|
// trace.getErrorHandler().genericError(element.getNode(), "This function must return a value of type " + expectedReturnType);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkFunctionReturnType(JetScope functionInnerScope, JetDeclarationWithBody function, FunctionDescriptor functionDescriptor, @Nullable final JetType expectedReturnType) {
|
||||||
JetExpression bodyExpression = function.getBodyExpression();
|
JetExpression bodyExpression = function.getBodyExpression();
|
||||||
assert bodyExpression != null;
|
assert bodyExpression != null;
|
||||||
JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(outerScope, functionDescriptor, trace);
|
|
||||||
new TypeInferrerVisitor(functionInnerScope, function.hasBlockBody(), DataFlowInfo.getEmpty(), null, expectedReturnType).getType(bodyExpression);
|
new TypeInferrerVisitor(functionInnerScope, function.hasBlockBody(), DataFlowInfo.getEmpty(), null, expectedReturnType).getType(bodyExpression);
|
||||||
|
|
||||||
List<JetElement> unreachableElements = Lists.newArrayList();
|
List<JetElement> unreachableElements = Lists.newArrayList();
|
||||||
@@ -356,37 +391,6 @@ public class JetTypeInferrer {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// Map<JetElement, JetType> typeMap = collectReturnedExpressionsWithTypes(outerScope, function, functionDescriptor, expectedReturnType);
|
|
||||||
// if (typeMap.isEmpty()) {
|
|
||||||
// return; // The function returns Nothing
|
|
||||||
// }
|
|
||||||
// for (Map.Entry<JetElement, JetType> entry : typeMap.entrySet()) {
|
|
||||||
// JetType actualType = entry.getValue();
|
|
||||||
// JetElement element = entry.getKey();
|
|
||||||
// JetTypeChecker typeChecker = semanticServices.getTypeChecker();
|
|
||||||
// if (!typeChecker.isSubtypeOf(actualType, expectedReturnType)) {
|
|
||||||
// if (typeChecker.isConvertibleBySpecialConversion(actualType, expectedReturnType)) {
|
|
||||||
// if (expectedReturnType.getConstructor().equals(JetStandardClasses.getUnitType().getConstructor())
|
|
||||||
// && element.getParent() instanceof JetReturnExpression) {
|
|
||||||
// trace.getErrorHandler().genericError(element.getNode(), "This function must return a value of type Unit");
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// else {
|
|
||||||
// if (element == function) {
|
|
||||||
// JetExpression bodyExpression = function.getBodyExpression();
|
|
||||||
// assert bodyExpression != null;
|
|
||||||
// trace.getErrorHandler().genericError(bodyExpression.getNode(), "This function must return a value of type " + expectedReturnType);
|
|
||||||
// }
|
|
||||||
// else if (element instanceof JetExpression) {
|
|
||||||
// JetExpression expression = (JetExpression) element;
|
|
||||||
// trace.getErrorHandler().typeMismatch(expression, expectedReturnType, actualType);
|
|
||||||
// }
|
|
||||||
// else {
|
|
||||||
// trace.getErrorHandler().genericError(element.getNode(), "This function must return a value of type " + expectedReturnType);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
@@ -110,4 +110,13 @@ fun blockReturnValueTypeMatch() : Int {
|
|||||||
else return <error>1.0</error>
|
else return <error>1.0</error>
|
||||||
}
|
}
|
||||||
|
|
||||||
val a = <error>return 1</error>
|
val a = <error>return 1</error>
|
||||||
|
|
||||||
|
class A() {
|
||||||
|
this(a : Int) : this() {
|
||||||
|
if (a == 1)
|
||||||
|
return
|
||||||
|
return <error>1</error>
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user