diff options
| author | Michael Williamson <mike@zwobble.org> | 2023-11-03 18:47:52 +0000 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2023-11-03 18:47:52 +0000 |
| commit | 65cb451bbfe923a88100a882709e287b8fe5dbb5 (patch) | |
| tree | 520c1d017830a92b5ff7f79536a4597f36ca2859 /src/test/java | |
| parent | edb9d960f411d28e693237c46a2aadf72fdcc6e2 (diff) | |
Implement subtyping for function types
Diffstat (limited to 'src/test/java')
| -rw-r--r-- | src/test/java/org/shedlang/compiler/typechecker/TypeCheckerIsSubTypeTests.java | 100 |
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)); + } } |
