From 112cb9b4e0d4e455b473205f2cd5953a2164994d Mon Sep 17 00:00:00 2001 From: Lars Reimann Date: Sat, 28 Dec 2024 14:56:51 +0100 Subject: [PATCH] fix: subtype check for literal and union types --- .../src/language/typing/safe-ds-type-checker.ts | 11 ++++++++--- .../typing/type checker/isSubOrSupertypeOf.test.ts | 5 +++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/packages/safe-ds-lang/src/language/typing/safe-ds-type-checker.ts b/packages/safe-ds-lang/src/language/typing/safe-ds-type-checker.ts index 87d4962aa..3e4b21d2e 100644 --- a/packages/safe-ds-lang/src/language/typing/safe-ds-type-checker.ts +++ b/packages/safe-ds-lang/src/language/typing/safe-ds-type-checker.ts @@ -75,7 +75,8 @@ export class SafeDsTypeChecker { // Handle union types if (type instanceof UnionType) { return type.types.every((it) => this.isSubtypeOf(it, other, options)); - } else if (other instanceof UnionType) { + } else if (other instanceof UnionType && !(type instanceof LiteralType)) { + // For literal types the quantifiers would be the wrong way around return other.types.some((it) => this.isSubtypeOf(type, it, options)); } @@ -264,17 +265,21 @@ export class SafeDsTypeChecker { return true; } - return type.constants.every((constant) => this.constantIsSubtypeOfClassType(constant, other, options)); + return type.constants.every((constant) => this.constantIsSubtypeOf(constant, other, options)); } else if (other instanceof LiteralType) { return type.constants.every((constant) => other.constants.some((otherConstant) => constant.equals(otherConstant)), ); + } else if (other instanceof UnionType) { + return type.constants.every((constant) => + other.types.some((it) => this.constantIsSubtypeOf(constant, it, options)), + ); } else { return false; } } - private constantIsSubtypeOfClassType(constant: Constant, other: ClassType, options: TypeCheckOptions): boolean { + private constantIsSubtypeOf(constant: Constant, other: Type, options: TypeCheckOptions): boolean { const classType = this.typeComputer().computeClassTypeForConstant(constant); return this.isSubtypeOf(classType, other, options); } diff --git a/packages/safe-ds-lang/tests/language/typing/type checker/isSubOrSupertypeOf.test.ts b/packages/safe-ds-lang/tests/language/typing/type checker/isSubOrSupertypeOf.test.ts index fdda32898..6c145f42b 100644 --- a/packages/safe-ds-lang/tests/language/typing/type checker/isSubOrSupertypeOf.test.ts +++ b/packages/safe-ds-lang/tests/language/typing/type checker/isSubOrSupertypeOf.test.ts @@ -508,6 +508,11 @@ const basic = async (): Promise => { type2: factory.createUnionType(coreTypes.String), expected: false, }, + { + type1: factory.createLiteralType(new IntConstant(1n), new StringConstant('')), + type2: factory.createUnionType(coreTypes.Int, coreTypes.String), + expected: true, + }, // Literal type to other { type1: factory.createLiteralType(), // Empty literal type