diff --git a/ets2panda/checker/ets/function.cpp b/ets2panda/checker/ets/function.cpp index 4e1e35a33d2043702f3af0144b59ab30b07fe24f..d238150d25e711c3bf384cc941c8bc07b61d8f13 100644 --- a/ets2panda/checker/ets/function.cpp +++ b/ets2panda/checker/ets/function.cpp @@ -229,6 +229,11 @@ Signature *ETSChecker::ValidateSignature(Signature *signature, const ir::TSTypeP return nullptr; } + if (argument->IsArrayExpression()) { + argument->AsArrayExpression()->GetPrefferedTypeFromFuncParam( + this, substituted_sig->Function()->Params()[index], flags); + } + auto *const argument_type = argument->Check(this); if (auto const invocation_ctx = checker::InvocationContext( diff --git a/ets2panda/checker/ets/typeRelationContext.h b/ets2panda/checker/ets/typeRelationContext.h index bd08c6587ad565e45c4c9e8a11f57ed6defeb724..e62cdfb939c13a5c3dfcf71f77a616cdb9254ab8 100644 --- a/ets2panda/checker/ets/typeRelationContext.h +++ b/ets2panda/checker/ets/typeRelationContext.h @@ -69,7 +69,7 @@ public: relation->SetNode(nullptr); relation->SetFlags(TypeRelationFlag::NONE); - assignable_ = true; + assignable_ = relation->IsTrue(); } bool IsAssignable() const diff --git a/ets2panda/ir/expressions/arrayExpression.cpp b/ets2panda/ir/expressions/arrayExpression.cpp index e620acd9eda9e729a7553f2c251ec7910c5e1d63..36ec0221e5c8f421eb7264aa98221f6e285a790c 100644 --- a/ets2panda/ir/expressions/arrayExpression.cpp +++ b/ets2panda/ir/expressions/arrayExpression.cpp @@ -366,4 +366,26 @@ checker::Type *ArrayExpression::Check(checker::ETSChecker *checker) { return checker->GetAnalyzer()->Check(this); } + +void ArrayExpression::GetPrefferedTypeFromFuncParam(checker::ETSChecker *checker, Expression *param, + checker::TypeRelationFlag flags) +{ + if (preferred_type_ != nullptr) { + return; + } + auto param_type = param->Check(checker); + if (param_type->IsETSArrayType()) { + param_type = param_type->AsETSArrayType()->ElementType(); + } + bool is_assignable = true; + for (auto elem : elements_) { + auto assign_ctx = checker::AssignmentContext(checker->Relation(), elem, elem->Check(checker), param_type, + elem->Start(), {""}, checker::TypeRelationFlag::NO_THROW | flags); + is_assignable &= assign_ctx.IsAssignable(); + } + if (is_assignable) { + preferred_type_ = param->Check(checker); + } +} + } // namespace panda::es2panda::ir diff --git a/ets2panda/ir/expressions/arrayExpression.h b/ets2panda/ir/expressions/arrayExpression.h index 50284260f208a837c1edcf8eb40f11e7626ae473..763374a61119e359d1e655a7628130f268fa0fd6 100644 --- a/ets2panda/ir/expressions/arrayExpression.h +++ b/ets2panda/ir/expressions/arrayExpression.h @@ -18,6 +18,7 @@ #include "ir/expression.h" #include "ir/validationInfo.h" +#include "checker/types/ets/etsArrayType.h" namespace panda::es2panda::checker { class ETSAnalyzer; @@ -139,6 +140,9 @@ public: v->Accept(this); } + void GetPrefferedTypeFromFuncParam(checker::ETSChecker *checker, Expression *param, + checker::TypeRelationFlag flags); + private: ArenaVector decorators_; ArenaVector elements_; diff --git a/ets2panda/test/runtime/ets/array_inf.ets b/ets2panda/test/runtime/ets/array_inf.ets new file mode 100644 index 0000000000000000000000000000000000000000..5c09324c73c9a65d126c415696b3276b2640b7e5 --- /dev/null +++ b/ets2panda/test/runtime/ets/array_inf.ets @@ -0,0 +1,27 @@ +class A { + foo(p: Object[]): int { + let s = 0 + for (let v of p) { + s += v instanceof A ? 1 : 0 + } + return s + } + bar(p: A[]): int { + let s = 0 + for (let v of p) { + s += v instanceof A ? 1 : 0 + } + return s + } +} + + +class B extends A{} + +function main() { + assert new A().foo([new Object(), new Long(), new Int()]) == 0 + assert new A().foo([new A(), new A(), new Object()]) == 2 + assert new A().foo(["aaa", new A(), new Object()]) == 1 + assert new A().foo([1, "hello", new A()]) == 1 + assert new A().bar([new B(), new B(), new A()]) == 3 +}