已关闭
Fix function types and lambda exp with receiver #10491
Fouckttt创建于 4月19日关闭于 6月22日
Fix function types and lambda exp with receiver #10491
已关闭
共 19 个文件变更+550-46
| @@ -3198,7 +3198,7 @@ std::vector<ResolveResult *> ETSChecker::ResolveMemberReference(const ir::Member | |||
| 3198 | LogError(diagnostic::EXTENSION_ACCESSOR_INVALID_CALL, {}, memberExpr->Start()); | 3198 | LogError(diagnostic::EXTENSION_ACCESSOR_INVALID_CALL, {}, memberExpr->Start()); |
| 3199 | return resolveRes; | 3199 | return resolveRes; |
| 3200 | } | 3200 | } |
| 3201 | - if (resolvedKind == ResolvedKind::EXTENSION_FUNCTION && !globalFunctionVar->TsType()->IsETSArrowType() && | 3201 | + if (prop == nullptr && resolvedKind == ResolvedKind::EXTENSION_FUNCTION && |
| 3202 | !memberExpr->Parent()->IsCallExpression()) { | 3202 | !memberExpr->Parent()->IsCallExpression()) { |
| 3203 | LogError(diagnostic::PROPERTY_NONEXISTENT, | 3203 | LogError(diagnostic::PROPERTY_NONEXISTENT, |
| 3204 | {memberExpr->Property()->AsIdentifier()->Name(), memberExpr->ObjType()}, | 3204 | {memberExpr->Property()->AsIdentifier()->Name(), memberExpr->ObjType()}, |
| @@ -353,7 +353,8 @@ bool Type::IsETSRelaxedAnyType() const | |||
| 353 | TypeFlag::ETS_TYPE_PARAMETER | TypeFlag::ETS_NONNULLISH | TypeFlag::ETS_REQUIRED_TYPE_PARAMETER | | 353 | TypeFlag::ETS_TYPE_PARAMETER | TypeFlag::ETS_NONNULLISH | TypeFlag::ETS_REQUIRED_TYPE_PARAMETER | |
| 354 | TypeFlag::ETS_ANY | TypeFlag::ETS_NEVER | TypeFlag::ETS_UNION | TypeFlag::ETS_ARRAY | TypeFlag::FUNCTION | | 354 | TypeFlag::ETS_ANY | TypeFlag::ETS_NEVER | TypeFlag::ETS_UNION | TypeFlag::ETS_ARRAY | TypeFlag::FUNCTION | |
| 355 | TypeFlag::ETS_PARTIAL_TYPE_PARAMETER | TypeFlag::ETS_TUPLE | TypeFlag::ETS_ENUM | TypeFlag::ETS_READONLY | | 355 | TypeFlag::ETS_PARTIAL_TYPE_PARAMETER | TypeFlag::ETS_TUPLE | TypeFlag::ETS_ENUM | TypeFlag::ETS_READONLY | |
| 356 | - TypeFlag::ETS_AWAITED | TypeFlag::ETS_RETURN_TYPE_UTILITY | TypeFlag::ETS_WILDCARD; | 356 | + TypeFlag::ETS_AWAITED | TypeFlag::ETS_RETURN_TYPE_UTILITY | TypeFlag::ETS_WILDCARD | |
| 357 | + TypeFlag::ETS_EXTENSION_FUNC_HELPER; | ||
| 357 | 358 | ||
| 358 | // Issues | 359 | // Issues |
| 359 | if (type->IsETSTypeAliasType()) { // NOTE(vpukhov): #20561 | 360 | if (type->IsETSTypeAliasType()) { // NOTE(vpukhov): #20561 |
| @@ -1193,7 +1193,7 @@ struct UnboxVisitor : public ir::visitor::EmptyAstVisitor { | |||
| 1193 | 1193 | ||
| 1194 | static bool IsStaticMemberExpression(ir::MemberExpression *mexpr) | 1194 | static bool IsStaticMemberExpression(ir::MemberExpression *mexpr) |
| 1195 | { | 1195 | { |
| 1196 | - ES2PANDA_ASSERT(mexpr->Kind() == ir::MemberExpressionKind::PROPERTY_ACCESS); | 1196 | + ES2PANDA_ASSERT(mexpr->HasMemberKind(ir::MemberExpressionKind::PROPERTY_ACCESS)); |
| 1197 | 1197 | ||
| 1198 | auto *propDeclNode = mexpr->Property()->Variable()->Declaration()->Node(); | 1198 | auto *propDeclNode = mexpr->Property()->Variable()->Declaration()->Node(); |
| 1199 | if (propDeclNode->IsMethodDefinition()) { | 1199 | if (propDeclNode->IsMethodDefinition()) { |
| @@ -1274,6 +1274,23 @@ struct UnboxVisitor : public ir::visitor::EmptyAstVisitor { | |||
| 1274 | return false; | 1274 | return false; |
| 1275 | } | 1275 | } |
| 1276 | 1276 | ||
| 1277 | + checker::Type *GetMemberPropertyType(ir::MemberExpression *mexpr, varbinder::Variable *propVar) | ||
| 1278 | + { | ||
| 1279 | + ES2PANDA_ASSERT(propVar != nullptr); | ||
| 1280 | + if (HandleDeclarationIfNeeded(mexpr, propVar)) { | ||
| 1281 | + return propVar->Declaration()->Node()->AsTyped()->TsType(); | ||
| 1282 | + } | ||
| 1283 | + if (propVar->TsType() != nullptr) { | ||
| 1284 | + return propVar->TsType(); | ||
| 1285 | + } | ||
| 1286 | + | ||
| 1287 | + if (mexpr->Property()->TsType() != nullptr) { | ||
| 1288 | + return mexpr->Property()->TsType(); | ||
| 1289 | + } | ||
| 1290 | + | ||
| 1291 | + return mexpr->TsType(); | ||
| 1292 | + } | ||
| 1293 | + | ||
| 1277 | void SetUnboxedPropType(ir::MemberExpression *mexpr, checker::Type *propType) | 1294 | void SetUnboxedPropType(ir::MemberExpression *mexpr, checker::Type *propType) |
| 1278 | { | 1295 | { |
| 1279 | /* Special handling for getters/setters. */ | 1296 | /* Special handling for getters/setters. */ |
| @@ -1327,21 +1344,14 @@ struct UnboxVisitor : public ir::visitor::EmptyAstVisitor { | |||
| 1327 | // CC-OFFNXT(huge_cyclomatic_complexity, huge_depth[C++], huge_depth, huge_method, G.FUN.01-CPP, G.FUN.05) solid | 1344 | // CC-OFFNXT(huge_cyclomatic_complexity, huge_depth[C++], huge_depth, huge_method, G.FUN.01-CPP, G.FUN.05) solid |
| 1328 | void VisitMemberExpression(ir::MemberExpression *mexpr) override | 1345 | void VisitMemberExpression(ir::MemberExpression *mexpr) override |
| 1329 | { | 1346 | { |
| 1330 | - if (mexpr->Kind() == ir::MemberExpressionKind::PROPERTY_ACCESS || | 1347 | + if (mexpr->HasMemberKind(ir::MemberExpressionKind::PROPERTY_ACCESS) || |
| 1331 | /* Workaround for memo plugin */ | 1348 | /* Workaround for memo plugin */ |
| 1332 | - mexpr->Kind() == ir::MemberExpressionKind::NONE || mexpr->Kind() == ir::MemberExpressionKind::GETTER || | 1349 | + mexpr->Kind() == ir::MemberExpressionKind::NONE || mexpr->HasMemberKind(ir::MemberExpressionKind::GETTER) || |
| 1333 | - mexpr->Kind() == ir::MemberExpressionKind::SETTER) { | 1350 | + mexpr->HasMemberKind(ir::MemberExpressionKind::SETTER)) { |
| 1334 | if (auto propVar = mexpr->Property()->Variable(); propVar != nullptr) { | 1351 | if (auto propVar = mexpr->Property()->Variable(); propVar != nullptr) { |
| 1335 | - checker::Type *propType = nullptr; | 1352 | + if (auto *propType = GetMemberPropertyType(mexpr, propVar); propType != nullptr) { |
| 1336 | - if (HandleDeclarationIfNeeded(mexpr, propVar)) { | 1353 | + SetUnboxedPropType(mexpr, propType); |
| 1337 | - propType = propVar->Declaration()->Node()->AsTyped()->TsType(); | ||
| 1338 | - } else if (propVar->TsType() != nullptr) { | ||
| 1339 | - propType = propVar->TsType(); | ||
| 1340 | - } else { | ||
| 1341 | - propType = mexpr->Property()->TsType(); | ||
| 1342 | } | 1354 | } |
| 1343 | - ES2PANDA_ASSERT(propType != nullptr); | ||
| 1344 | - SetUnboxedPropType(mexpr, propType); | ||
| 1345 | } else if (mexpr->Object()->TsType()->IsETSUnionType()) { | 1355 | } else if (mexpr->Object()->TsType()->IsETSUnionType()) { |
| 1346 | auto memberType = AdjustUnionMemberType(mexpr); | 1356 | auto memberType = AdjustUnionMemberType(mexpr); |
| 1347 | if (memberType != nullptr) { | 1357 | if (memberType != nullptr) { |
| @@ -1356,7 +1366,7 @@ struct UnboxVisitor : public ir::visitor::EmptyAstVisitor { | |||
| 1356 | // NOTE(gogabr): need to handle some elementary method calls as intrinsics | 1366 | // NOTE(gogabr): need to handle some elementary method calls as intrinsics |
| 1357 | mexpr->SetObject(InsertBoxing(uctx_, mexpr->Object())); | 1367 | mexpr->SetObject(InsertBoxing(uctx_, mexpr->Object())); |
| 1358 | } | 1368 | } |
| 1359 | - } else if (mexpr->Kind() == ir::MemberExpressionKind::ELEMENT_ACCESS) { | 1369 | + } else if (mexpr->HasMemberKind(ir::MemberExpressionKind::ELEMENT_ACCESS)) { |
| 1360 | /* Getters are already handled in a lowering, we need a primtive as an index */ | 1370 | /* Getters are already handled in a lowering, we need a primtive as an index */ |
| 1361 | if (TypeIsBoxedPrimitive(mexpr->Property()->TsType())) { | 1371 | if (TypeIsBoxedPrimitive(mexpr->Property()->TsType())) { |
| 1362 | mexpr->SetProperty(InsertUnboxing(uctx_, mexpr->Property())); | 1372 | mexpr->SetProperty(InsertUnboxing(uctx_, mexpr->Property())); |
| @@ -152,6 +152,70 @@ checker::Type *MemberExpression::Check(checker::TSChecker *checker) | |||
| 152 | return checker->GetAnalyzer()->Check(this); | 152 | return checker->GetAnalyzer()->Check(this); |
| 153 | } | 153 | } |
| 154 | 154 | ||
| 155 | +namespace { | ||
| 156 | + | ||
| 157 | +using ResolveObjectMemberResult = std::pair<checker::Type *, varbinder::LocalVariable *>; | ||
| 158 | + | ||
| 159 | +bool IsMemberExpressionCall(const MemberExpression *memberExpr) | ||
| 160 | +{ | ||
| 161 | + return memberExpr->Parent()->IsCallExpression() && memberExpr->Parent()->AsCallExpression()->Callee() == memberExpr; | ||
| 162 | +} | ||
| 163 | + | ||
| 164 | +ResolveObjectMemberResult ResolvePropertyMember(const MemberExpression *memberExpr, checker::ETSChecker *checker, | ||
| 165 | + varbinder::Variable *variable) | ||
| 166 | +{ | ||
| 167 | + auto *var = variable->AsLocalVariable(); | ||
| 168 | + checker->ValidatePropertyAccess(var, memberExpr->ObjType(), memberExpr->Property()); | ||
| 169 | + return {checker->GetTypeOfVariable(var), var}; | ||
| 170 | +} | ||
| 171 | + | ||
| 172 | +ResolveObjectMemberResult ResolveExtensionAccessorMember(const MemberExpression *memberExpr, | ||
| 173 | + varbinder::Variable *variable) | ||
| 174 | +{ | ||
| 175 | + const_cast<MemberExpression *>(memberExpr)->AddMemberKind(ir::MemberExpressionKind::EXTENSION_ACCESSOR); | ||
| 176 | + return {variable->TsType(), nullptr}; | ||
| 177 | +} | ||
| 178 | + | ||
| 179 | +ResolveObjectMemberResult ResolveSingleObjectMemberResult(const MemberExpression *memberExpr, | ||
| 180 | + checker::ETSChecker *checker, | ||
| 181 | + checker::ResolveResult *resolveRes) | ||
| 182 | +{ | ||
| 183 | + if (resolveRes->Kind() == checker::ResolvedKind::PROPERTY) { | ||
| 184 | + return ResolvePropertyMember(memberExpr, checker, resolveRes->Variable()); | ||
| 185 | + } | ||
| 186 | + | ||
| 187 | + if (resolveRes->Kind() == checker::ResolvedKind::EXTENSION_ACCESSOR) { | ||
| 188 | + return ResolveExtensionAccessorMember(memberExpr, resolveRes->Variable()); | ||
| 189 | + } | ||
| 190 | + | ||
| 191 | + return {checker->GetTypeOfVariable(resolveRes->Variable()), nullptr}; | ||
| 192 | +} | ||
| 193 | + | ||
| 194 | +ResolveObjectMemberResult ResolvePropertyAndExtensionMember(const MemberExpression *memberExpr, | ||
| 195 | + checker::ETSChecker *checker, | ||
| 196 | + const std::vector<checker::ResolveResult *> &resolveRes) | ||
| 197 | +{ | ||
| 198 | + auto *classMethodType = checker->GetTypeOfVariable(resolveRes[1]->Variable()); | ||
| 199 | + auto *extensionMethodType = checker->GetTypeOfVariable(resolveRes[0]->Variable()); | ||
| 200 | + const bool isCall = IsMemberExpressionCall(memberExpr); | ||
| 201 | + if (classMethodType->IsETSArrowType()) { | ||
| 202 | + if (isCall) { | ||
| 203 | + return ResolveExtensionAccessorMember(memberExpr, resolveRes[0]->Variable()); | ||
| 204 | + } | ||
| 205 | + return ResolvePropertyMember(memberExpr, checker, resolveRes[1]->Variable()); | ||
| 206 | + } | ||
| 207 | + | ||
| 208 | + auto *resolvedType = extensionMethodType; | ||
| 209 | + if (classMethodType->IsETSFunctionType()) { | ||
| 210 | + ES2PANDA_ASSERT(extensionMethodType->IsETSFunctionType()); | ||
| 211 | + resolvedType = checker->CreateETSExtensionFuncHelperType(classMethodType->AsETSFunctionType(), | ||
| 212 | + extensionMethodType->AsETSFunctionType()); | ||
| 213 | + } | ||
| 214 | + return {resolvedType, nullptr}; | ||
| 215 | +} | ||
| 216 | + | ||
| 217 | +} // namespace | ||
| 218 | + | ||
| 155 | bool MemberExpression::CheckRequiredCallError(checker::ETSChecker *checker, | 219 | bool MemberExpression::CheckRequiredCallError(checker::ETSChecker *checker, |
| 156 | const std::vector<checker::ResolveResult *> &resolveRes) const | 220 | const std::vector<checker::ResolveResult *> &resolveRes) const |
| 157 | { | 221 | { |
| @@ -183,36 +247,10 @@ std::pair<checker::Type *, varbinder::LocalVariable *> MemberExpression::Resolve | |||
| 183 | return {nullptr, nullptr}; | 247 | return {nullptr, nullptr}; |
| 184 | } | 248 | } |
| 185 | case 1U: { | 249 | case 1U: { |
| 186 | - if (resolveRes[0]->Kind() == checker::ResolvedKind::PROPERTY) { | 250 | + return ResolveSingleObjectMemberResult(this, checker, resolveRes[0]); |
| 187 | - auto var = resolveRes[0]->Variable()->AsLocalVariable(); | ||
| 188 | - checker->ValidatePropertyAccess(var, objType_, property_); | ||
| 189 | - return {checker->GetTypeOfVariable(var), var}; | ||
| 190 | - } | ||
| 191 | - | ||
| 192 | - if (resolveRes[0]->Kind() == checker::ResolvedKind::EXTENSION_ACCESSOR) { | ||
| 193 | - auto *callee = const_cast<ir::Expression *>(this->AsExpression()); | ||
| 194 | - callee->AsMemberExpression()->AddMemberKind(ir::MemberExpressionKind::EXTENSION_ACCESSOR); | ||
| 195 | - return {resolveRes[0]->Variable()->TsType(), nullptr}; | ||
| 196 | - } | ||
| 197 | - | ||
| 198 | - return {checker->GetTypeOfVariable(resolveRes[0]->Variable()), nullptr}; | ||
| 199 | } | 251 | } |
| 200 | case 2U: { | 252 | case 2U: { |
| 201 | - auto classMethodType = checker->GetTypeOfVariable(resolveRes[1]->Variable()); | 253 | + return ResolvePropertyAndExtensionMember(this, checker, resolveRes); |
| 202 | - auto extensionMethodType = checker->GetTypeOfVariable(resolveRes[0]->Variable()); | ||
| 203 | - auto *resolvedType = extensionMethodType; | ||
| 204 | - if (classMethodType->IsETSArrowType()) { | ||
| 205 | - auto *callee = const_cast<ir::Expression *>(this->AsExpression()); | ||
| 206 | - callee->AsMemberExpression()->AddMemberKind(ir::MemberExpressionKind::EXTENSION_ACCESSOR); | ||
| 207 | - return {resolveRes[0]->Variable()->TsType(), nullptr}; | ||
| 208 | - } | ||
| 209 | - | ||
| 210 | - if (classMethodType->IsETSFunctionType()) { | ||
| 211 | - ES2PANDA_ASSERT(extensionMethodType->IsETSFunctionType()); | ||
| 212 | - resolvedType = checker->CreateETSExtensionFuncHelperType(classMethodType->AsETSFunctionType(), | ||
| 213 | - extensionMethodType->AsETSFunctionType()); | ||
| 214 | - } | ||
| 215 | - return {resolvedType, nullptr}; | ||
| 216 | } | 254 | } |
| 217 | default: { | 255 | default: { |
| 218 | ES2PANDA_UNREACHABLE(); | 256 | ES2PANDA_UNREACHABLE(); |
| @@ -255,7 +293,7 @@ void MemberExpression::CollectUnionSignatures(checker::ETSChecker *checker, chec | |||
| 255 | } | 293 | } |
| 256 | } | 294 | } |
| 257 | 295 | ||
| 258 | -static bool haveDifferentSignatures(checker::ETSChecker *checker, | 296 | +static bool HaveDifferentSignatures(checker::ETSChecker *checker, |
| 259 | const MemberExpression::ComponentTypeMemberAccessors &typeSignatures) | 297 | const MemberExpression::ComponentTypeMemberAccessors &typeSignatures) |
| 260 | { | 298 | { |
| 261 | if (typeSignatures.size() < 2U || !std::holds_alternative<checker::Signature *>(typeSignatures[0].second)) { | 299 | if (typeSignatures.size() < 2U || !std::holds_alternative<checker::Signature *>(typeSignatures[0].second)) { |
| @@ -355,7 +393,7 @@ checker::Type *MemberExpression::TraverseUnionMember(checker::ETSChecker *checke | |||
| 355 | commonPropType = checker->GlobalTypeError(); | 393 | commonPropType = checker->GlobalTypeError(); |
| 356 | } | 394 | } |
| 357 | } | 395 | } |
| 358 | - if (haveDifferentSignatures(checker, this->GetComponentTypeMemberAccessors())) { | 396 | + if (HaveDifferentSignatures(checker, this->GetComponentTypeMemberAccessors())) { |
| 359 | checker->LogError(diagnostic::MEMBER_TYPE_MISMATCH_ACROSS_UNION, {}, Start()); | 397 | checker->LogError(diagnostic::MEMBER_TYPE_MISMATCH_ACROSS_UNION, {}, Start()); |
| 360 | commonPropType = checker->GlobalTypeError(); | 398 | commonPropType = checker->GlobalTypeError(); |
| 361 | } | 399 | } |
Aets2panda/test/ast/compiler/ets/lambda_with_receiver_tests/arrowPropertyVsExtensionNonCallSite.ets+31-0
| @@ -0,0 +1,31 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 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 | +class A { | ||
| 17 | + f(): int { | ||
| 18 | + return 1 | ||
| 19 | + } | ||
| 20 | +} | ||
| 21 | + | ||
| 22 | +let f = (this: A): int => { | ||
| 23 | + return 42 | ||
| 24 | +} | ||
| 25 | + | ||
| 26 | +function main() { | ||
| 27 | + let a = new A() | ||
| 28 | + let fn: () => int = a.f | ||
| 29 | +} | ||
| 30 | + | ||
| 31 | +/* @@? 28:25 Error Semantic error ESE0318: Type '(() => Int) | ((p1: A) => Int)' cannot be assigned to type '(() => Int)' */ | ||
| @@ -0,0 +1,30 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 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 | +class A {} | ||
| 17 | +type FA = (this: A) => Function | ||
| 18 | + | ||
| 19 | +let g = (this: A): boolean => { | ||
| 20 | + return true | ||
| 21 | +} | ||
| 22 | + | ||
| 23 | +let f: FA = (this: A): Function => { | ||
| 24 | + this.g() | ||
| 25 | + return () => { | ||
| 26 | + return 1 | ||
| 27 | + } | ||
| 28 | + let a = new A() | ||
| 29 | + a.g() | ||
| 30 | +} | ||
| @@ -0,0 +1,35 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 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 | +class A {} | ||
| 17 | +type FA = (this: A) => Function | ||
| 18 | + | ||
| 19 | +function main() { | ||
| 20 | + let g = (this: A): boolean => { | ||
| 21 | + return true | ||
| 22 | + } | ||
| 23 | + let f: FA = (this: A): Function => { | ||
| 24 | + this.g() | ||
| 25 | + return () => { | ||
| 26 | + return 1 | ||
| 27 | + } | ||
| 28 | + let a = new A() | ||
| 29 | + a.g() | ||
| 30 | + } | ||
| 31 | +} | ||
| 32 | + | ||
| 33 | + | ||
| 34 | +/* @@? 28:9 Warning Warning W0026: Unreachable statement. */ | ||
| 35 | +/* @@? 29:9 Warning Warning W0026: Unreachable statement. */ | ||
| @@ -0,0 +1,34 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 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 | +class A {} | ||
| 17 | +type FA = (this: A) => Function | ||
| 18 | + | ||
| 19 | +function main() { | ||
| 20 | + let g = (this: A): boolean => { | ||
| 21 | + return true | ||
| 22 | + } | ||
| 23 | + let f: FA = (this: A): Function => { | ||
| 24 | + return () => { | ||
| 25 | + return 1 | ||
| 26 | + } | ||
| 27 | + let a = new A() | ||
| 28 | + a.g() | ||
| 29 | + } | ||
| 30 | +} | ||
| 31 | + | ||
| 32 | + | ||
| 33 | +/* @@? 27:9 Warning Warning W0026: Unreachable statement. */ | ||
| 34 | +/* @@? 28:9 Warning Warning W0026: Unreachable statement. */ | ||
| @@ -0,0 +1,28 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 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 | +class A {} | ||
| 17 | +type FA = (this: A) => Function | ||
| 18 | + | ||
| 19 | +function main() { | ||
| 20 | + let a: A = new A() | ||
| 21 | + let f: FA = (this: A): Function => { | ||
| 22 | + return this.f | ||
| 23 | + } | ||
| 24 | + a.f() | ||
| 25 | +} | ||
| 26 | + | ||
| 27 | + | ||
| 28 | +/* @@? 22:21 Error Semantic error ESE0087: Property 'f' does not exist on type 'A' */ | ||
| @@ -0,0 +1,27 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 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 | +interface I {} | ||
| 17 | +type FI = (this: I) => Function | ||
| 18 | + | ||
| 19 | +function main() { | ||
| 20 | + let i: I = {} | ||
| 21 | + let f: FI = (this: I): Function => { | ||
| 22 | + return this.f | ||
| 23 | + } | ||
| 24 | +} | ||
What additional value does this test bring compared to ![]() ![]() | |||
| 25 | + | ||
| 26 | + | ||
| 27 | +/* @@? 22:21 Error Semantic error ESE0087: Property 'f' does not exist on type 'I' */ | ||
| @@ -0,0 +1,26 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 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 | +class A {} | ||
| 17 | +type FA = (this: A) => Function | ||
| 18 | + | ||
| 19 | +let a: A = new A() | ||
| 20 | + | ||
| 21 | +function foo(this: A) { | ||
| 22 | + return this.foo | ||
| 23 | +} | ||
| 24 | + | ||
| 25 | + | ||
| 26 | +/* @@? 22:17 Error Semantic error ESE0087: Property 'foo' does not exist on type 'A' */ | ||
| @@ -0,0 +1,29 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 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 | +class A {} | ||
| 17 | +type FA = (this: A) => Function | ||
| 18 | + | ||
| 19 | +let a: A = new A() | ||
| 20 | +let f = (this: A) => { | ||
| 21 | + return 1 | ||
| 22 | +} | ||
| 23 | + | ||
| 24 | +function foo(this: A) { | ||
| 25 | + return this.f | ||
| 26 | +} | ||
| 27 | + | ||
| 28 | + | ||
| 29 | +/* @@? 25:17 Error Semantic error ESE0087: Property 'f' does not exist on type 'A' */ | ||
| @@ -0,0 +1,27 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 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 | +class A {} | ||
| 17 | +type FA = (this: A) => Function | ||
| 18 | + | ||
| 19 | +let a: A = new A() | ||
| 20 | + | ||
| 21 | +function f(this: A) { | ||
| 22 | + return 1 | ||
| 23 | +} | ||
| 24 | + | ||
| 25 | +function foo(this: A) { | ||
| 26 | + return this.f() | ||
| 27 | +} | ||
| @@ -0,0 +1,30 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 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 | +class A {} | ||
| 17 | +type FA = (this: A) => Function | ||
| 18 | + | ||
| 19 | +let a: A = new A() | ||
| 20 | + | ||
| 21 | +function f(this: A) { | ||
| 22 | + return 1 | ||
| 23 | +} | ||
| 24 | + | ||
| 25 | +function foo(this: A) { | ||
| 26 | + return this.f | ||
| 27 | +} | ||
| 28 | + | ||
| 29 | + | ||
| 30 | +/* @@? 26:17 Error Semantic error ESE0087: Property 'f' does not exist on type 'A' */ | ||
| @@ -0,0 +1,27 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 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 | +class A { | ||
| 17 | + f: () => int = () => 0 | ||
| 18 | +} | ||
| 19 | + | ||
| 20 | +let f = (this: A): int => { | ||
| 21 | + return 42 | ||
| 22 | +} | ||
| 23 | + | ||
| 24 | +function main() { | ||
| 25 | + let a = new A() | ||
| 26 | + arktest.assertEQ(a.f(), 42) | ||
| 27 | +} | ||
| @@ -0,0 +1,31 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 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 | +class A { | ||
| 17 | + val: int = 10 | ||
| 18 | + f: () => int = () => 0 | ||
| 19 | +} | ||
| 20 | + | ||
| 21 | +let f = (this: A): int => { | ||
| 22 | + return this.val + 100 | ||
| 23 | +} | ||
| 24 | + | ||
| 25 | +function main(): void { | ||
| 26 | + let a = new A() | ||
| 27 | + arktest.assertEQ(a.f(), 110) | ||
| 28 | + a.f = () => a.val | ||
| 29 | + let fn = a.f | ||
| 30 | + arktest.assertEQ(fn(), 10) | ||
| 31 | +} | ||
| @@ -0,0 +1,37 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 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 | +class A { | ||
| 17 | + _value: int = 10 | ||
| 18 | +} | ||
| 19 | + | ||
| 20 | +get value(this: A): int { | ||
| 21 | + return this._value | ||
| 22 | +} | ||
| 23 | + | ||
| 24 | +set value(this: A, v: int) { | ||
| 25 | + this._value = v | ||
| 26 | +} | ||
| 27 | + | ||
| 28 | +function main(): void { | ||
| 29 | + let a = new A() | ||
| 30 | + arktest.assertEQ(a.value, 10) | ||
| 31 | + a.value = 20 | ||
| 32 | + arktest.assertEQ(a.value, 20) | ||
| 33 | + a.value++ | ||
| 34 | + arktest.assertEQ(a.value, 21) | ||
| 35 | + ++a.value | ||
| 36 | + arktest.assertEQ(a.value, 22) | ||
| 37 | +} | ||
| @@ -0,0 +1,33 @@ | |||
| 1 | +/* | ||
| 2 | + * Copyright (c) 2026 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 | +class A { | ||
| 17 | + _value: int = 10 | ||
| 18 | +} | ||
| 19 | + | ||
| 20 | +get value(this: A): int { | ||
| 21 | + return this._value | ||
| 22 | +} | ||
| 23 | + | ||
| 24 | +set value(this: A, v: int) { | ||
| 25 | + this._value = v | ||
| 26 | +} | ||
| 27 | + | ||
| 28 | +function main(): void { | ||
| 29 | + let a = new A() | ||
| 30 | + arktest.assertEQ(a.value, 10) | ||
| 31 | + a.value = 20 | ||
| 32 | + arktest.assertEQ(a.value, 20) | ||
| 33 | +} | ||
| @@ -0,0 +1,30 @@ | |||
| 1 | +/* | ||
The case can be placed in the runtime test. ![]() ![]() | |||
| 2 | + * Copyright (c) 2026 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 | +class A { | ||
| 17 | + f(x: int): int { | ||
| 18 | + return x | ||
| 19 | + } | ||
| 20 | +} | ||
| 21 | + | ||
| 22 | +function f(this: A): int { | ||
| 23 | + return 42 | ||
| 24 | +} | ||
| 25 | + | ||
| 26 | +function main() { | ||
| 27 | + let a = new A() | ||
| 28 | + arktest.assertEQ(a.f(), 42) | ||
| 29 | + arktest.assertEQ(a.f(1), 1) | ||
| 30 | +} | ||


This is clearly not the expected behaviour. Expression
a.feither refers to the methodA.for to the global variablef. Depending on that resolution, it either has one or the other type, but the type of the expression is not their union.