Typechecker logic fixed for one-branch ifs and 'return x' for Unit-returning functions

This commit is contained in:
Andrey Breslav
2011-04-07 14:43:25 +04:00
parent e61e908ab7
commit 30d8349272
7 changed files with 39 additions and 15 deletions
+1
View File
@@ -16,6 +16,7 @@
<option name="VM_PARAMETERS" value="" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
<option name="FORK_MODE" />
<option name="ENV_VARIABLES" />
<option name="PASS_PARENT_ENVS" value="true" />
<option name="TEST_SEARCH_SCOPE">
@@ -287,7 +287,11 @@ public class JetTypeChecker {
}
public boolean isConvertibleTo(@NotNull JetType actual, @NotNull JetType expected) {
if (isSubtypeOf(actual, expected)) return true;
return isSubtypeOf(actual, expected) ||
isConvertibleBySpecialConversion(actual, expected);
}
public boolean isConvertibleBySpecialConversion(@NotNull JetType actual, @NotNull JetType expected) {
if (expected.getConstructor().equals(JetStandardClasses.getTuple(0).getTypeConstructor())) {
return true;
}
@@ -289,13 +289,22 @@ public class JetTypeInferrer {
for (Map.Entry<JetElement, JetType> entry : typeMap.entrySet()) {
JetType actualType = entry.getValue();
JetElement element = entry.getKey();
if (!semanticServices.getTypeChecker().isConvertibleTo(actualType, expectedReturnType)) {
if (element instanceof JetExpression) {
JetExpression expression = (JetExpression) element;
semanticServices.getErrorHandler().typeMismatch(expression, expectedReturnType, actualType);
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) {
semanticServices.getErrorHandler().genericError(element.getNode(), "This function must return a value of type Unit");
}
}
else {
semanticServices.getErrorHandler().genericError(element.getNode(), "This function must return a value of type " + expectedReturnType);
if (element instanceof JetExpression) {
JetExpression expression = (JetExpression) element;
semanticServices.getErrorHandler().typeMismatch(expression, expectedReturnType, actualType);
}
else {
semanticServices.getErrorHandler().genericError(element.getNode(), "This function must return a value of type " + expectedReturnType);
}
}
}
}
@@ -689,11 +698,19 @@ public class JetTypeInferrer {
// TODO : change types according to is and null checks
JetExpression elseBranch = expression.getElse();
JetExpression thenBranch = expression.getThen();
JetType thenType = null;
if (thenBranch != null) {
thenType = getType(scope, thenBranch, true);
if (elseBranch == null) {
if (thenBranch != null) {
getType(scope, thenBranch, true);
result = JetStandardClasses.getUnitType();
}
}
if (elseBranch != null) {
else if (thenBranch == null) {
getType(scope, elseBranch, true);
result = JetStandardClasses.getUnitType();
}
else {
JetType thenType = getType(scope, thenBranch, true);
JetType elseType = getType(scope, elseBranch, true);
if (thenType == null) {
result = elseType;
@@ -705,9 +722,6 @@ public class JetTypeInferrer {
result = semanticServices.getTypeChecker().commonSupertype(Arrays.asList(thenType, elseType));
}
}
else {
result = JetStandardClasses.getUnitType();
}
}
private void checkCondition(@NotNull JetScope scope, @Nullable JetExpression condition) {
+1 -1
View File
@@ -36,7 +36,7 @@ l5:
<END>
=====================
== nonlocals1 ==
fun nonlocals1(a : Boolean, b : Boolean) : Unit {
fun nonlocals1(a : Boolean, b : Boolean) : Any? {
if (a)
return 1
1
+1 -1
View File
@@ -1,4 +1,4 @@
fun nonlocals1(a : Boolean, b : Boolean) : Unit {
fun nonlocals1(a : Boolean, b : Boolean) : Any? {
if (a)
return 1
1
@@ -3,6 +3,8 @@
fun unitEmptyInfer() {}
fun unitEmpty() : Unit {}
fun unitEmptyReturn() : Unit {return}
fun unitIntReturn() : Unit {return <error>1</error>}
fun unitUnitReturn() : Unit {return ()}
fun unitShort() : Unit = ()
fun unitShortConv() : Unit = 1
fun unitShortNull() : Unit = null
@@ -101,6 +101,9 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
assertType("if (true) null else null", "Nothing?");
assertType("if (true) 1 else '1'", "Any");
assertType("if (true) else '1'", "Unit");
assertType("if (true) else a = 0", "Unit");
}
public void testWhen() throws Exception {