Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace empty check of error, warning and info list with check for errors only #15203

Open
wants to merge 3 commits into
base: develop
Choose a base branch
from

Conversation

matheusaaguiar
Copy link
Collaborator

This is a minor bug found here by @cameel.
There are some instances where an intended check for errors can incorrectly consider warnings and info as well.

@matheusaaguiar matheusaaguiar self-assigned this Jun 18, 2024
Copy link
Collaborator Author

@matheusaaguiar matheusaaguiar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is also an instance of using errors().empty() check at

else if (!m_unsupportedErrorReporter.errors().empty())

but in this case it is specifically used to collect only warnings in SMTEncoder, BMC and CHC.

@@ -1647,7 +1647,7 @@ Json StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings)
std::string const& sourceContents = _inputsAndSettings.sources.begin()->second;

// Inconsistent state - stop here to receive error reports from users
if (!stack.parseAndAnalyze(sourceName, sourceContents) && stack.errors().empty())
if (!stack.parseAndAnalyze(sourceName, sourceContents) && !stack.hasErrors())
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although there are no warnings in Yul Parser, if that happens to be the case in the future, this would already prevent the mistake of consider them as errors. Also, it follows the same logic of the changes made to instances of ErrorReporter::errors().

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean, we have no warnings in AsmParser but we do have some in AsmAnalysis. So you can actually get a warning from parseAndAnalyze().

But anyway, this is a good change.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, I'd go even further and make it an assert. That's what we do already in compileSolidity(). The exception will then be caught by the top-level handler in StandardCompiler::compile() and reported as error anyway.

This will affect the behavior slightly - the user will no longer get anything already added to output - but I think that's the correct behavior in case of a failed assumption anyway. I.e. drop everything and just fail immediately.

@@ -473,7 +473,7 @@ void CompilerContext::appendInlineAssembly(
dialect,
identifierAccess.resolve
).analyze(*parserResult);
if (!parserResult || !errorReporter.errors().empty() || !analyzerResult)
if (!parserResult || errorReporter.hasErrors() || !analyzerResult)
reportError("Invalid assembly generated by code generator.");
Copy link
Member

@cameel cameel Jun 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd actually keep it at !errorReporter.errors().empty() here. This only runs on our own code produced by the codegen, we don't want warnings there.

Same for the other checks in this file, below.

Copy link
Member

@cameel cameel Jun 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By the way, maybe we should actually introduce a new helper with a very overt name, like hasErrorsWarningsOrInfos() to make this error harder to make in the future. Then just remove all uses of errors().empty() anyway.

Alternatively, we could rename errors() to reports(). But a helper would require fewer changes, so maybe it's a better option for now.

@@ -1647,7 +1647,7 @@ Json StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings)
std::string const& sourceContents = _inputsAndSettings.sources.begin()->second;

// Inconsistent state - stop here to receive error reports from users
if (!stack.parseAndAnalyze(sourceName, sourceContents) && stack.errors().empty())
if (!stack.parseAndAnalyze(sourceName, sourceContents) && !stack.hasErrors())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean, we have no warnings in AsmParser but we do have some in AsmAnalysis. So you can actually get a warning from parseAndAnalyze().

But anyway, this is a good change.

@@ -1647,7 +1647,7 @@ Json StandardCompiler::compileYul(InputsAndSettings _inputsAndSettings)
std::string const& sourceContents = _inputsAndSettings.sources.begin()->second;

// Inconsistent state - stop here to receive error reports from users
if (!stack.parseAndAnalyze(sourceName, sourceContents) && stack.errors().empty())
if (!stack.parseAndAnalyze(sourceName, sourceContents) && !stack.hasErrors())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, I'd go even further and make it an assert. That's what we do already in compileSolidity(). The exception will then be caught by the top-level handler in StandardCompiler::compile() and reported as error anyway.

This will affect the behavior slightly - the user will no longer get anything already added to output - but I think that's the correct behavior in case of a failed assumption anyway. I.e. drop everything and just fail immediately.

Comment on lines 140 to 143
if (_canWarn)
BOOST_REQUIRE(!Error::containsErrors(stack.errors()));
else
BOOST_REQUIRE(stack.errors().empty());
BOOST_REQUIRE(!stack.hasErrors());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one was intentional. Note the _canWarn variable. If we're in the else branch, we don't expect any warnings.

@@ -228,7 +228,7 @@ BOOST_AUTO_TEST_CASE(print_string_literal_unicode)
DebugInfoSelection::None()
);
BOOST_REQUIRE(stack.parseAndAnalyze("", source));
BOOST_REQUIRE(stack.errors().empty());
BOOST_REQUIRE(!stack.hasErrors());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we don't want warnings or infos here.

Comment on lines 64 to 65
if (!stack.parseAndAnalyze("", _source) || !stack.errors().empty())
if (!stack.parseAndAnalyze("", _source) || stack.hasErrors())
BOOST_FAIL("Invalid source.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here. I think we don't want warnings or infos here.

@@ -65,7 +65,7 @@ std::pair<std::shared_ptr<Block>, std::shared_ptr<AsmAnalysisInfo>> parse(std::s
);
if (stack.parseAndAnalyze("--INPUT--", _source))
{
yulAssert(stack.errors().empty(), "Parsed successfully but had errors.");
yulAssert(!stack.hasErrors(), "Parsed successfully but had errors.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be best to check how it behaves on input that generates warnings. Try this:

{
    let x := 42
    switch x
        default {
            sstore(x, x)
        }
}

Also, to print those warnings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: In Progress
Development

Successfully merging this pull request may close these issues.

None yet

2 participants