diff --git a/ets2panda/checker/ETSAnalyzer.cpp b/ets2panda/checker/ETSAnalyzer.cpp index 3ec7df078b5a3fdef68561dfcffeb4816e8479bc..d8bf9f61269e516e296186a9980b69f6ba7b76b6 100644 --- a/ets2panda/checker/ETSAnalyzer.cpp +++ b/ets2panda/checker/ETSAnalyzer.cpp @@ -2493,6 +2493,10 @@ checker::Type *ETSAnalyzer::Check(ir::TSAsExpression *expr) const { ETSChecker *checker = GetETSChecker(); + if (expr->TsType() != nullptr) { + return expr->TsType(); + } + auto *const targetType = expr->TypeAnnotation()->AsTypeNode()->GetType(checker); // Object expression requires that its type be set by the context before checking. in this case, the target type // provides that context. diff --git a/ets2panda/checker/ETSchecker.h b/ets2panda/checker/ETSchecker.h index 5ff5bec1b9e860e247edde16143f3d5c25ddf61f..fd168f6bb6db0a973702e3f049762673579fe0d3 100644 --- a/ets2panda/checker/ETSchecker.h +++ b/ets2panda/checker/ETSchecker.h @@ -302,6 +302,8 @@ public: Type *argumentType, Substitution *substitution); [[nodiscard]] bool EnhanceSubstitutionForUnion(const ArenaVector &typeParams, ETSUnionType *paramUn, Type *argumentType, Substitution *substitution); + [[nodiscard]] bool EnhanceSubstitutionForArray(const ArenaVector &typeParams, ETSArrayType *paramType, + Type *argumentType, Substitution *substitution); Signature *ValidateParameterlessConstructor(Signature *signature, const lexer::SourcePosition &pos, TypeRelationFlag flags); Signature *CollectParameterlessConstructor(ArenaVector &signatures, const lexer::SourcePosition &pos, diff --git a/ets2panda/checker/ets/function.cpp b/ets2panda/checker/ets/function.cpp index cd5bf515fce5509f56efc5a94ce2ac644eb946be..b8874c13cdfe92b50b7c445528f12692d71715b4 100644 --- a/ets2panda/checker/ets/function.cpp +++ b/ets2panda/checker/ets/function.cpp @@ -110,6 +110,10 @@ bool ETSChecker::EnhanceSubstitutionForType(const ArenaVector &typeParam if (paramType->IsETSObjectType()) { return EnhanceSubstitutionForObject(typeParams, paramType->AsETSObjectType(), argumentType, substitution); } + if (paramType->IsETSArrayType()) { + return EnhanceSubstitutionForArray(typeParams, paramType->AsETSArrayType(), argumentType, substitution); + } + return true; } @@ -194,6 +198,15 @@ bool ETSChecker::EnhanceSubstitutionForObject(const ArenaVector &typePar return true; } +bool ETSChecker::EnhanceSubstitutionForArray(const ArenaVector &typeParams, ETSArrayType *const paramType, + Type *const argumentType, Substitution *const substitution) +{ + auto *const elementType = + argumentType->IsETSArrayType() ? argumentType->AsETSArrayType()->ElementType() : argumentType; + + return EnhanceSubstitutionForType(typeParams, paramType->ElementType(), elementType, substitution); +} + Signature *ETSChecker::ValidateParameterlessConstructor(Signature *signature, const lexer::SourcePosition &pos, TypeRelationFlag flags) { diff --git a/ets2panda/checker/ets/function_helpers.h b/ets2panda/checker/ets/function_helpers.h index f93e8562fddcfe74256f015dc1831b464792d688..174375932cff631f62b4c98372c1834ad385f17a 100644 --- a/ets2panda/checker/ets/function_helpers.h +++ b/ets2panda/checker/ets/function_helpers.h @@ -87,18 +87,25 @@ static const Substitution *BuildImplicitSubstitutionForArguments(ETSChecker *che { Substitution *substitution = checker->NewSubstitution(); auto *sigInfo = signature->GetSignatureInfo(); + for (size_t ix = 0; ix < arguments.size(); ix++) { auto *arg = arguments[ix]; if (arg->IsObjectExpression()) { continue; } - auto *argType = MaybeBoxedType(checker, arg->Check(checker), arg); - auto *paramType = (ix < signature->MinArgCount()) ? sigInfo->params[ix]->TsType() - : sigInfo->restVar != nullptr ? sigInfo->restVar->TsType() - : nullptr; + + auto *const argType = arg->IsSpreadElement() + ? MaybeBoxedType(checker, arg->AsSpreadElement()->Argument()->Check(checker), + arg->AsSpreadElement()->Argument()) + : MaybeBoxedType(checker, arg->Check(checker), arg); + auto *const paramType = (ix < signature->MinArgCount()) ? sigInfo->params[ix]->TsType() + : sigInfo->restVar != nullptr ? sigInfo->restVar->TsType() + : nullptr; + if (paramType == nullptr) { continue; } + if (!checker->EnhanceSubstitutionForType(sigInfo->typeParams, paramType, argType, substitution)) { return nullptr; } @@ -159,7 +166,7 @@ static Signature *MaybeSubstituteTypeParameters(ETSChecker *checker, Signature * const Substitution *substitution = (typeArguments != nullptr) ? BuildExplicitSubstitutionForArguments(checker, signature, typeArguments->Params(), pos, flags) - : (signature->GetSignatureInfo()->params.empty() + : (signature->GetSignatureInfo()->params.empty() && signature->GetSignatureInfo()->restVar == nullptr ? nullptr : BuildImplicitSubstitutionForArguments(checker, signature, arguments)); diff --git a/ets2panda/test/compiler/ets/generic_func_rest_param_spread_infer-expected.txt b/ets2panda/test/compiler/ets/generic_func_rest_param_spread_infer-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..3246383e922777376731d67086ab440d4c4854dc --- /dev/null +++ b/ets2panda/test/compiler/ets/generic_func_rest_param_spread_infer-expected.txt @@ -0,0 +1,974 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "_$init$_", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 10 + }, + "end": { + "line": 16, + "column": 14 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "main", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 10 + }, + "end": { + "line": 16, + "column": 14 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "arr1", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 9 + }, + "end": { + "line": 17, + "column": 13 + } + } + }, + "init": { + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Array", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 16 + }, + "end": { + "line": 17, + "column": 21 + } + } + }, + "property": { + "type": "Identifier", + "name": "of", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 22 + }, + "end": { + "line": 17, + "column": 24 + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 17, + "column": 16 + }, + "end": { + "line": 17, + "column": 24 + } + } + }, + "arguments": [ + { + "type": "SpreadElement", + "argument": { + "type": "TSAsExpression", + "expression": { + "type": "ArrayExpression", + "elements": [ + { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 17, + "column": 30 + }, + "end": { + "line": 17, + "column": 31 + } + } + }, + { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 17, + "column": 33 + }, + "end": { + "line": 17, + "column": 34 + } + } + }, + { + "type": "NumberLiteral", + "value": 3, + "loc": { + "start": { + "line": 17, + "column": 36 + }, + "end": { + "line": 17, + "column": 37 + } + } + } + ], + "loc": { + "start": { + "line": 17, + "column": 29 + }, + "end": { + "line": 17, + "column": 38 + } + } + }, + "typeAnnotation": { + "type": "TSArrayType", + "elementType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Int", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 42 + }, + "end": { + "line": 17, + "column": 45 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 42 + }, + "end": { + "line": 17, + "column": 46 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 42 + }, + "end": { + "line": 17, + "column": 46 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 47 + }, + "end": { + "line": 17, + "column": 48 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 28 + }, + "end": { + "line": 17, + "column": 48 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 25 + }, + "end": { + "line": 17, + "column": 48 + } + } + } + ], + "optional": false, + "loc": { + "start": { + "line": 17, + "column": 16 + }, + "end": { + "line": 17, + "column": 49 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 9 + }, + "end": { + "line": 17, + "column": 49 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 17, + "column": 5 + }, + "end": { + "line": 17, + "column": 50 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "arr2", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 9 + }, + "end": { + "line": 18, + "column": 13 + } + } + }, + "init": { + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Array", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 16 + }, + "end": { + "line": 18, + "column": 21 + } + } + }, + "property": { + "type": "Identifier", + "name": "of", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 22 + }, + "end": { + "line": 18, + "column": 24 + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 18, + "column": 16 + }, + "end": { + "line": 18, + "column": 24 + } + } + }, + "arguments": [ + { + "type": "SpreadElement", + "argument": { + "type": "TSAsExpression", + "expression": { + "type": "ArrayExpression", + "elements": [ + { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 18, + "column": 30 + }, + "end": { + "line": 18, + "column": 31 + } + } + }, + { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 18, + "column": 33 + }, + "end": { + "line": 18, + "column": 34 + } + } + }, + { + "type": "NumberLiteral", + "value": 3, + "loc": { + "start": { + "line": 18, + "column": 36 + }, + "end": { + "line": 18, + "column": 37 + } + } + } + ], + "loc": { + "start": { + "line": 18, + "column": 29 + }, + "end": { + "line": 18, + "column": 38 + } + } + }, + "typeAnnotation": { + "type": "TSArrayType", + "elementType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Double", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 42 + }, + "end": { + "line": 18, + "column": 48 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 42 + }, + "end": { + "line": 18, + "column": 49 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 42 + }, + "end": { + "line": 18, + "column": 49 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 50 + }, + "end": { + "line": 18, + "column": 51 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 28 + }, + "end": { + "line": 18, + "column": 51 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 25 + }, + "end": { + "line": 18, + "column": 51 + } + } + } + ], + "optional": false, + "loc": { + "start": { + "line": 18, + "column": 16 + }, + "end": { + "line": 18, + "column": 52 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 9 + }, + "end": { + "line": 18, + "column": 52 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 53 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "arr3", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 9 + }, + "end": { + "line": 19, + "column": 13 + } + } + }, + "init": { + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "Array", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 16 + }, + "end": { + "line": 19, + "column": 21 + } + } + }, + "property": { + "type": "Identifier", + "name": "of", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 22 + }, + "end": { + "line": 19, + "column": 24 + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 19, + "column": 16 + }, + "end": { + "line": 19, + "column": 24 + } + } + }, + "arguments": [ + { + "type": "SpreadElement", + "argument": { + "type": "TSAsExpression", + "expression": { + "type": "ArrayExpression", + "elements": [ + { + "type": "NumberLiteral", + "value": 1, + "loc": { + "start": { + "line": 19, + "column": 30 + }, + "end": { + "line": 19, + "column": 31 + } + } + }, + { + "type": "NumberLiteral", + "value": 2, + "loc": { + "start": { + "line": 19, + "column": 33 + }, + "end": { + "line": 19, + "column": 34 + } + } + }, + { + "type": "NumberLiteral", + "value": 3, + "loc": { + "start": { + "line": 19, + "column": 36 + }, + "end": { + "line": 19, + "column": 37 + } + } + } + ], + "loc": { + "start": { + "line": 19, + "column": 29 + }, + "end": { + "line": 19, + "column": 38 + } + } + }, + "typeAnnotation": { + "type": "TSArrayType", + "elementType": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "Object", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 42 + }, + "end": { + "line": 19, + "column": 48 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 42 + }, + "end": { + "line": 19, + "column": 49 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 42 + }, + "end": { + "line": 19, + "column": 49 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 50 + }, + "end": { + "line": 19, + "column": 51 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 28 + }, + "end": { + "line": 19, + "column": 51 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 25 + }, + "end": { + "line": 19, + "column": 51 + } + } + } + ], + "optional": false, + "loc": { + "start": { + "line": 19, + "column": 16 + }, + "end": { + "line": 19, + "column": 52 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 9 + }, + "end": { + "line": 19, + "column": 52 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 19, + "column": 5 + }, + "end": { + "line": 19, + "column": 53 + } + } + } + ], + "loc": { + "start": { + "line": 16, + "column": 17 + }, + "end": { + "line": 20, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 14 + }, + "end": { + "line": 20, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 14 + }, + "end": { + "line": 20, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 20, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 21, + "column": 1 + } + } +} diff --git a/ets2panda/test/compiler/ets/generic_func_rest_param_spread_infer.ets b/ets2panda/test/compiler/ets/generic_func_rest_param_spread_infer.ets new file mode 100644 index 0000000000000000000000000000000000000000..a24750613382dd170ff3a3e0d587f555fe0efeba --- /dev/null +++ b/ets2panda/test/compiler/ets/generic_func_rest_param_spread_infer.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +function main() { + let arr1 = Array.of(...([1, 2, 3] as Int[])); + let arr2 = Array.of(...([1, 2, 3] as Double[])); + let arr3 = Array.of(...([1, 2, 3] as Object[])); +}