diff --git a/ets2panda/checker/ETSchecker.cpp b/ets2panda/checker/ETSchecker.cpp index ce5dd58750cf2af73e27ba167dafc524205d481a..36830c6155627fd285cb71743531dbda1fa0590b 100644 --- a/ets2panda/checker/ETSchecker.cpp +++ b/ets2panda/checker/ETSchecker.cpp @@ -679,9 +679,9 @@ ETSObjectType *ETSChecker::GlobalBuiltinBoxType(Type *contents) return AsETSObjectType(&GlobalTypesHolder::GlobalDoubleBoxBuiltinType); default: { auto *base = AsETSObjectType(&GlobalTypesHolder::GlobalBoxBuiltinType); - auto *substitution = NewSubstitution(); - substitution->emplace(base->TypeArguments()[0]->AsETSTypeParameter(), contents); - return base->Substitute(Relation(), substitution); + auto substitution = Substitution {}; + substitution.emplace(base->TypeArguments()[0]->AsETSTypeParameter(), contents); + return base->Substitute(Relation(), &substitution); } } } diff --git a/ets2panda/checker/ETSchecker.h b/ets2panda/checker/ETSchecker.h index b3ced7b7d372663b02d01071966e28c29a3ef118..978b0b2beed1b92403a6815b076183561f709bea 100644 --- a/ets2panda/checker/ETSchecker.h +++ b/ets2panda/checker/ETSchecker.h @@ -74,7 +74,7 @@ using DynamicLambdaObjectSignatureMap = ArenaUnorderedMap; using TypeMapping = ArenaUnorderedMap; using DynamicCallNamesMap = ArenaMap, uint32_t>; -using ConstraintCheckRecord = std::tuple *, const Substitution *, lexer::SourcePosition>; +using ConstraintCheckRecord = std::tuple *, const Substitution, lexer::SourcePosition>; // can't use util::DiagnosticWithParams because std::optional can't contain references using MaybeDiagnosticInfo = std::optional>; @@ -87,7 +87,6 @@ public: // NOLINTNEXTLINE(readability-redundant-member-init) : Checker(allocator, diagnosticEngine, programAllocator), arrayTypes_(Allocator()->Adapter()), - pendingConstraintCheckRecords_(Allocator()->Adapter()), objectInstantiationMap_(Allocator()->Adapter()), invokeToArrowSignatures_(Allocator()->Adapter()), arrowToFuncInterfaces_(Allocator()->Adapter()), @@ -417,21 +416,20 @@ public: bool CheckLambdaAssignableUnion(ir::AstNode *typeAnn, ir::ScriptFunction *lambda); bool IsCompatibleTypeArgument(ETSTypeParameter *typeParam, Type *typeArgument, const Substitution *substitution); - Substitution *NewSubstitution() + ArenaSubstitution *NewArenaSubstitution() { - return ProgramAllocator()->New(ProgramAllocator()->Adapter()); + return ProgramAllocator()->New(ProgramAllocator()->Adapter()); } - Substitution *CopySubstitution(const Substitution *src) - { - return ProgramAllocator()->New(*src); - } bool ValidateTypeSubstitution(const ArenaVector &typeParams, Type *ctype, Type *argumentType, Substitution *substitution); bool ProcessUntypedParameter(ir::AstNode *declNode, size_t paramIndex, Signature *paramSig, Signature *argSig, Substitution *substitution); + static Substitution ArenaSubstitutionToSubstitution(const ArenaSubstitution *orig); void EmplaceSubstituted(Substitution *substitution, ETSTypeParameter *tparam, Type *typeArg); + void EmplaceSubstituted(ArenaSubstitution *substitution, ETSTypeParameter *tparam, Type *typeArg); + [[nodiscard]] bool EnhanceSubstitutionForType(const ArenaVector &typeParams, Type *paramType, Type *argumentType, Substitution *substitution); [[nodiscard]] bool EnhanceSubstitutionForReadonly(const ArenaVector &typeParams, ETSReadonlyType *paramType, @@ -830,7 +828,7 @@ public: return util::NodeAllocator::ForceSetParent(ProgramAllocator(), std::forward(args)...); } - ArenaVector &PendingConstraintCheckRecords(); + std::vector &PendingConstraintCheckRecords(); size_t &ConstraintCheckScopesCount(); ETSObjectType *GetCachedFunctionalInterface(ir::ETSFunctionType *type); @@ -1053,7 +1051,7 @@ private: std::unordered_set &typeAliases); ArrayMap arrayTypes_; - ArenaVector pendingConstraintCheckRecords_; + std::vector pendingConstraintCheckRecords_ {}; ObjectInstantiationMap objectInstantiationMap_; FunctionSignatureMap invokeToArrowSignatures_; FunctionInterfaceMap arrowToFuncInterfaces_; diff --git a/ets2panda/checker/TSchecker.h b/ets2panda/checker/TSchecker.h index 4d360a1f4fa9a948ca4eace745779c1adb8b7aaf..77756cb4891aa666dcdf36041f559260a12ff917 100644 --- a/ets2panda/checker/TSchecker.h +++ b/ets2panda/checker/TSchecker.h @@ -101,7 +101,7 @@ class TSMethodSignature; class ChainExpression; class VariableDeclarator; -enum class AstNodeType; +enum class AstNodeType : uint8_t; } // namespace ark::es2panda::ir namespace ark::es2panda::checker { diff --git a/ets2panda/checker/checker.h b/ets2panda/checker/checker.h index c41af2dbd818e3aa0df7266e0b115847fb411979..ce3672522a65f76f10158ee76019eecf051438c3 100644 --- a/ets2panda/checker/checker.h +++ b/ets2panda/checker/checker.h @@ -33,7 +33,7 @@ namespace ark::es2panda::ir { class AstNode; class Expression; class BlockStatement; -enum class AstNodeType; +enum class AstNodeType : uint8_t; } // namespace ark::es2panda::ir namespace ark::es2panda::varbinder { diff --git a/ets2panda/checker/ets/assignAnalyzer.cpp b/ets2panda/checker/ets/assignAnalyzer.cpp index 8b29b6e855f4fd3acb58d88e3409dcc3758e3a40..bbc3f6aa283e574a2b643b0ac5410c48c018dcbf 100644 --- a/ets2panda/checker/ets/assignAnalyzer.cpp +++ b/ets2panda/checker/ets/assignAnalyzer.cpp @@ -1212,7 +1212,7 @@ util::StringView AssignAnalyzer::GetVariableName(const ir::AstNode *node) const } } -const lexer::SourcePosition &AssignAnalyzer::GetVariablePosition(const ir::AstNode *node) const +lexer::SourcePosition AssignAnalyzer::GetVariablePosition(const ir::AstNode *node) const { switch (node->Type()) { case ir::AstNodeType::CLASS_PROPERTY: @@ -1394,7 +1394,7 @@ void AssignAnalyzer::LetInit(const ir::AstNode *node) // check reassignment of readonly properties util::StringView type = GetVariableType(declNode); util::StringView name = GetVariableName(declNode); - const lexer::SourcePosition &pos = GetVariablePosition(node); + const lexer::SourcePosition pos = GetVariablePosition(node); auto uninit = [this](NodeId a) { uninits_.Excl(a); @@ -1459,7 +1459,7 @@ void AssignAnalyzer::CheckInit(const ir::AstNode *node) util::StringView type = GetVariableType(declNode); util::StringView name = GetVariableName(declNode); - const lexer::SourcePosition &pos = GetVariablePosition(node); + const lexer::SourcePosition pos = GetVariablePosition(node); std::stringstream ss; if (node->IsClassProperty()) { diff --git a/ets2panda/checker/ets/assignAnalyzer.h b/ets2panda/checker/ets/assignAnalyzer.h index 621a24ba9e18239450879b044fd7fa70b0bf1823..c5004e5fae3e216dadfdda8282fd03dfb64ad9d6 100644 --- a/ets2panda/checker/ets/assignAnalyzer.h +++ b/ets2panda/checker/ets/assignAnalyzer.h @@ -150,7 +150,7 @@ private: NodeId GetNodeId(const ir::AstNode *node) const; util::StringView GetVariableType(const ir::AstNode *node) const; util::StringView GetVariableName(const ir::AstNode *node) const; - const lexer::SourcePosition &GetVariablePosition(const ir::AstNode *node) const; + lexer::SourcePosition GetVariablePosition(const ir::AstNode *node) const; const ir::AstNode *GetDeclaringNode(const ir::AstNode *node); varbinder::Variable *GetBoundVariable(const ir::AstNode *node); bool VariableHasDefaultValue(const ir::AstNode *node); diff --git a/ets2panda/checker/ets/baseAnalyzer.h b/ets2panda/checker/ets/baseAnalyzer.h index 8599c5d00a4cf3d9ed0b8b8b11b719a40f323683..93ed62e4836982c61eb7fce7ea3387956c0408d1 100644 --- a/ets2panda/checker/ets/baseAnalyzer.h +++ b/ets2panda/checker/ets/baseAnalyzer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-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 @@ -21,7 +21,7 @@ namespace ark::es2panda::ir { class AstNode; -enum class AstNodeType; +enum class AstNodeType : uint8_t; } // namespace ark::es2panda::ir namespace ark::es2panda::checker { diff --git a/ets2panda/checker/ets/function.cpp b/ets2panda/checker/ets/function.cpp index ea80a961c377bad8c0774150bebde324fc61cc1b..22f1c94672ee59da68944b5fef8c27d3f81db994 100644 --- a/ets2panda/checker/ets/function.cpp +++ b/ets2panda/checker/ets/function.cpp @@ -1815,14 +1815,14 @@ Signature *ETSChecker::AdjustForTypeParameters(Signature *source, Signature *tar if (sourceTypeParams.empty()) { return target; } - auto *substitution = NewSubstitution(); + auto substitution = Substitution {}; for (size_t ix = 0; ix < sourceTypeParams.size(); ix++) { if (!targetTypeParams[ix]->IsETSTypeParameter()) { continue; } - EmplaceSubstituted(substitution, targetTypeParams[ix]->AsETSTypeParameter(), sourceTypeParams[ix]); + EmplaceSubstituted(&substitution, targetTypeParams[ix]->AsETSTypeParameter(), sourceTypeParams[ix]); } - return target->Substitute(Relation(), substitution); + return target->Substitute(Relation(), &substitution); } void ETSChecker::ReportOverrideError(Signature *signature, Signature *overriddenSignature, @@ -2432,7 +2432,7 @@ void ETSChecker::CollectReturnStatements(ir::AstNode *parent) }); } -ArenaVector &ETSChecker::PendingConstraintCheckRecords() +std::vector &ETSChecker::PendingConstraintCheckRecords() { return pendingConstraintCheckRecords_; } diff --git a/ets2panda/checker/ets/function_helpers.h b/ets2panda/checker/ets/function_helpers.h index 2ed4c6b430b254b5237d17726eaa2200711f2c37..c4803d3dd896e27239b8844a6bf467821b768e44 100644 --- a/ets2panda/checker/ets/function_helpers.h +++ b/ets2panda/checker/ets/function_helpers.h @@ -116,56 +116,56 @@ static void InferUntilFail(Signature const *const signature, const ArenaVectorRemoveStatus(checker::CheckerStatus::IN_TYPE_INFER); } -static const Substitution *BuildImplicitSubstitutionForArguments(ETSChecker *checker, Signature *signature, - const ArenaVector &arguments) +static std::optional BuildImplicitSubstitutionForArguments(ETSChecker *checker, Signature *signature, + const ArenaVector &arguments) { - Substitution *substitution = checker->NewSubstitution(); + auto substitution = Substitution {}; auto *sigInfo = signature->GetSignatureInfo(); auto &sigParams = signature->GetSignatureInfo()->typeParams; - InferUntilFail(signature, arguments, checker, substitution); + InferUntilFail(signature, arguments, checker, &substitution); - if (substitution->size() != sigParams.size()) { + if (substitution.size() != sigParams.size()) { for (const auto typeParam : sigParams) { auto newTypeParam = typeParam->AsETSTypeParameter(); - if (auto it = substitution->find(newTypeParam); it != substitution->cend()) { + if (auto it = substitution.find(newTypeParam); it != substitution.cend()) { continue; } if (newTypeParam->GetDefaultType() == nullptr) { - checker->EmplaceSubstituted(substitution, newTypeParam, checker->GlobalETSNeverType()); + checker->EmplaceSubstituted(&substitution, newTypeParam, checker->GlobalETSNeverType()); continue; } - auto dflt = newTypeParam->GetDefaultType()->Substitute(checker->Relation(), substitution); - if (!checker->EnhanceSubstitutionForType(sigInfo->typeParams, newTypeParam, dflt, substitution)) { - return nullptr; + auto dflt = newTypeParam->GetDefaultType()->Substitute(checker->Relation(), &substitution); + if (!checker->EnhanceSubstitutionForType(sigInfo->typeParams, newTypeParam, dflt, &substitution)) { + return std::nullopt; } } } - if (substitution->size() != sigParams.size() && + if (substitution.size() != sigParams.size() && (signature->Function()->ReturnTypeAnnotation() == nullptr || !checker->EnhanceSubstitutionForType(sigInfo->typeParams, signature->Function()->ReturnTypeAnnotation()->TsType(), - signature->ReturnType(), substitution))) { - return nullptr; + signature->ReturnType(), &substitution))) { + return std::nullopt; } return substitution; } -static const Substitution *BuildExplicitSubstitutionForArguments(ETSChecker *checker, Signature *signature, - const ArenaVector ¶ms, - const lexer::SourcePosition &pos, - TypeRelationFlag flags) +static std::optional BuildExplicitSubstitutionForArguments(ETSChecker *checker, Signature *signature, + const ArenaVector ¶ms, + const lexer::SourcePosition &pos, + TypeRelationFlag flags) { auto &sigParams = signature->GetSignatureInfo()->typeParams; - auto *substitution = checker->NewSubstitution(); - auto *constraintsSubstitution = checker->NewSubstitution(); + auto substitution = Substitution {}; + auto constraintsSubstitution = Substitution {}; ArenaVector instArgs {checker->Allocator()->Adapter()}; for (size_t ix = 0; ix < params.size(); ++ix) { instArgs.push_back(MaybeBoxedType(checker, params[ix]->GetType(checker), params[ix])); if (ix < sigParams.size()) { - checker->EmplaceSubstituted(constraintsSubstitution, sigParams[ix]->AsETSTypeParameter(), instArgs[ix]); + checker->EmplaceSubstituted(&constraintsSubstitution, sigParams[ix]->AsETSTypeParameter(), instArgs[ix]); } } for (size_t ix = instArgs.size(); ix < sigParams.size(); ++ix) { @@ -174,23 +174,23 @@ static const Substitution *BuildExplicitSubstitutionForArguments(ETSChecker *che break; } - dflt = dflt->Substitute(checker->Relation(), constraintsSubstitution); + dflt = dflt->Substitute(checker->Relation(), &constraintsSubstitution); instArgs.push_back(dflt); - checker->EmplaceSubstituted(constraintsSubstitution, sigParams[ix]->AsETSTypeParameter(), instArgs[ix]); + checker->EmplaceSubstituted(&constraintsSubstitution, sigParams[ix]->AsETSTypeParameter(), instArgs[ix]); } if (sigParams.size() != instArgs.size()) { if ((flags & TypeRelationFlag::NO_THROW) == static_cast>(0U)) { checker->LogError(diagnostic::RTYPE_PARAM_COUNT_MISMATCH, {sigParams.size(), instArgs.size()}, pos); } - return nullptr; + return std::nullopt; } for (size_t ix = 0; ix < sigParams.size(); ix++) { if (!checker->IsCompatibleTypeArgument(sigParams[ix]->AsETSTypeParameter(), instArgs[ix], - constraintsSubstitution)) { - return nullptr; + &constraintsSubstitution)) { + return std::nullopt; } - checker->EmplaceSubstituted(substitution, sigParams[ix]->AsETSTypeParameter(), instArgs[ix]); + checker->EmplaceSubstituted(&substitution, sigParams[ix]->AsETSTypeParameter(), instArgs[ix]); } return substitution; } @@ -204,12 +204,12 @@ static Signature *MaybeSubstituteTypeParameters(ETSChecker *checker, Signature * return signature; } - const Substitution *substitution = + const std::optional substitution = (typeArguments != nullptr) ? BuildExplicitSubstitutionForArguments(checker, signature, typeArguments->Params(), pos, flags) : BuildImplicitSubstitutionForArguments(checker, signature, arguments); - return (substitution == nullptr) ? nullptr : signature->Substitute(checker->Relation(), substitution); + return (!substitution.has_value()) ? nullptr : signature->Substitute(checker->Relation(), &substitution.value()); } static bool CheckInterfaceOverride(ETSChecker *const checker, ETSObjectType *const interface, diff --git a/ets2panda/checker/ets/helpers.cpp b/ets2panda/checker/ets/helpers.cpp index 553abd66e2047e601d4e4440b62db65fc8eadec5..2d284a52d0cdb8acb5c41c3d66f89c35fa3dd538 100644 --- a/ets2panda/checker/ets/helpers.cpp +++ b/ets2panda/checker/ets/helpers.cpp @@ -1576,14 +1576,14 @@ Type *ETSChecker::HandleTypeAlias(ir::Expression *const name, const ir::TSTypePa // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) Type *const aliasType = GetReferencedTypeBase(name); - auto *substitution = NewSubstitution(); + auto substitution = Substitution {}; if (CheckMinimumTypeArgsPresent(typeAliasNode, typeParams)) { return GlobalTypeError(); } std::set parametersNeedToBeBoxed; - auto expandedAliasType = aliasType->Substitute(Relation(), substitution); + auto expandedAliasType = aliasType->Substitute(Relation(), &substitution); CollectAliasParametersForBoxing(expandedAliasType, parametersNeedToBeBoxed, false); for (std::size_t idx = 0; idx < typeAliasNode->TypeParams()->Params().size(); ++idx) { @@ -1601,13 +1601,13 @@ Type *ETSChecker::HandleTypeAlias(ir::Expression *const name, const ir::TSTypePa paramType = boxedType; } } - substitution->insert({typeAliasType->AsETSTypeParameter(), paramType}); // #21835: type argument is not boxed + substitution.insert({typeAliasType->AsETSTypeParameter(), paramType}); // #21835: type argument is not boxed } // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) ValidateGenericTypeAliasForClonedNode(typeAliasNode->AsTSTypeAliasDeclaration(), typeParams); - return aliasType->Substitute(Relation(), substitution); + return aliasType->Substitute(Relation(), &substitution); } std::vector ETSChecker::GetNameForSynteticObjectType(const util::StringView &source) @@ -2289,6 +2289,13 @@ ETSObjectType *ETSChecker::GetRelevantArgumentedTypeFromChild(ETSObjectType *con return GetRelevantArgumentedTypeFromChild(child->SuperType(), target); } +Substitution ETSChecker::ArenaSubstitutionToSubstitution(const ArenaSubstitution *orig) +{ + Substitution copied {}; + std::copy(orig->begin(), orig->end(), std::inserter(copied, copied.end())); + return copied; +} + void ETSChecker::EmplaceSubstituted(Substitution *substitution, ETSTypeParameter *tparam, Type *typeArg) { // *only* reference type may be substituted, no exceptions @@ -2296,6 +2303,13 @@ void ETSChecker::EmplaceSubstituted(Substitution *substitution, ETSTypeParameter substitution->emplace(tparam, typeArg); } +void ETSChecker::EmplaceSubstituted(ArenaSubstitution *substitution, ETSTypeParameter *tparam, Type *typeArg) +{ + // *only* reference type may be substituted, no exceptions + ES2PANDA_ASSERT(typeArg->IsETSReferenceType()); + substitution->emplace(tparam, typeArg); +} + util::StringView ETSChecker::GetHashFromTypeArguments(const ArenaVector &typeArgTypes) { std::stringstream ss; diff --git a/ets2panda/checker/ets/typeCreation.cpp b/ets2panda/checker/ets/typeCreation.cpp index 1c8c6c9a98910a1e00c65c7f932c68aaca91f26f..8b6d09ef64068c587391e35af20fc75497529f6f 100644 --- a/ets2panda/checker/ets/typeCreation.cpp +++ b/ets2panda/checker/ets/typeCreation.cpp @@ -84,10 +84,10 @@ ETSResizableArrayType *ETSChecker::CreateETSMultiDimResizableArrayType(Type *ele Type *baseArrayType = element; for (size_t dim = 0; dim < dimSize; ++dim) { - Substitution *tmpSubstitution = NewSubstitution(); - EmplaceSubstituted(tmpSubstitution, arrayType->TypeArguments()[0]->AsETSTypeParameter()->GetOriginal(), + auto tmpSubstitution = Substitution {}; + EmplaceSubstituted(&tmpSubstitution, arrayType->TypeArguments()[0]->AsETSTypeParameter()->GetOriginal(), MaybeBoxType(baseArrayType)); - baseArrayType = arrayType->Substitute(Relation(), tmpSubstitution); + baseArrayType = arrayType->Substitute(Relation(), &tmpSubstitution); } return baseArrayType->AsETSResizableArrayType(); } @@ -97,10 +97,10 @@ ETSResizableArrayType *ETSChecker::CreateETSResizableArrayType(Type *element) ETSResizableArrayType *arrayType = GlobalBuiltinETSResizableArrayType()->AsETSResizableArrayType(); ES2PANDA_ASSERT(arrayType->TypeArguments().size() == 1U); - Substitution *substitution = NewSubstitution(); - EmplaceSubstituted(substitution, arrayType->TypeArguments()[0]->AsETSTypeParameter()->GetOriginal(), + auto substitution = Substitution {}; + EmplaceSubstituted(&substitution, arrayType->TypeArguments()[0]->AsETSTypeParameter()->GetOriginal(), MaybeBoxType(element)); - return arrayType->Substitute(Relation(), substitution); + return arrayType->Substitute(Relation(), &substitution); } ETSArrayType *ETSChecker::CreateETSArrayType(Type *elementType, bool isCachePolluting) @@ -402,10 +402,10 @@ ETSObjectType *ETSChecker::CreatePromiseOf(Type *type) ETSObjectType *const promiseType = GlobalBuiltinPromiseType(); ES2PANDA_ASSERT(promiseType->TypeArguments().size() == 1U); - Substitution *substitution = NewSubstitution(); - EmplaceSubstituted(substitution, promiseType->TypeArguments()[0]->AsETSTypeParameter()->GetOriginal(), type); + auto substitution = Substitution {}; + EmplaceSubstituted(&substitution, promiseType->TypeArguments()[0]->AsETSTypeParameter()->GetOriginal(), type); - return promiseType->Substitute(Relation(), substitution); + return promiseType->Substitute(Relation(), &substitution); } static bool IsInValidKeyofTypeNode(ir::AstNode *node) diff --git a/ets2panda/checker/ets/typeRelationContext.cpp b/ets2panda/checker/ets/typeRelationContext.cpp index f2aecd19fbb5122d9facfc69dc153844cedf8252..bfcd8ef61af7936503c974f504988e0bee77c4ef 100644 --- a/ets2panda/checker/ets/typeRelationContext.cpp +++ b/ets2panda/checker/ets/typeRelationContext.cpp @@ -137,7 +137,7 @@ void ConstraintCheckScope::TryCheckConstraints() if (Unlock()) { auto &records = checker_->PendingConstraintCheckRecords(); for (auto const &[typeParams, substitution, pos] : records) { - CheckInstantiationConstraints(checker_, *typeParams, substitution, pos); + CheckInstantiationConstraints(checker_, *typeParams, &substitution, pos); } records.clear(); } @@ -153,20 +153,20 @@ void InstantiationContext::InstantiateType(ETSObjectType *type, ArenaVectorNewSubstitution(); + auto substitution = Substitution {}; for (size_t idx = 0; idx < typeParams.size(); idx++) { if (!typeParams[idx]->IsETSTypeParameter()) { continue; } - checker_->EmplaceSubstituted(substitution, typeParams[idx]->AsETSTypeParameter(), typeArgTypes[idx]); + checker_->EmplaceSubstituted(&substitution, typeParams[idx]->AsETSTypeParameter(), typeArgTypes[idx]); } ConstraintCheckScope ctScope(checker_); + result_ = type->Substitute(checker_->Relation(), &substitution)->AsETSObjectType(); if (!checker_->Relation()->NoThrowGenericTypeAlias()) { - checker_->PendingConstraintCheckRecords().push_back({&typeParams, substitution, pos}); + checker_->PendingConstraintCheckRecords().emplace_back(&typeParams, std::move(substitution), pos); } - result_ = type->Substitute(checker_->Relation(), substitution)->AsETSObjectType(); type->InsertInstantiationMap(hash, result_->AsETSObjectType()); result_->AddTypeFlag(TypeFlag::GENERIC); diff --git a/ets2panda/checker/types/ets/etsFunctionType.cpp b/ets2panda/checker/types/ets/etsFunctionType.cpp index d6b776d64c800deb2cbf8058eadc24cf26fc107c..0ec3b4ecaca3259907143dc8f1e7358d05407ff4 100644 --- a/ets2panda/checker/types/ets/etsFunctionType.cpp +++ b/ets2panda/checker/types/ets/etsFunctionType.cpp @@ -74,19 +74,19 @@ static ETSObjectType *FunctionTypeToFunctionalInterfaceType(ETSChecker *checker, if (signature->RestVar() != nullptr) { auto nPosParams = signature->Params().size(); auto *functionN = checker->GlobalBuiltinFunctionType(nPosParams, true)->AsETSObjectType(); - auto *substitution = checker->NewSubstitution(); + auto substitution = Substitution {}; for (size_t i = 0; i < nPosParams; i++) { - substitution->emplace(functionN->TypeArguments()[i]->AsETSTypeParameter(), - checker->MaybeBoxType(signature->Params()[i]->TsType())); + substitution.emplace(functionN->TypeArguments()[i]->AsETSTypeParameter(), + checker->MaybeBoxType(signature->Params()[i]->TsType())); } auto *elementType = !signature->RestVar()->TsType()->IsETSTupleType() ? checker->GetElementTypeOfArray(signature->RestVar()->TsType()) : checker->GlobalETSAnyType(); - substitution->emplace(functionN->TypeArguments()[nPosParams]->AsETSTypeParameter(), - checker->MaybeBoxType(elementType)); - substitution->emplace(functionN->TypeArguments()[nPosParams + 1]->AsETSTypeParameter(), - checker->MaybeBoxType(signature->ReturnType())); - auto result = functionN->Substitute(checker->Relation(), substitution, true, isExtensionHack); + substitution.emplace(functionN->TypeArguments()[nPosParams]->AsETSTypeParameter(), + checker->MaybeBoxType(elementType)); + substitution.emplace(functionN->TypeArguments()[nPosParams + 1]->AsETSTypeParameter(), + checker->MaybeBoxType(signature->ReturnType())); + auto result = functionN->Substitute(checker->Relation(), &substitution, true, isExtensionHack); result->AddObjectFlag(checker::ETSObjectFlags::FUNCTIONAL); return result; } @@ -99,15 +99,15 @@ static ETSObjectType *FunctionTypeToFunctionalInterfaceType(ETSChecker *checker, } auto *funcIface = checker->GlobalBuiltinFunctionType(arity, false)->AsETSObjectType(); - auto *substitution = checker->NewSubstitution(); + auto substitution = Substitution {}; for (size_t i = 0; i < arity; i++) { - substitution->emplace(funcIface->TypeArguments()[i]->AsETSTypeParameter(), - checker->MaybeBoxType(signature->Params()[i]->TsType())); + substitution.emplace(funcIface->TypeArguments()[i]->AsETSTypeParameter(), + checker->MaybeBoxType(signature->Params()[i]->TsType())); } - substitution->emplace(funcIface->TypeArguments()[arity]->AsETSTypeParameter(), - checker->MaybeBoxType(signature->ReturnType())); - auto result = funcIface->Substitute(checker->Relation(), substitution, true, isExtensionHack); + substitution.emplace(funcIface->TypeArguments()[arity]->AsETSTypeParameter(), + checker->MaybeBoxType(signature->ReturnType())); + auto result = funcIface->Substitute(checker->Relation(), &substitution, true, isExtensionHack); if (signature->HasSignatureFlag(SignatureFlags::THIS_RETURN_TYPE)) { HackThisParameterInExtensionFunctionInvoke(result, arity); @@ -179,10 +179,10 @@ static inline void AssertNoMethodsInFunctionRelation([[maybe_unused]] Type *left static Signature *EnhanceSignatureSubstitution(TypeRelation *relation, Signature *super, Signature *sub) { auto checker = relation->GetChecker()->AsETSChecker(); - auto *substitution = checker->NewSubstitution(); + auto substitution = Substitution {}; - auto const enhance = [checker, sub, substitution](Type *param, Type *arg) { - return checker->EnhanceSubstitutionForType(sub->GetSignatureInfo()->typeParams, param, arg, substitution); + auto const enhance = [checker, sub, &substitution](Type *param, Type *arg) { + return checker->EnhanceSubstitutionForType(sub->GetSignatureInfo()->typeParams, param, arg, &substitution); }; for (size_t ix = 0; ix < super->MinArgCount(); ix++) { if (!enhance(sub->GetSignatureInfo()->params[ix]->TsType(), super->GetSignatureInfo()->params[ix]->TsType())) { @@ -194,7 +194,7 @@ static Signature *EnhanceSignatureSubstitution(TypeRelation *relation, Signature return nullptr; } } - return sub->Substitute(relation, substitution); + return sub->Substitute(relation, &substitution); } static uint8_t SignatureThrowKindToOrder(Signature *sig) diff --git a/ets2panda/checker/types/ets/etsObjectType.cpp b/ets2panda/checker/types/ets/etsObjectType.cpp index ace95542ceaa04a6f103ad55cebd1e61ff3ffa0d..2a1169740f150f9035ee5953a91cd4ff96189005 100644 --- a/ets2panda/checker/types/ets/etsObjectType.cpp +++ b/ets2panda/checker/types/ets/etsObjectType.cpp @@ -490,7 +490,8 @@ void ETSObjectType::SubstitutePartialTypes(TypeRelation *relation, Type *other) ES2PANDA_ASSERT(IsPartial()); if ((baseType_->IsGeneric() || baseType_->IsETSTypeParameter()) && effectiveSubstitution_ != nullptr) { - if (auto *newBaseType = baseType_->Substitute(relation, effectiveSubstitution_); + auto subst = ETSChecker::ArenaSubstitutionToSubstitution(effectiveSubstitution_); + if (auto *newBaseType = baseType_->Substitute(relation, &subst); newBaseType->IsETSObjectType() && !relation->IsIdenticalTo(newBaseType, baseType_)) { baseType_ = newBaseType->AsETSObjectType(); } @@ -500,7 +501,8 @@ void ETSObjectType::SubstitutePartialTypes(TypeRelation *relation, Type *other) auto *otherPartial = other->AsETSObjectType(); if ((otherPartial->baseType_->IsGeneric() || otherPartial->baseType_->IsETSTypeParameter()) && otherPartial->effectiveSubstitution_ != nullptr) { - if (auto *newBaseType = otherPartial->baseType_->Substitute(relation, otherPartial->effectiveSubstitution_); + auto subst = ETSChecker::ArenaSubstitutionToSubstitution(otherPartial->effectiveSubstitution_); + if (auto *newBaseType = otherPartial->baseType_->Substitute(relation, &subst); newBaseType->IsETSObjectType() && !relation->IsIdenticalTo(newBaseType, otherPartial->baseType_)) { otherPartial->baseType_ = newBaseType->AsETSObjectType(); } @@ -1079,13 +1081,13 @@ bool ETSObjectType::SubstituteTypeArgs(TypeRelation *const relation, ArenaVector return anyChange; } -static Substitution *ComputeEffectiveSubstitution(TypeRelation *const relation, - const ArenaVector &baseTypeParams, - ArenaVector &newTypeArgs) +static ArenaSubstitution *ComputeEffectiveSubstitution(TypeRelation *const relation, + const ArenaVector &baseTypeParams, + ArenaVector &newTypeArgs) { ES2PANDA_ASSERT(baseTypeParams.size() == newTypeArgs.size()); auto *const checker = relation->GetChecker()->AsETSChecker(); - auto *effectiveSubstitution = checker->NewSubstitution(); + auto *effectiveSubstitution = checker->NewArenaSubstitution(); for (size_t ix = 0; ix < baseTypeParams.size(); ix++) { checker->EmplaceSubstituted(effectiveSubstitution, baseTypeParams[ix]->AsETSTypeParameter(), newTypeArgs[ix]); @@ -1279,16 +1281,16 @@ ETSObjectType *ETSObjectType::SubstituteArguments(TypeRelation *relation, ArenaV } auto *checker = relation->GetChecker()->AsETSChecker(); - auto *substitution = checker->NewSubstitution(); + auto substitution = Substitution {}; ES2PANDA_ASSERT(baseType_ == nullptr); ES2PANDA_ASSERT(typeArguments_.size() == arguments.size()); for (size_t ix = 0; ix < typeArguments_.size(); ix++) { - substitution->emplace(typeArguments_[ix]->AsETSTypeParameter(), checker->MaybeBoxType(arguments[ix])); + substitution.emplace(typeArguments_[ix]->AsETSTypeParameter(), checker->MaybeBoxType(arguments[ix])); } - return Substitute(relation, substitution); + return Substitute(relation, &substitution); } ETSChecker *ETSObjectType::GetETSChecker() @@ -1309,44 +1311,48 @@ void ETSObjectType::InstantiateProperties() const ES2PANDA_ASSERT(!propertiesInstantiated_); declNode_->Check(checker); + auto subst = effectiveSubstitution_ == nullptr + ? Substitution {} + : ETSChecker::ArenaSubstitutionToSubstitution(effectiveSubstitution_); + for (auto *const it : baseType_->ConstructSignatures()) { - auto *newSig = it->Substitute(relation_, effectiveSubstitution_); + auto *newSig = it->Substitute(relation_, &subst); constructSignatures_.push_back(newSig); } for (auto const &[_, prop] : baseType_->InstanceFields()) { (void)_; - auto *copiedProp = CopyPropertyWithTypeArguments(prop, relation_, effectiveSubstitution_); + auto *copiedProp = CopyPropertyWithTypeArguments(prop, relation_, &subst); properties_[static_cast(PropertyType::INSTANCE_FIELD)].emplace(prop->Name(), copiedProp); } for (auto const &[_, prop] : baseType_->StaticFields()) { (void)_; - auto *copiedProp = CopyPropertyWithTypeArguments(prop, relation_, effectiveSubstitution_); + auto *copiedProp = CopyPropertyWithTypeArguments(prop, relation_, &subst); properties_[static_cast(PropertyType::STATIC_FIELD)].emplace(prop->Name(), copiedProp); } for (auto const &[_, prop] : baseType_->InstanceMethods()) { (void)_; - auto *copiedProp = CopyPropertyWithTypeArguments(prop, relation_, effectiveSubstitution_); + auto *copiedProp = CopyPropertyWithTypeArguments(prop, relation_, &subst); properties_[static_cast(PropertyType::INSTANCE_METHOD)].emplace(prop->Name(), copiedProp); } for (auto const &[_, prop] : baseType_->StaticMethods()) { (void)_; - auto *copiedProp = CopyPropertyWithTypeArguments(prop, relation_, effectiveSubstitution_); + auto *copiedProp = CopyPropertyWithTypeArguments(prop, relation_, &subst); properties_[static_cast(PropertyType::STATIC_METHOD)].emplace(prop->Name(), copiedProp); } for (auto const &[_, prop] : baseType_->InstanceDecls()) { (void)_; - auto *copiedProp = CopyPropertyWithTypeArguments(prop, relation_, effectiveSubstitution_); + auto *copiedProp = CopyPropertyWithTypeArguments(prop, relation_, &subst); properties_[static_cast(PropertyType::INSTANCE_DECL)].emplace(prop->Name(), copiedProp); } for (auto const &[_, prop] : baseType_->StaticDecls()) { (void)_; - auto *copiedProp = CopyPropertyWithTypeArguments(prop, relation_, effectiveSubstitution_); + auto *copiedProp = CopyPropertyWithTypeArguments(prop, relation_, &subst); properties_[static_cast(PropertyType::STATIC_DECL)].emplace(prop->Name(), copiedProp); } } diff --git a/ets2panda/checker/types/ets/etsObjectType.h b/ets2panda/checker/types/ets/etsObjectType.h index 5f60a202513851e7544bfdc8579dfeb45a116804..672914ec1cb829fa580189c5013a7acebe4f1a29 100644 --- a/ets2panda/checker/types/ets/etsObjectType.h +++ b/ets2panda/checker/types/ets/etsObjectType.h @@ -462,7 +462,7 @@ private: // for lazy properties instantiation TypeRelation *relation_ = nullptr; - const Substitution *effectiveSubstitution_ = nullptr; + const ArenaSubstitution *effectiveSubstitution_ = nullptr; mutable bool propertiesInstantiated_ = false; mutable ArenaVector constructSignatures_; mutable PropertyHolder properties_; diff --git a/ets2panda/checker/types/ets/etsTypeAliasType.cpp b/ets2panda/checker/types/ets/etsTypeAliasType.cpp index 411b0bbe09f49f9b0f6b77f5f48c6c045bd031c6..5ed633b2b93ef245dc7cbd8d02598d95eba37e51 100644 --- a/ets2panda/checker/types/ets/etsTypeAliasType.cpp +++ b/ets2panda/checker/types/ets/etsTypeAliasType.cpp @@ -280,7 +280,8 @@ void ETSTypeAliasType::ApplySubstitution(TypeRelation *relation) while (!(types = getTypes(), types.empty())) { for (auto type : types) { - type->SetTargetType(type->parent_->targetType_->Substitute(relation, type->substitution_)); + auto subst = ETSChecker::ArenaSubstitutionToSubstitution(type->substitution_); + type->SetTargetType(type->parent_->targetType_->Substitute(relation, &subst)); } } } @@ -311,10 +312,13 @@ Type *ETSTypeAliasType::Substitute(TypeRelation *relation, const Substitution *s return copiedType; } + auto arenaSubst = checker->NewArenaSubstitution(); + std::copy(substitution->begin(), substitution->end(), std::inserter(*arenaSubst, arenaSubst->end())); + copiedType = checker->CreateETSTypeAliasType(name_, declNode_, isRecursive_); copiedType->base_ = base_ == nullptr ? this : base_; copiedType->parent_ = this; - copiedType->substitution_ = substitution; + copiedType->substitution_ = arenaSubst; copiedType->typeArguments_ = newTypeArgs; EmplaceInstantiatedType(hash, copiedType); diff --git a/ets2panda/checker/types/ets/etsTypeAliasType.h b/ets2panda/checker/types/ets/etsTypeAliasType.h index f5b249c69257d449d8e86183704cfe796d98c0e0..aafefa6d3f070502d0840352015315063e7c4204 100644 --- a/ets2panda/checker/types/ets/etsTypeAliasType.h +++ b/ets2panda/checker/types/ets/etsTypeAliasType.h @@ -107,7 +107,7 @@ private: Type *targetType_ = nullptr; InstantiationMap instantiationMap_; ArenaVector typeArguments_; - const Substitution *substitution_ = nullptr; + const ArenaSubstitution *substitution_ = nullptr; mutable bool recursionCount_ = false; }; } // namespace ark::es2panda::checker diff --git a/ets2panda/checker/types/type.h b/ets2panda/checker/types/type.h index d3f83e9d37094cd16ce4d49ef9be620eae5bd5ae..4d59dfa0368951becd37b19f4ebe98a58f63d233 100644 --- a/ets2panda/checker/types/type.h +++ b/ets2panda/checker/types/type.h @@ -43,7 +43,8 @@ class ETSStringType; class ETSBigIntType; class ETSResizableArrayType; -using Substitution = ArenaMap; +using Substitution = std::map; +using ArenaSubstitution = ArenaMap; class Type { public: diff --git a/ets2panda/compiler/core/compilerImpl.cpp b/ets2panda/compiler/core/compilerImpl.cpp index f62aaf1083f5cb9475524e7d843ab93790112a2d..e1591dcf76b69468cf5c9a8ceee2786e4b8e7786 100644 --- a/ets2panda/compiler/core/compilerImpl.cpp +++ b/ets2panda/compiler/core/compilerImpl.cpp @@ -154,7 +154,7 @@ static bool RunVerifierAndPhases(public_lib::Context &context, parser::Program & if (name == compiler::CheckerPhase::NAME) { afterCheckerPhase = true; } - ES2PANDA_PERF_EVENT_SCOPE("phases/" + name); + ES2PANDA_PERF_EVENT_SCOPE("@phases/" + name); if (options.GetSkipPhases().count(name) > 0) { continue; @@ -350,7 +350,7 @@ static void SavePermanents(public_lib::Context *ctx, parser::Program *program) static pandasm::Program *EmitProgram(CompilerImpl *compilerImpl, public_lib::Context *context, const CompilationUnit &unit) { - ES2PANDA_PERF_SCOPE("EmitProgram"); + ES2PANDA_PERF_SCOPE("@EmitProgram"); context->emitter->GenAnnotation(); auto result = compilerImpl->Emit(context); if (unit.ext == ScriptExtension::ETS && context->compilingState != public_lib::CompilingState::SINGLE_COMPILING) { @@ -361,7 +361,7 @@ static pandasm::Program *EmitProgram(CompilerImpl *compilerImpl, public_lib::Con static bool ExecuteParsingAndCompiling(const CompilationUnit &unit, public_lib::Context *context) { - ES2PANDA_PERF_SCOPE("Parser and pipeline phases"); + ES2PANDA_PERF_SCOPE("@phases"); parser::Program *program = context->parserProgram; if (unit.ext == ScriptExtension::ETS && context->compilingState == public_lib::CompilingState::MULTI_COMPILING_FOLLOW) { diff --git a/ets2panda/compiler/lowering/ets/genericBridgesLowering.cpp b/ets2panda/compiler/lowering/ets/genericBridgesLowering.cpp index d147a29ab9fb8f8d619f072f43875f14a15ebdd7..1e2d1d47ff9d8033fe37cff06d61883a1c7e3e2d 100644 --- a/ets2panda/compiler/lowering/ets/genericBridgesLowering.cpp +++ b/ets2panda/compiler/lowering/ets/genericBridgesLowering.cpp @@ -147,21 +147,21 @@ void GenericBridgesPhase::ProcessScriptFunction(ir::ClassDefinition const *const // We are not interested in functions that either don't have type parameters at all // or have type parameters that are not modified in the derived class - auto const *baseSignature1 = baseFunction->Signature()->Substitute(relation, substitutions.baseConstraints); + auto const *baseSignature1 = baseFunction->Signature()->Substitute(relation, &substitutions.baseConstraints); if (baseSignature1 == baseFunction->Signature()) { return; } - auto *baseSignature2 = baseFunction->Signature()->Substitute(relation, substitutions.derivedSubstitutions); + auto *baseSignature2 = baseFunction->Signature()->Substitute(relation, &substitutions.derivedSubstitutions); if (baseSignature2 == baseFunction->Signature()) { return; } - baseSignature2 = baseSignature2->Substitute(relation, substitutions.derivedConstraints); + baseSignature2 = baseSignature2->Substitute(relation, &substitutions.derivedConstraints); ir::ScriptFunction *derivedFunction = nullptr; checker::ETSFunctionType const *methodType = derivedMethod->Id()->Variable()->TsType()->AsETSFunctionType(); for (auto *signature : methodType->CallSignatures()) { - signature = signature->Substitute(relation, substitutions.derivedConstraints); + signature = signature->Substitute(relation, &substitutions.derivedConstraints); // A special case is when the overriding function's return type is going to be unboxed. if ((overrides(baseSignature1, signature) || checker->HasSameAssemblySignature(baseSignature1, signature)) && baseSignature1->ReturnType()->IsETSUnboxableObject() == signature->ReturnType()->IsETSUnboxableObject()) { @@ -198,21 +198,53 @@ void GenericBridgesPhase::MaybeAddGenericBridges(ir::ClassDefinition const *cons } } +static ir::MethodDefinition *FindBridgeCandidate(ir::ClassDefinition const *const classDefinition, + ir::MethodDefinition *baseMethod) +{ + auto const &classBody = classDefinition->Body(); + + // Skip `static`, `final` and special methods... + if (baseMethod->Kind() != ir::MethodDefinitionKind::METHOD || baseMethod->IsStatic() || baseMethod->IsFinal() || + baseMethod->Id()->Name().Utf8().find("lambda$invoke$") != std::string_view::npos) { + return nullptr; + } + + // Check if the derived class has any possible overrides of this method + auto isOverridePred = [&name = baseMethod->Id()->Name()](ir::AstNode const *node) -> bool { + return node->IsMethodDefinition() && !node->IsStatic() && node->AsMethodDefinition()->Id()->Name() == name; + }; + auto it = std::find_if(classBody.cbegin(), classBody.end(), isOverridePred); + return it == classBody.cend() ? nullptr : (*it)->AsMethodDefinition(); +} + +static bool HasBridgeCandidates(ir::ClassDefinition const *const classDefinition, + ArenaVector const &items) +{ + for (auto *item : items) { + if (item->IsMethodDefinition()) { + auto method = item->AsMethodDefinition(); + auto derivedMethod = FindBridgeCandidate(classDefinition, method); + if (derivedMethod != nullptr) { + return true; + } + } + } + return false; +} + void GenericBridgesPhase::CreateGenericBridges(ir::ClassDefinition const *const classDefinition, Substitutions &substitutions, ArenaVector const &items) const { - auto const &classBody = classDefinition->Body(); - // Collect type parameters defaults/constraints in the derived class auto *checker = context_->GetChecker()->AsETSChecker(); - substitutions.derivedConstraints = checker->NewSubstitution(); + substitutions.derivedConstraints = checker::Substitution {}; auto const *const classType = classDefinition->TsType()->AsETSObjectType(); auto const &typeParameters = classType->GetConstOriginalBaseType()->AsETSObjectType()->TypeArguments(); for (auto *const parameter : typeParameters) { auto *const typeParameter = parameter->AsETSTypeParameter(); - checker->EmplaceSubstituted(substitutions.derivedConstraints, typeParameter, + checker->EmplaceSubstituted(&substitutions.derivedConstraints, typeParameter, typeParameter->GetConstraintType()); } @@ -220,19 +252,9 @@ void GenericBridgesPhase::CreateGenericBridges(ir::ClassDefinition const *const if (item->IsMethodDefinition()) { // Skip `static`, `final` and special methods... auto *const method = item->AsMethodDefinition(); - if (method->Kind() != ir::MethodDefinitionKind::METHOD || method->IsStatic() || method->IsFinal() || - method->Id()->Name().Utf8().find("lambda$invoke$") != std::string_view::npos) { - continue; - } - - // Check if the derived class has any possible overrides of this method - auto isOverridePred = [&name = method->Id()->Name()](ir::AstNode const *node) -> bool { - return node->IsMethodDefinition() && !node->IsStatic() && - node->AsMethodDefinition()->Id()->Name() == name; - }; - auto it = std::find_if(classBody.cbegin(), classBody.end(), isOverridePred); - if (it != classBody.cend()) { - MaybeAddGenericBridges(classDefinition, method, (*it)->AsMethodDefinition(), substitutions); + auto derivedMethod = FindBridgeCandidate(classDefinition, method); + if (derivedMethod != nullptr) { + MaybeAddGenericBridges(classDefinition, method, derivedMethod, substitutions); } } } @@ -247,8 +269,6 @@ GenericBridgesPhase::Substitutions GenericBridgesPhase::GetSubstitutions( auto *checker = context_->GetChecker()->AsETSChecker(); Substitutions substitutions {}; - substitutions.derivedSubstitutions = checker->NewSubstitution(); - substitutions.baseConstraints = checker->NewSubstitution(); // We need to check if the class derived from base generic class (or implementing generic interface) // has either explicit class type substitutions or type parameters with narrowing constraints. @@ -258,11 +278,11 @@ GenericBridgesPhase::Substitutions GenericBridgesPhase::GetSubstitutions( // Collect type parameters defaults/constraints in the base class // and type argument substitutions in the derived class - checker->EmplaceSubstituted(substitutions.derivedSubstitutions, typeParameter, typeArgument); + checker->EmplaceSubstituted(&substitutions.derivedSubstitutions, typeParameter, typeArgument); if (auto *const defaultType = typeParameter->GetDefaultType(); defaultType != nullptr) { - checker->EmplaceSubstituted(substitutions.baseConstraints, typeParameter, defaultType); + checker->EmplaceSubstituted(&substitutions.baseConstraints, typeParameter, defaultType); } else { - checker->EmplaceSubstituted(substitutions.baseConstraints, typeParameter, + checker->EmplaceSubstituted(&substitutions.baseConstraints, typeParameter, typeParameter->GetConstraintType()); } } @@ -274,13 +294,12 @@ void GenericBridgesPhase::ProcessInterfaces(ir::ClassDefinition *const classDefi ArenaVector const &interfaces) const { for (auto const *interfaceType : interfaces) { - if (auto const &typeParameters = interfaceType->GetConstOriginalBaseType()->AsETSObjectType()->TypeArguments(); - !typeParameters.empty()) { - if (Substitutions substitutions = GetSubstitutions(interfaceType, typeParameters); - // NOLINTNEXTLINE(clang-analyzer-core.CallAndMessage) - !substitutions.derivedSubstitutions->empty()) { + auto const &typeParameters = interfaceType->GetConstOriginalBaseType()->AsETSObjectType()->TypeArguments(); + if (!typeParameters.empty()) { + auto const &interfaceBody = interfaceType->GetDeclNode()->AsTSInterfaceDeclaration()->Body()->Body(); + if (HasBridgeCandidates(classDefinition, interfaceBody)) { + Substitutions substitutions = GetSubstitutions(interfaceType, typeParameters); ES2PANDA_ASSERT(interfaceType->GetDeclNode()->IsTSInterfaceDeclaration()); - auto const &interfaceBody = interfaceType->GetDeclNode()->AsTSInterfaceDeclaration()->Body()->Body(); CreateGenericBridges(classDefinition, substitutions, interfaceBody); } } @@ -310,7 +329,7 @@ ir::ClassDefinition *GenericBridgesPhase::ProcessClassDefinition(ir::ClassDefini // or type parameters with narrowing constraints. if (Substitutions substitutions = GetSubstitutions(superType, typeParameters); // NOLINTNEXTLINE(clang-analyzer-core.CallAndMessage) - !substitutions.derivedSubstitutions->empty()) { + !substitutions.derivedSubstitutions.empty()) { // If it has, then probably the generic bridges should be created. auto const &superClassBody = classDefinition->Super()->TsType()->AsETSObjectType()->GetDeclNode()->AsClassDefinition()->Body(); diff --git a/ets2panda/compiler/lowering/ets/genericBridgesLowering.h b/ets2panda/compiler/lowering/ets/genericBridgesLowering.h index 4fafc089c686a6d3fee0ec1d1aa40b5029084e34..c9b64c44d1eb0d56df7b2f71a79335b24c080bc5 100644 --- a/ets2panda/compiler/lowering/ets/genericBridgesLowering.h +++ b/ets2panda/compiler/lowering/ets/genericBridgesLowering.h @@ -31,9 +31,9 @@ public: private: struct Substitutions { - checker::Substitution *derivedSubstitutions = nullptr; - checker::Substitution *baseConstraints = nullptr; - checker::Substitution *derivedConstraints = nullptr; + checker::Substitution derivedSubstitutions {}; + checker::Substitution baseConstraints {}; + checker::Substitution derivedConstraints {}; }; ir::ClassDefinition *ProcessClassDefinition(ir::ClassDefinition *classDefinition) const; diff --git a/ets2panda/compiler/lowering/ets/lambdaLowering.cpp b/ets2panda/compiler/lowering/ets/lambdaLowering.cpp index c62bcac5c1bd15b538287363c64fe95f302ff04a..00485472a3b292b537c896dadaac8d16766808cf 100644 --- a/ets2panda/compiler/lowering/ets/lambdaLowering.cpp +++ b/ets2panda/compiler/lowering/ets/lambdaLowering.cpp @@ -92,12 +92,12 @@ static util::StringView CreateCalleeName(ArenaAllocator *allocator) return name.View(); } -static std::pair CloneTypeParams( +static std::pair CloneTypeParams( public_lib::Context *ctx, ir::TSTypeParameterDeclaration *oldIrTypeParams, ir::ScriptFunction *enclosingFunction, varbinder::Scope *enclosingScope) { if (oldIrTypeParams == nullptr) { - return {nullptr, nullptr}; + return {nullptr, {}}; } auto *allocator = ctx->allocator; @@ -106,7 +106,7 @@ static std::pair Clon auto *newScope = allocator->New(allocator, enclosingScope); auto newTypeParams = ArenaVector(allocator->Adapter()); auto newTypeParamNodes = ArenaVector(allocator->Adapter()); - auto *substitution = checker->NewSubstitution(); + auto substitution = checker::Substitution {}; for (size_t ix = 0; ix < oldIrTypeParams->Params().size(); ix++) { auto *oldTypeParamNode = oldIrTypeParams->Params()[ix]; @@ -128,20 +128,20 @@ static std::pair Clon newTypeParams.push_back(newTypeParam); newTypeParamNodes.push_back(newTypeParamNode); - substitution->emplace(oldTypeParam, newTypeParam); + substitution.emplace(oldTypeParam, newTypeParam); } for (size_t ix = 0; ix < oldIrTypeParams->Params().size(); ix++) { auto *oldTypeParam = enclosingFunction->Signature()->TypeParams()[ix]->AsETSTypeParameter(); if (auto *oldConstraint = oldTypeParam->GetConstraintType(); oldConstraint != nullptr) { - auto *newConstraint = oldConstraint->Substitute(checker->Relation(), substitution); + auto *newConstraint = oldConstraint->Substitute(checker->Relation(), &substitution); newTypeParams[ix]->SetConstraintType(newConstraint); newTypeParamNodes[ix]->SetConstraint(allocator->New(newConstraint, allocator)); newTypeParamNodes[ix]->Constraint()->SetParent(newTypeParamNodes[ix]); } if (auto *oldDefault = oldTypeParam->GetDefaultType(); oldDefault != nullptr) { - auto *newDefault = oldDefault->Substitute(checker->Relation(), substitution); + auto *newDefault = oldDefault->Substitute(checker->Relation(), &substitution); newTypeParams[ix]->SetDefaultType(newDefault); newTypeParamNodes[ix]->SetDefaultType(allocator->New(newDefault, allocator)); newTypeParamNodes[ix]->DefaultType()->SetParent(newTypeParamNodes[ix]); @@ -152,7 +152,7 @@ static std::pair Clon allocator, std::move(newTypeParamNodes), oldIrTypeParams->RequiredParams()); newIrTypeParams->SetScope(newScope); - return {newIrTypeParams, substitution}; + return {newIrTypeParams, std::move(substitution)}; } using ParamsAndVarMap = @@ -325,19 +325,19 @@ static ir::MethodDefinition *CreateCalleeMethod(public_lib::Context *ctx, ir::Ar info->callReceiver != nullptr ? classScope->InstanceMethodScope() : classScope->StaticMethodScope(); auto [newTypeParams, subst0] = CloneTypeParams(ctx, oldTypeParams, info->enclosingFunction, enclosingScope); - auto *substitution = subst0; // NOTE(gogabr): needed to capture in a lambda later. + auto &substitution = subst0; // NOTE(gogabr): needed to capture in a lambda later. auto *scopeForMethod = newTypeParams != nullptr ? newTypeParams->Scope() : enclosingScope; auto lexScope = varbinder::LexicalScope::Enter(varBinder, enclosingScope); auto paramScope = allocator->New(allocator, scopeForMethod); - auto [params, vMap] = CreateLambdaCalleeParameters(ctx, lambda, *info->capturedVars, paramScope, substitution); + auto [params, vMap] = CreateLambdaCalleeParameters(ctx, lambda, *info->capturedVars, paramScope, &substitution); auto varMap = std::move(vMap); auto *returnType = cmInfo->forcedReturnType != nullptr ? cmInfo->forcedReturnType - : lambda->Function()->Signature()->ReturnType()->Substitute(checker->Relation(), substitution); + : lambda->Function()->Signature()->ReturnType()->Substitute(checker->Relation(), &substitution); auto returnTypeAnnotation = allocator->New(returnType, allocator); auto funcFlags = ir::ScriptFunctionFlags::METHOD | cmInfo->auxFunctionFlags; @@ -355,7 +355,7 @@ static ir::MethodDefinition *CreateCalleeMethod(public_lib::Context *ctx, ir::Ar : cmInfo->body->Scope()->AsFunctionScope(); funcScope->BindName(info->calleeClass->Definition()->TsType()->AsETSObjectType()->AssemblerName()); func->SetScope(funcScope); - ProcessCalleeMethodBody(cmInfo->body, checker, paramScope, substitution, varMap); + ProcessCalleeMethodBody(cmInfo->body, checker, paramScope, &substitution, varMap); for (auto *param : func->Params()) { param->SetParent(func); @@ -856,9 +856,9 @@ static ir::ClassDeclaration *CreateLambdaClass(public_lib::Context *ctx, checker auto *oldTypeParams = (info->enclosingFunction != nullptr) ? info->enclosingFunction->TypeParams() : nullptr; auto [newTypeParams, subst0] = CloneTypeParams(ctx, oldTypeParams, info->enclosingFunction, ctx->parserProgram->GlobalClassScope()); - auto *substitution = subst0; // NOTE(gogabr): needed to capture in a lambda later. + auto &substitution = subst0; // NOTE(gogabr): needed to capture in a lambda later. - auto fnInterface = fntype->Substitute(checker->Relation(), substitution)->ArrowToFunctionalInterface(checker); + auto fnInterface = fntype->Substitute(checker->Relation(), &substitution)->ArrowToFunctionalInterface(checker); auto lambdaProviderClass = FunctionTypeToLambdaProviderType(checker, fntype->ArrowSignature()); auto lexScope = varbinder::LexicalScope::Enter(varBinder, ctx->parserProgram->GlobalClassScope()); @@ -872,15 +872,15 @@ static ir::ClassDeclaration *CreateLambdaClass(public_lib::Context *ctx, checker ir::ClassDefinitionModifiers::FUNCTIONAL_REFERENCE); } - CreateLambdaClassFields(ctx, classDefinition, info, substitution); - CreateLambdaClassConstructor(ctx, classDefinition, info, substitution); + CreateLambdaClassFields(ctx, classDefinition, info, &substitution); + CreateLambdaClassConstructor(ctx, classDefinition, info, &substitution); auto signature = fntype->ArrowSignature(); LambdaClassInvokeInfo lciInfo; lciInfo.callee = callee; lciInfo.classDefinition = classDefinition; - lciInfo.substitution = substitution; + lciInfo.substitution = &substitution; lciInfo.lambdaSignature = signature; for (size_t arity = signature->MinArgCount(); arity <= signature->ArgCount(); ++arity) { diff --git a/ets2panda/ir/astNode.cpp b/ets2panda/ir/astNode.cpp index 36d07cd98be875de21389c7ebf7ba8e604dba902..696841c7b6690c9523e924f1eacafff0fc336eb3 100644 --- a/ets2panda/ir/astNode.cpp +++ b/ets2panda/ir/astNode.cpp @@ -164,17 +164,10 @@ AstNode *AstNode::OriginalNode() const noexcept return GetHistoryNode()->originalNode_; } -const std::optional> &AstNode::TransformedNode() const noexcept -{ - return GetHistoryNode()->transformedNode_; -} - -void AstNode::SetTransformedNode(std::string_view const transformationName, AstNode *transformedNode) +void AstNode::SetTransformedNode([[maybe_unused]] std::string_view const transformationName, AstNode *transformedNode) { if (transformedNode != nullptr) { transformedNode->SetOriginalNode(this); - GetOrCreateHistoryNode()->transformedNode_ = - std::make_optional(std::make_pair(transformationName, transformedNode)); } } @@ -239,7 +232,6 @@ void AstNode::CopyTo(AstNode *other) const other->history_ = history_; other->variable_ = variable_; other->originalNode_ = originalNode_; - other->transformedNode_ = transformedNode_; } AstNode *AstNode::Construct([[maybe_unused]] ArenaAllocator *allocator) diff --git a/ets2panda/ir/astNode.h b/ets2panda/ir/astNode.h index 431dd5a0462974f4c18e7fe4f6fbb3628001931c..3f5a8edd9a3f9e08266302b9827d362f1b13d625 100644 --- a/ets2panda/ir/astNode.h +++ b/ets2panda/ir/astNode.h @@ -67,7 +67,7 @@ using NodeTransformer = std::function; using NodeTraverser = std::function; using NodePredicate = std::function; -enum class AstNodeType { +enum class AstNodeType : uint8_t { /* CC-OFFNXT(G.PRE.02,G.PRE.09) name part*/ // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define DECLARE_NODE_TYPES(nodeType, className) nodeType, @@ -135,7 +135,7 @@ AST_NODE_REINTERPRET_MAPPING(DECLARE_CLASSES) class AstNode { public: explicit AstNode(AstNodeType type) : type_(type) {}; - explicit AstNode(AstNodeType type, ModifierFlags flags) : type_(type), flags_(flags) {}; + explicit AstNode(AstNodeType type, ModifierFlags flags) : flags_(flags), type_(type) {}; virtual ~AstNode() = default; AstNode() = delete; @@ -281,38 +281,38 @@ public: void SetRange(const lexer::SourceRange &loc) noexcept { - if (GetHistoryNode()->range_ != loc) { - GetOrCreateHistoryNode()->range_ = loc; + if (GetHistoryNode()->range_.GetRange() != loc) { + GetOrCreateHistoryNode()->range_.SetRange(loc); } } void SetStart(const lexer::SourcePosition &start) noexcept { - if (GetHistoryNode()->range_.start != start) { - GetOrCreateHistoryNode()->range_.start = start; + if (GetHistoryNode()->range_.GetStart() != start) { + GetOrCreateHistoryNode()->range_.SetStart(start); } } void SetEnd(const lexer::SourcePosition &end) noexcept { - if (GetHistoryNode()->range_.end != end) { - GetOrCreateHistoryNode()->range_.end = end; + if (GetHistoryNode()->range_.GetEnd() != end) { + GetOrCreateHistoryNode()->range_.SetEnd(end); } } - [[nodiscard]] const lexer::SourcePosition &Start() const noexcept + [[nodiscard]] lexer::SourcePosition Start() const noexcept { - return GetHistoryNode()->range_.start; + return GetHistoryNode()->range_.GetStart(); } - [[nodiscard]] const lexer::SourcePosition &End() const noexcept + [[nodiscard]] lexer::SourcePosition End() const noexcept { - return GetHistoryNode()->range_.end; + return GetHistoryNode()->range_.GetEnd(); } - [[nodiscard]] const lexer::SourceRange &Range() const noexcept + [[nodiscard]] lexer::SourceRange Range() const noexcept { - return GetHistoryNode()->range_; + return GetHistoryNode()->range_.GetRange(); } [[nodiscard]] AstNodeType Type() const noexcept @@ -724,23 +724,19 @@ protected: friend class SizeOfNodeTest; // NOLINTBEGIN(misc-non-private-member-variables-in-classes) AstNode *parent_ {}; - lexer::SourceRange range_ {}; - AstNodeType type_; + AstNodeHistory *history_ {nullptr}; + lexer::CompressedSourceRange range_ {}; ModifierFlags flags_ {}; mutable AstNodeFlags astNodeFlags_ {}; - AstNodeHistory *history_ {nullptr}; + AstNodeType type_; // NOLINTEND(misc-non-private-member-variables-in-classes) private: compiler::PhaseId GetFirstCreated() const; AstNode &operator=(const AstNode &) = default; - const std::optional> &TransformedNode() const noexcept; - varbinder::Variable *variable_ {}; AstNode *originalNode_ = nullptr; - // {lowering_phase_name, new_generated_node} - std::optional> transformedNode_ = std::nullopt; }; template diff --git a/ets2panda/ir/astNodeFlags.h b/ets2panda/ir/astNodeFlags.h index 88169f4b563d8d14a2280b73df73263ddcc5bbeb..ea8783348a459dc4a81adc8a5e8cf43c9cd7bc04 100644 --- a/ets2panda/ir/astNodeFlags.h +++ b/ets2panda/ir/astNodeFlags.h @@ -24,7 +24,7 @@ namespace ark::es2panda::ir { using ENUMBITOPS_OPERATORS; -enum class AstNodeFlags { +enum class AstNodeFlags : uint16_t { NO_OPTS = 0, CHECKCAST = 1U << 0U, ALLOW_REQUIRED_INSTANTIATION = 1U << 2U, @@ -35,6 +35,8 @@ enum class AstNodeFlags { RESIZABLE_REST = 1U << 7U, // TO BE REMOVED AFTER COMPLETE PRIMITIVE TYPES REFACTORING, DO NOT USE!! TMP_CONVERT_PRIMITIVE_CAST_METHOD_CALL = 1U << 8U, + // Moved out of the ir::Expression + IS_GROUPED = 1U << 9U, /* do not introduce new flags. all the existing to be removed */ }; diff --git a/ets2panda/ir/expression.cpp b/ets2panda/ir/expression.cpp index eb5ea5540298844feddda7f0921454b8e4f7853d..53f7b961715ba0c18e51686677f7659f18278f79 100644 --- a/ets2panda/ir/expression.cpp +++ b/ets2panda/ir/expression.cpp @@ -39,10 +39,7 @@ std::string Expression::ToString() const void Expression::CopyTo(AstNode *other) const { - auto otherImpl = other->AsExpression(); - - otherImpl->grouped_ = grouped_; - + [[maybe_unused]] auto otherImpl = other->AsExpression(); TypedAstNode::CopyTo(other); } diff --git a/ets2panda/ir/expression.h b/ets2panda/ir/expression.h index 00c10eaec81bcce401519dc9cef807033c92f126..776fc8ca6dc3442ba43d8be364d9bd9e91608760 100644 --- a/ets2panda/ir/expression.h +++ b/ets2panda/ir/expression.h @@ -33,13 +33,13 @@ public: [[nodiscard]] bool IsGrouped() const noexcept { - return AstNode::GetHistoryNodeAs()->grouped_; + return AstNode::GetHistoryNodeAs()->HasAstNodeFlags(AstNodeFlags::IS_GROUPED); } void SetGrouped() noexcept { if (!IsGrouped()) { - AstNode::GetOrCreateHistoryNodeAs()->grouped_ = true; + AstNode::GetOrCreateHistoryNodeAs()->SetAstNodeFlags(AstNodeFlags::IS_GROUPED); } } @@ -109,14 +109,10 @@ protected: explicit Expression(AstNodeType const type) : TypedAstNode(type) {} explicit Expression(AstNodeType const type, ModifierFlags const flags) : TypedAstNode(type, flags) {} - Expression(Expression const &other) : TypedAstNode(static_cast(other)) - { - grouped_ = other.IsGrouped(); - } + Expression(Expression const &other) : TypedAstNode(static_cast(other)) {} private: friend class SizeOfNodeTest; - bool grouped_ {}; }; class AnnotatedExpression : public Annotated { diff --git a/ets2panda/ir/statements/annotationUsage.cpp b/ets2panda/ir/statements/annotationUsage.cpp index 3ef4f21fafbe7b09e688fbd299363bc1161b52da..c67884104a94cf5335ba02dde41f392242bb0ecd 100644 --- a/ets2panda/ir/statements/annotationUsage.cpp +++ b/ets2panda/ir/statements/annotationUsage.cpp @@ -87,7 +87,7 @@ AnnotationUsage *AnnotationUsage::Clone(ArenaAllocator *const allocator, AstNode clone->AddProperty(property->Clone(allocator, clone)); } - clone->SetRange(range_); + clone->SetRange(range_.GetRange()); clone->SetScope(propertiesScope_); return clone; diff --git a/ets2panda/ir/statements/expressionStatement.cpp b/ets2panda/ir/statements/expressionStatement.cpp index f4bb8535148401c14e916d3cabd6b3104086e0cb..58cbd0e3d196802c536110aac8c7b3630436d38a 100644 --- a/ets2panda/ir/statements/expressionStatement.cpp +++ b/ets2panda/ir/statements/expressionStatement.cpp @@ -55,7 +55,7 @@ ExpressionStatement *ExpressionStatement::Clone(ArenaAllocator *const allocator, if (parent != nullptr) { clone->SetParent(parent); } - clone->SetRange(range_); + clone->SetRange(range_.GetRange()); return clone; } diff --git a/ets2panda/ir/statements/throwStatement.cpp b/ets2panda/ir/statements/throwStatement.cpp index 83b2159df5ea7f23e5d1c6d8907a673907f68496..ee2f446c43799716cd4b22ec33d4e5abe8fd90c4 100644 --- a/ets2panda/ir/statements/throwStatement.cpp +++ b/ets2panda/ir/statements/throwStatement.cpp @@ -74,7 +74,7 @@ ThrowStatement *ThrowStatement::Clone(ArenaAllocator *const allocator, AstNode * if (parent != nullptr) { clone->SetParent(parent); } - clone->SetRange(range_); + clone->SetRange(range_.GetRange()); return clone; } } // namespace ark::es2panda::ir diff --git a/ets2panda/ir/statements/variableDeclarator.cpp b/ets2panda/ir/statements/variableDeclarator.cpp index 78ee2fd4f8d96bd15b1e87376e49fd117c0a500f..02780398c0b4b73fcf1e6acb9b10875bc313487e 100644 --- a/ets2panda/ir/statements/variableDeclarator.cpp +++ b/ets2panda/ir/statements/variableDeclarator.cpp @@ -89,7 +89,7 @@ VariableDeclarator *VariableDeclarator::Clone(ArenaAllocator *const allocator, A clone->SetParent(parent); } - clone->SetRange(range_); + clone->SetRange(range_.GetRange()); return clone; } diff --git a/ets2panda/ir/ts/tsArrayType.cpp b/ets2panda/ir/ts/tsArrayType.cpp index 8ab2361fb9039274516edac8ef14f3d914e4b5f2..fe5c8a30495f35427f0f0ffc07fad05e90b65acf 100644 --- a/ets2panda/ir/ts/tsArrayType.cpp +++ b/ets2panda/ir/ts/tsArrayType.cpp @@ -120,7 +120,7 @@ TSArrayType *TSArrayType::Clone(ArenaAllocator *const allocator, AstNode *const clone->SetAnnotations(std::move(annotationUsages)); } - clone->SetRange(range_); + clone->SetRange(range_.GetRange()); return clone; } } // namespace ark::es2panda::ir diff --git a/ets2panda/ir/ts/tsNonNullExpression.cpp b/ets2panda/ir/ts/tsNonNullExpression.cpp index f789ed7a7b3a302a722791ca04b4e70bbc0144af..61768c5e4cbb21d7e62d5dbb357a3c48cd9d1add 100644 --- a/ets2panda/ir/ts/tsNonNullExpression.cpp +++ b/ets2panda/ir/ts/tsNonNullExpression.cpp @@ -74,7 +74,7 @@ TSNonNullExpression *TSNonNullExpression::Clone(ArenaAllocator *const allocator, if (parent != nullptr) { clone->SetParent(parent); } - clone->SetRange(range_); + clone->SetRange(range_.GetRange()); return clone; } diff --git a/ets2panda/ir/ts/tsTypeParameter.cpp b/ets2panda/ir/ts/tsTypeParameter.cpp index 4a8d2538091f49b1c2581e45882b1b64083a07af..2483117d15ada0b2cc97d08f8d0a37efc4ceb524 100644 --- a/ets2panda/ir/ts/tsTypeParameter.cpp +++ b/ets2panda/ir/ts/tsTypeParameter.cpp @@ -158,7 +158,7 @@ TSTypeParameter *TSTypeParameter::Clone(ArenaAllocator *allocator, AstNode *pare name_->Clone(allocator, this), constraint_ == nullptr ? nullptr : constraint_->Clone(allocator, this), defaultType_ == nullptr ? nullptr : defaultType_->Clone(allocator, this), allocator); clone->SetParent(parent); - clone->SetRange(range_); + clone->SetRange(range_.GetRange()); if (!Annotations().empty()) { ArenaVector annotationUsages {allocator->Adapter()}; diff --git a/ets2panda/ir/ts/tsTypeParameterDeclaration.cpp b/ets2panda/ir/ts/tsTypeParameterDeclaration.cpp index b6d574499828ec0b908aa3377fff49c7ac48b22a..78bd362f4ed32df7bdfdb7c197a4a58fc8277624 100644 --- a/ets2panda/ir/ts/tsTypeParameterDeclaration.cpp +++ b/ets2panda/ir/ts/tsTypeParameterDeclaration.cpp @@ -103,7 +103,7 @@ TSTypeParameterDeclaration *TSTypeParameterDeclaration::Clone(ArenaAllocator *al if (parent != nullptr) { clone->SetParent(parent); } - clone->SetRange(range_); + clone->SetRange(range_.GetRange()); return clone; } diff --git a/ets2panda/ir/ts/tsTypeParameterInstantiation.cpp b/ets2panda/ir/ts/tsTypeParameterInstantiation.cpp index 08a18265509d6d35709c4cf81f9c2fe3e9f8b90d..306816edeac35d1a3b64bd46f231479217d019da 100644 --- a/ets2panda/ir/ts/tsTypeParameterInstantiation.cpp +++ b/ets2panda/ir/ts/tsTypeParameterInstantiation.cpp @@ -37,7 +37,7 @@ TSTypeParameterInstantiation *TSTypeParameterInstantiation::Clone(ArenaAllocator if (parent != nullptr) { clone->SetParent(parent); } - clone->SetRange(range_); + clone->SetRange(range_.GetRange()); return clone; } diff --git a/ets2panda/lexer/token/sourceLocation.h b/ets2panda/lexer/token/sourceLocation.h index b6557e4d6320509ddfce93860c717d38ec5a289e..2da2a89b3541b03c84ad417fce360bb165710f7f 100644 --- a/ets2panda/lexer/token/sourceLocation.h +++ b/ets2panda/lexer/token/sourceLocation.h @@ -19,6 +19,7 @@ #include "macros.h" #include #include +#include #include namespace ark::es2panda::parser { @@ -80,6 +81,62 @@ public: } }; +class CompressedSourceRange { +public: + explicit CompressedSourceRange() = default; + DEFAULT_COPY_SEMANTIC(CompressedSourceRange); + DEFAULT_MOVE_SEMANTIC(CompressedSourceRange); + ~CompressedSourceRange() = default; + + void SetStart(SourcePosition const &s) + { + startLine_ = Limit(s.line); + startIndex_ = Limit(s.index); + program_ = s.Program(); + } + + void SetEnd(SourcePosition const &e) + { + endLine_ = Limit(e.line); + endIndex_ = Limit(e.index); + program_ = e.Program(); + } + + SourcePosition GetStart() const + { + return SourcePosition(startIndex_, startLine_, program_); + } + + SourcePosition GetEnd() const + { + return SourcePosition(endIndex_, endLine_, program_); + } + + void SetRange(SourceRange const &r) + { + SetStart(r.start); + SetEnd(r.end); + } + + SourceRange GetRange() const + { + return SourceRange(GetStart(), GetEnd()); + } + +private: + template + static T Limit(uint64_t val) + { + return val > std::numeric_limits::max() ? std::numeric_limits::max() : val; + } + + parser::Program const *program_ {}; + uint32_t startLine_ {}; + uint32_t endLine_ {}; + uint32_t startIndex_ {}; + uint32_t endIndex_ {}; +}; + class SourceLocation { public: explicit SourceLocation() noexcept = default; diff --git a/ets2panda/parser/ASparser.cpp b/ets2panda/parser/ASparser.cpp index b7dbd5b0f1e16b003c6b7fb9e8d1a80cb53ac7c9..8fc21e2cbb1860b1571d0d1593d240736aa62718 100644 --- a/ets2panda/parser/ASparser.cpp +++ b/ets2panda/parser/ASparser.cpp @@ -768,6 +768,7 @@ bool ASParser::ParsePotentialNonNullExpression(ir::Expression **returnExpression } *returnExpression = AllocNode(*returnExpression); + // NOLINTNEXTLINE(clang-analyzer-core.CallAndMessage) (*returnExpression)->SetRange({startLoc, Lexer()->GetToken().End()}); Lexer()->NextToken(); return false; diff --git a/ets2panda/parser/expressionTSParser.cpp b/ets2panda/parser/expressionTSParser.cpp index 86f1232891b4b65215fc1c02150c7d4c820c46f2..0820dc473a97dacfd7230de1ff7682d4f3e461cb 100644 --- a/ets2panda/parser/expressionTSParser.cpp +++ b/ets2panda/parser/expressionTSParser.cpp @@ -379,6 +379,7 @@ bool TSParser::ParsePotentialNonNullExpression(ir::Expression **returnExpression } *returnExpression = AllocNode(*returnExpression); + // NOLINTNEXTLINE(clang-analyzer-core.CallAndMessage) (*returnExpression)->SetRange({startLoc, Lexer()->GetToken().End()}); Lexer()->NextToken(); return false; diff --git a/ets2panda/public/cppToCTypes.yaml b/ets2panda/public/cppToCTypes.yaml index 10e1650666a4751492058c9f438720b80251668d..8e8f440bb0f04d4735ad0e557ee030c45452ad31 100644 --- a/ets2panda/public/cppToCTypes.yaml +++ b/ets2panda/public/cppToCTypes.yaml @@ -2789,7 +2789,7 @@ change_types: min_ptr_depth: 1 new_args: - type: - name: "ArenaMap" + name: "Map" ptr_depth: '|es2panda_arg.type.ptr_depth_int|' template_args: - type: diff --git a/ets2panda/test/test-lists/astchecker/astchecker-ets-ignored.txt b/ets2panda/test/test-lists/astchecker/astchecker-ets-ignored.txt index 303bff6cd20d4f5577e84212a168342d08e65e23..c40b6e68a0c4757cb0efb90c534c8ebd47bcfe1b 100644 --- a/ets2panda/test/test-lists/astchecker/astchecker-ets-ignored.txt +++ b/ets2panda/test/test-lists/astchecker/astchecker-ets-ignored.txt @@ -157,3 +157,6 @@ ast/parser/ets/returntype_override_primitive.ets ast/parser/ets/switch_num_compare_char_duplicate.ets # No-primitives #24986 [end] + +#26700 +ast/parser/ets/unexpected_token_62.ets diff --git a/ets2panda/test/test-lists/parser/parser-ets-ignored.txt b/ets2panda/test/test-lists/parser/parser-ets-ignored.txt index 98373f508405b4ca37d07e85fb9fcc7143456b1c..2613b44115a14c43feb1a9f3e37d43a9d72042d0 100644 --- a/ets2panda/test/test-lists/parser/parser-ets-ignored.txt +++ b/ets2panda/test/test-lists/parser/parser-ets-ignored.txt @@ -46,3 +46,9 @@ parser/ets/test_jsvalue_get_double.ets parser/ets/lambda-type-inference-overloaded.ets # No-primitives #24986 [end] + +#26700 +ark_tests/parser/js/classes/test-class-private-field.js +parser/ets/constructor_with_optional_parameter.ets +parser/ets/default_parameter8.ets +parser/js/test-private-field.js diff --git a/ets2panda/test/unit/plugin_conversion_rule/plugin_conversion_rule_part_i.cpp b/ets2panda/test/unit/plugin_conversion_rule/plugin_conversion_rule_part_i.cpp index 7e88eff58069a34f01ac3ba0abc2ed237d37e9c3..585921f05c96daec124a912fbeadc42a24f846ab 100644 --- a/ets2panda/test/unit/plugin_conversion_rule/plugin_conversion_rule_part_i.cpp +++ b/ets2panda/test/unit/plugin_conversion_rule/plugin_conversion_rule_part_i.cpp @@ -389,35 +389,6 @@ es2panda_Scope *classInstance/*return_args:*/, es2panda_Variable ***arenaMapValu EXPECT_TRUE(HasMatched(targetAPIWithNoSpace)); } -/* Signature *Substitute(TypeRelation *relation, const Substitution *substitution) */ -TEST_F(PluginConversionRuleUnitTest, ArenaMapPtrInputValue) -{ - std::string targetCAPI {R"( - extern "C" es2panda_Signature *SignatureSubstitute([[maybe_unused]] es2panda_Context *context, -es2panda_Signature *classInstance, [[maybe_unused]] es2panda_TypeRelation *relation, -[[maybe_unused]] es2panda_Type **substitutionKeyArray, es2panda_Type **substitutionValueArray, -size_t substitutionLen/*return_args:*/) - { - auto *relationE2p = reinterpret_cast(relation); - auto *substitutionArenaMap = reinterpret_cast(context)->allocator->New>(reinterpret_cast(context)->allocator->Adapter()); - for (size_t i = 0; i < substitutionLen; ++i) { - auto *substitutionElement1 = substitutionKeyArray[i]; - auto *substitutionElement2 = substitutionValueArray[i]; - auto *substitutionElement1E2p = reinterpret_cast(substitutionElement1); - auto *substitutionElement2E2p = reinterpret_cast(substitutionElement2); - (*substitutionArenaMap)[substitutionElement1E2p] = substitutionElement2E2p; - } - auto apiRes = reinterpret_cast< es2panda_Signature *> - ((reinterpret_cast< checker::Signature *>(classInstance))->Substitute(relationE2p, substitutionArenaMap)); - return apiRes; - } - )"}; - - std::string targetAPIWithNoSpace = RemoveWhitespace(targetCAPI); - EXPECT_TRUE(HasMatched(targetAPIWithNoSpace)); -} - /* Typed *AsTyped() */ TEST_F(PluginConversionRuleUnitTest, IrTypedPtrReturnValue) { diff --git a/ets2panda/test/unit/plugin_conversion_rule/plugin_conversion_rule_part_iii.cpp b/ets2panda/test/unit/plugin_conversion_rule/plugin_conversion_rule_part_iii.cpp index 7c111a02bf1cb936eb920ec6ebace5d6144cae3d..399a7398534ddbae5dc10b2a87a7018a5e97fd57 100644 --- a/ets2panda/test/unit/plugin_conversion_rule/plugin_conversion_rule_part_iii.cpp +++ b/ets2panda/test/unit/plugin_conversion_rule/plugin_conversion_rule_part_iii.cpp @@ -206,38 +206,6 @@ TEST_F(PluginConversionRuleUnitTest, SourcePositionInputParameter) EXPECT_TRUE(HasMatched(targetAPIWithNoSpace)); } -// apiName: AstNodeStartConst -TEST_F(PluginConversionRuleUnitTest, SourcePositionPtrReturnValue) -{ - std::string targetCAPI {R"( - extern "C" const es2panda_SourcePosition *AstNodeStartConst([[maybe_unused]] es2panda_Context *context, - es2panda_AstNode *classInstance/*return_args:*/) - { - auto apiRes = reinterpret_cast(reinterpret_cast(context)-> - allocator->New(((reinterpret_cast(classInstance))->Start()))); - return apiRes; - })"}; - - std::string targetAPIWithNoSpace = RemoveWhitespace(targetCAPI); - EXPECT_TRUE(HasMatched(targetAPIWithNoSpace)); -} - -// apiName: AstNodeRangeConst -TEST_F(PluginConversionRuleUnitTest, SourceRangePtrInputParameter) -{ - std::string targetCAPI {R"( - extern "C" const es2panda_SourceRange *AstNodeRangeConst([[maybe_unused]] es2panda_Context *context, - es2panda_AstNode *classInstance/*return_args:*/) - { - auto apiRes = reinterpret_cast(reinterpret_cast(context)->allocator-> - New(((reinterpret_cast(classInstance))->Range()))); - return apiRes; - })"}; - - std::string targetAPIWithNoSpace = RemoveWhitespace(targetCAPI); - EXPECT_TRUE(HasMatched(targetAPIWithNoSpace)); -} - // apiName: MemberExpressionCompileToRegConst TEST_F(PluginConversionRuleUnitTest, VRegInputParameter) { diff --git a/ets2panda/test/unit/sizeof_node_test.cpp b/ets2panda/test/unit/sizeof_node_test.cpp index b5912cb841a8de81faca52a1ad50db6dcf990068..5f150147f1120426098672c1ee84daa396532c32 100644 --- a/ets2panda/test/unit/sizeof_node_test.cpp +++ b/ets2panda/test/unit/sizeof_node_test.cpp @@ -70,8 +70,7 @@ size_t SizeOfNodeTest::SizeOf() sizeof(node->astNodeFlags_) + sizeof(node->history_) + sizeof(node->variable_) + - sizeof(node->originalNode_) + - sizeof(node->transformedNode_)); + sizeof(node->originalNode_)); // clang-format on } @@ -441,11 +440,10 @@ size_t SizeOfNodeTest::SizeOf() template <> size_t SizeOfNodeTest::SizeOf() { - Expression *node = nullptr; + [[maybe_unused]] Expression *node = nullptr; // clang-format off - return SizeOf() + - Align(sizeof(node->grouped_)); + return SizeOf(); // clang-format on } diff --git a/ets2panda/util/generateBin.cpp b/ets2panda/util/generateBin.cpp index 028875d16ac2f2c071a260e4a29016e49e2d7a22..442bd41bc4ffd105a7a021fcdbe295e986c4faa3 100644 --- a/ets2panda/util/generateBin.cpp +++ b/ets2panda/util/generateBin.cpp @@ -104,7 +104,7 @@ static int GenerateProgramImpl(ark::pandasm::Program *prog, const util::Options int GenerateProgram(ark::pandasm::Program *prog, const util::Options &options, const ReporterFun &reporter) { - ES2PANDA_PERF_SCOPE("GenerateProgram"); + ES2PANDA_PERF_SCOPE("@GenerateProgram"); std::map stat; std::map *statp = options.GetOptLevel() != 0 ? &stat : nullptr; ark::pandasm::AsmEmitter::PandaFileToPandaAsmMaps maps {}; @@ -112,7 +112,7 @@ int GenerateProgram(ark::pandasm::Program *prog, const util::Options &options, c #ifdef PANDA_WITH_BYTECODE_OPTIMIZER { - ES2PANDA_PERF_SCOPE("GenerateProgram/OptimizeBytecode"); + ES2PANDA_PERF_SCOPE("@GenerateProgram/OptimizeBytecode"); if (OptimizeBytecode(prog, options, reporter, statp, mapsp) != 0) { return 1; } diff --git a/ets2panda/util/helpers.h b/ets2panda/util/helpers.h index 841f00656668b496015d7aafcdc690a8020f1317..f8255dc4771fce090d54d04c4d4a7ce47d50d160 100644 --- a/ets2panda/util/helpers.h +++ b/ets2panda/util/helpers.h @@ -19,6 +19,7 @@ #include "varbinder/variableFlags.h" #include "mem/pool_manager.h" #include "util/ustring.h" +#include "util/perfMetrics.h" #include "ir/module/importSpecifier.h" #include @@ -56,7 +57,7 @@ class ClassStaticBlock; class TSInterfaceDeclaration; class TSEnumDeclaration; class ETSImportDeclaration; -enum class AstNodeType; +enum class AstNodeType : uint8_t; } // namespace ark::es2panda::ir namespace ark::es2panda::util { diff --git a/ets2panda/util/importPathManager.cpp b/ets2panda/util/importPathManager.cpp index 7cf04669276b7b647c1a6d4a086c986641ad2d86..ae0e0b61c667f5aed3e51f57fa87adde4d1683e1 100644 --- a/ets2panda/util/importPathManager.cpp +++ b/ets2panda/util/importPathManager.cpp @@ -62,7 +62,7 @@ ImportPathManager::ImportMetadata ImportPathManager::GatherImportMetadata(parser ImportFlags importFlags, ir::StringLiteral *importPath) { - srcPos_ = &importPath->Start(); + srcPos_ = importPath->Start(); // NOTE(dkofanov): The code below expresses the idea of 'dynamicPaths' defining separated, virtual file system. // Probably, paths of common imports should be isolated from the host fs as well, being resolved by 'ModuleInfo' // instead of 'AbsoluteName'. @@ -113,7 +113,7 @@ static bool IsRelativePath(std::string_view path) util::StringView ImportPathManager::ResolvePathAPI(StringView curModulePath, ir::StringLiteral *importPath) const { - srcPos_ = &importPath->Start(); + srcPos_ = importPath->Start(); // NOTE(dkofanov): #23698 related. In case of 'dynamicPaths', resolved path is "virtual" module-path, may be not // what the plugin expecting. return ResolvePath(curModulePath.Utf8(), importPath).resolvedPath; @@ -177,7 +177,7 @@ ImportPathManager::ResolvedPathRes ImportPathManager::ResolveAbsolutePath(const diagnosticEngine_.LogDiagnostic( diagnostic::IMPORT_CANT_FIND_PREFIX, util::DiagnosticMessageParams {util::StringView(importPath), util::StringView(arktsConfig_->ConfigPath())}, - *srcPos_); + srcPos_); return {""}; } return AppendExtensionOrIndexFileIfOmitted(UString(resolvedPath.value(), allocator_).View()); @@ -190,7 +190,7 @@ void ImportPathManager::UnixWalkThroughDirectoryAndAddToParseList(const ImportMe DIR *dir = opendir(directoryPath.c_str()); if (dir == nullptr) { diagnosticEngine_.LogDiagnostic(diagnostic::OPEN_FOLDER_FAILED, util::DiagnosticMessageParams {directoryPath}, - *srcPos_); + srcPos_); return; } @@ -219,7 +219,7 @@ void ImportPathManager::UnixWalkThroughDirectoryAndAddToParseList(const ImportMe void ImportPathManager::AddImplicitPackageImportToParseList(StringView packageDir, const lexer::SourcePosition &srcPos) { - srcPos_ = &srcPos; + srcPos_ = srcPos; ES2PANDA_ASSERT( IsAbsolute(packageDir.Mutf8())); // This should be an absolute path for 'AddToParseList' be able to resolve it. AddToParseList({util::ImportFlags::IMPLICIT_PACKAGE_IMPORT, Language::Id::ETS, packageDir.Utf8(), @@ -271,7 +271,7 @@ void ImportPathManager::AddToParseList(const ImportMetadata importMetadata) if (!isDeclForDynamic && !ark::os::file::File::IsRegularFile(std::string(resolvedPath))) { diagnosticEngine_.LogDiagnostic(diagnostic::UNAVAILABLE_SRC_PATH, util::DiagnosticMessageParams {resolvedPath}, - *srcPos_); + srcPos_); return; } @@ -366,7 +366,7 @@ ImportPathManager::ResolvedPathRes ImportPathManager::AppendExtensionOrIndexFile } diagnosticEngine_.LogDiagnostic(diagnostic::UNSUPPORTED_PATH, - util::DiagnosticMessageParams {util::StringView(path.Mutf8())}, *srcPos_); + util::DiagnosticMessageParams {util::StringView(path.Mutf8())}, srcPos_); return {""}; } @@ -409,7 +409,7 @@ util::StringView ImportPathManager::FormModuleNameSolelyByAbsolutePath(const uti std::string filePath(path.GetAbsolutePath()); if (filePath.rfind(absoluteEtsPath_, 0) != 0) { diagnosticEngine_.LogDiagnostic(diagnostic::SOURCE_OUTSIDE_ETS_PATH, - util::DiagnosticMessageParams {util::StringView(filePath)}, *srcPos_); + util::DiagnosticMessageParams {util::StringView(filePath)}, srcPos_); return ""; } auto name = FormRelativeModuleName(filePath.substr(absoluteEtsPath_.size())); @@ -434,7 +434,7 @@ static std::string TryFormDynamicModuleName(const DynamicPaths &dynPaths, const util::StringView ImportPathManager::FormModuleName(const util::Path &path, const lexer::SourcePosition &srcPos) { - srcPos_ = &srcPos; + srcPos_ = srcPos; return FormModuleName(path); } @@ -492,7 +492,7 @@ util::StringView ImportPathManager::FormModuleName(const util::Path &path) } diagnosticEngine_.LogDiagnostic(diagnostic::UNRESOLVED_MODULE, - util::DiagnosticMessageParams {util::StringView(filePath)}, *srcPos_); + util::DiagnosticMessageParams {util::StringView(filePath)}, srcPos_); return ""; } diff --git a/ets2panda/util/importPathManager.h b/ets2panda/util/importPathManager.h index 9e011a215919850377801f2c805284ab4e50a03d..169960dff2f4533702a06388d342749e11489e7b 100644 --- a/ets2panda/util/importPathManager.h +++ b/ets2panda/util/importPathManager.h @@ -181,7 +181,7 @@ private: parser::Program *globalProgram_; util::DiagnosticEngine &diagnosticEngine_; std::string_view pathDelimiter_ {ark::os::file::File::GetPathDelim()}; - mutable const lexer::SourcePosition *srcPos_ {}; + mutable lexer::SourcePosition srcPos_ {}; bool isDynamic_ = false; }; diff --git a/ets2panda/util/perfMetrics.cpp b/ets2panda/util/perfMetrics.cpp index 7d207d956f8f51069209884686c0b2528b2cbb1d..981ec934c40d631b1461b4f71c4f1e24e5b40a8e 100644 --- a/ets2panda/util/perfMetrics.cpp +++ b/ets2panda/util/perfMetrics.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #ifdef PANDA_TARGET_UNIX #include "sys/resource.h" @@ -226,7 +227,7 @@ static void DumpPerfMetricRecord(std::stringstream &ss, PerfMetricRecord const * auto const &stats = rec->GetStats(); // NOLINTBEGIN(readability-magic-numbers) - ss << "#" << std::left << std::setw(50U) << rec->GetName() << ": "; + ss << ":" << std::left << std::setw(50U) << rec->GetName() << ": "; if (rec->GetMaxNesting() > 1) { metric("nesting", 6U) << rec->GetMaxNesting(); } @@ -240,11 +241,14 @@ static void DumpPerfMetricRecord(std::stringstream &ss, PerfMetricRecord const * // NOLINTEND(readability-magic-numbers) } -// You may want to add __attribute__((destructor)) for the debugging needs -void DumpPerfMetrics() +static void DumpPerfMetricsImpl(std::optional prefix) { std::lock_guard lk(g_perfMetricsListsMtx); // prevents new thread from appearing + if (g_perfMetricsLists.begin() == g_perfMetricsLists.end()) { + return; + } + auto getSortVal = [](PerfMetricRecord *rec) { return rec->GetStats().GetTimeNanoseconds(); }; std::stringstream ss; @@ -253,7 +257,9 @@ void DumpPerfMetrics() for (auto &tlsdata : g_perfMetricsLists) { std::vector records; for (auto &rec : tlsdata.second) { - records.push_back(&rec); + if (prefix.has_value() && rec.GetName().rfind(*prefix, 0) != std::string::npos) { + records.push_back(&rec); + } } std::sort(records.begin(), records.end(), [getSortVal](PerfMetricRecord *r1, PerfMetricRecord *r2) { return getSortVal(r1) > getSortVal(r2); }); @@ -269,4 +275,15 @@ void DumpPerfMetrics() std::cout << ss.str(); } +void DumpPerfMetrics() +{ + DumpPerfMetricsImpl("@"); +} + +// You may want to add __attribute__((destructor)) for the debugging needs +[[maybe_unused]] static void DbgDumpPerfMetrics() +{ + DumpPerfMetricsImpl("%"); +} + } // namespace ark::es2panda::util