diff --git a/ets2panda/bindings/src/generated/Es2pandaEnums.ts b/ets2panda/bindings/src/generated/Es2pandaEnums.ts index 5638cddfaff08abd6bb89807cd16965825611186..b7bd7000ff2e9815c9807ee1986195c0b8f1a244 100644 --- a/ets2panda/bindings/src/generated/Es2pandaEnums.ts +++ b/ets2panda/bindings/src/generated/Es2pandaEnums.ts @@ -71,19 +71,19 @@ export enum Es2pandaId { export enum Es2pandaCheckerStatus { CHECKER_STATUS_NO_OPTS = 0, - CHECKER_STATUS_FORCE_TUPLE = 1, - CHECKER_STATUS_IN_CONST_CONTEXT = 2, - CHECKER_STATUS_KEEP_LITERAL_TYPE = 4, - CHECKER_STATUS_IN_PARAMETER = 8, - CHECKER_STATUS_IN_CLASS = 16, - CHECKER_STATUS_IN_INTERFACE = 32, - CHECKER_STATUS_IN_ABSTRACT = 64, - CHECKER_STATUS_IN_STATIC_CONTEXT = 128, - CHECKER_STATUS_IN_CONSTRUCTOR = 256, - CHECKER_STATUS_IN_STATIC_BLOCK = 512, - CHECKER_STATUS_INNER_CLASS = 1024, - CHECKER_STATUS_IN_ENUM = 2048, - CHECKER_STATUS_BUILTINS_INITIALIZED = 4096, + CHECKER_STATUS_BUILTINS_INITIALIZED = 1, + CHECKER_STATUS_FORCE_TUPLE = 2, + CHECKER_STATUS_IN_CONST_CONTEXT = 4, + CHECKER_STATUS_KEEP_LITERAL_TYPE = 8, + CHECKER_STATUS_IN_PARAMETER = 16, + CHECKER_STATUS_IN_CLASS = 32, + CHECKER_STATUS_IN_INTERFACE = 64, + CHECKER_STATUS_IN_ABSTRACT = 128, + CHECKER_STATUS_IN_STATIC_CONTEXT = 256, + CHECKER_STATUS_IN_CONSTRUCTOR = 512, + CHECKER_STATUS_IN_STATIC_BLOCK = 1024, + CHECKER_STATUS_INNER_CLASS = 2048, + CHECKER_STATUS_IN_ENUM = 4096, CHECKER_STATUS_IN_LAMBDA = 8192, CHECKER_STATUS_IGNORE_VISIBILITY = 16384, CHECKER_STATUS_IN_INSTANCE_EXTENSION_METHOD = 32768, diff --git a/ets2panda/checker/ETSAnalyzer.cpp b/ets2panda/checker/ETSAnalyzer.cpp index ca365e2a61a38520779e0572b1f9310578e60b12..bd5c95be85067c6ff0b3e833240682ff9fa89db0 100644 --- a/ets2panda/checker/ETSAnalyzer.cpp +++ b/ets2panda/checker/ETSAnalyzer.cpp @@ -3662,6 +3662,7 @@ checker::Type *ETSAnalyzer::Check(ir::TSQualifiedName *expr) const checker::Type *ETSAnalyzer::Check(ir::TSTypeAliasDeclaration *st) const { ETSChecker *checker = GetETSChecker(); + auto checkerContext = SavedCheckerContext(checker, CheckerStatus::NO_OPTS, checker->Context().ContainingClass()); checker->CheckAnnotations(st->Annotations()); diff --git a/ets2panda/checker/checker.h b/ets2panda/checker/checker.h index e3ae34e68457fba2aecfd8671fb7601dfa4fb0cc..1dbf5c12f4393298e7bd47fde7b291e09e0682ac 100644 --- a/ets2panda/checker/checker.h +++ b/ets2panda/checker/checker.h @@ -407,7 +407,8 @@ public: : checker_(checker), prev_(checker->context_) { const bool inExternal = checker->HasStatus(CheckerStatus::IN_EXTERNAL); - checker_->context_ = CheckerContext(checker, newStatus, containingClass, containingSignature); + auto stickies = CheckerStatus(checker_->context_.Status() & CheckerStatus::STICKY_FLAGS); + checker_->context_ = CheckerContext(checker, newStatus | stickies, containingClass, containingSignature); if (inExternal) { // handled here instead of at call sites to make things more foolproof checker_->context_.Status() |= CheckerStatus::IN_EXTERNAL; diff --git a/ets2panda/checker/checkerContext.h b/ets2panda/checker/checkerContext.h index aa5e6b26fcdbad5213fec9eecbe6e003013339d3..d369ead3a350ce3daaf1eace101979344c121122 100644 --- a/ets2panda/checker/checkerContext.h +++ b/ets2panda/checker/checkerContext.h @@ -47,19 +47,19 @@ using ENUMBITOPS_OPERATORS; enum class CheckerStatus : uint32_t { NO_OPTS = 0U, - FORCE_TUPLE = 1U << 0U, - IN_CONST_CONTEXT = 1U << 1U, - KEEP_LITERAL_TYPE = 1U << 2U, - IN_PARAMETER = 1U << 3U, - IN_CLASS = 1U << 4U, - IN_INTERFACE = 1U << 5U, - IN_ABSTRACT = 1U << 6U, - IN_STATIC_CONTEXT = 1U << 7U, - IN_CONSTRUCTOR = 1U << 8U, - IN_STATIC_BLOCK = 1U << 9U, - INNER_CLASS = 1U << 10U, - IN_ENUM = 1U << 11U, - BUILTINS_INITIALIZED = 1U << 12U, + BUILTINS_INITIALIZED = 1U << 0U, + FORCE_TUPLE = 1U << 1U, + IN_CONST_CONTEXT = 1U << 2U, + KEEP_LITERAL_TYPE = 1U << 3U, + IN_PARAMETER = 1U << 4U, + IN_CLASS = 1U << 5U, + IN_INTERFACE = 1U << 6U, + IN_ABSTRACT = 1U << 7U, + IN_STATIC_CONTEXT = 1U << 8U, + IN_CONSTRUCTOR = 1U << 9U, + IN_STATIC_BLOCK = 1U << 10U, + INNER_CLASS = 1U << 11U, + IN_ENUM = 1U << 12U, IN_LAMBDA = 1U << 13U, IGNORE_VISIBILITY = 1U << 14U, IN_EXTENSION_METHOD = 1U << 15U, @@ -77,6 +77,9 @@ enum class CheckerStatus : uint32_t { IN_SETTER = 1U << 27U, IN_EXTENSION_ACCESSOR_CHECK = 1U << 28U, IN_TYPE_INFER = 1U << 29U, + + // This status flag should never be removed once set. + STICKY_FLAGS = BUILTINS_INITIALIZED, }; } // namespace ark::es2panda::checker @@ -150,6 +153,11 @@ public: return status_; } + [[nodiscard]] CheckerStatus &Status() noexcept + { + return status_; + } + [[nodiscard]] ETSObjectType *ContainingClass() const noexcept { return const_cast(containingClass_); @@ -160,11 +168,6 @@ public: return containingSignature_; } - [[nodiscard]] CheckerStatus &Status() noexcept - { - return status_; - } - void SetContainingSignature(Signature *containingSignature) noexcept { containingSignature_ = containingSignature; diff --git a/ets2panda/checker/ets/object.cpp b/ets2panda/checker/ets/object.cpp index f3c52febcb5f7a8b3148660ee9b89a3bea289fcf..810d01985cf51c3cec806256ee7df794e48d498a 100644 --- a/ets2panda/checker/ets/object.cpp +++ b/ets2panda/checker/ets/object.cpp @@ -448,6 +448,13 @@ Type *ETSChecker::BuildBasicInterfaceProperties(ir::TSInterfaceDeclaration *inte type = Program()->IsDeclForDynamicStaticInterop() ? CreateGradualType(interfaceType) : interfaceType; } + // Save before we mess with savedContext. + bool builtinsInitialized = HasStatus(CheckerStatus::BUILTINS_INITIALIZED); + + auto *enclosingClass = Context().ContainingClass(); + interfaceType->SetEnclosingType(enclosingClass); + CheckerStatus newStatus = CheckerStatus::IN_INTERFACE; + auto savedContext = checker::SavedCheckerContext(this, newStatus, interfaceType); ConstraintCheckScope ctScope(this); if (interfaceDecl->TypeParams() != nullptr) { interfaceType->AddTypeFlag(TypeFlag::GENERIC); @@ -461,7 +468,7 @@ Type *ETSChecker::BuildBasicInterfaceProperties(ir::TSInterfaceDeclaration *inte // Skip this check if the builtins are not initialized. // They will be initialized in different order, // and it is possible that the FunctionType interface is not yet created. - if (HasStatus(CheckerStatus::BUILTINS_INITIALIZED)) { + if (builtinsInitialized) { CheckInterfaceFunctions(interfaceType); } diff --git a/ets2panda/test/runtime/ets/27016.ets b/ets2panda/test/runtime/ets/27016.ets new file mode 100644 index 0000000000000000000000000000000000000000..fa618d9c23fac39e4b9f405c613162f09efed707 --- /dev/null +++ b/ets2panda/test/runtime/ets/27016.ets @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class NNBB { + static f(a: Object) { + return a instanceof B + } +} + +interface A { + get(): TA +} +interface B extends A { +} + +class D implements B { + constructor(d: TD) { + this.d = d + } + get(): TD { + return this.d + } + d: TD +} + +function main() { + let a: A = new D(5) + arktest.assertEQ(a.get(), 5) +} diff --git a/ets2panda/test/runtime/ets/27016_2.ets b/ets2panda/test/runtime/ets/27016_2.ets new file mode 100644 index 0000000000000000000000000000000000000000..9e95ee41cde0499d6e3bc43b90dc4dcd155cd602 --- /dev/null +++ b/ets2panda/test/runtime/ets/27016_2.ets @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class A { + f(b: object) { + b instanceof B + let c: B = {v: 1} + return c + } +} + +type B = C + +interface C { + v: T +} + +function main() { + let a = new A + arktest.assertEQ(a.f(a).v, 1) +} diff --git a/ets2panda/util/perfMetrics.cpp b/ets2panda/util/perfMetrics.cpp index 981ec934c40d631b1461b4f71c4f1e24e5b40a8e..91cbcbe7a536141f9e3d465f76ae9396d573ee02 100644 --- a/ets2panda/util/perfMetrics.cpp +++ b/ets2panda/util/perfMetrics.cpp @@ -18,6 +18,7 @@ #include "libpandabase/utils/logger.h" #include "libpandabase/utils/type_converter.h" #include "libpandabase/mem/mem.h" +#include #include #include #include