Skip to content

Commit

Permalink
feat: LCS returns Any or Any? instead of $unknown
Browse files Browse the repository at this point in the history
  • Loading branch information
lars-reimann committed Feb 20, 2024
1 parent bf18e02 commit efd9d53
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 32 deletions.
30 changes: 21 additions & 9 deletions packages/safe-ds-lang/src/language/typing/safe-ds-type-computer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -742,14 +742,22 @@ export class SafeDsTypeComputer {
}
});

// Includes type with unknown supertype
// Group types by their kind
const groupedTypes = this.groupTypes(replacedTypes);
if (groupedTypes.hasTypeWithUnknownSupertype) {
return UnknownType;

// Includes unknown type
if (groupedTypes.containsUnknownType) {
return this.coreTypes.AnyOrNull;
}

// The result must be nullable if any of the types is nullable
const isNullable = replacedTypes.some((it) => it.isExplicitlyNullable);

// Includes unhandled type
if (groupedTypes.containsUnhandledType) {
return this.Any(isNullable);
}

// Class-based types
if (!isEmpty(groupedTypes.classTypes)) {
if (!isEmpty(groupedTypes.enumTypes) || !isEmpty(groupedTypes.enumVariantTypes)) {
Expand Down Expand Up @@ -786,7 +794,8 @@ export class SafeDsTypeComputer {
classTypes: [],
enumTypes: [],
enumVariantTypes: [],
hasTypeWithUnknownSupertype: false,
containsUnhandledType: false,
containsUnknownType: false,
};

for (const type of types) {
Expand All @@ -803,11 +812,13 @@ export class SafeDsTypeComputer {
if (classType instanceof ClassType) {
result.classTypes.push(classType);
} else {
result.hasTypeWithUnknownSupertype = true;
result.containsUnknownType = true;

Check warning on line 815 in packages/safe-ds-lang/src/language/typing/safe-ds-type-computer.ts

View check run for this annotation

Codecov / codecov/patch

packages/safe-ds-lang/src/language/typing/safe-ds-type-computer.ts#L815

Added line #L815 was not covered by tests
}
} else if (type === UnknownType) {
result.containsUnknownType = true;
} else {
// Other types don't have a clear lowest common supertype
result.hasTypeWithUnknownSupertype = true;
// Since these types don't occur in legal programs, we don't need to handle them better
result.containsUnhandledType = true;
return result;
}
}
Expand Down Expand Up @@ -1022,7 +1033,7 @@ export class SafeDsTypeComputer {
current = this.parentClassType(current);
}

const Any = this.coreTypes.Any.withExplicitNullability(type.isExplicitlyNullable);
const Any = this.Any(type.isExplicitlyNullable);
if (Any instanceof ClassType && !visited.has(Any.declaration)) {
yield Any;
}
Expand Down Expand Up @@ -1072,7 +1083,8 @@ interface GroupTypesResult {
classTypes: ClassType[];
enumTypes: EnumType[];
enumVariantTypes: EnumVariantType[];
hasTypeWithUnknownSupertype: boolean;
containsUnhandledType: boolean;
containsUnknownType: boolean;
}

const NO_SUBSTITUTIONS: TypeParameterSubstitutions = new Map();
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package tests.typing.lowestCommonSupertype.unhandledType

class C
@Pure fun f() -> (r1: Int, r2: Int)

segment mySegment() {
// $TEST$ serialization List<Any>
»[1, f]«;

// $TEST$ serialization List<Any?>
»[null, f]«;

// $TEST$ serialization List<Any>
»[1, C]«;

// $TEST$ serialization List<Any?>
»[null, C]«;

// $TEST$ serialization List<Any>
»[1, f()]«;

// $TEST$ serialization List<Any?>
»[null, f()]«;
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package tests.typing.lowestCommonSupertype.unknownType

segment mySegment() {
// $TEST$ serialization List<Any?>
»[1, unknown]«;

// $TEST$ serialization List<Any?>
»[null, unknown]«;
}

0 comments on commit efd9d53

Please sign in to comment.