From 9d5b1b279e060c16c06aeec500d3305e0ea7ca1a Mon Sep 17 00:00:00 2001 From: Christian Parpart Date: Tue, 27 Apr 2021 16:25:04 +0200 Subject: [PATCH] Change `error` from directive to keyword. --- Changelog.md | 16 ++++------- docs/090-breaking-changes.rst | 28 +++++++++++++++++++ docs/grammar/SolidityLexer.g4 | 2 +- docs/grammar/SolidityParser.g4 | 5 ++-- docs/index.rst | 7 +++-- liblangutil/Token.h | 1 + libsolidity/parsing/Parser.cpp | 23 ++++----------- .../semanticTests/errors/weird_name.sol | 11 -------- .../semanticTests/reverts/error_struct.sol | 18 ------------ .../syntaxTests/errors/struct_named_error.sol | 2 +- .../syntaxTests/errors/weird_name.sol | 8 ++++++ .../syntaxTests/unusedVariables/try_catch.sol | 4 +-- 12 files changed, 59 insertions(+), 66 deletions(-) create mode 100644 docs/090-breaking-changes.rst delete mode 100644 test/libsolidity/semanticTests/errors/weird_name.sol delete mode 100644 test/libsolidity/semanticTests/reverts/error_struct.sol create mode 100644 test/libsolidity/syntaxTests/errors/weird_name.sol diff --git a/Changelog.md b/Changelog.md index 0179f7524..541d22e9e 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,16 +1,10 @@ +### 0.9.0 (unreleased) + +Breaking changes: + * `error` is now a keyword that can only be used for defining errors. + ### 0.8.5 (unreleased) -Language Features: - * Allowing conversion from ``bytes`` and ``bytes`` slices to ``bytes1``/.../``bytes32``. - * Yul: Add ``verbatim`` builtin function to inject arbitrary bytecode. - - -Compiler Features: - * Yul Optimizer: Evaluate ``keccak256(a, c)``, when the value at memory location ``a`` is known at compile time and ``c`` is a constant ``<= 32``. - - -Bugfixes: - ### 0.8.4 (2021-04-21) diff --git a/docs/090-breaking-changes.rst b/docs/090-breaking-changes.rst new file mode 100644 index 000000000..67aed0623 --- /dev/null +++ b/docs/090-breaking-changes.rst @@ -0,0 +1,28 @@ +******************************** +Solidity v0.8.0 Breaking Changes +******************************** + +This section highlights the main breaking changes introduced in Solidity +version 0.9.0. +For the full list check +`the release changelog `_. + +Silent Changes of the Semantics +=============================== + +... + +New Restrictions +================ + +- `error` is now a keyword and cannot be used as identifier anymore. + +Interface Changes +================= + +... + +How to update your code +======================= + +... diff --git a/docs/grammar/SolidityLexer.g4 b/docs/grammar/SolidityLexer.g4 index f21640264..018df681a 100644 --- a/docs/grammar/SolidityLexer.g4 +++ b/docs/grammar/SolidityLexer.g4 @@ -29,7 +29,7 @@ Do: 'do'; Else: 'else'; Emit: 'emit'; Enum: 'enum'; -Error: 'error'; // not a real keyword +Error: 'error'; Revert: 'revert'; // not a real keyword Event: 'event'; External: 'external'; diff --git a/docs/grammar/SolidityParser.g4 b/docs/grammar/SolidityParser.g4 index 0dbc7339d..ccd4c8679 100644 --- a/docs/grammar/SolidityParser.g4 +++ b/docs/grammar/SolidityParser.g4 @@ -13,6 +13,7 @@ sourceUnit: ( pragmaDirective | importDirective | contractDefinition + | errorDefinition | interfaceDefinition | libraryDefinition | functionDefinition @@ -379,9 +380,9 @@ tupleExpression: LParen (expression? ( Comma expression?)* ) RParen; inlineArrayExpression: LBrack (expression ( Comma expression)* ) RBrack; /** - * Besides regular non-keyword Identifiers, some keywords like 'from' and 'error' can also be used as identifiers. + * Besides regular non-keyword Identifiers, some keywords like 'from' can also be used as identifiers. */ -identifier: Identifier | From | Error | Revert; +identifier: Identifier | From | Revert; literal: stringLiteral | numberLiteral | booleanLiteral | hexStringLiteral | unicodeStringLiteral; booleanLiteral: True | False; diff --git a/docs/index.rst b/docs/index.rst index 1674248c1..cb9fd6479 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -28,8 +28,8 @@ a 0.x version number `to indicate this fast pace of change `. + Solidity recently released the 0.9.x version that introduced a lot of breaking + changes. Make sure you read :doc:`the full list <090-breaking-changes>`. Ideas for improving Solidity or this documentation are always welcome, read our :doc:`contributors guide ` for more details. @@ -155,6 +155,7 @@ Contents 060-breaking-changes.rst 070-breaking-changes.rst 080-breaking-changes.rst + 090-breaking-changes.rst natspec-format.rst security-considerations.rst smtchecker.rst @@ -165,4 +166,4 @@ Contents bugs.rst contributing.rst brand-guide.rst - language-influences.rst \ No newline at end of file + language-influences.rst diff --git a/liblangutil/Token.h b/liblangutil/Token.h index 13f836589..7ac607aaa 100644 --- a/liblangutil/Token.h +++ b/liblangutil/Token.h @@ -158,6 +158,7 @@ namespace solidity::langutil K(Else, "else", 0) \ K(Enum, "enum", 0) \ K(Emit, "emit", 0) \ + K(Error, "error", 0) \ K(Event, "event", 0) \ K(External, "external", 0) \ K(Fallback, "fallback", 0) \ diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index cad62e173..5d910c4ef 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -111,17 +111,12 @@ ASTPointer Parser::parse(shared_ptr const& _scanner) case Token::Function: nodes.push_back(parseFunctionDefinition(true)); break; + case Token::Error: + nodes.push_back(parseErrorDefinition()); + break; default: - if ( - // Workaround because `error` is not a keyword. - m_scanner->currentToken() == Token::Identifier && - currentLiteral() == "error" && - m_scanner->peekNextToken() == Token::Identifier && - m_scanner->peekNextNextToken() == Token::LParen - ) - nodes.push_back(parseErrorDefinition()); // Constant variable. - else if (variableDeclarationStart() && m_scanner->peekNextToken() != Token::EOS) + if (variableDeclarationStart() && m_scanner->peekNextToken() != Token::EOS) { VarDeclParserOptions options; options.kind = VarDeclKind::FileLevel; @@ -359,13 +354,7 @@ ASTPointer Parser::parseContractDefinition() subNodes.push_back(parseStructDefinition()); else if (currentTokenValue == Token::Enum) subNodes.push_back(parseEnumDefinition()); - else if ( - // Workaround because `error` is not a keyword. - currentTokenValue == Token::Identifier && - currentLiteral() == "error" && - m_scanner->peekNextToken() == Token::Identifier && - m_scanner->peekNextNextToken() == Token::LParen - ) + else if (currentTokenValue == Token::Error) subNodes.push_back(parseErrorDefinition()); else if (variableDeclarationStart()) { @@ -936,7 +925,7 @@ ASTPointer Parser::parseErrorDefinition() ASTNodeFactory nodeFactory(*this); ASTPointer documentation = parseStructuredDocumentation(); - solAssert(*expectIdentifierToken() == "error", ""); + expectToken(Token::Error); auto&& [name, nameLocation] = expectIdentifierWithLocation(); ASTPointer parameters = parseParameterList({}); diff --git a/test/libsolidity/semanticTests/errors/weird_name.sol b/test/libsolidity/semanticTests/errors/weird_name.sol deleted file mode 100644 index 5998dc851..000000000 --- a/test/libsolidity/semanticTests/errors/weird_name.sol +++ /dev/null @@ -1,11 +0,0 @@ -error error(uint a); -contract C { - function f() public pure { - revert error(2); - } -} -// ==== -// compileViaYul: also -// compileToEwasm: also -// ---- -// f() -> FAILURE, hex"b48fb6cf", hex"0000000000000000000000000000000000000000000000000000000000000002" diff --git a/test/libsolidity/semanticTests/reverts/error_struct.sol b/test/libsolidity/semanticTests/reverts/error_struct.sol deleted file mode 100644 index d837068a7..000000000 --- a/test/libsolidity/semanticTests/reverts/error_struct.sol +++ /dev/null @@ -1,18 +0,0 @@ -struct error { uint error; } -contract C { - error test(); - error _struct; - function f() public { - revert test(); - } - function g(uint x) public returns (uint) { - _struct.error = x; - return _struct.error; - } -} -// ==== -// compileViaYul: also -// compileToEwasm: also -// ---- -// f() -> FAILURE, hex"f8a8fd6d" -// g(uint256): 7 -> 7 diff --git a/test/libsolidity/syntaxTests/errors/struct_named_error.sol b/test/libsolidity/syntaxTests/errors/struct_named_error.sol index 0ee82ead6..6d9be65c5 100644 --- a/test/libsolidity/syntaxTests/errors/struct_named_error.sol +++ b/test/libsolidity/syntaxTests/errors/struct_named_error.sol @@ -1,6 +1,6 @@ -// Test that the parser workaround is not breaking. struct error {uint a;} contract C { error x; } // ---- +// ParserError 2314: (7-12): Expected identifier but got 'error' diff --git a/test/libsolidity/syntaxTests/errors/weird_name.sol b/test/libsolidity/syntaxTests/errors/weird_name.sol new file mode 100644 index 000000000..873fbfecc --- /dev/null +++ b/test/libsolidity/syntaxTests/errors/weird_name.sol @@ -0,0 +1,8 @@ +error error(uint a); +contract C { + function f() public pure { + revert error(2); + } +} +// ---- +// ParserError 2314: (6-11): Expected identifier but got 'error' diff --git a/test/libsolidity/syntaxTests/unusedVariables/try_catch.sol b/test/libsolidity/syntaxTests/unusedVariables/try_catch.sol index 0376c3e13..1e64bf949 100644 --- a/test/libsolidity/syntaxTests/unusedVariables/try_catch.sol +++ b/test/libsolidity/syntaxTests/unusedVariables/try_catch.sol @@ -4,7 +4,7 @@ contract test { } catch Error(string memory message) { - } catch (bytes memory error) { + } catch (bytes memory _error) { } } @@ -15,4 +15,4 @@ contract test { // Warning 5667: (49-55): Unused function parameter. Remove or comment out the variable name to silence this warning. // Warning 5667: (89-95): Unused try/catch parameter. Remove or comment out the variable name to silence this warning. // Warning 5667: (122-143): Unused try/catch parameter. Remove or comment out the variable name to silence this warning. -// Warning 5667: (165-183): Unused try/catch parameter. Remove or comment out the variable name to silence this warning. +// Warning 5667: (165-184): Unused try/catch parameter. Remove or comment out the variable name to silence this warning.