Skip to content

Commit

Permalink
Make union types more efficient by eliminating unnecessary redundancy.
Browse files Browse the repository at this point in the history
This change modifies union types to always leave structural subtypes in
the union.  This can result in additional types errors if the previously
collapsed type provides a definition for a property or if the collapsed
type was @struct (as any @struct member of the union causes the member
to be considered @struct).

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=242546590
  • Loading branch information
concavelenz authored and brad4d committed Apr 9, 2019
1 parent e036fe1 commit 0eabec0
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 173 deletions.
2 changes: 1 addition & 1 deletion src/com/google/javascript/jscomp/JsIterables.java
Expand Up @@ -135,7 +135,7 @@ static final MaybeBoxedIterableOrAsyncIterable maybeBoxIterableOrAsyncIterable(
// Note: we don't just use JSType.autobox() here because that removes null and undefined.
// We want to keep null and undefined around because they should cause a mismatch.
if (type.isUnionType()) {
for (JSType alt : type.toMaybeUnionType().getAlternatesWithoutStructuralTyping()) {
for (JSType alt : type.toMaybeUnionType().getAlternates()) {
alt = alt.isBoxableScalar() ? alt.autoboxesTo() : alt;
boolean isIterable = alt.isSubtypeOf(typeRegistry.getNativeType(ITERABLE_TYPE));
boolean isAsyncIterable = alt.isSubtypeOf(typeRegistry.getNativeType(ASYNC_ITERABLE_TYPE));
Expand Down
2 changes: 1 addition & 1 deletion src/com/google/javascript/jscomp/Promises.java
Expand Up @@ -74,7 +74,7 @@ static final JSType getResolvedType(JSTypeRegistry registry, JSType type) {

if (type.isUnionType()) {
UnionTypeBuilder unionTypeBuilder = UnionTypeBuilder.create(registry);
for (JSType alternate : type.toMaybeUnionType().getAlternatesWithoutStructuralTyping()) {
for (JSType alternate : type.toMaybeUnionType().getAlternates()) {
unionTypeBuilder.addAlternate(getResolvedType(registry, alternate));
}
return unionTypeBuilder.build();
Expand Down
2 changes: 1 addition & 1 deletion src/com/google/javascript/jscomp/TypeValidator.java
Expand Up @@ -283,7 +283,7 @@ boolean expectAutoboxesToIterable(Node n, JSType type, String msg) {
// Note: we don't just use JSType.autobox() here because that removes null and undefined.
// We want to keep null and undefined around.
if (type.isUnionType()) {
for (JSType alt : type.toMaybeUnionType().getAlternatesWithoutStructuralTyping()) {
for (JSType alt : type.toMaybeUnionType().getAlternates()) {
alt = alt.isBoxableScalar() ? alt.autoboxesTo() : alt;
if (!alt.isSubtypeOf(getNativeType(ITERABLE_TYPE))) {
mismatch(n, msg, type, ITERABLE_TYPE);
Expand Down
11 changes: 4 additions & 7 deletions src/com/google/javascript/rhino/jstype/JSType.java
Expand Up @@ -1448,9 +1448,7 @@ public TypePair getTypesUnderShallowInequality(JSType that) {
}

public Iterable<JSType> getUnionMembers() {
return isUnionType()
? this.toMaybeUnionType().getAlternatesWithoutStructuralTyping()
: null;
return isUnionType() ? this.toMaybeUnionType().getAlternates() : null;
}

/**
Expand Down Expand Up @@ -1558,10 +1556,9 @@ static boolean isSubtypeHelper(JSType thisType, JSType thatType,
if (thatType.isUnionType()) {
UnionType union = thatType.toMaybeUnionType();
// use an indexed for-loop to avoid allocations
ImmutableList<JSType> alternatesWithoutStucturalTyping =
union.getAlternatesWithoutStructuralTyping();
for (int i = 0; i < alternatesWithoutStucturalTyping.size(); i++) {
JSType element = alternatesWithoutStucturalTyping.get(i);
ImmutableList<JSType> alternates = union.getAlternates();
for (int i = 0; i < alternates.size(); i++) {
JSType element = alternates.get(i);
if (thisType.isSubtype(element, implicitImplCache, subtypingMode)) {
return true;
}
Expand Down

0 comments on commit 0eabec0

Please sign in to comment.