Fixes incorrect MismatchedCount error message when returning (#103)

This commit is contained in:
Valts Liepiņš 2021-11-04 06:23:20 +02:00 committed by GitHub
parent e3f8c25e9e
commit 344d37f0b1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 33 additions and 15 deletions

View File

@ -112,21 +112,20 @@ struct ErrorConverter
std::string operator()(const Luau::CountMismatch& e) const
{
const std::string expectedS = e.expected == 1 ? "" : "s";
const std::string actualS = e.actual == 1 ? "" : "s";
const std::string actualVerb = e.actual == 1 ? "is" : "are";
switch (e.context)
{
case CountMismatch::Return:
{
const std::string expectedS = e.expected == 1 ? "" : "s";
const std::string actualS = e.actual == 1 ? "is" : "are";
return "Expected to return " + std::to_string(e.expected) + " value" + expectedS + ", but " + std::to_string(e.actual) + " " + actualS +
" returned here";
}
return "Expected to return " + std::to_string(e.expected) + " value" + expectedS + ", but " +
std::to_string(e.actual) + " " + actualVerb + " returned here";
case CountMismatch::Result:
if (e.expected > e.actual)
return "Function returns " + std::to_string(e.expected) + " values but there are only " + std::to_string(e.expected) +
" values to unpack them into.";
else
return "Function only returns " + std::to_string(e.expected) + " values. " + std::to_string(e.actual) + " are required here";
// It is alright if right hand side produces more values than the
// left hand side accepts. In this context consider only the opposite case.
return "Function only returns " + std::to_string(e.expected) + " value" + expectedS + ". " +
std::to_string(e.actual) + " are required here";
case CountMismatch::Arg:
return "Argument count mismatch. Function " + wrongNumberOfArgsString(e.expected, e.actual);
}

View File

@ -626,11 +626,11 @@ void Unifier::tryUnify_(TypePackId superTp, TypePackId subTp, bool isFunctionCal
}
// This is a bit weird because we don't actually know expected vs actual. We just know
// subtype vs supertype. If we are checking a return value, we swap these to produce
// the expected error message.
// subtype vs supertype. If we are checking the values returned by a function, we swap
// these to produce the expected error message.
size_t expectedSize = size(superTp);
size_t actualSize = size(subTp);
if (ctx == CountMismatch::Result || ctx == CountMismatch::Return)
if (ctx == CountMismatch::Result)
std::swap(expectedSize, actualSize);
errors.push_back(TypeError{location, CountMismatch{expectedSize, actualSize, ctx}});

View File

@ -3251,7 +3251,24 @@ TEST_CASE_FIXTURE(Fixture, "too_many_return_values")
CountMismatch* acm = get<CountMismatch>(result.errors[0]);
REQUIRE(acm);
CHECK(acm->context == CountMismatch::Result);
CHECK_EQ(acm->context, CountMismatch::Result);
CHECK_EQ(acm->expected, 1);
CHECK_EQ(acm->actual, 2);
}
TEST_CASE_FIXTURE(Fixture, "ignored_return_values")
{
CheckResult result = check(R"(
--!strict
function f()
return 55, ""
end
local a = f()
)");
LUAU_REQUIRE_ERROR_COUNT(0, result);
}
TEST_CASE_FIXTURE(Fixture, "function_does_not_return_enough_values")
@ -3269,6 +3286,8 @@ TEST_CASE_FIXTURE(Fixture, "function_does_not_return_enough_values")
CountMismatch* acm = get<CountMismatch>(result.errors[0]);
REQUIRE(acm);
CHECK_EQ(acm->context, CountMismatch::Return);
CHECK_EQ(acm->expected, 2);
CHECK_EQ(acm->actual, 1);
}
TEST_CASE_FIXTURE(Fixture, "typecheck_unary_minus")