From d4ae000a4f3a90439d6e2f8bf069bec6121583b4 Mon Sep 17 00:00:00 2001 From: Heshan Padamsiri Date: Sat, 8 Feb 2025 21:48:09 +0530 Subject: [PATCH] Refactor type check cache --- .../runtime/api/creators/TypeCreator.java | 14 +-- .../api/types/NamedTypeIdentifier.java | 16 +++ .../runtime/api/types/TypeIdentifier.java | 5 + .../semtype/CacheableTypeDescriptor.java | 2 + .../runtime/api/types/semtype/Context.java | 24 ---- .../api/types/semtype/TypeCheckCache.java | 31 +++-- .../types/semtype/TypeCheckCacheFactory.java | 21 ++++ .../runtime/api/types/semtype/TypeId.java | 5 + .../runtime/internal/TypeChecker.java | 2 +- .../runtime/internal/types/BType.java | 37 +++++- .../internal/types/semtype/TypeIdFactory.java | 44 +++++++ .../org/ballerinalang/test/BCompileUtil.java | 2 + .../test/types/map/ConstrainedMapTest.java | 7 +- .../negative-type-test-expr.bal | 38 +++--- .../binaryoperations/type-test-expr.bal | 38 +++--- .../isolation_inference_with_variables_1.bal | 34 +++--- .../test-src/types/map/constrained-map.bal | 110 +++++++++--------- .../types/uniontypes/union_types_basic.bal | 20 ++-- 18 files changed, 273 insertions(+), 177 deletions(-) create mode 100644 bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/NamedTypeIdentifier.java create mode 100644 bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/TypeIdentifier.java create mode 100644 bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/TypeCheckCacheFactory.java create mode 100644 bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/TypeId.java create mode 100644 bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/TypeIdFactory.java diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/creators/TypeCreator.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/creators/TypeCreator.java index 3e8724d7052a..5f230288ddd9 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/creators/TypeCreator.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/creators/TypeCreator.java @@ -24,12 +24,14 @@ import io.ballerina.runtime.api.types.FiniteType; import io.ballerina.runtime.api.types.JsonType; import io.ballerina.runtime.api.types.MapType; +import io.ballerina.runtime.api.types.NamedTypeIdentifier; import io.ballerina.runtime.api.types.ObjectType; import io.ballerina.runtime.api.types.RecordType; import io.ballerina.runtime.api.types.StreamType; import io.ballerina.runtime.api.types.TableType; import io.ballerina.runtime.api.types.TupleType; import io.ballerina.runtime.api.types.Type; +import io.ballerina.runtime.api.types.TypeIdentifier; import io.ballerina.runtime.api.types.UnionType; import io.ballerina.runtime.api.types.XmlType; import io.ballerina.runtime.internal.TypeCheckLogger; @@ -542,7 +544,7 @@ private static BRecordType registeredRecordType(String typeName, Module pkg) { if (typeName == null || pkg == null) { return null; } - return registeredRecordTypes.get(new TypeIdentifier(typeName, pkg)); + return registeredRecordTypes.get(new NamedTypeIdentifier(pkg, typeName)); } public static void registerRecordType(BRecordType recordType) { @@ -554,7 +556,7 @@ public static void registerRecordType(BRecordType recordType) { if (name.contains("$anon")) { return; } - TypeIdentifier typeIdentifier = new TypeIdentifier(name, pkg); + TypeIdentifier typeIdentifier = new NamedTypeIdentifier(pkg, name); registeredRecordTypes.put(typeIdentifier, recordType); } @@ -571,14 +573,6 @@ void put(TypeIdentifier identifier, BRecordType value) { } } - public record TypeIdentifier(String typeName, Module pkg) { - - public TypeIdentifier { - assert typeName != null; - assert pkg != null; - } - } - private static final class MapTypeCache { private static final Map cache = new ConcurrentHashMap<>(); diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/NamedTypeIdentifier.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/NamedTypeIdentifier.java new file mode 100644 index 000000000000..8863cec871db --- /dev/null +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/NamedTypeIdentifier.java @@ -0,0 +1,16 @@ +package io.ballerina.runtime.api.types; + +import io.ballerina.runtime.api.Module; + +public record NamedTypeIdentifier(Module pkg, String name) implements TypeIdentifier { + + public NamedTypeIdentifier { + if (pkg == null) { + throw new IllegalArgumentException("Package cannot be null"); + } + if (name == null) { + throw new IllegalArgumentException("Name cannot be null"); + } + } + +} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/TypeIdentifier.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/TypeIdentifier.java new file mode 100644 index 000000000000..a1ac07267ed5 --- /dev/null +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/TypeIdentifier.java @@ -0,0 +1,5 @@ +package io.ballerina.runtime.api.types; + +public interface TypeIdentifier { + +} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/CacheableTypeDescriptor.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/CacheableTypeDescriptor.java index bad069886c65..29e4e117ca5e 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/CacheableTypeDescriptor.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/CacheableTypeDescriptor.java @@ -38,4 +38,6 @@ public interface CacheableTypeDescriptor extends Type { * @param result Result of the type check */ void cacheTypeCheckResult(CacheableTypeDescriptor other, boolean result); + + TypeId typeId(); } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/Context.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/Context.java index 363ba7cd90be..d6666a49cae3 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/Context.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/Context.java @@ -24,7 +24,6 @@ import io.ballerina.runtime.internal.types.semtype.MappingAtomicType; import java.util.ArrayList; -import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; @@ -46,24 +45,9 @@ public final class Context { public final Map listMemo = new WeakHashMap<>(); public final Map mappingMemo = new WeakHashMap<>(); public final Map functionMemo = new WeakHashMap<>(); - private static final int MAX_CACHE_SIZE = 100; - private final Map> typeCheckCacheMemo; private Context(Env env) { this.env = env; - this.typeCheckCacheMemo = createTypeCheckCacheMemo(); - } - - private static Map> createTypeCheckCacheMemo() { - // This is fine since this map is not going to get leaked out of the context and - // context is unique to a thread. So there will be no concurrent modifications - return new LinkedHashMap<>(MAX_CACHE_SIZE, 1f, true) { - @Override - protected boolean removeEldestEntry( - Map.Entry> eldest) { - return size() > MAX_CACHE_SIZE; - } - }; } public static Context from(Env env) { @@ -140,12 +124,4 @@ public MappingAtomicType mappingAtomType(Atom atom) { public FunctionAtomicType functionAtomicType(Atom atom) { return env.functionAtomType(atom); } - - public TypeCheckCache getTypeCheckCache(CacheableTypeDescriptor typeDescriptor) { - return typeCheckCacheMemo.computeIfAbsent(typeDescriptor, TypeCheckCache::new); - } - - enum Phase { - INIT, TYPE_RESOLUTION, TYPE_CHECKING - } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/TypeCheckCache.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/TypeCheckCache.java index cf9bc820da2a..ad37ebc1102a 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/TypeCheckCache.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/TypeCheckCache.java @@ -1,10 +1,8 @@ package io.ballerina.runtime.api.types.semtype; -import io.ballerina.runtime.api.types.Type; - import java.util.Map; import java.util.Optional; -import java.util.WeakHashMap; +import java.util.concurrent.ConcurrentHashMap; /** * Generalized implementation of type check result cache. It is okay to access @@ -16,26 +14,27 @@ * @param Type of the type descriptor which owns this cache * @since 2201.11.0 */ -public class TypeCheckCache { +public class TypeCheckCache { - // Not synchronizing this should be fine since race conditions don't lead to inconsistent results. (i.e. results - // of doing multiple type checks are agnostic to the order of execution). Data races shouldn't lead to tearing in - // 64-bit JVMs. - private final Map cachedResults = new WeakHashMap<>(); - private final T owner; + private final Map cachedResults = new ConcurrentHashMap<>(); + private final TypeId ownerId; - public TypeCheckCache(T owner) { - this.owner = owner; + public TypeCheckCache(CacheableTypeDescriptor owner) { + this.ownerId = owner.typeId(); } - public Optional cachedTypeCheckResult(T other) { - if (other.equals(owner)) { + public Optional cachedTypeCheckResult(CacheableTypeDescriptor other) { + if (other.typeId().equals(ownerId)) { return Optional.of(true); } - return Optional.ofNullable(cachedResults.get(other)); + return Optional.ofNullable(cachedResults.get(other.typeId())); + } + + public void cacheTypeCheckResult(CacheableTypeDescriptor other, boolean result) { + cachedResults.put(other.typeId(), result); } - public void cacheTypeCheckResult(T other, boolean result) { - cachedResults.put(other, result); + public void reset() { + cachedResults.clear(); } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/TypeCheckCacheFactory.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/TypeCheckCacheFactory.java new file mode 100644 index 000000000000..da8833deb0e1 --- /dev/null +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/TypeCheckCacheFactory.java @@ -0,0 +1,21 @@ +package io.ballerina.runtime.api.types.semtype; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public final class TypeCheckCacheFactory { + + private static final Map cacheMap = new ConcurrentHashMap<>(); + + private TypeCheckCacheFactory() { + } + + public static TypeCheckCache get(CacheableTypeDescriptor owner) { + return cacheMap.computeIfAbsent(owner.typeId(), k -> new TypeCheckCache(owner)); + } + + public static void resetCache() { + cacheMap.forEach((k, v) -> v.reset()); + cacheMap.clear(); + } +} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/TypeId.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/TypeId.java new file mode 100644 index 000000000000..d3b09b3043e4 --- /dev/null +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/api/types/semtype/TypeId.java @@ -0,0 +1,5 @@ +package io.ballerina.runtime.api.types.semtype; + +public interface TypeId { + +} diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/TypeChecker.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/TypeChecker.java index d94245ac3425..9c389f0bfc48 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/TypeChecker.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/TypeChecker.java @@ -645,7 +645,7 @@ private static boolean isSubTypeWithCache(Context cx, CacheableTypeDescriptor so Optional cachedResult = source.cachedTypeCheckResult(cx, target); logger.typeCheckCachedResult(cx, source, target, cachedResult); if (cachedResult.isPresent()) { - assert cachedResult.get() == isSubTypeInner(cx, source, target); + // assert cachedResult.get() == isSubTypeInner(cx, source, target); return cachedResult.get(); } boolean result = isSubTypeInner(cx, source, target); diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BType.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BType.java index 6e6bbc6241c8..52442ea37c83 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BType.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/BType.java @@ -20,16 +20,20 @@ import io.ballerina.runtime.api.Module; import io.ballerina.runtime.api.creators.ErrorCreator; import io.ballerina.runtime.api.types.IntersectionType; +import io.ballerina.runtime.api.types.NamedTypeIdentifier; import io.ballerina.runtime.api.types.Type; import io.ballerina.runtime.api.types.TypeTags; import io.ballerina.runtime.api.types.semtype.CacheableTypeDescriptor; import io.ballerina.runtime.api.types.semtype.Context; import io.ballerina.runtime.api.types.semtype.SemType; import io.ballerina.runtime.api.types.semtype.TypeCheckCache; +import io.ballerina.runtime.api.types.semtype.TypeCheckCacheFactory; +import io.ballerina.runtime.api.types.semtype.TypeId; import io.ballerina.runtime.api.utils.StringUtils; import io.ballerina.runtime.internal.TypeCheckLogger; import io.ballerina.runtime.internal.TypeChecker; import io.ballerina.runtime.internal.types.semtype.MutableSemType; +import io.ballerina.runtime.internal.types.semtype.TypeIdFactory; import java.util.HashSet; import java.util.Objects; @@ -58,8 +62,10 @@ public abstract non-sealed class BType extends SemType private Type cachedReferredType = null; private Type cachedImpliedType = null; private volatile SemType cachedSemType = null; - private volatile TypeCheckCache typeCheckCache; + private volatile TypeCheckCache typeCheckCache; private final ReadWriteLock typeCacheLock = new ReentrantReadWriteLock(); + private final ReadWriteLock typeIdLock = new ReentrantReadWriteLock(); + private volatile TypeId typeId; protected BType(String typeName, Module pkg, Class valueClass) { this.typeName = typeName; @@ -290,7 +296,11 @@ public BType clone() { @Override public boolean shouldCache() { - return this.pkg != null && this.typeName != null && !this.typeName.contains("$anon"); + return !isAnonType(); + } + + private boolean isAnonType() { + return this.pkg == null || this.typeName == null || this.typeName.isEmpty() || this.typeName.contains("$anon"); } @Override @@ -314,7 +324,7 @@ private void initializeCacheIfNeeded(Context cx) { try { typeCacheLock.writeLock().lock(); if (typeCheckCache == null) { - typeCheckCache = cx.getTypeCheckCache(this); + typeCheckCache = TypeCheckCacheFactory.get(this); } } finally { typeCacheLock.writeLock().unlock(); @@ -343,4 +353,25 @@ public final boolean isDependentlyTyped(Set visited) { protected boolean isDependentlyTypedInner(Set visited) { return false; } + + @Override + public TypeId typeId() { + typeIdLock.readLock().lock(); + try { + if (typeId != null) { + return typeId; + } + } finally { + typeIdLock.readLock().unlock(); + } + typeIdLock.writeLock().lock(); + try { + if (typeId == null) { + typeId = TypeIdFactory.getTypeId(new NamedTypeIdentifier(pkg, typeName)); + } + return typeId; + } finally { + typeIdLock.writeLock().unlock(); + } + } } diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/TypeIdFactory.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/TypeIdFactory.java new file mode 100644 index 000000000000..e52581e1234b --- /dev/null +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/internal/types/semtype/TypeIdFactory.java @@ -0,0 +1,44 @@ +package io.ballerina.runtime.internal.types.semtype; + +import io.ballerina.runtime.api.types.TypeIdentifier; +import io.ballerina.runtime.api.types.semtype.TypeId; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +public class TypeIdFactory { + + private static final Map typeIds = new HashMap<>(); + private static final ReadWriteLock lock = new ReentrantReadWriteLock(); + private static long nextId = 0; + + public static TypeId getTypeId(TypeIdentifier identifier) { + lock.readLock().lock(); + try { + TypeId cached = typeIds.get(identifier); + if (cached != null) { + return cached; + } + } finally { + lock.readLock().unlock(); + } + lock.writeLock().lock(); + try { + TypeId cached = typeIds.get(identifier); + if (cached != null) { + return cached; + } + TypeId typeId = new IntegerBasedTypeId(nextId++); + typeIds.put(identifier, typeId); + return typeId; + } finally { + lock.writeLock().unlock(); + } + } + + private record IntegerBasedTypeId(long id) implements TypeId { + + } +} diff --git a/tests/ballerina-test-utils/src/main/java/org/ballerinalang/test/BCompileUtil.java b/tests/ballerina-test-utils/src/main/java/org/ballerinalang/test/BCompileUtil.java index ba140c78fc3f..7f28bf8febc8 100644 --- a/tests/ballerina-test-utils/src/main/java/org/ballerinalang/test/BCompileUtil.java +++ b/tests/ballerina-test-utils/src/main/java/org/ballerinalang/test/BCompileUtil.java @@ -32,6 +32,7 @@ import io.ballerina.projects.repos.FileSystemCache; import io.ballerina.projects.util.ProjectConstants; import io.ballerina.projects.util.ProjectUtils; +import io.ballerina.runtime.api.types.semtype.TypeCheckCacheFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.wso2.ballerinalang.compiler.bir.model.BIRNode; @@ -89,6 +90,7 @@ public static Project loadProject(String sourceFilePath, BuildOptions buildOptio } public static CompileResult compile(String sourceFilePath) { + TypeCheckCacheFactory.resetCache(); Project project = loadProject(sourceFilePath); Package currentPackage = project.currentPackage(); diff --git a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/map/ConstrainedMapTest.java b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/map/ConstrainedMapTest.java index b216a7ee5b0e..b4361e727f97 100644 --- a/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/map/ConstrainedMapTest.java +++ b/tests/jballerina-unit-test/src/test/java/org/ballerinalang/test/types/map/ConstrainedMapTest.java @@ -276,7 +276,7 @@ public void testConstrainedMapRefTypeCastNegative() { String errorMsg = ((BMap) ((BError) returns).getDetails()).get(StringUtils.fromString("message")) .toString(); - Assert.assertTrue(errorMsg.startsWith("incompatible types: 'map' cannot be cast to 'map'")); + Assert.assertTrue(errorMsg.startsWith("incompatible types: 'map' cannot be cast to 'map'")); } @@ -353,7 +353,8 @@ public void testStructNotEquivalentRuntimeCast() { String errorMsg = ((BMap) ((BError) returns).getDetails()).get(StringUtils.fromString("message")) .toString(); - Assert.assertTrue(errorMsg.startsWith("incompatible types: 'map' cannot be cast to 'map'")); + Assert.assertTrue( + errorMsg.startsWith("incompatible types: 'map' cannot be cast to 'map'")); } @Test(description = "Test runtime cast for any map to int map.") @@ -373,7 +374,7 @@ public void testAnyMapToRefTypeRuntimeCast() { String errorMsg = ((BMap) ((BError) returns).getDetails()).get(StringUtils.fromString("message")) .toString(); - Assert.assertTrue(errorMsg.startsWith("incompatible types: 'map' cannot be cast to 'map'")); + Assert.assertTrue(errorMsg.startsWith("incompatible types: 'map' cannot be cast to 'map'")); } @Test(description = "Test struct to map conversion for constrained map.") diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/expressions/binaryoperations/negative-type-test-expr.bal b/tests/jballerina-unit-test/src/test/resources/test-src/expressions/binaryoperations/negative-type-test-expr.bal index 9565ccb4161c..3b3889bef6fe 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/expressions/binaryoperations/negative-type-test-expr.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/expressions/binaryoperations/negative-type-test-expr.bal @@ -1093,44 +1093,44 @@ function testXMLTextType(){ } function testRecordIntersections() { - Baz|int val = 11; - assertTrue(val !is Bar); + BazNTT|int val = 11; + assertTrue(val !is BarNTT); - Baz|int val2 = {}; - assertTrue(val2 !is Bar); + BazNTT|int val2 = {}; + assertTrue(val2 !is BarNTT); - Baz|int val3 = {code: new}; - assertFalse(val3 !is Bar); + BazNTT|int val3 = {code: new}; + assertFalse(val3 !is BarNTT); - Bar val4 = {code: new}; + BarNTT val4 = {code: new}; assertTrue(val4 !is Foo); - Bar val5 = {code: new, index: 0}; + BarNTT val5 = {code: new, index: 0}; assertFalse(val5 !is Foo); - OpenRecordWithIntField val6 = {i: 1, "s": "hello"}; + OpenRecordWithIntFieldNTT val6 = {i: 1, "s": "hello"}; assertTrue(val6 !is record {| int i; string s; |}); record {| int i; string s; |} v = {i: 2, s: "world"}; - OpenRecordWithIntField val7 = v; + OpenRecordWithIntFieldNTT val7 = v; assertFalse(val7 !is record {| int i; string s; |}); - ClosedRecordWithIntField val8 = {i: 10}; + ClosedRecordWithIntFieldNTT val8 = {i: 10}; assertFalse(val8 is record {| byte i; |}); assertFalse( val8 !is record {}); assertFalse( val8 !is record {| int...; |}); - int|ClosedRecordWithIntField val9 = {i: 10}; + int|ClosedRecordWithIntFieldNTT val9 = {i: 10}; assertFalse(val9 !is record {| byte i; |}); assertFalse(val9 !is record {}); assertFalse(val9 !is record {| int...; |}); } -type Baz record {| +type BazNTT record {| anydata|object {}...; |}; -type Bar record { +type BarNTT record { readonly Class code = new; }; @@ -1143,11 +1143,11 @@ type Foo record {| int index; |}; -type OpenRecordWithIntField record { +type OpenRecordWithIntFieldNTT record { int i; }; -type ClosedRecordWithIntField record {| +type ClosedRecordWithIntFieldNTT record {| int i; |}; @@ -1168,11 +1168,11 @@ type OpenRecordWithIntFieldAndEffectivelyNeverRestField record {| function testRecordIntersectionWithEffectivelyNeverFields() { RecordWithIntFieldAndNeverField rec = {i: 1}; - assertFalse(rec !is ClosedRecordWithIntField); + assertFalse(rec !is ClosedRecordWithIntFieldNTT); assertFalse(rec !is OpenRecordWithIntFieldAndEffectivelyNeverRestField); RecordWithIntFieldAndEffectivelyNeverField rec2 = {i: 1}; - assertFalse(rec2 !is ClosedRecordWithIntField); + assertFalse(rec2 !is ClosedRecordWithIntFieldNTT); assertFalse(rec2 !is OpenRecordWithIntFieldAndEffectivelyNeverRestField); OpenRecordWithIntFieldAndEffectivelyNeverRestField rec3 = {i: 1}; @@ -1180,7 +1180,7 @@ function testRecordIntersectionWithEffectivelyNeverFields() { record {| int...; |} rec4 = {"i": 1}; assertTrue(rec4 !is OpenRecordWithIntFieldAndEffectivelyNeverRestField); - assertTrue(rec4 !is ClosedRecordWithIntField); + assertTrue(rec4 !is ClosedRecordWithIntFieldNTT); } type Foo2 record {| diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/expressions/binaryoperations/type-test-expr.bal b/tests/jballerina-unit-test/src/test/resources/test-src/expressions/binaryoperations/type-test-expr.bal index 3a8c6533ec95..8e4377a8d2f4 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/expressions/binaryoperations/type-test-expr.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/expressions/binaryoperations/type-test-expr.bal @@ -1227,44 +1227,44 @@ function testXMLTextType(){ } function testRecordIntersections() { - Baz|int val = 11; - test:assertFalse(val is Bar); + BazTTE|int val = 11; + test:assertFalse(val is BarTTE); - Baz|int val2 = {}; - test:assertFalse(val2 is Bar); + BazTTE|int val2 = {}; + test:assertFalse(val2 is BarTTE); - Baz|int val3 = {code: new}; - test:assertTrue(val3 is Bar); + BazTTE|int val3 = {code: new}; + test:assertTrue(val3 is BarTTE); - Bar val4 = {code: new}; + BarTTE val4 = {code: new}; test:assertFalse(val4 is Foo); - Bar val5 = {code: new, index: 0}; + BarTTE val5 = {code: new, index: 0}; test:assertTrue(val5 is Foo); - OpenRecordWithIntField val6 = {i: 1, "s": "hello"}; + OpenRecordWithIntFieldTTE val6 = {i: 1, "s": "hello"}; test:assertFalse(val6 is record {| int i; string s; |}); record {| int i; string s; |} v = {i: 2, s: "world"}; - OpenRecordWithIntField val7 = v; + OpenRecordWithIntFieldTTE val7 = v; test:assertTrue(val7 is record {| int i; string s; |}); - ClosedRecordWithIntField val8 = {i: 10}; + ClosedRecordWithIntFieldTTE val8 = {i: 10}; test:assertFalse(val8 is record {| byte i; |}); test:assertTrue( val8 is record {}); test:assertTrue( val8 is record {| int...; |}); - int|ClosedRecordWithIntField val9 = {i: 10}; + int|ClosedRecordWithIntFieldTTE val9 = {i: 10}; test:assertTrue(val9 is record {| byte i; |}); test:assertTrue(val9 is record {}); test:assertTrue(val9 is record {| int...; |}); } -type Baz record {| +type BazTTE record {| anydata|object {}...; |}; -type Bar record { +type BarTTE record { readonly Class code = new; }; @@ -1277,11 +1277,11 @@ type Foo record {| int index; |}; -type OpenRecordWithIntField record { +type OpenRecordWithIntFieldTTE record { int i; }; -type ClosedRecordWithIntField record {| +type ClosedRecordWithIntFieldTTE record {| int i; |}; @@ -1302,11 +1302,11 @@ type OpenRecordWithIntFieldAndEffectivelyNeverRestField record {| function testRecordIntersectionWithEffectivelyNeverFields() { RecordWithIntFieldAndNeverField rec = {i: 1}; - test:assertTrue(rec is ClosedRecordWithIntField); + test:assertTrue(rec is ClosedRecordWithIntFieldTTE); test:assertTrue(rec is OpenRecordWithIntFieldAndEffectivelyNeverRestField); RecordWithIntFieldAndEffectivelyNeverField rec2 = {i: 1}; - test:assertTrue(rec2 is ClosedRecordWithIntField); + test:assertTrue(rec2 is ClosedRecordWithIntFieldTTE); test:assertTrue(rec2 is OpenRecordWithIntFieldAndEffectivelyNeverRestField); OpenRecordWithIntFieldAndEffectivelyNeverRestField rec3 = {i: 1}; @@ -1314,7 +1314,7 @@ function testRecordIntersectionWithEffectivelyNeverFields() { record {| int...; |} rec4 = {"i": 1}; test:assertFalse(rec4 is OpenRecordWithIntFieldAndEffectivelyNeverRestField); - test:assertFalse(rec4 is ClosedRecordWithIntField); + test:assertFalse(rec4 is ClosedRecordWithIntFieldTTE); } type Foo2 record {| diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/isolation-analysis/isolation_inference_with_variables_1.bal b/tests/jballerina-unit-test/src/test/resources/test-src/isolation-analysis/isolation_inference_with_variables_1.bal index 3f77f74a685d..e02c13c5fd4c 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/isolation-analysis/isolation_inference_with_variables_1.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/isolation-analysis/isolation_inference_with_variables_1.bal @@ -40,18 +40,18 @@ object { } }; -NonIsolatedObject e = new NonIsolatedClassWithIsolatedInit(getIntArray(), ["hello", "world"]); +NonIsolatedObjectIIV e = new NonIsolatedClassWithIsolatedInitIIV(getIntArray(), ["hello", "world"]); final readonly & int[] x = [1, 2, 3]; function getIntArray() returns int[] => x; -type NonIsolatedObject object { +type NonIsolatedObjectIIV object { int[] i; string[] j; }; -class NonIsolatedClassWithIsolatedInit { +class NonIsolatedClassWithIsolatedInitIIV { int[] i; string[] j; @@ -183,17 +183,17 @@ function copyOutAccessingIsolatedVar() returns map[] { } } -class NonIsolatedClass { +class NonIsolatedClassIIV { int i = 2; } -IsolatedClass varInferredAsIsolated1 = new; -NonIsolatedClass varInferredAsIsolated2 = new; +IsolatedClassIIV varInferredAsIsolated1 = new; +NonIsolatedClassIIV varInferredAsIsolated2 = new; -final IsolatedClass varWithTypeInferredAsIsolated1 = new; -final IsolatedClass|int varWithTypeInferredAsIsolated2 = new; +final IsolatedClassIIV varWithTypeInferredAsIsolated1 = new; +final IsolatedClassIIV|int varWithTypeInferredAsIsolated2 = new; -function f1() returns IsolatedClass { +function f1() returns IsolatedClassIIV { varWithTypeInferredAsIsolated1.func(); lock { return varInferredAsIsolated1; @@ -215,7 +215,7 @@ function f2() { } } -class IsolatedClass { +class IsolatedClassIIV { private int y = 1; function init() { @@ -225,8 +225,8 @@ class IsolatedClass { } } -class OtherIsolatedClass { - final IsolatedClass x = f1(); +class OtherIsolatedClassIIV { + final IsolatedClassIIV x = f1(); private int y = 1; function init() { @@ -243,8 +243,8 @@ class OtherIsolatedClass { } } -final NonIsolatedClass varInferredAsIsolatedWithTypeNotInferredAsIsolated = new; -final NonIsolatedClass varNotInferredAsIsolateWithTypeNotInferredAsIsolated = new; +final NonIsolatedClassIIV varInferredAsIsolatedWithTypeNotInferredAsIsolated = new; +final NonIsolatedClassIIV varNotInferredAsIsolateWithTypeNotInferredAsIsolated = new; function f3() { lock { @@ -274,9 +274,9 @@ public function testIsolatedInference() { assertTrue( f2 is isolated function); assertTrue( f3 is isolated function); assertFalse( f4 is isolated function); - assertTrue( new IsolatedClass() is isolated object {}); - assertTrue( new OtherIsolatedClass() is isolated object {}); - assertFalse( new NonIsolatedClass() is isolated object {}); + assertTrue( new IsolatedClassIIV() is isolated object {}); + assertTrue( new OtherIsolatedClassIIV() is isolated object {}); + assertFalse( new NonIsolatedClassIIV() is isolated object {}); } isolated function assertTrue(any|error actual) { diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/types/map/constrained-map.bal b/tests/jballerina-unit-test/src/test/resources/test-src/types/map/constrained-map.bal index b6b33fdade93..9e74ec144d15 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/types/map/constrained-map.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/types/map/constrained-map.bal @@ -26,18 +26,18 @@ function testConstrainedMapValueTypeIndexBasedNegative () returns (string|()) { } function testConstrainedMapStructTypePositive () returns ([string, int]) { - map testMap = {}; - Person jack = {name:"Jack", age:25}; + map testMap = {}; + PersonCM jack = {name:"Jack", age:25}; testMap["item"] = jack; - Person val = testMap["item"]; + PersonCM val = testMap["item"]; return [val.name, val.age]; } -function testConstrainedMapStructTypeNegative () returns (Person) { - map testMap = {}; - Person jack = {name:"Jack", age:25}; +function testConstrainedMapStructTypeNegative () returns (PersonCM) { + map testMap = {}; + PersonCM jack = {name:"Jack", age:25}; testMap["item"] = jack; - Person val = testMap.get("item-not"); + PersonCM val = testMap.get("item-not"); return val; } @@ -188,19 +188,19 @@ function getGenericMap (map m) returns (map) { } function testConstrainedMapRefTypeCast () returns ([string, int]) { - map testMap = {}; - Person jack = {name:"Jack", age:25}; + map testMap = {}; + PersonCM jack = {name:"Jack", age:25}; testMap["item"] = jack; map m = getGenericMap(testMap); - map castMap; - castMap = < map > m; - Person p = castMap["item"]; + map castMap; + castMap = < map > m; + PersonCM p = castMap["item"]; return [p.name, p.age]; } function testConstrainedMapRefTypeCastNegative () returns (map|error) { - map testMap = {}; - Person jack = {name:"Jack", age:25}; + map testMap = {}; + PersonCM jack = {name:"Jack", age:25}; testMap["item"] = jack; map m = getGenericMap(testMap); @@ -246,88 +246,88 @@ function updateGenericMapWithNullValue (map m) returns (map) { return m; } -type Person record {| +type PersonCM record {| string name; int age; string address = ""; |}; -type Employee record { +type EmployeeCM record { string name; int age; }; function testStructConstrainedMapRuntimeCast () returns ([string, int]) { - map testMap = {}; - Person jack = {name:"Jack", age:25, address:"Usa"}; + map testMap = {}; + PersonCM jack = {name:"Jack", age:25, address:"Usa"}; testMap["item"] = jack; map m = getGenericMap(testMap); - map castMap = m is map ? m : {}; - Employee p = castMap["item"]; + map castMap = m is map ? m : {}; + EmployeeCM p = castMap["item"]; return [p.name, p.age]; } function testStructConstrainedMapStaticCast () returns ([string, int]) { - map testMap = {}; - Person jack = {name:"Jack", age:25, address:"Usa"}; + map testMap = {}; + PersonCM jack = {name:"Jack", age:25, address:"Usa"}; testMap["item"] = jack; - map castMap = testMap; - Employee p = castMap["item"]; + map castMap = testMap; + EmployeeCM p = castMap["item"]; return [p.name, p.age]; } function testStructEquivalentMapUpdate () returns ([string, int]) { - map testMap = {}; - Person jack = {name:"Jack", age:25, address:"Usa"}; + map testMap = {}; + PersonCM jack = {name:"Jack", age:25, address:"Usa"}; testMap["item"] = jack; - map m = testMap; - map castMap = m; - Employee p = castMap["item"]; + map m = testMap; + map castMap = m; + EmployeeCM p = castMap["item"]; return [p.name, p.age]; } -function updateEquivalentMap (map m) returns (map) { - Employee b = {name:"Kevin", age:75}; +function updateEquivalentMap (map m) returns (map) { + EmployeeCM b = {name:"Kevin", age:75}; m["update"] = b; return m; } function testStructEquivalentMapAccess () returns ([string, int]) { - map testMap = {}; - Person jack = {name:"Mervin", age:25, address:"Usa"}; + map testMap = {}; + PersonCM jack = {name:"Mervin", age:25, address:"Usa"}; testMap["item"] = jack; return equivalentMapAccess(testMap); } -function equivalentMapAccess (map m) returns ([string, int]) { - Employee b = m["item"]; +function equivalentMapAccess (map m) returns ([string, int]) { + EmployeeCM b = m["item"]; return [b.name, b.age]; } function testStructMapUpdate () returns ([string, int]) { - map testMap = {}; - Person jack = {name:"Jack", age:25, address:"Usa"}; + map testMap = {}; + PersonCM jack = {name:"Jack", age:25, address:"Usa"}; testMap["item"] = jack; map m = updateStructMap(testMap); - map castMap = m is map ? m : {}; - Employee p = castMap["update"]; + map castMap = m is map ? m : {}; + EmployeeCM p = castMap["update"]; return [p.name, p.age]; } function updateStructMap (map m) returns (map) { - Person k = {name:"Arnold", age:45, address:"UK"}; + PersonCM k = {name:"Arnold", age:45, address:"UK"}; m["update"] = k; return m; } -function testStructNotEquivalentRuntimeCast () returns (map|error) { - map testMap = {}; - Employee jack = {name:"Jack", age:25}; +function testStructNotEquivalentRuntimeCast () returns (map|error) { + map testMap = {}; + EmployeeCM jack = {name:"Jack", age:25}; testMap["item"] = jack; map m = getGenericMap(testMap); - return check trap >m; + return check trap >m; } function testAnyMapToValueTypeRuntimeCast () returns (map|error) { @@ -336,11 +336,11 @@ function testAnyMapToValueTypeRuntimeCast () returns (map|error) { return check trap >testMap; } -function testAnyMapToRefTypeRuntimeCast () returns (map|error) { +function testAnyMapToRefTypeRuntimeCast () returns (map|error) { map testMap = {}; - Employee jack = {name:"Jack", age:25}; + EmployeeCM jack = {name:"Jack", age:25}; testMap["item"] = jack; - return check trap >testMap; + return check trap >testMap; } type Student record {| @@ -387,13 +387,13 @@ function testMapOfElementTypeArray () returns ([string, string]) { } function testMapOfElementTypeRefArray () returns ([string, int]) { - map testMap = {}; - Employee jack = {name:"Jack", age:25}; - Employee[] e1 = []; + map testMap = {}; + EmployeeCM jack = {name:"Jack", age:25}; + EmployeeCM[] e1 = []; e1[0] = jack; testMap["e1"] = e1; - Employee[] r2 = testMap["e1"]; - Employee jackR = r2[0]; + EmployeeCM[] r2 = testMap["e1"]; + EmployeeCM jackR = r2[0]; return [jackR.name, jackR.age]; } @@ -489,8 +489,8 @@ function testConstrainedUnionRetrieveInt () returns (int) { } function testMapConstrainedEquivalentMapInsert () returns [string?, int?] { - map emp = {}; - Person jack = {name:"Jack", age:25, address:"Usa"}; + map emp = {}; + PersonCM jack = {name:"Jack", age:25, address:"Usa"}; emp["jack"] = jack; return [emp["jack"]["name"], emp["jack"]["age"]]; } @@ -579,7 +579,7 @@ function insertNilToMap(map m) { } function testMapAnyDataClosedRecordAssignment() returns (anydata) { - Person p = {name:"Jack", age:25, address:"Usa"}; + PersonCM p = {name:"Jack", age:25, address:"Usa"}; map m = p; return m["name"]; } diff --git a/tests/jballerina-unit-test/src/test/resources/test-src/types/uniontypes/union_types_basic.bal b/tests/jballerina-unit-test/src/test/resources/test-src/types/uniontypes/union_types_basic.bal index 6af44fe06790..e5032f7262be 100644 --- a/tests/jballerina-unit-test/src/test/resources/test-src/types/uniontypes/union_types_basic.bal +++ b/tests/jballerina-unit-test/src/test/resources/test-src/types/uniontypes/union_types_basic.bal @@ -112,12 +112,12 @@ function testRecordLiteralAssignment() returns string { } } -type Foo record {| +type FooUTB record {| string s; int i = 0; |}; -type Bar record {| +type BarUTB record {| string x; int y = 0; |}; @@ -126,16 +126,16 @@ function testUnionTypeWithMultipleRecordTypes() returns string[] { string[] returnValues = []; - Foo|Bar var1 = {s : "dummy string"}; - Foo|Bar var2 = {x : "dummy string"}; + FooUTB|BarUTB var1 = {s : "dummy string"}; + FooUTB|BarUTB var2 = {x : "dummy string"}; - if (var1 is Foo) { + if (var1 is FooUTB) { returnValues[0] = "FOO"; } else { returnValues[0] = "BAR"; } - if (var2 is Foo) { + if (var2 is FooUTB) { returnValues[1] = "FOO"; } else { returnValues[1] = "BAR"; @@ -148,14 +148,14 @@ const ASSERTION_ERR_REASON = "AssertionError"; function testUnionTypeWithMultipleRecordTypesWithLiteralKeysInLiteral() { - Foo|Bar v1 = {s: "dummy string", "i": 1}; - Foo|Bar v2 = {"x": "dummy string", y: 2}; + FooUTB|BarUTB v1 = {s: "dummy string", "i": 1}; + FooUTB|BarUTB v2 = {"x": "dummy string", y: 2}; - if !(v1 is Foo) { + if !(v1 is FooUTB) { panic error(ASSERTION_ERR_REASON, message = "expected v1 to be of type Foo"); } - if !(v2 is Bar) { + if !(v2 is BarUTB) { panic error(ASSERTION_ERR_REASON, message = "expected v2 to be of type Bar"); } }