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

Remove overly specific handlers for unexpected exceptions #15186

Merged
merged 3 commits into from
Jun 20, 2024

Conversation

cameel
Copy link
Member

@cameel cameel commented Jun 6, 2024

In some places we have handlers for some exceptions that are unexpected and can reach those handlers only as a result of a bug. This is unnecessary and just complicates error handling. We should be explicitly handling expected exceptions and let everything else bubble up as far as possible and deal with it in the most generic handler possible.

@cameel cameel added the refactor label Jun 6, 2024
@cameel cameel self-assigned this Jun 6, 2024
Comment on lines -1767 to -1781
catch (Json::parse_error const& _exception)
{
return formatFatalError(Error::Type::InternalCompilerError, std::string("JSON parse_error exception: ") + util::removeNlohmannInternalErrorIdentifier(_exception.what()));
}
catch (Json::invalid_iterator const& _exception)
{
return formatFatalError(Error::Type::InternalCompilerError, std::string("JSON invalid_iterator exception: ") + util::removeNlohmannInternalErrorIdentifier(_exception.what()));
}
catch (Json::type_error const& _exception)
{
return formatFatalError(Error::Type::InternalCompilerError, std::string("JSON type_error exception: ") + util::removeNlohmannInternalErrorIdentifier(_exception.what()));
}
catch (Json::out_of_range const& _exception)
{
return formatFatalError(Error::Type::InternalCompilerError, std::string("JSON out_of_range exception: ") + util::removeNlohmannInternalErrorIdentifier(_exception.what()));
}
catch (Json::other_error const& _exception)
{
return formatFatalError(Error::Type::InternalCompilerError, std::string("JSON other_error exception: ") + util::removeNlohmannInternalErrorIdentifier(_exception.what()));
}
catch (Json::exception const& _exception)
{
return formatFatalError(Error::Type::InternalCompilerError, std::string("JSON runtime exception: ") + util::removeNlohmannInternalErrorIdentifier(_exception.what()));
}
Copy link
Member Author

Choose a reason for hiding this comment

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

Note that we do want this kind of error handling during deserialization of JSON input and serialization of output to JSON. It's covered by separate handlers in StandardCompiler::compile(string) below and is not being removed here.

I'm only removing the handlers for the exceptions that are basically equivalent to failed assertions. This is the case if they occur during processing of already deserialized input, compilation or preparing the output for serialization. This should not normally happen because we're expected to validate the input before using it and generate a proper JSONError if it's invalid. If they do happen it represents a bug - a missing validation or some kind of misuse of the JSON library.

Copy link
Member Author

Choose a reason for hiding this comment

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

Note also that by removing those we're not losing any details. In the generic exception handler we'll still get the full message and also diagnostics saying where it was thrown from. For an ICE the message does not need to be sanitized with removeNlohmannInternalErrorIdentifier(), because it can be considered diagnostic info too. In fact, the more internal details the better.

This sanitization is still good for proper JSONErrors though, because those can appear in test expectations and are considered a part of our interface.

Comment on lines -918 to -937
catch (Error const& _error)
{
if (_error.type() == Error::Type::DocstringParsingError)
{
report(Error::Severity::Error, *boost::get_error_info<errinfo_comment>(_error));
solThrow(CommandLineExecutionError, "Documentation parsing failed.");
}
else
{
m_hasOutput = true;
formatter.printErrorInformation(_error);
solThrow(CommandLineExecutionError, "");
}
}
Copy link
Member Author

Choose a reason for hiding this comment

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

I always thought that we do this sometimes with analysis or parsing errors but turns out we don't. Removing this handler does not result in any failures in the test suite so no properly reported errors need it.

In particular DocstringParsingErrors are not fatal so ErrorReporter::docstringParsingError() does not throw them. And even if they were, ErrorReporter throws FatalError, not util::Error and that would be caught in CompilerStack::analyze().

I think that we only ever throw util::Error at the codegen and later stages, so handling it only in CompilerStack::compile() seems enough. It should never get to this handler or the one in StandardCompiler.

Comment on lines -759 to 751
if (_error.type() != Error::Type::CodeGenerationError)
throw;
// Since codegen has no access to the error reporter, the only way for it to
// report an error is to throw. In most cases it uses dedicated exceptions,
// but CodeGenerationError is one case where someone decided to just throw Error.
solAssert(_error.type() == Error::Type::CodeGenerationError);
m_errorReporter.error(_error.errorId(), _error.type(), SourceLocation(), _error.what());
Copy link
Member Author

Choose a reason for hiding this comment

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

We should define a separate exception type for CodeGenerationError. It seems to be the only weird case that's thrown inside a util::Error. Other failures during codegen have dedicated exception classes: StackTooDeep, OptimizerError, etc.

We should also be handling those existing exceptions here along with CodeGenerationError, but that's a different story (and the subject of #15139).

@cameel cameel force-pushed the remove-overly-specific-exception-handlers branch 2 times, most recently from 833fb69 to f5bb300 Compare June 12, 2024 19:59
matheusaaguiar
matheusaaguiar previously approved these changes Jun 12, 2024
@cameel
Copy link
Member Author

cameel commented Jun 13, 2024

I found some more unnecessary handlers in other places. Their removal is based on the same principle so I thought I'd add them ere instead of creating a new PR. Please take another look at it.

@cameel cameel force-pushed the remove-overly-specific-exception-handlers branch 2 times, most recently from 114d706 to 1e9e83e Compare June 18, 2024 12:53
matheusaaguiar
matheusaaguiar previously approved these changes Jun 19, 2024
- In analysis we use an error reporter and never just throw util::Error. We do it in one case in the codegen (CodeGenerationError) but outside of that case this should not be treated as a proper way to report an error.
- Now such errors will be treated as unexpected. They're bugs that should be fixed.
Copy link
Collaborator

@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.

Just rebased and resolved the conflict at StandardCompiler.cpp.
LGTM

@cameel
Copy link
Member Author

cameel commented Jun 20, 2024

Thanks!

@cameel cameel merged commit a5f5eac into develop Jun 20, 2024
72 checks passed
@cameel cameel deleted the remove-overly-specific-exception-handlers branch June 20, 2024 18:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants