• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "varbinder/ETSBinder.h"
17 #include "checker/ETSchecker.h"
18 #include "checker/ets/castingContext.h"
19 #include "checker/ets/function_helpers.h"
20 #include "checker/ets/typeRelationContext.h"
21 #include "checker/types/ets/etsAsyncFuncReturnType.h"
22 #include "checker/types/ets/etsObjectType.h"
23 #include "ir/base/catchClause.h"
24 #include "ir/base/classDefinition.h"
25 #include "ir/base/classProperty.h"
26 #include "ir/base/methodDefinition.h"
27 #include "ir/base/scriptFunction.h"
28 #include "ir/base/spreadElement.h"
29 #include "ir/ets/etsFunctionType.h"
30 #include "ir/ets/etsParameterExpression.h"
31 #include "ir/ets/etsTypeReference.h"
32 #include "ir/ets/etsTypeReferencePart.h"
33 #include "ir/ets/etsUnionType.h"
34 #include "ir/expressions/arrowFunctionExpression.h"
35 #include "ir/expressions/assignmentExpression.h"
36 #include "ir/expressions/callExpression.h"
37 #include "ir/expressions/functionExpression.h"
38 #include "ir/expressions/identifier.h"
39 #include "ir/expressions/literals/numberLiteral.h"
40 #include "ir/expressions/literals/undefinedLiteral.h"
41 #include "ir/expressions/memberExpression.h"
42 #include "ir/expressions/objectExpression.h"
43 #include "ir/expressions/thisExpression.h"
44 #include "ir/statements/blockStatement.h"
45 #include "ir/statements/doWhileStatement.h"
46 #include "ir/statements/expressionStatement.h"
47 #include "ir/statements/forInStatement.h"
48 #include "ir/statements/forOfStatement.h"
49 #include "ir/statements/forUpdateStatement.h"
50 #include "ir/statements/returnStatement.h"
51 #include "ir/statements/switchStatement.h"
52 #include "ir/statements/whileStatement.h"
53 #include "ir/ts/tsTypeAliasDeclaration.h"
54 #include "ir/ts/tsTypeParameter.h"
55 #include "ir/ts/tsTypeParameterInstantiation.h"
56 #include "parser/program/program.h"
57 #include "util/helpers.h"
58 #include "util/language.h"
59 
60 namespace ark::es2panda::checker {
61 
62 // NOTE: #14993 merge with InstantiationContext::ValidateTypeArg
IsCompatibleTypeArgument(ETSTypeParameter * typeParam,Type * typeArgument,const Substitution * substitution)63 bool ETSChecker::IsCompatibleTypeArgument(ETSTypeParameter *typeParam, Type *typeArgument,
64                                           const Substitution *substitution)
65 {
66     if (typeArgument->IsWildcardType()) {
67         return true;
68     }
69     ASSERT(IsReferenceType(typeArgument) || typeArgument->IsETSVoidType());
70     auto *constraint = typeParam->GetConstraintType()->Substitute(Relation(), substitution);
71     if (typeArgument->IsETSVoidType()) {
72         return Relation()->IsSupertypeOf(constraint, GlobalETSUndefinedType());
73     }
74     return Relation()->IsSupertypeOf(constraint, typeArgument);
75 }
76 
HasTypeArgsOfObject(Type * argType,Type * paramType)77 bool ETSChecker::HasTypeArgsOfObject(Type *argType, Type *paramType)
78 {
79     return paramType->IsETSObjectType() && argType->IsETSObjectType() &&
80            !argType->AsETSObjectType()->TypeArguments().empty() &&
81            !paramType->AsETSObjectType()->TypeArguments().empty();
82 }
83 
InsertTypeIntoSubstitution(const ArenaVector<Type * > & typeParams,const Type * typeParam,const size_t index,Substitution * substitution,Type * objectParam)84 bool ETSChecker::InsertTypeIntoSubstitution(const ArenaVector<Type *> &typeParams, const Type *typeParam,
85                                             const size_t index, Substitution *substitution, Type *objectParam)
86 {
87     // Check if the type parameter is in the signature, and the type argument is not already in the return vector
88     if (typeParams.size() > index &&
89         IsCompatibleTypeArgument(typeParams[index]->AsETSTypeParameter(), objectParam, substitution) &&
90         std::find(typeParams.begin(), typeParams.end(), typeParam) != typeParams.end()) {
91         substitution->emplace(typeParams[index]->AsETSTypeParameter(), objectParam);
92         return true;
93     }
94 
95     return false;
96 }
97 
EnhanceSubstitutionForGenericType(const ArenaVector<Type * > & typeParams,const Type * argType,const Type * paramType,Substitution * substitution)98 bool ETSChecker::EnhanceSubstitutionForGenericType(const ArenaVector<Type *> &typeParams, const Type *argType,
99                                                    const Type *paramType, Substitution *substitution)
100 {
101     ArenaVector<Type *> objectParams(Allocator()->Adapter());
102 
103     if (!argType->AsETSObjectType()->GetDeclNode()->IsClassDefinition()) {
104         return false;
105     }
106 
107     const auto paramTypeArgs = paramType->AsETSObjectType()->TypeArguments();
108 
109     for (const auto it : typeParams) {
110         bool found = false;
111 
112         for (size_t i = 0; i < paramTypeArgs.size() && !found; i++) {
113             if (paramTypeArgs[i] == it) {
114                 objectParams.push_back(argType->AsETSObjectType()->TypeArguments()[i]);
115                 found = true;
116             }
117         }
118 
119         if (!found) {
120             objectParams.push_back(nullptr);
121         }
122     }
123 
124     if (objectParams.size() < paramTypeArgs.size()) {
125         return false;
126     }
127 
128     bool res = true;
129     for (size_t j = 0; j < paramTypeArgs.size() && res; ++j) {
130         if (objectParams[j] != nullptr) {
131             res = InsertTypeIntoSubstitution(typeParams, paramTypeArgs[j], j, substitution, objectParams[j]);
132         } else {
133             res = EnhanceSubstitutionForType(typeParams, paramTypeArgs[j],
134                                              argType->AsETSObjectType()->TypeArguments()[j], substitution);
135         }
136     }
137 
138     return res;
139 }
140 
EnhanceSubstitutionForReadonly(const ArenaVector<Type * > & typeParams,ETSReadonlyType * paramType,Type * argumentType,Substitution * substitution)141 bool ETSChecker::EnhanceSubstitutionForReadonly(const ArenaVector<Type *> &typeParams, ETSReadonlyType *paramType,
142                                                 Type *argumentType, Substitution *substitution)
143 {
144     return EnhanceSubstitutionForType(typeParams, paramType->GetUnderlying(), GetReadonlyType(argumentType),
145                                       substitution);
146 }
147 
148 /* A very rough and imprecise partial type inference */
EnhanceSubstitutionForType(const ArenaVector<Type * > & typeParams,Type * paramType,Type * argumentType,Substitution * substitution)149 bool ETSChecker::EnhanceSubstitutionForType(const ArenaVector<Type *> &typeParams, Type *paramType, Type *argumentType,
150                                             Substitution *substitution)
151 {
152     if (argumentType->HasTypeFlag(TypeFlag::ETS_PRIMITIVE)) {
153         argumentType = PrimitiveTypeAsETSBuiltinType(argumentType);
154     }
155     if (paramType->IsETSTypeParameter()) {
156         auto *const tparam = paramType->AsETSTypeParameter();
157         auto *const originalTparam = tparam->GetOriginal();
158         if (std::find(typeParams.begin(), typeParams.end(), originalTparam) != typeParams.end() &&
159             substitution->count(originalTparam) == 0) {
160             if (!IsReferenceType(argumentType)) {
161                 ThrowTypeError({argumentType, " is not compatible with type ", tparam}, tparam->GetDeclNode()->Start());
162             }
163 
164             ETSChecker::EmplaceSubstituted(substitution, originalTparam, argumentType);
165             return IsCompatibleTypeArgument(tparam, argumentType, substitution);
166         }
167     }
168 
169     if (paramType->IsETSReadonlyType()) {
170         return EnhanceSubstitutionForReadonly(typeParams, paramType->AsETSReadonlyType(), argumentType, substitution);
171     }
172     if (paramType->IsETSUnionType()) {
173         return EnhanceSubstitutionForUnion(typeParams, paramType->AsETSUnionType(), argumentType, substitution);
174     }
175     if (paramType->IsETSObjectType()) {
176         if (HasTypeArgsOfObject(argumentType, paramType) &&
177             EnhanceSubstitutionForGenericType(typeParams, argumentType, paramType, substitution)) {
178             return true;
179         }
180         return EnhanceSubstitutionForObject(typeParams, paramType->AsETSObjectType(), argumentType, substitution);
181     }
182     if (paramType->IsETSArrayType()) {
183         return EnhanceSubstitutionForArray(typeParams, paramType->AsETSArrayType(), argumentType, substitution);
184     }
185 
186     return true;
187 }
188 
EnhanceSubstitutionForUnion(const ArenaVector<Type * > & typeParams,ETSUnionType * paramUn,Type * argumentType,Substitution * substitution)189 bool ETSChecker::EnhanceSubstitutionForUnion(const ArenaVector<Type *> &typeParams, ETSUnionType *paramUn,
190                                              Type *argumentType, Substitution *substitution)
191 {
192     if (!argumentType->IsETSUnionType()) {
193         return std::any_of(
194             paramUn->ConstituentTypes().begin(), paramUn->ConstituentTypes().end(),
195             [this, typeParams, argumentType, substitution](Type *ctype) {
196                 return EnhanceSubstitutionForType(typeParams, ctype, argumentType, substitution) &&
197                        (!ctype->IsETSTypeParameter() ||
198                         (substitution->find(ctype->AsETSTypeParameter()) != substitution->end() &&
199                          Relation()->IsAssignableTo(argumentType, substitution->at(ctype->AsETSTypeParameter()))));
200             });
201     }
202     auto *const argUn = argumentType->AsETSUnionType();
203 
204     ArenaVector<Type *> paramWlist(Allocator()->Adapter());
205     ArenaVector<Type *> argWlist(Allocator()->Adapter());
206 
207     for (auto *pc : paramUn->ConstituentTypes()) {
208         for (auto *ac : argUn->ConstituentTypes()) {
209             if (ETSChecker::GetOriginalBaseType(pc) != ETSChecker::GetOriginalBaseType(ac)) {
210                 paramWlist.push_back(pc);
211                 argWlist.push_back(ac);
212                 continue;
213             }
214             if (!EnhanceSubstitutionForType(typeParams, pc, ac, substitution)) {
215                 return false;
216             }
217         }
218     }
219     auto *const newArg = CreateETSUnionType(std::move(argWlist));
220 
221     for (auto *pc : paramWlist) {
222         if (!EnhanceSubstitutionForType(typeParams, pc, newArg, substitution)) {
223             return false;
224         }
225     }
226     return true;
227 }
228 
EnhanceSubstitutionForObject(const ArenaVector<Type * > & typeParams,ETSObjectType * paramType,Type * argumentType,Substitution * substitution)229 bool ETSChecker::EnhanceSubstitutionForObject(const ArenaVector<Type *> &typeParams, ETSObjectType *paramType,
230                                               Type *argumentType, Substitution *substitution)
231 {
232     auto *paramObjType = paramType->AsETSObjectType();
233 
234     auto const enhance = [this, typeParams, substitution](Type *ptype, Type *atype) {
235         return EnhanceSubstitutionForType(typeParams, ptype, atype, substitution);
236     };
237 
238     if (argumentType->IsETSObjectType()) {
239         auto *argObjType = argumentType->AsETSObjectType();
240         if (GetOriginalBaseType(argObjType) != GetOriginalBaseType(paramObjType)) {
241             return true;  // don't attempt anything fancy for now
242         }
243         bool res = true;
244         for (size_t i = 0; i < argObjType->TypeArguments().size(); i++) {
245             res &= enhance(paramObjType->TypeArguments()[i], argObjType->TypeArguments()[i]);
246         }
247         return res;
248     }
249 
250     if (argumentType->IsETSFunctionType() && paramObjType->HasObjectFlag(ETSObjectFlags::FUNCTIONAL_INTERFACE)) {
251         auto &parameterSignatures =
252             paramObjType
253                 ->GetOwnProperty<checker::PropertyType::INSTANCE_METHOD>(FUNCTIONAL_INTERFACE_INVOKE_METHOD_NAME)
254                 ->TsType()
255                 ->AsETSFunctionType()
256                 ->CallSignatures();
257         auto &argumentSignatures = argumentType->AsETSFunctionType()->CallSignatures();
258         ASSERT(argumentSignatures.size() == 1);
259         ASSERT(parameterSignatures.size() == 1);
260         auto *argumentSignature = argumentSignatures[0];
261         auto *parameterSignature = parameterSignatures[0];
262         // NOTE(gogabr): handle rest parameter for argumentSignature
263         if (parameterSignature->GetSignatureInfo()->params.size() !=
264             argumentSignature->GetSignatureInfo()->params.size()) {
265             return false;
266         }
267         bool res = true;
268         for (size_t idx = 0; idx < argumentSignature->GetSignatureInfo()->params.size(); idx++) {
269             res &= enhance(parameterSignature->GetSignatureInfo()->params[idx]->TsType(),
270                            argumentSignature->GetSignatureInfo()->params[idx]->TsType());
271         }
272         res &= enhance(parameterSignature->ReturnType(), argumentSignature->ReturnType());
273         return res;
274     }
275 
276     return true;
277 }
278 
EnhanceSubstitutionForArray(const ArenaVector<Type * > & typeParams,ETSArrayType * const paramType,Type * const argumentType,Substitution * const substitution)279 bool ETSChecker::EnhanceSubstitutionForArray(const ArenaVector<Type *> &typeParams, ETSArrayType *const paramType,
280                                              Type *const argumentType, Substitution *const substitution)
281 {
282     auto *const elementType =
283         argumentType->IsETSArrayType() ? argumentType->AsETSArrayType()->ElementType() : argumentType;
284 
285     return EnhanceSubstitutionForType(typeParams, paramType->ElementType(), elementType, substitution);
286 }
287 
ValidateParameterlessConstructor(Signature * signature,const lexer::SourcePosition & pos,TypeRelationFlag flags)288 Signature *ETSChecker::ValidateParameterlessConstructor(Signature *signature, const lexer::SourcePosition &pos,
289                                                         TypeRelationFlag flags)
290 {
291     std::size_t const parameterCount = signature->MinArgCount();
292     auto const throwError = (flags & TypeRelationFlag::NO_THROW) == 0;
293 
294     if (parameterCount != 0) {
295         if (throwError) {
296             ThrowTypeError({"No Matching Parameterless Constructor, parameter count ", parameterCount}, pos);
297         }
298         return nullptr;
299     }
300     return signature;
301 }
302 
CheckOptionalLambdaFunction(ir::Expression * argument,Signature * substitutedSig,std::size_t index)303 bool ETSChecker::CheckOptionalLambdaFunction(ir::Expression *argument, Signature *substitutedSig, std::size_t index)
304 {
305     if (argument->IsArrowFunctionExpression()) {
306         auto *const arrowFuncExpr = argument->AsArrowFunctionExpression();
307 
308         if (ir::ScriptFunction *const lambda = arrowFuncExpr->Function();
309             CheckLambdaAssignable(substitutedSig->Function()->Params()[index], lambda)) {
310             if (arrowFuncExpr->TsType() != nullptr) {
311                 arrowFuncExpr->Check(this);
312                 return true;
313             }
314         }
315     }
316 
317     return false;
318 }
319 
ValidateArgumentAsIdentifier(const ir::Identifier * identifier)320 bool ETSChecker::ValidateArgumentAsIdentifier(const ir::Identifier *identifier)
321 {
322     auto result = Scope()->Find(identifier->Name());
323     return result.variable != nullptr && (result.variable->HasFlag(varbinder::VariableFlags::CLASS_OR_INTERFACE));
324 }
325 
ValidateSignatureRequiredParams(Signature * substitutedSig,const ArenaVector<ir::Expression * > & arguments,TypeRelationFlag flags,const std::vector<bool> & argTypeInferenceRequired,bool throwError)326 bool ETSChecker::ValidateSignatureRequiredParams(Signature *substitutedSig,
327                                                  const ArenaVector<ir::Expression *> &arguments, TypeRelationFlag flags,
328                                                  const std::vector<bool> &argTypeInferenceRequired, bool throwError)
329 {
330     std::size_t const argumentCount = arguments.size();
331     std::size_t const parameterCount = substitutedSig->MinArgCount();
332     auto count = std::min(parameterCount, argumentCount);
333     for (std::size_t index = 0; index < count; ++index) {
334         auto &argument = arguments[index];
335 
336         if (argument->IsObjectExpression()) {
337             if (substitutedSig->Params()[index]->TsType()->IsETSObjectType()) {
338                 // No chance to check the argument at this point
339                 continue;
340             }
341             return false;
342         }
343 
344         if (argument->IsMemberExpression()) {
345             SetArrayPreferredTypeForNestedMemberExpressions(arguments[index]->AsMemberExpression(),
346                                                             substitutedSig->Params()[index]->TsType());
347         } else if (argument->IsSpreadElement()) {
348             if (throwError) {
349                 ThrowTypeError("Spread argument cannot be passed for ordinary parameter.", argument->Start());
350             }
351             return false;
352         }
353 
354         if (argTypeInferenceRequired[index]) {
355             ASSERT(argument->IsArrowFunctionExpression());
356             auto *const arrowFuncExpr = argument->AsArrowFunctionExpression();
357             ir::ScriptFunction *const lambda = arrowFuncExpr->Function();
358             if (CheckLambdaAssignable(substitutedSig->Function()->Params()[index], lambda)) {
359                 continue;
360             }
361             return false;
362         }
363 
364         if (argument->IsArrayExpression()) {
365             argument->AsArrayExpression()->GetPrefferedTypeFromFuncParam(
366                 this, substitutedSig->Function()->Params()[index], flags);
367         }
368 
369         if (!CheckInvokable(substitutedSig, argument, index, flags)) {
370             return false;
371         }
372 
373         if (argument->IsIdentifier() && ValidateArgumentAsIdentifier(argument->AsIdentifier())) {
374             ThrowTypeError("Class name can't be the argument of function or method.", argument->Start());
375         }
376 
377         // clang-format off
378         if (!ValidateSignatureInvocationContext(
379             substitutedSig, argument,
380             TryGettingFunctionTypeFromInvokeFunction(substitutedSig->Params()[index]->TsType()), index, flags)) {
381             // clang-format on
382             return false;
383         }
384     }
385 
386     return true;
387 }
388 
CheckInvokable(Signature * substitutedSig,ir::Expression * argument,std::size_t index,TypeRelationFlag flags)389 bool ETSChecker::CheckInvokable(Signature *substitutedSig, ir::Expression *argument, std::size_t index,
390                                 TypeRelationFlag flags)
391 {
392     auto *argumentType = argument->Check(this);
393     auto *targetType = substitutedSig->Params()[index]->TsType();
394 
395     auto const invocationCtx =
396         checker::InvocationContext(Relation(), argument, argumentType, targetType, argument->Start(),
397                                    {"Type '", argumentType, "' is not compatible with type '",
398                                     TryGettingFunctionTypeFromInvokeFunction(targetType), "' at index ", index + 1},
399                                    flags);
400     return invocationCtx.IsInvocable() || CheckOptionalLambdaFunction(argument, substitutedSig, index);
401 }
402 
ValidateSignatureInvocationContext(Signature * substitutedSig,ir::Expression * argument,const Type * targetType,std::size_t index,TypeRelationFlag flags)403 bool ETSChecker::ValidateSignatureInvocationContext(Signature *substitutedSig, ir::Expression *argument,
404                                                     const Type *targetType, std::size_t index, TypeRelationFlag flags)
405 {
406     Type *argumentType = argument->Check(this);
407     auto const invocationCtx = checker::InvocationContext(
408         Relation(), argument, argumentType, substitutedSig->Params()[index]->TsType(), argument->Start(),
409         {"Type '", argumentType, "' is not compatible with type '", targetType, "' at index ", index + 1}, flags);
410     if (!invocationCtx.IsInvocable()) {
411         return CheckOptionalLambdaFunction(argument, substitutedSig, index);
412     }
413 
414     return true;
415 }
416 
ValidateSignatureRestParams(Signature * substitutedSig,const ArenaVector<ir::Expression * > & arguments,TypeRelationFlag flags,bool throwError)417 bool ETSChecker::ValidateSignatureRestParams(Signature *substitutedSig, const ArenaVector<ir::Expression *> &arguments,
418                                              TypeRelationFlag flags, bool throwError)
419 {
420     std::size_t const argumentCount = arguments.size();
421     std::size_t const parameterCount = substitutedSig->MinArgCount();
422     auto count = std::min(parameterCount, argumentCount);
423     auto const restCount = argumentCount - count;
424 
425     for (std::size_t index = count; index < argumentCount; ++index) {
426         auto &argument = arguments[index];
427 
428         if (!argument->IsSpreadElement()) {
429             auto *const argumentType = argument->Check(this);
430             const Type *targetType = TryGettingFunctionTypeFromInvokeFunction(
431                 substitutedSig->RestVar()->TsType()->AsETSArrayType()->ElementType());
432             const Type *sourceType = TryGettingFunctionTypeFromInvokeFunction(argumentType);
433             auto const invocationCtx = checker::InvocationContext(
434                 Relation(), argument, argumentType,
435                 substitutedSig->RestVar()->TsType()->AsETSArrayType()->ElementType(), argument->Start(),
436                 {"Type '", sourceType, "' is not compatible with rest parameter type '", targetType, "' at index ",
437                  index + 1},
438                 flags);
439             if (!invocationCtx.IsInvocable()) {
440                 return false;
441             }
442             continue;
443         }
444 
445         if (restCount > 1U) {
446             if (throwError) {
447                 ThrowTypeError("Spread argument for the rest parameter can be only one.", argument->Start());
448             }
449             return false;
450         }
451 
452         auto *const restArgument = argument->AsSpreadElement()->Argument();
453         auto *const argumentType = restArgument->Check(this);
454         const Type *targetType = TryGettingFunctionTypeFromInvokeFunction(substitutedSig->RestVar()->TsType());
455         const Type *sourceType = TryGettingFunctionTypeFromInvokeFunction(argumentType);
456 
457         auto const invocationCtx = checker::InvocationContext(
458             Relation(), restArgument, argumentType, substitutedSig->RestVar()->TsType(), argument->Start(),
459             {"Type '", sourceType, "' is not compatible with rest parameter type '", targetType, "' at index ",
460              index + 1},
461             flags);
462         if (!invocationCtx.IsInvocable()) {
463             return false;
464         }
465     }
466 
467     return true;
468 }
469 
MaybeSubstituteLambdaArgumentsInFunctionCall(ir::CallExpression * callExpr)470 void ETSChecker::MaybeSubstituteLambdaArgumentsInFunctionCall(ir::CallExpression *callExpr)
471 {
472     ir::AstNode *expr = callExpr;
473 
474     while (!expr->IsFunctionExpression()) {
475         if (expr->Parent() == nullptr || expr->Parent()->IsClassDefinition()) {
476             return;
477         }
478         expr = expr->Parent();
479     }
480 
481     for (const auto it : expr->AsFunctionExpression()->Function()->Params()) {
482         if (const auto ident = it->AsETSParameterExpression()->Ident();
483             callExpr->Callee()->IsIdentifier() && ident->Name() == callExpr->Callee()->AsIdentifier()->Name() &&
484             ident->IsAnnotatedExpression()) {
485             if (ident->AsAnnotatedExpression()->TypeAnnotation()->IsETSFunctionType()) {
486                 MaybeSubstituteLambdaArguments(
487                     ident->AsAnnotatedExpression()->TypeAnnotation()->AsETSFunctionType()->Params(), callExpr);
488             }
489         }
490     }
491 }
492 
MaybeSubstituteLambdaArgumentsInFunctionCallHelper(ir::CallExpression * callExpr,ir::Identifier * ident)493 void ETSChecker::MaybeSubstituteLambdaArgumentsInFunctionCallHelper(ir::CallExpression *callExpr, ir::Identifier *ident)
494 {
495     ir::ETSFunctionType *funcType = nullptr;
496     ir::TypeNode *typeAnnotation = ident->TypeAnnotation();
497 
498     if (typeAnnotation->IsETSTypeReference()) {
499         auto typeAnnotationIdentifier = ident->TypeAnnotation()->AsETSTypeReference()->Part()->Name()->Variable();
500         typeAnnotation = typeAnnotationIdentifier->Declaration()->Node()->AsTSTypeAliasDeclaration()->TypeAnnotation();
501     }
502 
503     if (typeAnnotation->IsETSFunctionType()) {
504         funcType = typeAnnotation->AsETSFunctionType();
505     } else if (typeAnnotation->IsETSUnionType()) {
506         auto found = std::find_if(typeAnnotation->AsETSUnionType()->Types().begin(),
507                                   typeAnnotation->AsETSUnionType()->Types().end(),
508                                   [](ir::TypeNode *const type) { return type->IsETSFunctionType(); });
509         if (found != typeAnnotation->AsETSUnionType()->Types().end()) {
510             funcType = (*found)->AsETSFunctionType();
511         }
512     }
513 
514     if (funcType == nullptr) {
515         return;
516     }
517 
518     MaybeSubstituteLambdaArguments(funcType->AsETSFunctionType()->Params(), callExpr);
519 }
520 
MaybeSubstituteLambdaArguments(const ArenaVector<ir::Expression * > & params,ir::CallExpression * callExpr)521 void ETSChecker::MaybeSubstituteLambdaArguments(const ArenaVector<ir::Expression *> &params,
522                                                 ir::CallExpression *callExpr)
523 {
524     for (size_t i = 0; i < params.size(); i++) {
525         if (params[i]->AsETSParameterExpression()->IsDefault() && callExpr->Arguments().size() <= i &&
526             params[i]->AsETSParameterExpression()->Initializer() != nullptr) {
527             callExpr->Arguments().push_back(
528                 params[i]->AsETSParameterExpression()->Initializer()->Clone(Allocator(), callExpr)->AsExpression());
529         }
530     }
531 }
532 
ValidateSignature(std::tuple<Signature *,const ir::TSTypeParameterInstantiation *,TypeRelationFlag> info,const ArenaVector<ir::Expression * > & arguments,const lexer::SourcePosition & pos,const std::vector<bool> & argTypeInferenceRequired)533 Signature *ETSChecker::ValidateSignature(
534     std::tuple<Signature *, const ir::TSTypeParameterInstantiation *, TypeRelationFlag> info,
535     const ArenaVector<ir::Expression *> &arguments, const lexer::SourcePosition &pos,
536     const std::vector<bool> &argTypeInferenceRequired)
537 {
538     auto [signature, typeArguments, flags] = info;
539     Signature *substitutedSig = MaybeSubstituteTypeParameters(this, signature, typeArguments, arguments, pos, flags);
540     if (substitutedSig == nullptr) {
541         return nullptr;
542     }
543 
544     fflush(stdout);
545 
546     auto const hasRestParameter = substitutedSig->RestVar() != nullptr;
547     std::size_t const argumentCount = arguments.size();
548     std::size_t const parameterCount = substitutedSig->MinArgCount();
549     auto const throwError = (flags & TypeRelationFlag::NO_THROW) == 0;
550 
551     if (argumentCount < parameterCount || (argumentCount > parameterCount && !hasRestParameter)) {
552         if (throwError) {
553             ThrowTypeError({"Expected ", parameterCount, " arguments, got ", argumentCount, "."}, pos);
554         }
555         return nullptr;
556     }
557 
558     if (argumentCount > parameterCount && hasRestParameter && (flags & TypeRelationFlag::IGNORE_REST_PARAM) != 0) {
559         return nullptr;
560     }
561 
562     auto count = std::min(parameterCount, argumentCount);
563     // Check all required formal parameter(s) first
564     if (!ValidateSignatureRequiredParams(substitutedSig, arguments, flags, argTypeInferenceRequired, throwError)) {
565         return nullptr;
566     }
567 
568     // Check rest parameter(s) if any exists
569     if (!hasRestParameter || count >= argumentCount) {
570         return substitutedSig;
571     }
572     if (!ValidateSignatureRestParams(substitutedSig, arguments, flags, throwError)) {
573         return nullptr;
574     }
575 
576     return substitutedSig;
577 }
578 
CollectParameterlessConstructor(ArenaVector<Signature * > & signatures,const lexer::SourcePosition & pos,TypeRelationFlag resolveFlags)579 Signature *ETSChecker::CollectParameterlessConstructor(ArenaVector<Signature *> &signatures,
580                                                        const lexer::SourcePosition &pos, TypeRelationFlag resolveFlags)
581 {
582     Signature *compatibleSignature = nullptr;
583 
584     auto collectSignatures = [&](TypeRelationFlag relationFlags) {
585         for (auto *sig : signatures) {
586             if (auto *concreteSig = ValidateParameterlessConstructor(sig, pos, relationFlags); concreteSig != nullptr) {
587                 compatibleSignature = concreteSig;
588                 break;
589             }
590         }
591     };
592 
593     // We are able to provide more specific error messages.
594     if (signatures.size() == 1) {
595         collectSignatures(resolveFlags);
596     } else {
597         collectSignatures(resolveFlags | TypeRelationFlag::NO_THROW);
598     }
599 
600     if (compatibleSignature == nullptr) {
601         if ((resolveFlags & TypeRelationFlag::NO_THROW) == 0) {
602             ThrowTypeError({"No matching parameterless constructor"}, pos);
603         } else {
604             return nullptr;
605         }
606     }
607     return compatibleSignature;
608 }
609 
IsSignatureAccessible(Signature * sig,ETSObjectType * containingClass,TypeRelation * relation)610 bool IsSignatureAccessible(Signature *sig, ETSObjectType *containingClass, TypeRelation *relation)
611 {
612     // NOTE(vivienvoros): this check can be removed if signature is implicitly declared as public according to the spec.
613     if (!sig->HasSignatureFlag(SignatureFlags::PUBLIC | SignatureFlags::PROTECTED | SignatureFlags::PRIVATE |
614                                SignatureFlags::INTERNAL)) {
615         return true;
616     }
617 
618     // NOTE(vivienvoros): take care of SignatureFlags::INTERNAL and SignatureFlags::INTERNAL_PROTECTED
619     if (sig->HasSignatureFlag(SignatureFlags::INTERNAL) && !sig->HasSignatureFlag(SignatureFlags::PROTECTED)) {
620         return true;
621     }
622 
623     if (sig->HasSignatureFlag(SignatureFlags::PUBLIC) || sig->Owner() == containingClass ||
624         (sig->HasSignatureFlag(SignatureFlags::PROTECTED) && relation->IsSupertypeOf(sig->Owner(), containingClass))) {
625         return true;
626     }
627 
628     return false;
629 }
630 
631 // NOLINTNEXTLINE(readability-magic-numbers)
GetFlagVariants()632 std::array<TypeRelationFlag, 9U> GetFlagVariants()
633 {
634     // NOTE(boglarkahaag): Not in sync with specification, but solves the issues with rest params for now (#17483)
635     return {
636         TypeRelationFlag::NO_THROW | TypeRelationFlag::NO_UNBOXING | TypeRelationFlag::NO_BOXING |
637             TypeRelationFlag::IGNORE_REST_PARAM,
638         TypeRelationFlag::NO_THROW | TypeRelationFlag::NO_UNBOXING | TypeRelationFlag::NO_BOXING,
639         TypeRelationFlag::NO_THROW | TypeRelationFlag::IGNORE_REST_PARAM,
640         TypeRelationFlag::NO_THROW,
641         TypeRelationFlag::NO_THROW | TypeRelationFlag::WIDENING | TypeRelationFlag::NO_UNBOXING |
642             TypeRelationFlag::NO_BOXING | TypeRelationFlag::IGNORE_REST_PARAM,
643         TypeRelationFlag::NO_THROW | TypeRelationFlag::WIDENING | TypeRelationFlag::NO_UNBOXING |
644             TypeRelationFlag::NO_BOXING,
645         TypeRelationFlag::NO_THROW | TypeRelationFlag::WIDENING | TypeRelationFlag::IGNORE_REST_PARAM,
646         TypeRelationFlag::NO_THROW | TypeRelationFlag::WIDENING,
647         TypeRelationFlag::NO_THROW | TypeRelationFlag::STRING_TO_CHAR,
648     };
649 }
CollectSignatures(ArenaVector<Signature * > & signatures,const ir::TSTypeParameterInstantiation * typeArguments,const ArenaVector<ir::Expression * > & arguments,const lexer::SourcePosition & pos,TypeRelationFlag resolveFlags)650 ArenaVector<Signature *> ETSChecker::CollectSignatures(ArenaVector<Signature *> &signatures,
651                                                        const ir::TSTypeParameterInstantiation *typeArguments,
652                                                        const ArenaVector<ir::Expression *> &arguments,
653                                                        const lexer::SourcePosition &pos, TypeRelationFlag resolveFlags)
654 {
655     ArenaVector<Signature *> compatibleSignatures(Allocator()->Adapter());
656     std::vector<bool> argTypeInferenceRequired = FindTypeInferenceArguments(arguments);
657     Signature *notVisibleSignature = nullptr;
658 
659     auto collectSignatures = [&](TypeRelationFlag relationFlags) {
660         for (auto *sig : signatures) {
661             if (notVisibleSignature != nullptr &&
662                 !IsSignatureAccessible(sig, Context().ContainingClass(), Relation())) {
663                 continue;
664             }
665             auto *concreteSig = ValidateSignature(std::make_tuple(sig, typeArguments, relationFlags), arguments, pos,
666                                                   argTypeInferenceRequired);
667             if (concreteSig == nullptr) {
668                 continue;
669             }
670             if (notVisibleSignature == nullptr &&
671                 !IsSignatureAccessible(sig, Context().ContainingClass(), Relation())) {
672                 notVisibleSignature = concreteSig;
673             } else {
674                 compatibleSignatures.push_back(concreteSig);
675             }
676         }
677     };
678 
679     // If there's only one signature, we don't need special checks for boxing/unboxing/widening.
680     // We are also able to provide more specific error messages.
681     if (signatures.size() == 1) {
682         TypeRelationFlag flags = TypeRelationFlag::WIDENING | TypeRelationFlag::STRING_TO_CHAR | resolveFlags;
683         collectSignatures(flags);
684     } else {
685         for (auto flags : GetFlagVariants()) {
686             flags = flags | resolveFlags;
687             collectSignatures(flags);
688             if (!compatibleSignatures.empty()) {
689                 break;
690             }
691         }
692     }
693 
694     if (compatibleSignatures.empty() && notVisibleSignature != nullptr) {
695         ThrowTypeError(
696             {"Signature ", notVisibleSignature->Function()->Id()->Name(), notVisibleSignature, " is not visible here."},
697             pos);
698     }
699     return compatibleSignatures;
700 }
701 
GetMostSpecificSignature(ArenaVector<Signature * > & compatibleSignatures,const ArenaVector<ir::Expression * > & arguments,const lexer::SourcePosition & pos,TypeRelationFlag resolveFlags)702 Signature *ETSChecker::GetMostSpecificSignature(ArenaVector<Signature *> &compatibleSignatures,
703                                                 const ArenaVector<ir::Expression *> &arguments,
704                                                 const lexer::SourcePosition &pos, TypeRelationFlag resolveFlags)
705 {
706     std::vector<bool> argTypeInferenceRequired = FindTypeInferenceArguments(arguments);
707     Signature *mostSpecificSignature = ChooseMostSpecificSignature(compatibleSignatures, argTypeInferenceRequired, pos);
708 
709     if (mostSpecificSignature == nullptr) {
710         ThrowTypeError({"Reference to ", compatibleSignatures.front()->Function()->Id()->Name(), " is ambiguous"}, pos);
711     }
712 
713     if (!TypeInference(mostSpecificSignature, arguments, resolveFlags)) {
714         return nullptr;
715     }
716 
717     return mostSpecificSignature;
718 }
719 
ValidateSignatures(ArenaVector<Signature * > & signatures,const ir::TSTypeParameterInstantiation * typeArguments,const ArenaVector<ir::Expression * > & arguments,const lexer::SourcePosition & pos,std::string_view signatureKind,TypeRelationFlag resolveFlags)720 Signature *ETSChecker::ValidateSignatures(ArenaVector<Signature *> &signatures,
721                                           const ir::TSTypeParameterInstantiation *typeArguments,
722                                           const ArenaVector<ir::Expression *> &arguments,
723                                           const lexer::SourcePosition &pos, std::string_view signatureKind,
724                                           TypeRelationFlag resolveFlags)
725 {
726     auto compatibleSignatures = CollectSignatures(signatures, typeArguments, arguments, pos, resolveFlags);
727     if (!compatibleSignatures.empty()) {
728         return GetMostSpecificSignature(compatibleSignatures, arguments, pos, resolveFlags);
729     }
730 
731     if ((resolveFlags & TypeRelationFlag::NO_THROW) == 0 && !arguments.empty() && !signatures.empty()) {
732         std::stringstream ss;
733 
734         if (signatures[0]->Function()->IsConstructor()) {
735             ss << util::Helpers::GetClassDefiniton(signatures[0]->Function())->PrivateId().Mutf8();
736         } else {
737             ss << signatures[0]->Function()->Id()->Name().Mutf8();
738         }
739 
740         ss << "(";
741 
742         for (uint32_t index = 0; index < arguments.size(); ++index) {
743             if (arguments[index]->IsArrowFunctionExpression()) {
744                 // NOTE(peterseres): Refactor this case and add test case
745                 break;
746             }
747 
748             arguments[index]->Check(this);
749             arguments[index]->TsType()->ToString(ss);
750 
751             if (index == arguments.size() - 1) {
752                 ss << ")";
753                 ThrowTypeError({"No matching ", signatureKind, " signature for ", ss.str().c_str()}, pos);
754             }
755 
756             ss << ", ";
757         }
758     }
759 
760     if ((resolveFlags & TypeRelationFlag::NO_THROW) == 0) {
761         ThrowTypeError({"No matching ", signatureKind, " signature"}, pos);
762     }
763 
764     return nullptr;
765 }
766 
FindMostSpecificSignature(const ArenaVector<Signature * > & signatures,const ArenaMultiMap<size_t,Signature * > & bestSignaturesForParameter,size_t paramCount)767 Signature *ETSChecker::FindMostSpecificSignature(const ArenaVector<Signature *> &signatures,
768                                                  const ArenaMultiMap<size_t, Signature *> &bestSignaturesForParameter,
769                                                  size_t paramCount)
770 {
771     Signature *mostSpecificSignature = nullptr;
772 
773     for (auto *sig : signatures) {
774         bool mostSpecific = true;
775 
776         for (size_t paramIdx = 0; paramIdx < paramCount; ++paramIdx) {
777             const auto range = bestSignaturesForParameter.equal_range(paramIdx);
778             // Check if signature is most specific for i. parameter type.
779             mostSpecific = std::any_of(range.first, range.second, [&sig](auto entry) { return entry.second == sig; });
780             if (!mostSpecific) {
781                 break;
782             }
783         }
784 
785         if (!mostSpecific) {
786             continue;
787         }
788         if (mostSpecificSignature == nullptr) {
789             mostSpecificSignature = sig;
790             continue;
791         }
792         if (mostSpecificSignature->Owner() == sig->Owner()) {
793             // NOTE: audovichenko. Remove this 'if' when #12443 gets resolved
794             if (mostSpecificSignature->Function() == sig->Function()) {
795                 // The same signature
796                 continue;
797             }
798             return nullptr;
799         }
800     }
801     return mostSpecificSignature;
802 }
803 
InitMostSpecificType(const ArenaVector<Signature * > & signatures,Type * & mostSpecificType,Signature * & prevSig,const size_t idx)804 static void InitMostSpecificType(const ArenaVector<Signature *> &signatures, [[maybe_unused]] Type *&mostSpecificType,
805                                  [[maybe_unused]] Signature *&prevSig, const size_t idx)
806 {
807     for (auto *sig : signatures) {
808         if (Type *sigType = sig->Params().at(idx)->TsType();
809             sigType->IsETSObjectType() && !sigType->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::INTERFACE)) {
810             mostSpecificType = sigType;
811             prevSig = sig;
812             return;
813         }
814     }
815 }
816 
SearchAmongMostSpecificTypes(Type * & mostSpecificType,Signature * & prevSig,std::tuple<const lexer::SourcePosition &,size_t,size_t,size_t,Signature * > info,bool lookForClassType)817 void ETSChecker::SearchAmongMostSpecificTypes(
818     Type *&mostSpecificType, Signature *&prevSig,
819     std::tuple<const lexer::SourcePosition &, size_t, size_t, size_t, Signature *> info, bool lookForClassType)
820 {
821     auto [pos, argumentsSize, paramCount, idx, sig] = info;
822     if (lookForClassType && argumentsSize == ULONG_MAX) {
823         [[maybe_unused]] const bool equalParamSize = sig->Params().size() == paramCount;
824         ASSERT(equalParamSize);
825     }
826     Type *sigType = sig->Params().at(idx)->TsType();
827     const bool isClassType =
828         sigType->IsETSObjectType() && !sigType->AsETSObjectType()->HasObjectFlag(ETSObjectFlags::INTERFACE);
829     if (isClassType == lookForClassType) {
830         if (Relation()->IsIdenticalTo(sigType, mostSpecificType)) {
831             return;
832         }
833         if (Relation()->IsAssignableTo(sigType, mostSpecificType)) {
834             mostSpecificType = sigType;
835             prevSig = sig;
836         } else if (sigType->IsETSObjectType() && mostSpecificType->IsETSObjectType() &&
837                    !Relation()->IsAssignableTo(mostSpecificType, sigType)) {
838             auto funcName = sig->Function()->Id()->Name();
839             ThrowTypeError({"Call to `", funcName, "` is ambiguous as `2` versions of `", funcName,
840                             "` are available: `", funcName, prevSig, "` and `", funcName, sig, "`"},
841                            pos);
842         }
843     }
844 }
845 
GetSuitableSignaturesForParameter(const std::vector<bool> & argTypeInferenceRequired,size_t paramCount,ArenaVector<Signature * > & signatures,const lexer::SourcePosition & pos,size_t argumentsSize)846 ArenaMultiMap<size_t, Signature *> ETSChecker::GetSuitableSignaturesForParameter(
847     const std::vector<bool> &argTypeInferenceRequired, size_t paramCount, ArenaVector<Signature *> &signatures,
848     const lexer::SourcePosition &pos, size_t argumentsSize)
849 {
850     // Collect which signatures are most specific for each parameter.
851     ArenaMultiMap<size_t /* parameter index */, Signature *> bestSignaturesForParameter(Allocator()->Adapter());
852 
853     const checker::SavedTypeRelationFlagsContext savedTypeRelationFlagCtx(Relation(),
854                                                                           TypeRelationFlag::ONLY_CHECK_WIDENING);
855 
856     for (size_t i = 0; i < paramCount; ++i) {
857         if (argTypeInferenceRequired[i]) {
858             for (auto *sig : signatures) {
859                 bestSignaturesForParameter.insert({i, sig});
860             }
861             continue;
862         }
863         // 1st step: check which is the most specific parameter type for i. parameter.
864         Type *mostSpecificType = signatures.front()->Params().at(i)->TsType();
865         Signature *prevSig = signatures.front();
866 
867         InitMostSpecificType(signatures, mostSpecificType, prevSig, i);
868         for (auto *sig : signatures) {
869             SearchAmongMostSpecificTypes(mostSpecificType, prevSig,
870                                          std::make_tuple(pos, argumentsSize, paramCount, i, sig), true);
871         }
872         for (auto *sig : signatures) {
873             SearchAmongMostSpecificTypes(mostSpecificType, prevSig,
874                                          std::make_tuple(pos, argumentsSize, paramCount, i, sig), false);
875         }
876 
877         for (auto *sig : signatures) {
878             Type *sigType = sig->Params().at(i)->TsType();
879             if (Relation()->IsIdenticalTo(sigType, mostSpecificType)) {
880                 bestSignaturesForParameter.insert({i, sig});
881             }
882         }
883     }
884     return bestSignaturesForParameter;
885 }
886 
ChooseMostSpecificSignature(ArenaVector<Signature * > & signatures,const std::vector<bool> & argTypeInferenceRequired,const lexer::SourcePosition & pos,size_t argumentsSize)887 Signature *ETSChecker::ChooseMostSpecificSignature(ArenaVector<Signature *> &signatures,
888                                                    const std::vector<bool> &argTypeInferenceRequired,
889                                                    const lexer::SourcePosition &pos, size_t argumentsSize)
890 {
891     ASSERT(signatures.empty() == false);
892 
893     if (signatures.size() == 1) {
894         return signatures.front();
895     }
896 
897     size_t paramCount = signatures.front()->Params().size();
898     if (argumentsSize != ULONG_MAX) {
899         paramCount = argumentsSize;
900     }
901     // Multiple signatures with zero parameter because of inheritance.
902     // Return the closest one in inheritance chain that is defined at the beginning of the vector.
903     if (paramCount == 0) {
904         auto zeroParamSignature = std::find_if(signatures.begin(), signatures.end(),
905                                                [](auto *signature) { return signature->RestVar() == nullptr; });
906         // If there is a zero parameter signature, return that
907         if (zeroParamSignature != signatures.end()) {
908             return *zeroParamSignature;
909         }
910         // If there are multiple rest parameter signatures with different argument types, throw error
911         if (signatures.size() > 1 && std::any_of(signatures.begin(), signatures.end(), [signatures](const auto *param) {
912                 return param->RestVar()->TsType() != signatures.front()->RestVar()->TsType();
913             })) {
914             ThrowTypeError({"Call to `", signatures.front()->Function()->Id()->Name(), "` is ambiguous "}, pos);
915         }
916         // Else return the signature with the rest parameter
917         auto restParamSignature = std::find_if(signatures.begin(), signatures.end(),
918                                                [](auto *signature) { return signature->RestVar() != nullptr; });
919         return *restParamSignature;
920     }
921 
922     ArenaMultiMap<size_t /* parameter index */, Signature *> bestSignaturesForParameter =
923         GetSuitableSignaturesForParameter(argTypeInferenceRequired, paramCount, signatures, pos, argumentsSize);
924     // Find the signature that are most specific for all parameters.
925     Signature *mostSpecificSignature = FindMostSpecificSignature(signatures, bestSignaturesForParameter, paramCount);
926 
927     return mostSpecificSignature;
928 }
929 
ResolveCallExpressionAndTrailingLambda(ArenaVector<Signature * > & signatures,ir::CallExpression * callExpr,const lexer::SourcePosition & pos,const TypeRelationFlag throwFlag)930 Signature *ETSChecker::ResolveCallExpressionAndTrailingLambda(ArenaVector<Signature *> &signatures,
931                                                               ir::CallExpression *callExpr,
932                                                               const lexer::SourcePosition &pos,
933                                                               const TypeRelationFlag throwFlag)
934 {
935     Signature *sig = nullptr;
936     if (callExpr->TrailingBlock() == nullptr) {
937         for (auto it : signatures) {
938             MaybeSubstituteLambdaArguments(it->Function()->Params(), callExpr);
939 
940             if (callExpr->Arguments().size() != it->Function()->Params().size()) {
941                 MaybeSubstituteLambdaArgumentsInFunctionCall(callExpr);
942             }
943         }
944 
945         sig = ValidateSignatures(signatures, callExpr->TypeParams(), callExpr->Arguments(), pos, "call", throwFlag);
946         return sig;
947     }
948 
949     // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
950     auto arguments = ExtendArgumentsWithFakeLamda(callExpr);
951     sig = ValidateSignatures(signatures, callExpr->TypeParams(), arguments, pos, "call",
952                              TypeRelationFlag::NO_THROW | TypeRelationFlag::NO_CHECK_TRAILING_LAMBDA);
953     if (sig != nullptr) {
954         // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
955         TransformTraillingLambda(callExpr);
956         TypeInference(sig, callExpr->Arguments());
957         return sig;
958     }
959 
960     sig = ValidateSignatures(signatures, callExpr->TypeParams(), callExpr->Arguments(), pos, "call", throwFlag);
961     if (sig != nullptr) {
962         EnsureValidCurlyBrace(callExpr);
963     }
964 
965     return sig;
966 }
967 
ResolveConstructExpression(ETSObjectType * type,const ArenaVector<ir::Expression * > & arguments,const lexer::SourcePosition & pos)968 Signature *ETSChecker::ResolveConstructExpression(ETSObjectType *type, const ArenaVector<ir::Expression *> &arguments,
969                                                   const lexer::SourcePosition &pos)
970 {
971     return ValidateSignatures(type->ConstructSignatures(), nullptr, arguments, pos, "construct");
972 }
973 
974 /*
975  * Object literals do not get checked in the process of call resolution; we need to check them separately
976  * afterwards.
977  */
CheckObjectLiteralArguments(Signature * signature,ArenaVector<ir::Expression * > const & arguments)978 void ETSChecker::CheckObjectLiteralArguments(Signature *signature, ArenaVector<ir::Expression *> const &arguments)
979 {
980     for (uint32_t index = 0; index < arguments.size(); index++) {
981         if (!arguments[index]->IsObjectExpression()) {
982             continue;
983         }
984 
985         Type *tp;
986         if (index >= signature->MinArgCount()) {
987             ASSERT(signature->RestVar());
988             tp = signature->RestVar()->TsType();
989         } else {
990             tp = signature->Params()[index]->TsType();
991         }
992 
993         arguments[index]->AsObjectExpression()->SetPreferredType(tp);
994         arguments[index]->Check(this);
995     }
996 }
997 
BuildMethodSignature(ir::MethodDefinition * method)998 checker::ETSFunctionType *ETSChecker::BuildMethodSignature(ir::MethodDefinition *method)
999 {
1000     if (method->TsType() != nullptr) {
1001         return method->TsType()->AsETSFunctionType();
1002     }
1003 
1004     bool isConstructSig = method->IsConstructor();
1005 
1006     auto *funcType = BuildFunctionSignature(method->Function(), isConstructSig);
1007 
1008     std::vector<checker::ETSFunctionType *> overloads;
1009     for (ir::MethodDefinition *const currentFunc : method->Overloads()) {
1010         auto *const overloadType = BuildFunctionSignature(currentFunc->Function(), isConstructSig);
1011         CheckIdenticalOverloads(funcType, overloadType, currentFunc);
1012         currentFunc->SetTsType(overloadType);
1013         funcType->AddCallSignature(currentFunc->Function()->Signature());
1014         overloads.push_back(overloadType);
1015     }
1016     for (size_t baseFuncCounter = 0; baseFuncCounter < overloads.size(); ++baseFuncCounter) {
1017         auto *overloadType = overloads.at(baseFuncCounter);
1018         for (size_t compareFuncCounter = baseFuncCounter + 1; compareFuncCounter < overloads.size();
1019              compareFuncCounter++) {
1020             auto *compareOverloadType = overloads.at(compareFuncCounter);
1021             CheckIdenticalOverloads(overloadType, compareOverloadType, method->Overloads()[compareFuncCounter]);
1022         }
1023     }
1024 
1025     method->Id()->Variable()->SetTsType(funcType);
1026     return funcType;
1027 }
1028 
CheckIdenticalOverloads(ETSFunctionType * func,ETSFunctionType * overload,const ir::MethodDefinition * const currentFunc)1029 void ETSChecker::CheckIdenticalOverloads(ETSFunctionType *func, ETSFunctionType *overload,
1030                                          const ir::MethodDefinition *const currentFunc)
1031 {
1032     SavedTypeRelationFlagsContext savedFlagsCtx(Relation(), TypeRelationFlag::NO_RETURN_TYPE_CHECK);
1033 
1034     Relation()->IsIdenticalTo(func, overload);
1035     if (Relation()->IsTrue() && func->CallSignatures()[0]->GetSignatureInfo()->restVar ==
1036                                     overload->CallSignatures()[0]->GetSignatureInfo()->restVar) {
1037         ThrowTypeError("Function " + func->Name().Mutf8() + " is already declared.", currentFunc->Start());
1038     }
1039     if (HasSameAssemblySignature(func, overload)) {
1040         ThrowTypeError("Function " + func->Name().Mutf8() + " with this assembly signature already declared.",
1041                        currentFunc->Start());
1042     }
1043 }
1044 
ComposeSignature(ir::ScriptFunction * func,SignatureInfo * signatureInfo,Type * returnType,varbinder::Variable * nameVar)1045 Signature *ETSChecker::ComposeSignature(ir::ScriptFunction *func, SignatureInfo *signatureInfo, Type *returnType,
1046                                         varbinder::Variable *nameVar)
1047 {
1048     auto *signature = CreateSignature(signatureInfo, returnType, func);
1049     signature->SetOwner(Context().ContainingClass());
1050     signature->SetOwnerVar(nameVar);
1051 
1052     const auto *returnTypeAnnotation = func->ReturnTypeAnnotation();
1053     if (returnTypeAnnotation == nullptr && ((func->Flags() & ir::ScriptFunctionFlags::HAS_RETURN) != 0)) {
1054         signature->AddSignatureFlag(SignatureFlags::NEED_RETURN_TYPE);
1055     }
1056 
1057     if (returnTypeAnnotation != nullptr && returnTypeAnnotation->IsTSThisType()) {
1058         signature->AddSignatureFlag(SignatureFlags::THIS_RETURN_TYPE);
1059     }
1060 
1061     if (func->IsAbstract()) {
1062         signature->AddSignatureFlag(SignatureFlags::ABSTRACT);
1063         signature->AddSignatureFlag(SignatureFlags::VIRTUAL);
1064     }
1065 
1066     if (func->IsStatic()) {
1067         signature->AddSignatureFlag(SignatureFlags::STATIC);
1068     }
1069 
1070     if (func->IsConstructor()) {
1071         signature->AddSignatureFlag(SignatureFlags::CONSTRUCTOR);
1072     }
1073 
1074     if (signature->Owner()->GetDeclNode()->IsFinal() || func->IsFinal()) {
1075         signature->AddSignatureFlag(SignatureFlags::FINAL);
1076     }
1077 
1078     if (func->IsPublic()) {
1079         signature->AddSignatureFlag(SignatureFlags::PUBLIC);
1080     } else if (func->IsInternal()) {
1081         if (func->IsProtected()) {
1082             signature->AddSignatureFlag(SignatureFlags::INTERNAL_PROTECTED);
1083         } else {
1084             signature->AddSignatureFlag(SignatureFlags::INTERNAL);
1085         }
1086     } else if (func->IsProtected()) {
1087         signature->AddSignatureFlag(SignatureFlags::PROTECTED);
1088     } else if (func->IsPrivate()) {
1089         signature->AddSignatureFlag(SignatureFlags::PRIVATE);
1090     }
1091 
1092     return signature;
1093 }
1094 
ComposeReturnType(ir::ScriptFunction * func)1095 Type *ETSChecker::ComposeReturnType(ir::ScriptFunction *func)
1096 {
1097     auto *const returnTypeAnnotation = func->ReturnTypeAnnotation();
1098     checker::Type *returnType {};
1099 
1100     if (returnTypeAnnotation == nullptr) {
1101         // implicit void return type
1102         returnType = GlobalVoidType();
1103 
1104         if (func->IsAsyncFunc()) {
1105             auto implicitPromiseVoid = [this]() {
1106                 const auto &promiseGlobal = GlobalBuiltinPromiseType()->AsETSObjectType();
1107                 auto promiseType =
1108                     promiseGlobal->Instantiate(Allocator(), Relation(), GetGlobalTypesHolder())->AsETSObjectType();
1109                 promiseType->AddTypeFlag(checker::TypeFlag::GENERIC);
1110                 promiseType->TypeArguments().clear();
1111                 promiseType->TypeArguments().emplace_back(GlobalVoidType());
1112                 return promiseType;
1113             };
1114 
1115             returnType = implicitPromiseVoid();
1116         }
1117     } else if (func->IsEntryPoint() && returnTypeAnnotation->GetType(this) == GlobalVoidType()) {
1118         returnType = GlobalVoidType();
1119     } else {
1120         returnType = returnTypeAnnotation->GetType(this);
1121         returnTypeAnnotation->SetTsType(returnType);
1122     }
1123 
1124     return returnType;
1125 }
1126 
ComposeSignatureInfo(ir::ScriptFunction * func)1127 SignatureInfo *ETSChecker::ComposeSignatureInfo(ir::ScriptFunction *func)
1128 {
1129     auto *signatureInfo = CreateSignatureInfo();
1130     signatureInfo->restVar = nullptr;
1131     signatureInfo->minArgCount = 0;
1132 
1133     if ((func->IsConstructor() || !func->IsStatic()) && !func->IsArrow()) {
1134         auto *thisVar = func->Scope()->ParamScope()->Params().front();
1135         thisVar->SetTsType(Context().ContainingClass());
1136     }
1137 
1138     if (func->TypeParams() != nullptr) {
1139         auto [typeParamTypes, ok] = CreateUnconstrainedTypeParameters(func->TypeParams());
1140         signatureInfo->typeParams = std::move(typeParamTypes);
1141         if (ok) {
1142             AssignTypeParameterConstraints(func->TypeParams());
1143         }
1144     }
1145 
1146     for (auto *const it : func->Params()) {
1147         auto *const param = it->AsETSParameterExpression();
1148 
1149         if (param->IsRestParameter()) {
1150             auto const *const restIdent = param->Ident();
1151 
1152             ASSERT(restIdent->Variable());
1153             signatureInfo->restVar = restIdent->Variable()->AsLocalVariable();
1154 
1155             auto *const restParamTypeAnnotation = param->TypeAnnotation();
1156             ASSERT(restParamTypeAnnotation);
1157 
1158             signatureInfo->restVar->SetTsType(restParamTypeAnnotation->GetType(this));
1159             auto arrayType = signatureInfo->restVar->TsType()->AsETSArrayType();
1160             CreateBuiltinArraySignature(arrayType, arrayType->Rank());
1161         } else {
1162             auto *const paramIdent = param->Ident();
1163 
1164             varbinder::Variable *const paramVar = paramIdent->Variable();
1165             ASSERT(paramVar);
1166 
1167             auto *const paramTypeAnnotation = param->TypeAnnotation();
1168             if (paramIdent->TsType() == nullptr && paramTypeAnnotation == nullptr) {
1169                 ThrowTypeError({"The type of parameter '", paramIdent->Name(), "' cannot be determined"},
1170                                param->Start());
1171             }
1172 
1173             if (paramIdent->TsType() == nullptr) {
1174                 ASSERT(paramTypeAnnotation);
1175 
1176                 paramVar->SetTsType(paramTypeAnnotation->GetType(this));
1177             } else {
1178                 paramVar->SetTsType(paramIdent->TsType());
1179             }
1180             signatureInfo->params.push_back(paramVar->AsLocalVariable());
1181             ++signatureInfo->minArgCount;
1182         }
1183     }
1184 
1185     return signatureInfo;
1186 }
1187 
ComposeSignatureInfosForArrowFunction(ir::ArrowFunctionExpression * arrowFuncExpr)1188 ArenaVector<SignatureInfo *> ETSChecker::ComposeSignatureInfosForArrowFunction(
1189     ir::ArrowFunctionExpression *arrowFuncExpr)
1190 {
1191     ArenaVector<SignatureInfo *> signatureInfos(Allocator()->Adapter());
1192 
1193     for (size_t i = arrowFuncExpr->Function()->DefaultParamIndex(); i < arrowFuncExpr->Function()->Params().size();
1194          i++) {
1195         auto *signatureInfo = CreateSignatureInfo();
1196         signatureInfo->restVar = nullptr;
1197         signatureInfo->minArgCount = 0;
1198 
1199         if (arrowFuncExpr->Function()->TypeParams() != nullptr) {
1200             signatureInfo->typeParams =
1201                 CreateUnconstrainedTypeParameters(arrowFuncExpr->Function()->TypeParams()).first;
1202         }
1203 
1204         for (size_t j = 0; j < i; j++) {
1205             SetParamForSignatureInfoOfArrowFunction(signatureInfo,
1206                                                     arrowFuncExpr->Function()->Params()[j]->AsETSParameterExpression());
1207         }
1208 
1209         signatureInfos.push_back(signatureInfo);
1210     }
1211 
1212     return signatureInfos;
1213 }
1214 
SetParamForSignatureInfoOfArrowFunction(SignatureInfo * signatureInfo,ir::ETSParameterExpression * param)1215 void ETSChecker::SetParamForSignatureInfoOfArrowFunction(SignatureInfo *signatureInfo,
1216                                                          ir::ETSParameterExpression *param)
1217 {
1218     if (param->IsRestParameter()) {
1219         auto const *const restIdent = param->Ident();
1220 
1221         ASSERT(restIdent->Variable());
1222         signatureInfo->restVar = restIdent->Variable()->AsLocalVariable();
1223 
1224         auto *const restParamTypeAnnotation = param->TypeAnnotation();
1225         ASSERT(restParamTypeAnnotation);
1226 
1227         signatureInfo->restVar->SetTsType(restParamTypeAnnotation->GetType(this));
1228         auto arrayType = signatureInfo->restVar->TsType()->AsETSArrayType();
1229         CreateBuiltinArraySignature(arrayType, arrayType->Rank());
1230     } else {
1231         auto *const paramIdent = param->Ident();
1232 
1233         varbinder::Variable *const paramVar = paramIdent->Variable();
1234         ASSERT(paramVar);
1235 
1236         auto *const paramTypeAnnotation = param->TypeAnnotation();
1237         if (paramIdent->TsType() == nullptr) {
1238             ASSERT(paramTypeAnnotation);
1239 
1240             paramVar->SetTsType(paramTypeAnnotation->GetType(this));
1241         } else {
1242             paramVar->SetTsType(paramIdent->TsType());
1243         }
1244         signatureInfo->params.push_back(paramVar->AsLocalVariable());
1245         ++signatureInfo->minArgCount;
1246     }
1247 }
1248 
ValidateMainSignature(ir::ScriptFunction * func)1249 void ETSChecker::ValidateMainSignature(ir::ScriptFunction *func)
1250 {
1251     if (func->Params().size() >= 2U) {
1252         ThrowTypeError("0 or 1 argument are allowed", func->Start());
1253     }
1254 
1255     if (func->Params().size() == 1) {
1256         auto const *const param = func->Params()[0]->AsETSParameterExpression();
1257 
1258         if (param->IsRestParameter()) {
1259             ThrowTypeError("Rest parameter is not allowed in the 'main' function.", param->Start());
1260         }
1261 
1262         const auto paramType = param->Variable()->TsType();
1263         if (!paramType->IsETSArrayType() || !paramType->AsETSArrayType()->ElementType()->IsETSStringType()) {
1264             ThrowTypeError("Only 'string[]' type argument is allowed.", param->Start());
1265         }
1266     }
1267 }
1268 
AddSignatureFlags(const ir::ScriptFunction * const func,Signature * const signature)1269 static void AddSignatureFlags(const ir::ScriptFunction *const func, Signature *const signature)
1270 {
1271     if (func->IsAbstract()) {
1272         signature->AddSignatureFlag(SignatureFlags::ABSTRACT);
1273         signature->AddSignatureFlag(SignatureFlags::VIRTUAL);
1274     }
1275 
1276     if (func->IsStatic()) {
1277         signature->AddSignatureFlag(SignatureFlags::STATIC);
1278     }
1279 
1280     if (func->IsConstructor()) {
1281         signature->AddSignatureFlag(SignatureFlags::CONSTRUCTOR);
1282     }
1283 
1284     if (func->Signature()->Owner()->GetDeclNode()->IsFinal() || func->IsFinal()) {
1285         signature->AddSignatureFlag(SignatureFlags::FINAL);
1286     }
1287 
1288     if (func->IsPublic()) {
1289         signature->AddSignatureFlag(SignatureFlags::PUBLIC);
1290     } else if (func->IsInternal()) {
1291         if (func->IsProtected()) {
1292             signature->AddSignatureFlag(SignatureFlags::INTERNAL_PROTECTED);
1293         } else {
1294             signature->AddSignatureFlag(SignatureFlags::INTERNAL);
1295         }
1296     } else if (func->IsProtected()) {
1297         signature->AddSignatureFlag(SignatureFlags::PROTECTED);
1298     } else if (func->IsPrivate()) {
1299         signature->AddSignatureFlag(SignatureFlags::PRIVATE);
1300     }
1301 
1302     if (func->IsSetter()) {
1303         signature->AddSignatureFlag(SignatureFlags::SETTER);
1304     } else if (func->IsGetter()) {
1305         signature->AddSignatureFlag(SignatureFlags::GETTER);
1306     }
1307 }
1308 
BuildFunctionSignature(ir::ScriptFunction * func,bool isConstructSig)1309 checker::ETSFunctionType *ETSChecker::BuildFunctionSignature(ir::ScriptFunction *func, bool isConstructSig)
1310 {
1311     bool isArrow = func->IsArrow();
1312     auto *nameVar = isArrow ? nullptr : func->Id()->Variable();
1313     auto funcName = nameVar == nullptr ? util::StringView() : nameVar->Name();
1314 
1315     auto *signatureInfo = ComposeSignatureInfo(func);
1316 
1317     if (funcName.Is(compiler::Signatures::MAIN) &&
1318         func->Scope()->Name().Utf8().find(compiler::Signatures::ETS_GLOBAL) != std::string::npos) {
1319         func->AddFlag(ir::ScriptFunctionFlags::ENTRY_POINT);
1320     }
1321     if (func->IsEntryPoint()) {
1322         ValidateMainSignature(func);
1323     }
1324 
1325     auto *returnType = ComposeReturnType(func);
1326     auto *signature = ComposeSignature(func, signatureInfo, returnType, nameVar);
1327     if (isConstructSig) {
1328         signature->AddSignatureFlag(SignatureFlags::CONSTRUCT);
1329     } else {
1330         signature->AddSignatureFlag(SignatureFlags::CALL);
1331     }
1332 
1333     auto *funcType = CreateETSFunctionType(func, signature, funcName);
1334     func->SetSignature(signature);
1335     funcType->SetVariable(nameVar);
1336     VarBinder()->AsETSBinder()->BuildFunctionName(func);
1337 
1338     AddSignatureFlags(func, signature);
1339 
1340     if (!isArrow) {
1341         nameVar->SetTsType(funcType);
1342     }
1343 
1344     return funcType;
1345 }
1346 
CheckEveryAbstractSignatureIsOverridden(ETSFunctionType * target,ETSFunctionType * source)1347 Signature *ETSChecker::CheckEveryAbstractSignatureIsOverridden(ETSFunctionType *target, ETSFunctionType *source)
1348 {
1349     for (auto targetSig = target->CallSignatures().begin(); targetSig != target->CallSignatures().end();) {
1350         if (!(*targetSig)->HasSignatureFlag(SignatureFlags::ABSTRACT)) {
1351             continue;
1352         }
1353 
1354         bool isOverridden = false;
1355         for (auto sourceSig : source->CallSignatures()) {
1356             if ((*targetSig)->Function()->Id()->Name() == sourceSig->Function()->Id()->Name() &&
1357                 Relation()->IsCompatibleTo(*targetSig, sourceSig)) {
1358                 target->CallSignatures().erase(targetSig);
1359                 isOverridden = true;
1360                 break;
1361             }
1362             sourceSig++;
1363         }
1364 
1365         if (!isOverridden) {
1366             return *targetSig;
1367         }
1368     }
1369 
1370     return nullptr;
1371 }
1372 
IsOverridableIn(Signature * signature)1373 bool ETSChecker::IsOverridableIn(Signature *signature)
1374 {
1375     if (signature->HasSignatureFlag(SignatureFlags::PRIVATE)) {
1376         return false;
1377     }
1378 
1379     // NOTE: #15095 workaround, separate internal visibility check
1380     if (signature->HasSignatureFlag(SignatureFlags::PUBLIC | SignatureFlags::INTERNAL)) {
1381         return true;
1382     }
1383 
1384     return signature->HasSignatureFlag(SignatureFlags::PROTECTED);
1385 }
1386 
IsMethodOverridesOther(Signature * base,Signature * derived)1387 bool ETSChecker::IsMethodOverridesOther(Signature *base, Signature *derived)
1388 {
1389     if (derived->Function()->IsConstructor()) {
1390         return false;
1391     }
1392 
1393     if (base == derived) {
1394         return true;
1395     }
1396 
1397     if (derived->HasSignatureFlag(SignatureFlags::STATIC) != base->HasSignatureFlag(SignatureFlags::STATIC)) {
1398         return false;
1399     }
1400 
1401     if (IsOverridableIn(base)) {
1402         SavedTypeRelationFlagsContext savedFlagsCtx(Relation(), TypeRelationFlag::NO_RETURN_TYPE_CHECK |
1403                                                                     TypeRelationFlag::OVERRIDING_CONTEXT);
1404         if (Relation()->IsCompatibleTo(base, derived)) {
1405             CheckThrowMarkers(derived, base);
1406 
1407             if (derived->HasSignatureFlag(SignatureFlags::STATIC)) {
1408                 return false;
1409             }
1410 
1411             derived->Function()->SetOverride();
1412             return true;
1413         }
1414     }
1415 
1416     return false;
1417 }
1418 
CheckThrowMarkers(Signature * source,Signature * target)1419 void ETSChecker::CheckThrowMarkers(Signature *source, Signature *target)
1420 {
1421     ir::ScriptFunctionFlags throwMarkers = ir::ScriptFunctionFlags::THROWS | ir::ScriptFunctionFlags::RETHROWS;
1422     auto sourceThrowMarkers = source->Function()->Flags() & throwMarkers;
1423     auto targetThrowMarkers = target->Function()->Flags() & throwMarkers;
1424     if (sourceThrowMarkers != targetThrowMarkers) {
1425         ThrowTypeError(
1426             "A method that overrides or hides another method cannot change throw or rethrow clauses of the "
1427             "overridden "
1428             "or hidden method.",
1429             target->Function()->Body()->Start());
1430     }
1431 }
1432 
CheckOverride(Signature * signature,Signature * other)1433 OverrideErrorCode ETSChecker::CheckOverride(Signature *signature, Signature *other)
1434 {
1435     if (other->HasSignatureFlag(SignatureFlags::STATIC)) {
1436         ASSERT(signature->HasSignatureFlag(SignatureFlags::STATIC));
1437         return OverrideErrorCode::NO_ERROR;
1438     }
1439 
1440     if (other->IsFinal()) {
1441         return OverrideErrorCode::OVERRIDDEN_FINAL;
1442     }
1443 
1444     if (!IsReturnTypeSubstitutable(signature, other)) {
1445         return OverrideErrorCode::INCOMPATIBLE_RETURN;
1446     }
1447 
1448     if (signature->ProtectionFlag() > other->ProtectionFlag()) {
1449         return OverrideErrorCode::OVERRIDDEN_WEAKER;
1450     }
1451 
1452     return OverrideErrorCode::NO_ERROR;
1453 }
1454 
AdjustForTypeParameters(Signature * source,Signature * target)1455 Signature *ETSChecker::AdjustForTypeParameters(Signature *source, Signature *target)
1456 {
1457     auto &sourceTypeParams = source->GetSignatureInfo()->typeParams;
1458     auto &targetTypeParams = target->GetSignatureInfo()->typeParams;
1459     if (sourceTypeParams.size() != targetTypeParams.size()) {
1460         return nullptr;
1461     }
1462     if (sourceTypeParams.empty()) {
1463         return target;
1464     }
1465     auto *substitution = NewSubstitution();
1466     for (size_t ix = 0; ix < sourceTypeParams.size(); ix++) {
1467         if (!targetTypeParams[ix]->IsETSTypeParameter()) {
1468             continue;
1469         }
1470         ETSChecker::EmplaceSubstituted(substitution, targetTypeParams[ix]->AsETSTypeParameter(), sourceTypeParams[ix]);
1471     }
1472     return target->Substitute(Relation(), substitution);
1473 }
1474 
ThrowOverrideError(Signature * signature,Signature * overriddenSignature,const OverrideErrorCode & errorCode)1475 void ETSChecker::ThrowOverrideError(Signature *signature, Signature *overriddenSignature,
1476                                     const OverrideErrorCode &errorCode)
1477 {
1478     const char *reason {};
1479     switch (errorCode) {
1480         case OverrideErrorCode::OVERRIDDEN_FINAL: {
1481             reason = "overridden method is final.";
1482             break;
1483         }
1484         case OverrideErrorCode::INCOMPATIBLE_RETURN: {
1485             reason = "overriding return type is not compatible with the other return type.";
1486             break;
1487         }
1488         case OverrideErrorCode::OVERRIDDEN_WEAKER: {
1489             reason = "overridden method has weaker access privilege.";
1490             break;
1491         }
1492         default: {
1493             UNREACHABLE();
1494         }
1495     }
1496 
1497     ThrowTypeError({signature->Function()->Id()->Name(), signature, " in ", signature->Owner(), " cannot override ",
1498                     overriddenSignature->Function()->Id()->Name(), overriddenSignature, " in ",
1499                     overriddenSignature->Owner(), " because ", reason},
1500                    signature->Function()->Start());
1501 }
1502 
CheckOverride(Signature * signature,ETSObjectType * site)1503 bool ETSChecker::CheckOverride(Signature *signature, ETSObjectType *site)
1504 {
1505     auto *target = site->GetProperty(signature->Function()->Id()->Name(), PropertySearchFlags::SEARCH_METHOD);
1506     bool isOverridingAnySignature = false;
1507 
1508     if (target == nullptr) {
1509         return isOverridingAnySignature;
1510     }
1511 
1512     for (auto *it : target->TsType()->AsETSFunctionType()->CallSignatures()) {
1513         auto *itSubst = AdjustForTypeParameters(signature, it);
1514 
1515         if (itSubst == nullptr) {
1516             continue;
1517         }
1518 
1519         if (itSubst->HasSignatureFlag(SignatureFlags::ABSTRACT) || site->HasObjectFlag(ETSObjectFlags::INTERFACE)) {
1520             if (site->HasObjectFlag(ETSObjectFlags::INTERFACE)) {
1521                 CheckThrowMarkers(itSubst, signature);
1522             }
1523             if ((itSubst->Function()->IsSetter() && !signature->Function()->IsSetter()) ||
1524                 (itSubst->Function()->IsGetter() && !signature->Function()->IsGetter())) {
1525                 continue;
1526             }
1527         }
1528         if (!IsMethodOverridesOther(itSubst, signature)) {
1529             continue;
1530         }
1531 
1532         if (auto err = CheckOverride(signature, itSubst); err != OverrideErrorCode::NO_ERROR) {
1533             ThrowOverrideError(signature, it, err);
1534         }
1535 
1536         if (signature->Owner()->HasObjectFlag(ETSObjectFlags::INTERFACE) &&
1537             Relation()->IsIdenticalTo(itSubst->Owner(), GlobalETSObjectType()) &&
1538             !itSubst->HasSignatureFlag(SignatureFlags::PRIVATE)) {
1539             ThrowTypeError("Cannot override non-private method of the class Object from an interface.",
1540                            signature->Function()->Start());
1541         }
1542 
1543         isOverridingAnySignature = true;
1544         it->AddSignatureFlag(SignatureFlags::VIRTUAL);
1545     }
1546 
1547     return isOverridingAnySignature;
1548 }
1549 
CheckOverride(Signature * signature)1550 void ETSChecker::CheckOverride(Signature *signature)
1551 {
1552     auto *owner = signature->Owner();
1553     bool isOverriding = false;
1554 
1555     if (!owner->HasObjectFlag(ETSObjectFlags::CLASS | ETSObjectFlags::INTERFACE)) {
1556         return;
1557     }
1558 
1559     for (auto *const interface : owner->Interfaces()) {
1560         isOverriding |= CheckInterfaceOverride(this, interface, signature);
1561     }
1562 
1563     ETSObjectType *iter = owner->SuperType();
1564     while (iter != nullptr) {
1565         isOverriding |= CheckOverride(signature, iter);
1566 
1567         for (auto *const interface : iter->Interfaces()) {
1568             isOverriding |= CheckInterfaceOverride(this, interface, signature);
1569         }
1570 
1571         iter = iter->SuperType();
1572     }
1573 
1574     if (!isOverriding && signature->Function()->IsOverride()) {
1575         ThrowTypeError({"Method ", signature->Function()->Id()->Name(), signature, " in ", signature->Owner(),
1576                         " not overriding any method"},
1577                        signature->Function()->Start());
1578     }
1579 }
1580 
GetSignatureFromMethodDefinition(const ir::MethodDefinition * methodDef)1581 Signature *ETSChecker::GetSignatureFromMethodDefinition(const ir::MethodDefinition *methodDef)
1582 {
1583     ASSERT(methodDef->TsType() && methodDef->TsType()->IsETSFunctionType());
1584 
1585     for (auto *it : methodDef->TsType()->AsETSFunctionType()->CallSignatures()) {
1586         if (it->Function() == methodDef->Function()) {
1587             return it;
1588         }
1589     }
1590 
1591     return nullptr;
1592 }
1593 
ValidateSignatureAccessibility(ETSObjectType * callee,const ir::CallExpression * callExpr,Signature * signature,const lexer::SourcePosition & pos,char const * errorMessage)1594 void ETSChecker::ValidateSignatureAccessibility(ETSObjectType *callee, const ir::CallExpression *callExpr,
1595                                                 Signature *signature, const lexer::SourcePosition &pos,
1596                                                 char const *errorMessage)
1597 {
1598     if ((Context().Status() & CheckerStatus::IGNORE_VISIBILITY) != 0U ||
1599         (!signature->HasSignatureFlag(SignatureFlags::PRIVATE) &&
1600          !signature->HasSignatureFlag(SignatureFlags::PROTECTED))) {
1601         return;
1602     }
1603     const auto *declNode = callee->GetDeclNode();
1604     auto *containingClass = Context().ContainingClass();
1605     bool isContainingSignatureInherited = containingClass->IsSignatureInherited(signature);
1606     ASSERT(declNode && (declNode->IsClassDefinition() || declNode->IsTSInterfaceDeclaration()));
1607 
1608     if (declNode->IsTSInterfaceDeclaration()) {
1609         const auto *enclosingFunc =
1610             util::Helpers::FindAncestorGivenByType(callExpr, ir::AstNodeType::SCRIPT_FUNCTION)->AsScriptFunction();
1611         if (callExpr->Callee()->IsMemberExpression() &&
1612             callExpr->Callee()->AsMemberExpression()->Object()->IsThisExpression() &&
1613             signature->Function()->IsPrivate() && !enclosingFunc->IsPrivate()) {
1614             ThrowTypeError({"Cannot reference 'this' in this context."}, enclosingFunc->Start());
1615         }
1616 
1617         if (containingClass == declNode->AsTSInterfaceDeclaration()->TsType() && isContainingSignatureInherited) {
1618             return;
1619         }
1620     }
1621     if (containingClass == declNode->AsClassDefinition()->TsType() && isContainingSignatureInherited) {
1622         return;
1623     }
1624 
1625     bool isSignatureInherited = callee->IsSignatureInherited(signature);
1626     const auto *currentOutermost = containingClass->OutermostClass();
1627     if (!signature->HasSignatureFlag(SignatureFlags::PRIVATE) &&
1628         ((signature->HasSignatureFlag(SignatureFlags::PROTECTED) && containingClass->IsDescendantOf(callee)) ||
1629          (currentOutermost != nullptr && currentOutermost == callee->OutermostClass())) &&
1630         isSignatureInherited) {
1631         return;
1632     }
1633 
1634     if (errorMessage == nullptr) {
1635         ThrowTypeError({"Signature ", signature->Function()->Id()->Name(), signature, " is not visible here."}, pos);
1636     }
1637     ThrowTypeError(errorMessage, pos);
1638 }
1639 
CheckCapturedVariable(ir::AstNode * const node,varbinder::Variable * const var)1640 void ETSChecker::CheckCapturedVariable(ir::AstNode *const node, varbinder::Variable *const var)
1641 {
1642     if (node->IsIdentifier()) {
1643         const auto *const parent = node->Parent();
1644 
1645         if (parent->IsUpdateExpression() ||
1646             (parent->IsAssignmentExpression() && parent->AsAssignmentExpression()->Left() == node)) {
1647             const auto *const identNode = node->AsIdentifier();
1648 
1649             const auto *resolved = identNode->Variable();
1650 
1651             if (resolved == nullptr) {
1652                 resolved =
1653                     FindVariableInFunctionScope(identNode->Name(), varbinder::ResolveBindingOptions::ALL_NON_TYPE);
1654             }
1655 
1656             if (resolved == nullptr) {
1657                 resolved = FindVariableInGlobal(identNode, varbinder::ResolveBindingOptions::ALL_NON_TYPE);
1658             }
1659 
1660             if (resolved == var) {
1661                 // For mutable captured variable [possible] smart-cast is senseless (or even erroneous)
1662                 Context().RemoveSmartCast(var);
1663             }
1664         }
1665     }
1666 
1667     CheckCapturedVariableInSubnodes(node, var);
1668 }
1669 
CheckCapturedVariableInSubnodes(ir::AstNode * node,varbinder::Variable * var)1670 void ETSChecker::CheckCapturedVariableInSubnodes(ir::AstNode *node, varbinder::Variable *var)
1671 {
1672     if (!node->IsClassDefinition()) {
1673         node->Iterate([this, var](ir::AstNode *childNode) { CheckCapturedVariable(childNode, var); });
1674     }
1675 }
1676 
CheckCapturedVariables()1677 void ETSChecker::CheckCapturedVariables()
1678 {
1679     // If we want to capture non constant local variables, we should wrap them in a generic reference class
1680     for (auto [var, _] : Context().CapturedVars()) {
1681         (void)_;
1682         if ((var->Declaration() == nullptr) || var->Declaration()->IsConstDecl() ||
1683             !var->HasFlag(varbinder::VariableFlags::LOCAL) || var->GetScope()->Node()->IsArrowFunctionExpression()) {
1684             continue;
1685         }
1686 
1687         auto *searchNode = var->Declaration()->Node()->Parent();
1688 
1689         if (searchNode->IsVariableDeclarator()) {
1690             searchNode = searchNode->Parent()->Parent();
1691         }
1692 
1693         CheckCapturedVariableInSubnodes(searchNode, var);
1694     }
1695 }
1696 
AreOverrideEquivalent(Signature * const s1,Signature * const s2)1697 bool ETSChecker::AreOverrideEquivalent(Signature *const s1, Signature *const s2)
1698 {
1699     // Two functions, methods or constructors M and N have the same signature if
1700     // their names and type parameters (if any) are the same, and their formal parameter
1701     // types are also the same (after the formal parameter types of N are adapted to the type parameters of M).
1702     // Signatures s1 and s2 are override-equivalent only if s1 and s2 are the same.
1703 
1704     SavedTypeRelationFlagsContext savedFlagsCtx(Relation(), TypeRelationFlag::OVERRIDING_CONTEXT);
1705     return s1->Function()->Id()->Name() == s2->Function()->Id()->Name() && Relation()->IsCompatibleTo(s1, s2);
1706 }
1707 
IsReturnTypeSubstitutable(Signature * const s1,Signature * const s2)1708 bool ETSChecker::IsReturnTypeSubstitutable(Signature *const s1, Signature *const s2)
1709 {
1710     auto *const r1 = s1->ReturnType();
1711     auto *const r2 = s2->ReturnType();
1712 
1713     // A method declaration d1 with return type R1 is return-type-substitutable for another method d2 with return
1714     // type R2 if any of the following is true:
1715 
1716     // - If R1 is a primitive type then R2 is identical to R1.
1717     if (r1->HasTypeFlag(TypeFlag::ETS_PRIMITIVE | TypeFlag::ETS_INT_ENUM | TypeFlag::ETS_STRING_ENUM |
1718                         TypeFlag::ETS_VOID)) {
1719         return Relation()->IsIdenticalTo(r2, r1);
1720     }
1721 
1722     // - If R1 is a reference type then R1, adapted to the type parameters of d2 (link to generic methods), is a
1723     // subtype of R2.
1724     ASSERT(IsReferenceType(r1));
1725 
1726     if (Relation()->IsSupertypeOf(r2, r1)) {
1727         return true;
1728     }
1729 
1730     return s2->Function()->ReturnTypeAnnotation()->IsETSTypeReference() &&
1731            Relation()->IsSupertypeOf(
1732                s2->Function()->ReturnTypeAnnotation()->GetType(this)->AsETSTypeParameter()->GetConstraintType(), r1);
1733 }
1734 
GetAsyncImplName(const util::StringView & name)1735 std::string ETSChecker::GetAsyncImplName(const util::StringView &name)
1736 {
1737     std::string implName(name);
1738     implName += "$asyncimpl";
1739     return implName;
1740 }
1741 
GetAsyncImplName(ir::MethodDefinition * asyncMethod)1742 std::string ETSChecker::GetAsyncImplName(ir::MethodDefinition *asyncMethod)
1743 {
1744     ir::Identifier *asyncName = asyncMethod->Function()->Id();
1745     ASSERT(asyncName != nullptr);
1746     return GetAsyncImplName(asyncName->Name());
1747 }
1748 
IsAsyncImplMethod(ir::MethodDefinition const * method)1749 bool ETSChecker::IsAsyncImplMethod(ir::MethodDefinition const *method)
1750 {
1751     auto methodName = method->Key()->AsIdentifier()->Name().Utf8();
1752     std::string_view asyncSuffix = "$asyncimpl";
1753     if (methodName.size() < asyncSuffix.size()) {
1754         return false;
1755     }
1756     return methodName.substr(methodName.size() - asyncSuffix.size()) == asyncSuffix;
1757 }
1758 
CreateAsyncImplMethod(ir::MethodDefinition * asyncMethod,ir::ClassDefinition * classDef)1759 ir::MethodDefinition *ETSChecker::CreateAsyncImplMethod(ir::MethodDefinition *asyncMethod,
1760                                                         ir::ClassDefinition *classDef)
1761 {
1762     util::UString implName(GetAsyncImplName(asyncMethod), Allocator());
1763     ir::ModifierFlags modifiers = asyncMethod->Modifiers();
1764     // clear ASYNC flag for implementation
1765     modifiers &= ~ir::ModifierFlags::ASYNC;
1766     ir::ScriptFunction *asyncFunc = asyncMethod->Function();
1767     ir::ScriptFunctionFlags flags = ir::ScriptFunctionFlags::METHOD;
1768 
1769     if (asyncFunc->IsProxy()) {
1770         flags |= ir::ScriptFunctionFlags::PROXY;
1771     }
1772 
1773     if (asyncFunc->HasReturnStatement()) {
1774         flags |= ir::ScriptFunctionFlags::HAS_RETURN;
1775     }
1776 
1777     asyncMethod->AddModifier(ir::ModifierFlags::NATIVE);
1778     asyncFunc->AddModifier(ir::ModifierFlags::NATIVE);
1779     // Create async_impl method copied from CreateInvokeFunction
1780     auto scopeCtx =
1781         varbinder::LexicalScope<varbinder::ClassScope>::Enter(VarBinder(), classDef->Scope()->AsClassScope());
1782     auto *body = asyncFunc->Body();
1783     ArenaVector<ir::Expression *> params(Allocator()->Adapter());
1784     // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
1785     varbinder::FunctionParamScope *paramScope = CopyParams(asyncFunc->Params(), params);
1786 
1787     ir::ETSTypeReference *returnTypeAnn = nullptr;
1788 
1789     if (!asyncFunc->Signature()->HasSignatureFlag(SignatureFlags::NEED_RETURN_TYPE)) {
1790         // Set impl method return type "Object" because it may return Promise as well as Promise parameter's type
1791         auto *objectId = AllocNode<ir::Identifier>(compiler::Signatures::BUILTIN_OBJECT_CLASS, Allocator());
1792         objectId->SetReference();
1793         VarBinder()->AsETSBinder()->LookupTypeReference(objectId, false);
1794         returnTypeAnn =
1795             AllocNode<ir::ETSTypeReference>(AllocNode<ir::ETSTypeReferencePart>(objectId, nullptr, nullptr));
1796         objectId->SetParent(returnTypeAnn->Part());
1797         returnTypeAnn->Part()->SetParent(returnTypeAnn);
1798         auto *asyncFuncRetTypeAnn = asyncFunc->ReturnTypeAnnotation();
1799         auto *promiseType = [this](ir::TypeNode *type) {
1800             if (type != nullptr) {
1801                 return type->GetType(this)->AsETSObjectType();
1802             }
1803 
1804             return GlobalBuiltinPromiseType()->AsETSObjectType();
1805         }(asyncFuncRetTypeAnn);
1806         // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
1807         auto *retType = Allocator()->New<ETSAsyncFuncReturnType>(Allocator(), Relation(), promiseType);
1808         returnTypeAnn->SetTsType(retType);
1809     }
1810 
1811     ir::MethodDefinition *implMethod =
1812         CreateMethod(implName.View(), modifiers, flags, std::move(params), paramScope, returnTypeAnn, body);
1813     asyncFunc->SetBody(nullptr);
1814 
1815     if (returnTypeAnn != nullptr) {
1816         returnTypeAnn->SetParent(implMethod->Function());
1817     }
1818 
1819     implMethod->Function()->AddFlag(ir::ScriptFunctionFlags::ASYNC_IMPL);
1820     implMethod->SetParent(asyncMethod->Parent());
1821     return implMethod;
1822 }
1823 
CreateFuncDecl(ETSChecker * checker,ir::MethodDefinition * func,varbinder::LocalScope * scope)1824 static void CreateFuncDecl(ETSChecker *checker, ir::MethodDefinition *func, varbinder::LocalScope *scope)
1825 {
1826     auto *allocator = checker->Allocator();
1827     auto *varBinder = checker->VarBinder();
1828     // Add the function declarations to the lambda class scope
1829     auto ctx = varbinder::LexicalScope<varbinder::LocalScope>::Enter(varBinder, scope);
1830     varbinder::Variable *var = scope->FindLocal(func->Id()->Name(), varbinder::ResolveBindingOptions::ALL_DECLARATION);
1831     if (var == nullptr) {
1832         var = std::get<1>(
1833             varBinder->NewVarDecl<varbinder::FunctionDecl>(func->Start(), allocator, func->Id()->Name(), func));
1834     }
1835     var->AddFlag(varbinder::VariableFlags::METHOD);
1836     var->SetScope(ctx.GetScope());
1837     func->Function()->Id()->SetVariable(var);
1838 }
1839 
CreateAsyncProxy(ir::MethodDefinition * asyncMethod,ir::ClassDefinition * classDef,bool createDecl)1840 ir::MethodDefinition *ETSChecker::CreateAsyncProxy(ir::MethodDefinition *asyncMethod, ir::ClassDefinition *classDef,
1841                                                    bool createDecl)
1842 {
1843     ir::ScriptFunction *asyncFunc = asyncMethod->Function();
1844     if (!asyncFunc->IsExternal()) {
1845         VarBinder()->AsETSBinder()->GetRecordTable()->Signatures().push_back(asyncFunc->Scope());
1846     }
1847 
1848     // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
1849     ir::MethodDefinition *implMethod = CreateAsyncImplMethod(asyncMethod, classDef);
1850     varbinder::FunctionScope *implFuncScope = implMethod->Function()->Scope();
1851     for (auto *decl : asyncFunc->Scope()->Decls()) {
1852         auto res = asyncFunc->Scope()->Bindings().find(decl->Name());
1853         ASSERT(res != asyncFunc->Scope()->Bindings().end());
1854         auto *const var = std::get<1>(*res);
1855         var->SetScope(implFuncScope);
1856         implFuncScope->Decls().push_back(decl);
1857         implFuncScope->InsertBinding(decl->Name(), var);
1858     }
1859 
1860     ReplaceScope(implMethod->Function()->Body(), asyncFunc, implFuncScope);
1861 
1862     ArenaVector<varbinder::Variable *> captured(Allocator()->Adapter());
1863 
1864     bool isStatic = asyncMethod->IsStatic();
1865     if (createDecl) {
1866         if (isStatic) {
1867             CreateFuncDecl(this, implMethod, classDef->Scope()->AsClassScope()->StaticMethodScope());
1868         } else {
1869             CreateFuncDecl(this, implMethod, classDef->Scope()->AsClassScope()->InstanceMethodScope());
1870         }
1871         implMethod->Id()->SetVariable(implMethod->Function()->Id()->Variable());
1872     }
1873     VarBinder()->AsETSBinder()->BuildProxyMethod(implMethod->Function(), classDef->InternalName(), isStatic,
1874                                                  asyncFunc->IsExternal());
1875     implMethod->SetParent(asyncMethod->Parent());
1876 
1877     return implMethod;
1878 }
1879 
CreateMethod(const util::StringView & name,ir::ModifierFlags modifiers,ir::ScriptFunctionFlags flags,ArenaVector<ir::Expression * > && params,varbinder::FunctionParamScope * paramScope,ir::TypeNode * returnType,ir::AstNode * body)1880 ir::MethodDefinition *ETSChecker::CreateMethod(const util::StringView &name, ir::ModifierFlags modifiers,
1881                                                ir::ScriptFunctionFlags flags, ArenaVector<ir::Expression *> &&params,
1882                                                varbinder::FunctionParamScope *paramScope, ir::TypeNode *returnType,
1883                                                ir::AstNode *body)
1884 {
1885     // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
1886     auto *nameId = AllocNode<ir::Identifier>(name, Allocator());
1887     // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
1888     auto *scope = VarBinder()->Allocator()->New<varbinder::FunctionScope>(Allocator(), paramScope);
1889     // clang-format off
1890     auto *const func = AllocNode<ir::ScriptFunction>(
1891         Allocator(), ir::ScriptFunction::ScriptFunctionData {
1892             body, ir::FunctionSignature(nullptr, std::move(params), returnType), flags, modifiers});
1893     // clang-format on
1894     func->SetScope(scope);
1895     func->SetIdent(nameId);
1896     if (body != nullptr && body->IsBlockStatement()) {
1897         body->AsBlockStatement()->SetScope(scope);
1898     }
1899     scope->BindNode(func);
1900     paramScope->BindNode(func);
1901     scope->BindParamScope(paramScope);
1902     paramScope->BindFunctionScope(scope);
1903     // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
1904     auto *funcExpr = AllocNode<ir::FunctionExpression>(func);
1905     auto *nameClone = nameId->Clone(Allocator(), nullptr);
1906     // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
1907     auto *method = AllocNode<ir::MethodDefinition>(ir::MethodDefinitionKind::METHOD, nameClone, funcExpr, modifiers,
1908                                                    Allocator(), false);
1909     return method;
1910 }
1911 
CopyParams(const ArenaVector<ir::Expression * > & params,ArenaVector<ir::Expression * > & outParams)1912 varbinder::FunctionParamScope *ETSChecker::CopyParams(const ArenaVector<ir::Expression *> &params,
1913                                                       ArenaVector<ir::Expression *> &outParams)
1914 {
1915     auto paramCtx = varbinder::LexicalScope<varbinder::FunctionParamScope>(VarBinder());
1916 
1917     for (auto *const it : params) {
1918         auto *const paramOld = it->AsETSParameterExpression();
1919         // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
1920         auto *const paramNew = paramOld->Clone(Allocator(), paramOld->Parent())->AsETSParameterExpression();
1921 
1922         auto *const var = std::get<1>(VarBinder()->AddParamDecl(paramNew));
1923 
1924         var->SetTsType(paramOld->Ident()->Variable()->TsType());
1925         var->SetScope(paramCtx.GetScope());
1926         paramNew->SetVariable(var);
1927 
1928         paramNew->SetTsType(paramOld->Ident()->Variable()->TsType());
1929 
1930         outParams.emplace_back(paramNew);
1931     }
1932 
1933     return paramCtx.GetScope();
1934 }
1935 
ReplaceScope(ir::AstNode * root,ir::AstNode * oldNode,varbinder::Scope * newScope)1936 void ETSChecker::ReplaceScope(ir::AstNode *root, ir::AstNode *oldNode, varbinder::Scope *newScope)
1937 {
1938     if (root == nullptr) {
1939         return;
1940     }
1941 
1942     root->Iterate([this, oldNode, newScope](ir::AstNode *child) {
1943         auto *scope = NodeScope(child);
1944         if (scope != nullptr) {
1945             while (scope->Parent() != nullptr && scope->Parent()->Node() != oldNode) {
1946                 scope = scope->Parent();
1947             }
1948             scope->SetParent(newScope);
1949         } else {
1950             ReplaceScope(child, oldNode, newScope);
1951         }
1952     });
1953 }
1954 
MoveTrailingBlockToEnclosingBlockStatement(ir::CallExpression * callExpr)1955 void ETSChecker::MoveTrailingBlockToEnclosingBlockStatement(ir::CallExpression *callExpr)
1956 {
1957     if (callExpr == nullptr) {
1958         return;
1959     }
1960 
1961     ir::AstNode *parent = callExpr->Parent();
1962     ir::AstNode *current = callExpr;
1963     while (parent != nullptr) {
1964         if (!parent->IsBlockStatement()) {
1965             current = parent;
1966             parent = parent->Parent();
1967         } else {
1968             // Collect trailing block, insert it only when block statements traversal ends to avoid order mismatch.
1969             parent->AsBlockStatement()->AddTrailingBlock(current, callExpr->TrailingBlock());
1970             callExpr->TrailingBlock()->SetParent(parent);
1971             callExpr->SetTrailingBlock(nullptr);
1972             break;
1973         }
1974     }
1975 }
1976 
TransformTraillingLambda(ir::CallExpression * callExpr)1977 void ETSChecker::TransformTraillingLambda(ir::CallExpression *callExpr)
1978 {
1979     auto *trailingBlock = callExpr->TrailingBlock();
1980     ASSERT(trailingBlock != nullptr);
1981 
1982     auto *funcParamScope = varbinder::LexicalScope<varbinder::FunctionParamScope>(VarBinder()).GetScope();
1983     auto paramCtx = varbinder::LexicalScope<varbinder::FunctionParamScope>::Enter(VarBinder(), funcParamScope, false);
1984 
1985     auto funcCtx = varbinder::LexicalScope<varbinder::FunctionScope>(VarBinder());
1986     auto *funcScope = funcCtx.GetScope();
1987     funcScope->BindParamScope(funcParamScope);
1988     funcParamScope->BindFunctionScope(funcScope);
1989     funcParamScope->SetParent(trailingBlock->Scope()->Parent());
1990 
1991     for (auto [_, var] : trailingBlock->Scope()->Bindings()) {
1992         (void)_;
1993         if (var->GetScope() == trailingBlock->Scope()) {
1994             var->SetScope(funcScope);
1995             funcScope->InsertBinding(var->Name(), var);
1996         }
1997     }
1998 
1999     ArenaVector<ir::Expression *> params(Allocator()->Adapter());
2000     auto *funcNode = AllocNode<ir::ScriptFunction>(
2001         Allocator(), ir::ScriptFunction::ScriptFunctionData {trailingBlock,
2002                                                              ir::FunctionSignature(nullptr, std::move(params), nullptr),
2003                                                              ir::ScriptFunctionFlags::ARROW});
2004     funcNode->SetScope(funcScope);
2005     funcScope->BindNode(funcNode);
2006     funcParamScope->BindNode(funcNode);
2007 
2008     trailingBlock->SetScope(funcScope);
2009     ReplaceScope(funcNode->Body(), trailingBlock, funcScope);
2010     callExpr->SetTrailingBlock(nullptr);
2011 
2012     // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
2013     auto *arrowFuncNode = AllocNode<ir::ArrowFunctionExpression>(funcNode);
2014     arrowFuncNode->SetRange(trailingBlock->Range());
2015     arrowFuncNode->SetParent(callExpr);
2016 
2017     callExpr->Arguments().push_back(arrowFuncNode);
2018 }
2019 
ExtendArgumentsWithFakeLamda(ir::CallExpression * callExpr)2020 ArenaVector<ir::Expression *> ETSChecker::ExtendArgumentsWithFakeLamda(ir::CallExpression *callExpr)
2021 {
2022     auto funcCtx = varbinder::LexicalScope<varbinder::FunctionScope>(VarBinder());
2023     auto *funcScope = funcCtx.GetScope();
2024     ArenaVector<ir::Expression *> params(Allocator()->Adapter());
2025 
2026     ArenaVector<ir::Statement *> statements(Allocator()->Adapter());
2027     // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint)
2028     auto *body = AllocNode<ir::BlockStatement>(Allocator(), std::move(statements));
2029     body->SetScope(funcScope);
2030 
2031     auto *funcNode = AllocNode<ir::ScriptFunction>(
2032         Allocator(),
2033         ir::ScriptFunction::ScriptFunctionData {body, ir::FunctionSignature(nullptr, std::move(params), nullptr),
2034                                                 ir::ScriptFunctionFlags::ARROW});
2035     funcNode->SetScope(funcScope);
2036     funcScope->BindNode(funcNode);
2037     auto *arrowFuncNode = AllocNode<ir::ArrowFunctionExpression>(funcNode);
2038     arrowFuncNode->SetParent(callExpr);
2039 
2040     ArenaVector<ir::Expression *> fakeArguments = callExpr->Arguments();
2041     fakeArguments.push_back(arrowFuncNode);
2042     return fakeArguments;
2043 }
2044 
EnsureValidCurlyBrace(ir::CallExpression * callExpr)2045 void ETSChecker::EnsureValidCurlyBrace(ir::CallExpression *callExpr)
2046 {
2047     if (callExpr->TrailingBlock() == nullptr) {
2048         return;
2049     }
2050 
2051     if (callExpr->IsTrailingBlockInNewLine()) {
2052         MoveTrailingBlockToEnclosingBlockStatement(callExpr);
2053         return;
2054     }
2055 
2056     ThrowTypeError({"No matching call signature with trailing lambda"}, callExpr->Start());
2057 }
2058 
GetCachedFunctionalInterface(ir::ETSFunctionType * type)2059 ETSObjectType *ETSChecker::GetCachedFunctionalInterface(ir::ETSFunctionType *type)
2060 {
2061     auto hash = GetHashFromFunctionType(type);
2062     auto it = functionalInterfaceCache_.find(hash);
2063     if (it == functionalInterfaceCache_.cend()) {
2064         return nullptr;
2065     }
2066     return it->second;
2067 }
2068 
CacheFunctionalInterface(ir::ETSFunctionType * type,ETSObjectType * ifaceType)2069 void ETSChecker::CacheFunctionalInterface(ir::ETSFunctionType *type, ETSObjectType *ifaceType)
2070 {
2071     auto hash = GetHashFromFunctionType(type);
2072     ASSERT(functionalInterfaceCache_.find(hash) == functionalInterfaceCache_.cend());
2073     functionalInterfaceCache_.emplace(hash, ifaceType);
2074 }
2075 
CollectReturnStatements(ir::AstNode * parent)2076 void ETSChecker::CollectReturnStatements(ir::AstNode *parent)
2077 {
2078     parent->Iterate([this](ir::AstNode *childNode) -> void {
2079         if (childNode->IsScriptFunction()) {
2080             return;
2081         }
2082 
2083         if (childNode->IsReturnStatement()) {
2084             ir::ReturnStatement *returnStmt = childNode->AsReturnStatement();
2085             returnStmt->Check(this);
2086         }
2087 
2088         CollectReturnStatements(childNode);
2089     });
2090 }
2091 
PendingConstraintCheckRecords()2092 ArenaVector<ConstraintCheckRecord> &ETSChecker::PendingConstraintCheckRecords()
2093 {
2094     return pendingConstraintCheckRecords_;
2095 }
2096 
ConstraintCheckScopesCount()2097 size_t &ETSChecker::ConstraintCheckScopesCount()
2098 {
2099     return constraintCheckScopesCount_;
2100 }
2101 
2102 }  // namespace ark::es2panda::checker
2103