aboutsummaryrefslogtreecommitdiff
path: root/src/test/java
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2023-11-03 18:47:52 +0000
committerMichael Williamson <mike@zwobble.org>2023-11-03 18:47:52 +0000
commit65cb451bbfe923a88100a882709e287b8fe5dbb5 (patch)
tree520c1d017830a92b5ff7f79536a4597f36ca2859 /src/test/java
parentedb9d960f411d28e693237c46a2aadf72fdcc6e2 (diff)
Implement subtyping for function types
Diffstat (limited to 'src/test/java')
-rw-r--r--src/test/java/org/shedlang/compiler/typechecker/TypeCheckerIsSubTypeTests.java100
1 files changed, 96 insertions, 4 deletions
diff --git a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerIsSubTypeTests.java b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerIsSubTypeTests.java
index a144b78c..d6bd14be 100644
--- a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerIsSubTypeTests.java
+++ b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerIsSubTypeTests.java
@@ -1,10 +1,7 @@
package org.shedlang.compiler.typechecker;
import org.junit.jupiter.api.Test;
-import org.shedlang.compiler.types.NamespaceName;
-import org.shedlang.compiler.types.StructType;
-import org.shedlang.compiler.types.SumTypeInfo;
-import org.shedlang.compiler.types.Types;
+import org.shedlang.compiler.types.*;
import org.shedlang.compiler.util.P;
import static org.shedlang.compiler.typechecker.TypeCheckerSubTyping.isSubType;
@@ -133,4 +130,99 @@ public class TypeCheckerIsSubTypeTests {
assertThat(isSubType(sumType, variantType1, context), equalTo(false));
assertThat(isSubType(sumType, variantType2, context), equalTo(false));
}
+
+ @Test
+ public void whenFunctionsHaveDifferentPositionalParamCountsThenTheyAreNotSubtypes() {
+ var functionType1 = FunctionType.builder()
+ .addPositionalParam(Types.STRING)
+ .withReturnType(Types.UNIT)
+ .build();
+ var functionType2 = FunctionType.builder()
+ .addPositionalParam(Types.STRING)
+ .addPositionalParam(Types.BOOL)
+ .withReturnType(Types.UNIT)
+ .build();
+ var context = TypeCheckerContext.EMPTY;
+
+ assertThat(isSubType(functionType2, functionType1, context), equalTo(false));
+ assertThat(isSubType(functionType1, functionType2, context), equalTo(false));
+ }
+
+ @Test
+ public void functionPositionalParamsAreContravariant() {
+ var functionType1 = FunctionType.builder()
+ .addPositionalParam(Types.STRING)
+ .withReturnType(Types.UNIT)
+ .build();
+ var functionType2 = FunctionType.builder()
+ .addPositionalParam(Types.TOP)
+ .withReturnType(Types.UNIT)
+ .build();
+ var context = TypeCheckerContext.EMPTY;
+
+ assertThat(isSubType(functionType2, functionType1, context), equalTo(true));
+ assertThat(isSubType(functionType1, functionType2, context), equalTo(false));
+ }
+
+ @Test
+ public void whenFunctionsHaveDifferentNamedParamNamesThenTheyAreNotSubtypes() {
+ var functionType1 = FunctionType.builder()
+ .addNamedParam("x", Types.STRING)
+ .withReturnType(Types.UNIT)
+ .build();
+ var functionType2 = FunctionType.builder()
+ .addNamedParam("y", Types.STRING)
+ .withReturnType(Types.UNIT)
+ .build();
+ var context = TypeCheckerContext.EMPTY;
+
+ assertThat(isSubType(functionType2, functionType1, context), equalTo(false));
+ assertThat(isSubType(functionType1, functionType2, context), equalTo(false));
+ }
+
+ @Test
+ public void functionNamedParamsAreContravariant() {
+ var functionType1 = FunctionType.builder()
+ .addNamedParam("x", Types.STRING)
+ .withReturnType(Types.UNIT)
+ .build();
+ var functionType2 = FunctionType.builder()
+ .addNamedParam("x", Types.TOP)
+ .withReturnType(Types.UNIT)
+ .build();
+ var context = TypeCheckerContext.EMPTY;
+
+ assertThat(isSubType(functionType2, functionType1, context), equalTo(true));
+ assertThat(isSubType(functionType1, functionType2, context), equalTo(false));
+ }
+
+ @Test
+ public void functionTypeIsSubtypeOfOtherFunctionTypeWhenItHasSubeffectOfOtherFunction() {
+ var functionType1 = FunctionType.builder()
+ .withEffect(Effects.IO)
+ .withReturnType(Types.UNIT)
+ .build();
+ var functionType2 = FunctionType.builder()
+ .withEffect(Effects.NONE)
+ .withReturnType(Types.UNIT)
+ .build();
+ var context = TypeCheckerContext.EMPTY;
+
+ assertThat(isSubType(functionType2, functionType1, context), equalTo(true));
+ assertThat(isSubType(functionType1, functionType2, context), equalTo(false));
+ }
+
+ @Test
+ public void functionReturnTypeIsCovariant() {
+ var functionType1 = FunctionType.builder()
+ .withReturnType(Types.TOP)
+ .build();
+ var functionType2 = FunctionType.builder()
+ .withReturnType(Types.STRING)
+ .build();
+ var context = TypeCheckerContext.EMPTY;
+
+ assertThat(isSubType(functionType2, functionType1, context), equalTo(true));
+ assertThat(isSubType(functionType1, functionType2, context), equalTo(false));
+ }
}