aboutsummaryrefslogtreecommitdiff
path: root/src/test/java/org
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2024-01-05 21:11:11 +0000
committerMichael Williamson <mike@zwobble.org>2024-01-05 21:11:11 +0000
commit8564cba1883aa4100d0ce614f44af26adde12f41 (patch)
tree395b85fd1357e4be1afde564ab5523d342a2d2b7 /src/test/java/org
parent784de38fe0e07d827d6abf3f85ca34f441768a1c (diff)
Handle simple subtyping for constructed types
Diffstat (limited to 'src/test/java/org')
-rw-r--r--src/test/java/org/shedlang/compiler/typechecker/TypeCheckerIsSubTypeTests.java126
1 files changed, 125 insertions, 1 deletions
diff --git a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerIsSubTypeTests.java b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerIsSubTypeTests.java
index d758cd96..af4d46e4 100644
--- a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerIsSubTypeTests.java
+++ b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerIsSubTypeTests.java
@@ -133,7 +133,7 @@ public class TypeCheckerIsSubTypeTests {
Sources.NULL,
TypeCheckerSubTyping.constraints(List.of(typeParam), TypeInfos.EMPTY)
);
- var result = constraints.solve();
+ var result = constraints.solve(Sources.NULL);
assertThat(result, equalTo(TypeSubstitutionMap.of(
Map.entry(typeParam, Types.INT)
@@ -305,6 +305,130 @@ public class TypeCheckerIsSubTypeTests {
assertThat(isSubType(constructedSumType, variantType2, typeInfos), equalTo(false));
}
+ @Test
+ public void constraintsFromSumSupertypeAreRetained() {
+ var namespaceName = NamespaceName.of("Example", "Project");
+ var sumType = Types.sum(namespaceName, "Sum");
+ var variantType1 = Types.struct(namespaceName, "Variant1");
+ var variantType2 = Types.struct(namespaceName, "Variant2");
+ var variantTypeConstructor2 = Types.typeConstructor(
+ List.of(TypeParam.forStructType(variantType2, "T")),
+ variantType2
+ );
+ var typeInfos = TypeInfos.EMPTY
+ .addSumTypeInfo(sumType, new SumTypeInfo(P.orderedSet(
+ variantType1,
+ Types.constructedStructType(
+ variantTypeConstructor2,
+ List.of(TypeParam.forSumType(sumType, "T"))
+ )
+ )));
+
+ var constraints = TypeCheckerSubTyping.constraints(
+ List.of(TypeParam.forSumType(sumType, "T")),
+ typeInfos
+ );
+ constraints = TypeCheckerSubTyping.addSubtypeConstraint(
+ Types.constructedStructType(
+ variantTypeConstructor2,
+ List.of(Types.STRING)
+ ),
+ sumType,
+ Sources.NULL,
+ constraints
+ );
+ var result = constraints.solve(Sources.NULL);
+
+ assertThat(result, equalTo(TypeSubstitutionMap.of(
+ Map.entry(TypeParam.forSumType(sumType, "T"), Types.STRING)
+ )));
+ }
+
+ // == Constructed types ==
+
+ @Test
+ public void constructedTypeCanBeSubtypeOfConstructedTypeWithBoundTypeParam() {
+ var namespaceName = NamespaceName.of("Example", "Project");
+ var sumType = Types.sum(namespaceName, "Sum");
+ var structType = Types.struct(namespaceName, "Struct");
+ var typeConstructor = Types.typeConstructor(
+ List.of(TypeParam.forStructType(structType, "T")),
+ structType
+ );
+ var typeInfos = TypeInfos.EMPTY;
+
+ var constraints = TypeCheckerSubTyping.constraints(
+ List.of(TypeParam.forSumType(sumType, "T")),
+ typeInfos
+ );
+ constraints = TypeCheckerSubTyping.addSubtypeConstraint(
+ Types.constructedStructType(
+ typeConstructor,
+ List.of(Types.STRING)
+ ),
+ Types.constructedStructType(
+ typeConstructor,
+ List.of(TypeParam.forSumType(sumType, "T"))
+ ),
+ Sources.NULL,
+ constraints
+ );
+ var result = constraints.solve(Sources.NULL);
+
+ assertThat(result, equalTo(TypeSubstitutionMap.of(
+ Map.entry(TypeParam.forSumType(sumType, "T"), Types.STRING)
+ )));
+ }
+
+ @Test
+ public void constructedTypesWithDifferentArgsCannotBothBeSubtypesOfConstructedTypeWithInvariantTypeParam() {
+ var namespaceName = NamespaceName.of("Example", "Project");
+ var sumType = Types.sum(namespaceName, "Sum");
+ var structType = Types.struct(namespaceName, "Struct");
+ var typeConstructor = Types.typeConstructor(
+ List.of(TypeParam.forStructType(structType, "T")),
+ structType
+ );
+ var typeInfos = TypeInfos.EMPTY;
+
+ var constraints = TypeCheckerSubTyping.constraints(
+ List.of(TypeParam.forSumType(sumType, "T")),
+ typeInfos
+ );
+ constraints = TypeCheckerSubTyping.addSubtypeConstraint(
+ Types.constructedStructType(
+ typeConstructor,
+ List.of(Types.STRING)
+ ),
+ Types.constructedStructType(
+ typeConstructor,
+ List.of(TypeParam.forSumType(sumType, "T"))
+ ),
+ Sources.NULL,
+ constraints
+ );
+ constraints = TypeCheckerSubTyping.addSubtypeConstraint(
+ Types.constructedStructType(
+ typeConstructor,
+ List.of(Types.INT)
+ ),
+ Types.constructedStructType(
+ typeConstructor,
+ List.of(TypeParam.forSumType(sumType, "T"))
+ ),
+ Sources.NULL,
+ constraints
+ );
+ var c = constraints;
+ var error = assertThrows(
+ // TODO: more specific error
+ IllegalStateException.class,
+ () -> c.solve(Sources.NULL)
+ );
+
+ assertThat(error.getMessage(), equalTo("Incompatible type bounds"));
+ }
+
// == Function types ==
@Test