aboutsummaryrefslogtreecommitdiff
path: root/src/test/java
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2023-10-01 20:26:32 +0100
committerMichael Williamson <mike@zwobble.org>2023-10-01 20:26:32 +0100
commit43df1e1a688c1dcf5f6c39df47135b3b30573d71 (patch)
tree7736869576995b8ed6312a3c06a55b1beb5d8aac /src/test/java
parent527d979d6e0a9cb3296c6444419863c49bb7bed8 (diff)
Narrow type in when case bodies
Diffstat (limited to 'src/test/java')
-rw-r--r--src/test/java/org/shedlang/compiler/typechecker/TypeCheckerWhenTests.java59
1 files changed, 57 insertions, 2 deletions
diff --git a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerWhenTests.java b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerWhenTests.java
index f593a710..cc731458 100644
--- a/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerWhenTests.java
+++ b/src/test/java/org/shedlang/compiler/typechecker/TypeCheckerWhenTests.java
@@ -15,8 +15,7 @@ import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.shedlang.compiler.ast.typed.TypedNodeMatchers.*;
import static org.zwobble.precisely.AssertThat.assertThat;
-import static org.zwobble.precisely.Matchers.equalTo;
-import static org.zwobble.precisely.Matchers.isSequence;
+import static org.zwobble.precisely.Matchers.*;
public class TypeCheckerWhenTests {
private static final NamespaceName NAMESPACE_NAME = NamespaceName.of("Example", "Project");
@@ -253,4 +252,60 @@ public class TypeCheckerWhenTests {
assertThat(result.value().type(), equalTo(Types.TOP));
}
+
+ @Test
+ public void whenExpressionIsReferenceThenTypeIsNarrowedInCaseBodies() {
+ var untyped = Untyped.when(
+ Untyped.reference("x"),
+ List.of(
+ Untyped.whenCase(
+ Untyped.typeLevelReference(VARIANT_TYPE_1.name()),
+ Untyped.block(List.of(
+ Untyped.blockReturn(Untyped.fieldAccess(
+ Untyped.reference("x"),
+ "a"
+ ))
+ ))
+ ),
+ Untyped.whenCase(
+ Untyped.typeLevelReference(VARIANT_TYPE_2.name()),
+ Untyped.block(List.of(
+ Untyped.blockReturn(Untyped.fieldAccess(
+ Untyped.reference("x"),
+ "b"
+ ))
+ ))
+ )
+ )
+ );
+ var context = TypeCheckerContext.EMPTY
+ .addSumTypeInfo(SUM_TYPE, new SumTypeInfo(P.orderedSet(VARIANT_TYPE_1, VARIANT_TYPE_2)))
+ .addStructTypeInfo(VARIANT_TYPE_1, StructTypeInfo.fromFields(P.orderedMap(
+ Map.entry("a", Types.STRING)
+ )))
+ .addStructTypeInfo(VARIANT_TYPE_2, StructTypeInfo.fromFields(P.orderedMap(
+ Map.entry("b", Types.INT)
+ )))
+ .enterGlobal(P.map(
+ Map.entry("x", SUM_TYPE),
+ Map.entry(VARIANT_TYPE_1.name(), Types.metaType(VARIANT_TYPE_1)),
+ Map.entry(VARIANT_TYPE_2.name(), Types.metaType(VARIANT_TYPE_2))
+ ));
+
+ var result = TypeChecker.typeCheckExpression(untyped, context);
+
+ assertThat(result.value(), isTypedWhenNode(
+ isTypedReferenceNode("x", SUM_TYPE),
+ isSequence(
+ isTypedWhenCaseNode(
+ isTypedTypeLevelReferenceNode("Variant1", VARIANT_TYPE_1),
+ has("type", x -> x.type(), equalTo(Types.STRING))
+ ),
+ isTypedWhenCaseNode(
+ isTypedTypeLevelReferenceNode("Variant2", VARIANT_TYPE_2),
+ has("type", x -> x.type(), equalTo(Types.INT))
+ )
+ )
+ ));
+ }
}