Skip to content

Commit

Permalink
Fix invalid accepted type for union and tables
Browse files Browse the repository at this point in the history
  • Loading branch information
heshanpadmasiri committed Oct 1, 2024
1 parent 816e9b4 commit 5a76fb0
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import io.ballerina.runtime.api.types.Type;
import io.ballerina.runtime.api.values.BString;
import io.ballerina.runtime.api.values.BValue;
import io.ballerina.runtime.internal.types.TypeWithAcceptedType;
import io.ballerina.runtime.internal.types.TypeWithShape;
import io.ballerina.runtime.internal.values.DecimalValue;

Expand All @@ -14,8 +15,8 @@ private ShapeAnalyzer() {
}

public static Optional<SemType> acceptedTypeOf(Context cx, Type typeDesc) {
if (typeDesc instanceof TypeWithShape typeWithShape) {
return typeWithShape.acceptedTypeOf(cx);
if (typeDesc instanceof TypeWithAcceptedType typeWithAcceptedType) {
return typeWithAcceptedType.acceptedTypeOf(cx);
}
return Optional.of(SemType.tryInto(typeDesc));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Stream;
Expand Down Expand Up @@ -307,9 +306,7 @@ public static boolean checkIsLikeType(Object sourceValue, Type targetType) {
*/
public static boolean checkIsLikeType(Object sourceValue, Type targetType, boolean allowNumericConversion) {
Context cx = context();
Optional<SemType> readonlyShape = ShapeAnalyzer.shapeOf(cx, sourceValue);
assert readonlyShape.isPresent();
SemType shape = readonlyShape.get();
SemType shape = ShapeAnalyzer.shapeOf(cx, sourceValue).orElseThrow();
SemType targetSemType = ShapeAnalyzer.acceptedTypeOf(cx, targetType).orElseThrow();
if (Core.isSubType(cx, shape, NumericTypeHolder.NUMERIC_TYPE) && allowNumericConversion) {
targetSemType = appendNumericConversionTypes(targetSemType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import io.ballerina.runtime.api.types.semtype.Context;
import io.ballerina.runtime.api.types.semtype.Core;
import io.ballerina.runtime.api.types.semtype.SemType;
import io.ballerina.runtime.api.types.semtype.ShapeAnalyzer;
import io.ballerina.runtime.api.values.BTable;
import io.ballerina.runtime.internal.TypeChecker;
import io.ballerina.runtime.internal.types.semtype.TableUtils;
Expand Down Expand Up @@ -218,8 +219,17 @@ public Optional<SemType> shapeOf(Context cx, ShapeSupplier shapeSupplierFn, Obje

@Override
public Optional<SemType> acceptedTypeOf(Context cx) {
// TODO: this is not correct but can we actually match tables?
return Optional.of(getSemType());
SemType constraintType = ShapeAnalyzer.acceptedTypeOf(cx, this.constraint).orElseThrow();
SemType semType;
if (fieldNames.length > 0) {
semType = TableUtils.acceptedTypeContainingKeySpecifier(cx, constraintType, fieldNames);
} else if (keyType != null) {
SemType keyAcceptedType = ShapeAnalyzer.acceptedTypeOf(cx, keyType).orElseThrow();
semType = TableUtils.acceptedTypeContainingKeyConstraint(cx, constraintType, keyAcceptedType);
} else {
semType = TableUtils.acceptedType(cx.env, constraintType);
}
return Optional.of(semType);
}

private SemType valueShape(Context cx, ShapeSupplier shapeSupplier, BTable<?, ?> table) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@
import io.ballerina.runtime.api.types.Type;
import io.ballerina.runtime.api.types.UnionType;
import io.ballerina.runtime.api.types.semtype.Builder;
import io.ballerina.runtime.api.types.semtype.Context;
import io.ballerina.runtime.api.types.semtype.Core;
import io.ballerina.runtime.api.types.semtype.SemType;
import io.ballerina.runtime.api.types.semtype.ShapeAnalyzer;
import io.ballerina.runtime.api.utils.TypeUtils;
import io.ballerina.runtime.internal.TypeChecker;
import io.ballerina.runtime.internal.values.ReadOnlyUtils;
Expand All @@ -48,7 +50,7 @@
*
* @since 0.995.0
*/
public class BUnionType extends BType implements UnionType, SelectivelyImmutableReferenceType {
public class BUnionType extends BType implements UnionType, SelectivelyImmutableReferenceType, TypeWithAcceptedType {

public boolean isCyclic = false;
public static final String PIPE = "|";
Expand Down Expand Up @@ -554,4 +556,10 @@ public void setIntersectionType(IntersectionType intersectionType) {
public SemType createSemType() {
return memberTypes.stream().map(SemType::tryInto).reduce(Builder.neverType(), Core::union);
}

@Override
public Optional<SemType> acceptedTypeOf(Context cx) {
return Optional.of(memberTypes.stream().map(each -> ShapeAnalyzer.acceptedTypeOf(cx, each).orElseThrow())
.reduce(Builder.neverType(), Core::union));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package io.ballerina.runtime.internal.types;

import io.ballerina.runtime.api.types.semtype.Context;
import io.ballerina.runtime.api.types.semtype.SemType;

import java.util.Optional;

/**
* Any {@code Type} that contains selectively immutable types must implement this interface. It represents the type
* against which {@code isLikeType} operation is performed.
*/
public interface TypeWithAcceptedType {

Optional<SemType> acceptedTypeOf(Context cx);
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,11 @@
* different objects should be able to do their shape calculations in a non-blocking manner, even when they share the
* same instance of {@code TypeWithShape}.
*/
public interface TypeWithShape {
public interface TypeWithShape extends TypeWithAcceptedType {

Optional<SemType> inherentTypeOf(Context cx, ShapeSupplier shapeSupplierFn, Object object);

Optional<SemType> shapeOf(Context cx, ShapeSupplier shapeSupplierFn, Object object);

Optional<SemType> acceptedTypeOf(Context cx);

boolean couldInherentTypeBeDifferent();
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

import static io.ballerina.runtime.internal.types.semtype.CellAtomicType.CellMutability.CELL_MUT_LIMITED;
import static io.ballerina.runtime.internal.types.semtype.CellAtomicType.CellMutability.CELL_MUT_NONE;
import static io.ballerina.runtime.internal.types.semtype.CellAtomicType.CellMutability.CELL_MUT_UNLIMITED;

public final class TableUtils {

Expand All @@ -39,7 +40,16 @@ public final class TableUtils {
private TableUtils() {
}

public static SemType acceptedTypeContainingKeySpecifier(Context cx, SemType tableConstraint, String[] fieldNames) {
return tableContainingKeySpecifierInner(fieldNames, cx, tableConstraint, CELL_MUT_UNLIMITED);
}

public static SemType tableContainingKeySpecifier(Context cx, SemType tableConstraint, String[] fieldNames) {
return tableContainingKeySpecifierInner(fieldNames, cx, tableConstraint, CELL_MUT_LIMITED);
}

private static SemType tableContainingKeySpecifierInner(String[] fieldNames, Context cx, SemType tableConstraint,
CellAtomicType.CellMutability cellMutLimited) {
SemType[] fieldNameSingletons = new SemType[fieldNames.length];
SemType[] fieldTypes = new SemType[fieldNames.length];
for (int i = 0; i < fieldNames.length; i++) {
Expand All @@ -55,10 +65,20 @@ public static SemType tableContainingKeySpecifier(Context cx, SemType tableConst
SemType normalizedKc = fieldNames.length > 1 ? new ListDefinition().defineListTypeWrapped(cx.env, fieldTypes,
fieldTypes.length, Builder.neverType(), CELL_MUT_NONE) : fieldTypes[0];

return tableContaining(cx.env, tableConstraint, normalizedKc, normalizedKs, CELL_MUT_LIMITED);
return tableContaining(cx.env, tableConstraint, normalizedKc, normalizedKs, cellMutLimited);
}

public static SemType acceptedTypeContainingKeyConstraint(Context cx, SemType tableConstraint,
SemType keyConstraint) {
return tableContainingKeyConstraintInner(cx, tableConstraint, keyConstraint, CELL_MUT_UNLIMITED);
}

public static SemType tableContainingKeyConstraint(Context cx, SemType tableConstraint, SemType keyConstraint) {
return tableContainingKeyConstraintInner(cx, tableConstraint, keyConstraint, CELL_MUT_LIMITED);
}

private static SemType tableContainingKeyConstraintInner(Context cx, SemType tableConstraint, SemType keyConstraint,
CellAtomicType.CellMutability mut) {
Optional<ListAtomicType> lat = Core.listAtomicType(cx, keyConstraint);
SemType normalizedKc = lat.map(atom -> {
FixedLengthArray member = atom.members();
Expand All @@ -68,13 +88,17 @@ public static SemType tableContainingKeyConstraint(Context cx, SemType tableCons
default -> keyConstraint;
};
}).orElse(keyConstraint);
return tableContaining(cx.env, tableConstraint, normalizedKc, Builder.getValType(), CELL_MUT_LIMITED);
return tableContaining(cx.env, tableConstraint, normalizedKc, Builder.getValType(), mut);
}

public static SemType tableContaining(Env env, SemType tableConstraint) {
return tableContaining(env, tableConstraint, CELL_MUT_LIMITED);
}

public static SemType acceptedType(Env env, SemType tableConstraint) {
return tableContaining(env, tableConstraint, CELL_MUT_UNLIMITED);
}

private static SemType tableContaining(Env env, SemType tableConstraint, CellAtomicType.CellMutability mut) {
return tableContaining(env, tableConstraint, Builder.getValType(), Builder.getValType(), mut);
}
Expand Down

0 comments on commit 5a76fb0

Please sign in to comment.