diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/BIRGen.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/BIRGen.java index 1fa4d0f83db3..c12f323d9c0e 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/BIRGen.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/bir/BIRGen.java @@ -22,6 +22,7 @@ import io.ballerina.tools.diagnostics.Location; import io.ballerina.tools.text.LinePosition; import io.ballerina.tools.text.LineRange; +import io.ballerina.types.PredefinedType; import org.ballerinalang.model.TreeBuilder; import org.ballerinalang.model.elements.Flag; import org.ballerinalang.model.elements.PackageID; @@ -59,6 +60,7 @@ import org.wso2.ballerinalang.compiler.bir.model.VarScope; import org.wso2.ballerinalang.compiler.bir.optimizer.BIROptimizer; import org.wso2.ballerinalang.compiler.diagnostic.BLangDiagnosticLocation; +import org.wso2.ballerinalang.compiler.semantics.analyzer.SemTypeHelper; import org.wso2.ballerinalang.compiler.semantics.analyzer.Types; import org.wso2.ballerinalang.compiler.semantics.model.SymbolTable; import org.wso2.ballerinalang.compiler.semantics.model.symbols.BAnnotationSymbol; @@ -2801,10 +2803,7 @@ private void generateMappingAccess(BLangIndexBasedAccess astIndexBasedAccessExpr if (astIndexBasedAccessExpr.getKind() == NodeKind.XML_ATTRIBUTE_ACCESS_EXPR) { insKind = InstructionKind.XML_ATTRIBUTE_STORE; keyRegIndex = getQNameOP(astIndexBasedAccessExpr.indexExpr, keyRegIndex); - } else if (astAccessExprExprType.tag == TypeTags.OBJECT || - (astAccessExprExprType.tag == TypeTags.UNION && - Types.getImpliedType(((BUnionType) astAccessExprExprType).getMemberTypes().iterator() - .next()).tag == TypeTags.OBJECT)) { + } else if (SemTypeHelper.isSubtypeSimple(astAccessExprExprType, PredefinedType.OBJECT)) { insKind = InstructionKind.OBJECT_STORE; } else { insKind = InstructionKind.MAP_STORE; @@ -2833,10 +2832,7 @@ private void generateMappingAccess(BLangIndexBasedAccess astIndexBasedAccessExpr keyRegIndex); this.varAssignment = false; return; - } else if (astAccessExprExprType.tag == TypeTags.OBJECT || - (astAccessExprExprType.tag == TypeTags.UNION && - Types.getImpliedType(((BUnionType) astAccessExprExprType).getMemberTypes().iterator() - .next()).tag == TypeTags.OBJECT)) { + } else if (SemTypeHelper.isSubtypeSimple(astAccessExprExprType, PredefinedType.OBJECT)) { insKind = InstructionKind.OBJECT_LOAD; } else { insKind = InstructionKind.MAP_LOAD; diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/SemTypeHelper.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/SemTypeHelper.java index bee32420fa7b..71014a7c0403 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/SemTypeHelper.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/SemTypeHelper.java @@ -114,6 +114,21 @@ public static boolean isSubtypeSimple(BType bt, BasicTypeBitSet bbs) { return SemTypes.isSubtypeSimple(t, bbs); } + public static boolean isSubtypeSimpleNotNever(BType bt, BasicTypeBitSet bbs) { + SemType t = SemTypeHelper.semType(bt); + return SemTypes.isSubtypeSimpleNotNever(t, bbs); + } + + public static boolean containsBasicType(BType bt, BasicTypeBitSet bbs) { + SemType t = SemTypeHelper.semType(bt); + return SemTypes.containsBasicType(t, bbs); + } + + public static boolean containsType(Context ctx, BType bt, SemType bbs) { + SemType t = SemTypeHelper.semType(bt); + return SemTypes.containsType(ctx, t, bbs); + } + public static boolean isSubtype(Context context, BType bt, SemType st) { SemType s = SemTypeHelper.semType(bt); return SemTypes.isSubtype(context, s, st); diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/SymbolResolver.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/SymbolResolver.java index 072944f3bc70..933271878cbd 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/SymbolResolver.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/SymbolResolver.java @@ -19,6 +19,7 @@ import io.ballerina.tools.diagnostics.DiagnosticCode; import io.ballerina.tools.diagnostics.Location; +import io.ballerina.types.PredefinedType; import org.ballerinalang.model.TreeBuilder; import org.ballerinalang.model.elements.AttachPoint; import org.ballerinalang.model.elements.Flag; @@ -1551,32 +1552,11 @@ public BType transform(BLangConstrainedType constrainedTypeNode, AnalyzerData da } public void validateXMLConstraintType(BType type, Location pos) { - BType constraintType = Types.getImpliedType(type); - int constrainedTag = constraintType.tag; - - if (constrainedTag == TypeTags.UNION) { - checkUnionTypeForXMLSubTypes((BUnionType) constraintType, pos); - return; - } - - if (!TypeTags.isXMLTypeTag(constrainedTag) && constrainedTag != TypeTags.NEVER) { + if (!SemTypeHelper.isSubtypeSimple(type, PredefinedType.XML)) { dlog.error(pos, DiagnosticErrorCode.INCOMPATIBLE_TYPE_CONSTRAINT, symTable.xmlType, type); } } - private void checkUnionTypeForXMLSubTypes(BUnionType constraintUnionType, Location pos) { - for (BType memberType : constraintUnionType.getMemberTypes()) { - memberType = Types.getImpliedType(memberType); - if (memberType.tag == TypeTags.UNION) { - checkUnionTypeForXMLSubTypes((BUnionType) memberType, pos); - } - if (!TypeTags.isXMLTypeTag(memberType.tag)) { - dlog.error(pos, DiagnosticErrorCode.INCOMPATIBLE_TYPE_CONSTRAINT, symTable.xmlType, - constraintUnionType); - } - } - } - @Override public BType transform(BLangUserDefinedType userDefinedTypeNode, AnalyzerData data) { String name = userDefinedTypeNode.typeName.value; diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/Types.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/Types.java index 0be710b8cdc5..c8c107228b2a 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/Types.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/analyzer/Types.java @@ -389,7 +389,7 @@ public SemType anydata() { } public boolean isAnydata(BType type) { - return SemTypeHelper.isSubtype(semTypeCtx, type, Core.createAnydata(semTypeCtx)); + return isSubtype(type, Core.createAnydata(semTypeCtx)); } private boolean isSameType(BType source, BType target, Set unresolvedTypes) { @@ -447,44 +447,15 @@ boolean finiteTypeContainsNumericTypeValues(BFiniteType finiteType) { } public boolean containsErrorType(BType bType) { - BType type = getImpliedType(bType); - if (type.tag == TypeTags.UNION) { - return ((BUnionType) type).getMemberTypes().stream() - .anyMatch(this::containsErrorType); - } - - if (type.tag == TypeTags.READONLY) { - return true; - } - - return type.tag == TypeTags.ERROR; + return SemTypeHelper.containsBasicType(bType, PredefinedType.ERROR); } public boolean containsNilType(BType bType) { - BType type = getImpliedType(bType); - if (type.tag == TypeTags.UNION) { - for (BType memberType : ((BUnionType) type).getMemberTypes()) { - if (containsNilType(memberType)) { - return true; - } - } - return false; - } - - if (type.tag == TypeTags.READONLY) { - return true; - } - - return type.tag == TypeTags.NIL; + return SemTypeHelper.containsBasicType(bType, PredefinedType.NIL); } public boolean isSubTypeOfList(BType bType) { - BType type = getImpliedType(bType); - if (type.tag != TypeTags.UNION) { - return isSubTypeOfBaseType(type, TypeTags.ARRAY) || isSubTypeOfBaseType(type, TypeTags.TUPLE); - } - - return ((BUnionType) type).getMemberTypes().stream().allMatch(this::isSubTypeOfList); + return SemTypeHelper.isSubtypeSimpleNotNever(bType, PredefinedType.LIST); } BType resolvePatternTypeFromMatchExpr(BLangErrorBindingPattern errorBindingPattern, BLangExpression matchExpr, @@ -715,31 +686,11 @@ public BType resolvePatternTypeFromMatchExpr(BLangMappingBindingPattern mappingB } private boolean containsAnyType(BType type) { - type = getImpliedType(type); - if (type.tag != TypeTags.UNION) { - return type.tag == TypeTags.ANY; - } - - for (BType memberTypes : ((BUnionType) type).getMemberTypes()) { - if (getImpliedType(memberTypes).tag == TypeTags.ANY) { - return true; - } - } - return false; + return SemTypeHelper.containsType(semTypeCtx, type, PredefinedType.ANY); } private boolean containsAnyDataType(BType type) { - type = getImpliedType(type); - if (type.tag != TypeTags.UNION) { - return type.tag == TypeTags.ANYDATA; - } - - for (BType memberTypes : ((BUnionType) type).getMemberTypes()) { - if (getImpliedType(memberTypes).tag == TypeTags.ANYDATA) { - return true; - } - } - return false; + return SemTypeHelper.containsType(semTypeCtx, type, Core.createAnydata(semTypeCtx)); } BType mergeTypes(BType typeFirst, BType typeSecond) { @@ -762,11 +713,7 @@ BType mergeTypes(BType typeFirst, BType typeSecond) { } public boolean isSubTypeOfMapping(BType bType) { - BType type = getImpliedType(bType); - if (type.tag != TypeTags.UNION) { - return isSubTypeOfBaseType(type, TypeTags.MAP) || isSubTypeOfBaseType(type, TypeTags.RECORD); - } - return ((BUnionType) type).getMemberTypes().stream().allMatch(this::isSubTypeOfMapping); + return SemTypeHelper.isSubtypeSimpleNotNever(bType, PredefinedType.MAPPING); } public boolean isSubTypeOfBaseType(BType bType, int baseTypeTag) { @@ -839,6 +786,10 @@ public boolean isSubtype(SemType t1, SemType t2) { return SemTypes.isSubtype(semTypeCtx, t1, t2); } + public boolean isSubtype(BType t1, SemType t2) { + return SemTypeHelper.isSubtype(semTypeCtx, t1, t2); + } + BField getTableConstraintField(BType constraintType, String fieldName) { constraintType = getImpliedType(constraintType); switch (constraintType.tag) { @@ -2111,7 +2062,7 @@ boolean isNumericConversionPossible(BLangExpression expr, BType sourceType, } public boolean isAllErrorMembers(BUnionType actualType) { - return actualType.getMemberTypes().stream().allMatch(t -> isAssignable(t, symTable.errorType)); + return isSubtype(actualType, PredefinedType.ERROR); } public void setImplicitCastExpr(BLangExpression expr, BType actualType, BType targetType) { @@ -3456,51 +3407,13 @@ boolean validNumericTypeExists(BType type) { } boolean validIntegerTypeExists(BType bType) { - BType type = getImpliedType(bType); - if (type.isNullable() && type.tag != TypeTags.NIL) { - type = getSafeType(type, true, false); - } - if (TypeTags.isIntegerTypeTag(type.tag)) { - return true; - } - switch (type.tag) { - case TypeTags.BYTE: - return true; - case TypeTags.UNION: - LinkedHashSet memberTypes = ((BUnionType) type).getMemberTypes(); - for (BType memberType : memberTypes) { - memberType = getImpliedType(memberType); - if (!validIntegerTypeExists(memberType)) { - return false; - } - } - return true; - case TypeTags.FINITE: - return !Core.isEmpty(semTypeCtx, SemTypes.intersect(type.semType(), PredefinedType.INT)); - default: - return false; - } + SemType s = SemTypeHelper.semType(bType); + s = Core.diff(s, PredefinedType.NIL); // nil lift + return SemTypes.isSubtypeSimpleNotNever(s, PredefinedType.INT); } public boolean isStringSubType(BType type) { - type = getImpliedType(type); - if (TypeTags.isStringTypeTag(type.tag)) { - return true; - } - switch (type.tag) { - case TypeTags.UNION: - for (BType memType : ((BUnionType) type).getMemberTypes()) { - if (!isStringSubType(memType)) { - return false; - } - } - return true; - case TypeTags.FINITE: - SemType semType = type.semType(); - return SemTypes.isSubtype(semTypeCtx, semType, PredefinedType.STRING); - default: - return false; - } + return SemTypeHelper.isSubtypeSimpleNotNever(type, PredefinedType.STRING); } /** @@ -5055,13 +4968,8 @@ public boolean isSubTypeOfErrorOrNilContainingNil(BUnionType type) { return false; } - for (BType memType : type.getMemberTypes()) { - BType referredMemType = getImpliedType(memType); - if (referredMemType.tag != TypeTags.NIL && referredMemType.tag != TypeTags.ERROR) { - return false; - } - } - return true; + BasicTypeBitSet nilOrError = (BasicTypeBitSet) Core.union(PredefinedType.NIL, PredefinedType.ERROR); + return SemTypeHelper.isSubtypeSimpleNotNever(type, nilOrError); } /** @@ -5420,24 +5328,8 @@ public BType findCompatibleType(BType type) { } public boolean isNonNilSimpleBasicTypeOrString(BType bType) { - BType type = getImpliedType(bType); - if (type.tag == TypeTags.UNION) { - Set memberTypes = ((BUnionType) type).getMemberTypes(); - for (BType member : memberTypes) { - BType memType = getImpliedType(member); - if (memType.tag == TypeTags.FINITE || memType.tag == TypeTags.UNION) { - isNonNilSimpleBasicTypeOrString(memType); - continue; - } - if (memType.tag == TypeTags.NIL || !isSimpleBasicType(memType.tag)) { - return false; - } - } - return true; - } else if (type.tag == TypeTags.FINITE) { - return !type.isNullable(); - } - return type.tag != TypeTags.NIL && isSimpleBasicType(type.tag); + return SemTypeHelper.isSubtypeSimpleNotNever(bType, + (BasicTypeBitSet) Core.diff(PredefinedType.SIMPLE_OR_STRING, PredefinedType.NIL)); } public boolean isSubTypeOfReadOnlyOrIsolatedObjectUnion(BType bType) { @@ -5563,14 +5455,7 @@ boolean isNeverTypeOrStructureTypeWithARequiredNeverMember(BType type, Set memberTypes = ((BUnionType) type).getMemberTypes(); - return memberTypes.stream().allMatch(this::isNeverType); - } - return false; + return Core.isNever(SemTypeHelper.semType(type)); } boolean isSingletonType(BType bType) { diff --git a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BUnionType.java b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BUnionType.java index 8d8c28e0dab8..0da37c556c46 100644 --- a/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BUnionType.java +++ b/compiler/ballerina-lang/src/main/java/org/wso2/ballerinalang/compiler/semantics/model/types/BUnionType.java @@ -55,8 +55,6 @@ public class BUnionType extends BType implements UnionType { protected LinkedHashSet memberTypes; public LinkedHashSet memberSemTypes; - public Boolean isAnyData = null; - public Boolean isPureType = null; public boolean isCyclic = false; diff --git a/semtypes/src/main/java/io/ballerina/types/SemTypes.java b/semtypes/src/main/java/io/ballerina/types/SemTypes.java index 2601dda9c64d..037c9deac740 100644 --- a/semtypes/src/main/java/io/ballerina/types/SemTypes.java +++ b/semtypes/src/main/java/io/ballerina/types/SemTypes.java @@ -105,10 +105,18 @@ public static boolean isSubtypeSimple(SemType t1, BasicTypeBitSet t2) { return Core.isSubtypeSimple(t1, t2); } + public static boolean isSubtypeSimpleNotNever(SemType t1, BasicTypeBitSet t2) { + return !Core.isNever(t1) && Core.isSubtypeSimple(t1, t2); + } + public static boolean containsBasicType(SemType t1, BasicTypeBitSet t2) { return (Core.widenToBasicTypes(t1).bitset & t2.bitset) != 0; } + public static boolean containsType(Context context, SemType type, SemType typeToBeContained) { + return Core.isSameType(context, Core.intersect(type, typeToBeContained), typeToBeContained); + } + public static boolean isSameType(Context context, SemType t1, SemType t2) { return Core.isSameType(context, t1, t2); }