Skip to content

Commit

Permalink
feat: remove unneeded entries from union types
Browse files Browse the repository at this point in the history
  • Loading branch information
lars-reimann committed Feb 7, 2024
1 parent 6c5100b commit 3ff542d
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -657,10 +657,39 @@ export class SafeDsTypeComputer {
}

private simplifyUnionType(type: UnionType): Type {
// Handle empty union types
if (isEmpty(type.possibleTypes)) {
return this.coreTypes.Nothing;
}

// Simplify possible types
const newPossibleTypes = type.possibleTypes.map((it) => this.simplifyType(it));

// Remove types that are subtypes of others. We do this back-to-front to keep the first occurrence of duplicate
// types. It's also makes splicing easier.
for (let i = newPossibleTypes.length - 1; i >= 0; i--) {
const currentType = newPossibleTypes[i]!;

for (let j = 0; j < newPossibleTypes.length; j++) {
if (i === j) {
continue;
}

let otherType = newPossibleTypes[j]!;
otherType = otherType.updateNullability(currentType.isNullable || otherType.isNullable);

if (this.typeChecker.isAssignableTo(currentType, otherType)) {
newPossibleTypes.splice(j, 1, otherType); // Update nullability
newPossibleTypes.splice(i, 1);
break;
}
}
}

if (newPossibleTypes.length === 1) {
return newPossibleTypes[0]!;
} else {
return type;
return new UnionType(...newPossibleTypes);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ segment mySegment1(p: C<Int>) {
»nullableC()?.nonNullableMember«;
// $TEST$ serialization Int?
»nullableC()?.nullableMember«;
// $TEST$ serialization union<() -> (r: Int), literal<null>>
// $TEST$ serialization union<() -> (r: Int), Nothing?>
»nullableC()?.method«;
}

Expand Down Expand Up @@ -71,6 +71,6 @@ segment mySegment2(p: D) {
»nullableD()?.nonNullableMember«;
// $TEST$ serialization Int?
»nullableD()?.nullableMember«;
// $TEST$ serialization union<() -> (r: Int), literal<null>>
// $TEST$ serialization union<() -> (r: Int), Nothing?>
»nullableD()?.method«;
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,6 @@ pipeline myPipeline {
»nullableC()?.nonNullableMember«;
// $TEST$ equivalence_class nullableMember
»nullableC()?.nullableMember«;
// $TEST$ serialization union<() -> (r: Int), literal<null>>
// $TEST$ serialization union<() -> (r: Int), Nothing?>
»nullableC()?.method«;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package tests.typing.simplification.removeUnneededEntriesFromUnionTypes

class C(
// $TEST$ serialization Int
p1: »union<Int, Int>«,

// $TEST$ serialization union<Int, String>
p2: »union<Int, String, Int>«,


// $TEST$ serialization Number
p3: »union<Int, Number>«,

// $TEST$ serialization Number
p4: »union<Number, Int>«,

// $TEST$ serialization Number?
p5: »union<Number, Int?>«,

// $TEST$ serialization Any
p6: »union<Int, Number, Any>«,

// $TEST$ serialization Any
p7: »union<Any, Number, Int>«,

// $TEST$ serialization Any?
p8: »union<Int, Number?, Any>«,


// $TEST$ serialization union<Int, String>
p9: »union<Int, String>«,

// $TEST$ serialization union<Int, String?>
p10: »union<Int, String?>«,

// $TEST$ serialization union<Number, String>
p11: »union<Int, Number, String>«,

// $TEST$ serialization union<Number, String>
p12: »union<Number, Int, String>«,

// $TEST$ serialization Any
p13: »union<Int, String, Any>«,

// $TEST$ serialization Any?
p14: »union<Int, String?, Any>«,

// $TEST$ serialization Any
p15: »union<Any, String, Int>«,

// $TEST$ serialization Any?
p16: »union<Any, String?, Int>«,
)

0 comments on commit 3ff542d

Please sign in to comment.