JET-113 Check returns in secondary constructors

This commit is contained in:
Andrey Breslav
2011-06-17 18:31:51 +04:00
parent 03460e2bcc
commit 6d1823ac2a
3 changed files with 48 additions and 34 deletions
@@ -11,6 +11,7 @@ import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
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.JetTypeInferrer;
import org.jetbrains.jet.lexer.JetTokens;
@@ -727,7 +728,7 @@ public class TopDownAnalyzer {
JetFlowInformationProvider flowInformationProvider = classDescriptorResolver.computeFlowData(declaration, bodyExpression);
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) {
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();
assert bodyExpression != null;
JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(outerScope, functionDescriptor, trace);
new TypeInferrerVisitor(functionInnerScope, function.hasBlockBody(), DataFlowInfo.getEmpty(), null, expectedReturnType).getType(bodyExpression);
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
+10 -1
View File
@@ -110,4 +110,13 @@ fun blockReturnValueTypeMatch() : Int {
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>
}
}