From dad2bf64723cc83f0168bae0310714db01983a50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Tue, 30 May 2023 16:07:00 +0200 Subject: [PATCH] Relax restrictions on immutable initialization --- Changelog.md | 1 + docs/cheatsheet.rst | 2 +- docs/contracts/constant-state-variables.rst | 48 ++-- docs/ir-breaking-changes.rst | 2 + libsolidity/analysis/ImmutableValidator.cpp | 261 +----------------- libsolidity/analysis/ImmutableValidator.h | 38 +-- .../semanticTests/immutable/delete.sol | 15 + .../immutable/increment_decrement.sol | 18 ++ .../immutable/multiple_initializations.sol | 27 ++ .../semanticTests/immutable/uninitialized.sol | 11 + .../conditional_return_uninitialized.sol | 2 - .../immutable/conditionally_initialized.sol | 2 - .../ctor_initialization_indirect_reading.sol | 2 - .../immutable/ctor_initialization_reading.sol | 2 - .../immutable/ctor_modifier_args.sol | 1 - .../immutable/ctor_modifier_reading.sol | 2 - .../syntaxTests/immutable/decrement.sol | 2 - .../syntaxTests/immutable/delete.sol | 8 - .../immutable/delete_and_initialize.sol | 8 - .../function_initialization_reading.sol | 2 - .../function_pointer_initializing.sol | 1 - .../immutable/function_pointer_reading.sol | 1 - .../syntaxTests/immutable/increment.sol | 2 - .../immutable/increment_decrement.sol | 11 - .../indirect_reading_during_statevar_init.sol | 1 - .../immutable/inheritance_ctor_argument.sol | 2 - ...e_ctor_inherit_specifier_argument_init.sol | 2 - ...tor_inherit_specifier_argument_reading.sol | 2 - .../inheritance_virtual_functions.sol | 1 - .../inheritance_virtual_modifiers.sol | 2 - .../immutable/inheritance_wrong_ctor.sol | 2 - .../init_in_constructor_modifier_param.sol | 1 - .../immutable/init_in_ctor_param.sol | 2 - .../init_in_function_modifier_param.sol | 7 + .../init_in_function_via_contract_name.sol | 11 + .../immutable/init_in_function_via_super.sol | 13 + .../init_in_inheritance_specifier_param.sol | 2 - .../immutable/loop_initialized.sol | 2 - ...multiple_inheritance_virtual_functions.sol | 1 - ...heritance_virtual_functions_with_super.sol | 1 - .../immutable/multiple_initializations.sol | 2 - .../immutable/private_state_var.sol | 2 - .../read_in_function_before_init.sol | 2 - .../read_in_function_before_init2.sol | 2 - .../reading_after_initialization_function.sol | 1 - .../reading_during_statevar_init.sol | 2 - .../immutable/return_uninitialized.sol | 2 +- .../state_var_external_access_read.sol | 13 + .../state_var_external_access_write.sol | 11 + .../immutable/try_catch_initialized.sol | 6 - .../syntaxTests/immutable/uninitialized.sol | 2 - .../uninitialized_private_state_var.sol | 3 - .../variable_declaration_already.sol | 3 - .../immutable/variable_declaration_value.sol | 2 - 54 files changed, 178 insertions(+), 396 deletions(-) create mode 100644 test/libsolidity/semanticTests/immutable/delete.sol create mode 100644 test/libsolidity/semanticTests/immutable/increment_decrement.sol create mode 100644 test/libsolidity/semanticTests/immutable/multiple_initializations.sol create mode 100644 test/libsolidity/semanticTests/immutable/uninitialized.sol delete mode 100644 test/libsolidity/syntaxTests/immutable/delete.sol delete mode 100644 test/libsolidity/syntaxTests/immutable/delete_and_initialize.sol delete mode 100644 test/libsolidity/syntaxTests/immutable/increment_decrement.sol create mode 100644 test/libsolidity/syntaxTests/immutable/init_in_function_modifier_param.sol create mode 100644 test/libsolidity/syntaxTests/immutable/init_in_function_via_contract_name.sol create mode 100644 test/libsolidity/syntaxTests/immutable/init_in_function_via_super.sol create mode 100644 test/libsolidity/syntaxTests/immutable/state_var_external_access_read.sol create mode 100644 test/libsolidity/syntaxTests/immutable/state_var_external_access_write.sol diff --git a/Changelog.md b/Changelog.md index fa6ea616b..4cbddb3dd 100644 --- a/Changelog.md +++ b/Changelog.md @@ -2,6 +2,7 @@ Language Features: * Allow qualified access to events from other contracts. + * Relax restrictions on initialization of immutable variables. Reads and writes may now happen at any point at construction time outside of functions and modifiers. Explicit initialization is no longer mandatory. Compiler Features: * Commandline Interface: Add ``--ast-compact-json`` output in assembler mode. diff --git a/docs/cheatsheet.rst b/docs/cheatsheet.rst index 34ad46df6..a60d3b50f 100644 --- a/docs/cheatsheet.rst +++ b/docs/cheatsheet.rst @@ -150,7 +150,7 @@ Modifiers - ``view`` for functions: Disallows modification of state. - ``payable`` for functions: Allows them to receive Ether together with a call. - ``constant`` for state variables: Disallows assignment (except initialisation), does not occupy storage slot. -- ``immutable`` for state variables: Allows exactly one assignment at construction time and is constant afterwards. Is stored in code. +- ``immutable`` for state variables: Allows assignment at construction time and is constant when deployed. Is stored in code. - ``anonymous`` for events: Does not store event signature as topic. - ``indexed`` for event parameters: Stores the parameter as topic. - ``virtual`` for functions and modifiers: Allows the function's or modifier's diff --git a/docs/contracts/constant-state-variables.rst b/docs/contracts/constant-state-variables.rst index 1b57bf3be..a1bc24f50 100644 --- a/docs/contracts/constant-state-variables.rst +++ b/docs/contracts/constant-state-variables.rst @@ -30,19 +30,23 @@ Not all types for constants and immutables are implemented at this time. The onl .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 - pragma solidity >=0.7.4; + pragma solidity ^0.8.21; uint constant X = 32**22 + 8; contract C { string constant TEXT = "abc"; bytes32 constant MY_HASH = keccak256("abc"); - uint immutable decimals; + uint immutable decimals = 18; uint immutable maxBalance; address immutable owner = msg.sender; constructor(uint decimals_, address ref) { - decimals = decimals_; + if (decimals_ != 0) + // Immutables are only immutable when deployed. + // At construction time they can be assigned to any number of times. + decimals = decimals_; + // Assignments to immutables can even access the environment. maxBalance = ref.balance; } @@ -74,10 +78,29 @@ Immutable ========= Variables declared as ``immutable`` are a bit less restricted than those -declared as ``constant``: Immutable variables can be assigned an arbitrary -value in the constructor of the contract or at the point of their declaration. -They can be assigned only once and can, from that point on, be read even during -construction time. +declared as ``constant``: Immutable variables can be assigned a +value at construction time. +The value can be changed at any time before deployment and then it becomes permanent. + +One additional restriction is that immutables can only be assigned to inside expressions for which +there is no possibility of being executed after creation. +This excludes all modifier definitions and functions other than constructors. + +There are no restrictions on reading immutable variables. +The read is even allowed to happen before the variable is written to for the first time because variables in +Solidity always have a well-defined initial value. +For this reason it is also allowed to never explicitly assign a value to an immutable. + +.. warning:: + When accessing immutables at construction time, please keep the :ref:`initialization order + ` in mind. + Even if you provide an explicit initializer, some expressions may end up being evaluated before + that initializer, especially when they are at a different level in inheritance hierarchy. + +.. note:: + Before Solidity 0.8.21 initialization of immutable variables was more restrictive. + Such variables had to be initialized exactly once at construction time and could not be read + before then. The contract creation code generated by the compiler will modify the contract's runtime code before it is returned by replacing all references @@ -86,14 +109,3 @@ you are comparing the runtime code generated by the compiler with the one actually stored in the blockchain. The compiler outputs where these immutables are located in the deployed bytecode in the ``immutableReferences`` field of the :ref:`compiler JSON standard output `. - -.. note:: - Immutables that are assigned at their declaration are only considered - initialized once the constructor of the contract is executing. - This means you cannot initialize immutables inline with a value - that depends on another immutable. You can do this, however, - inside the constructor of the contract. - - This is a safeguard against different interpretations about the order - of state variable initialization and constructor execution, especially - with regards to inheritance. diff --git a/docs/ir-breaking-changes.rst b/docs/ir-breaking-changes.rst index 38e6b552f..4917cfc71 100644 --- a/docs/ir-breaking-changes.rst +++ b/docs/ir-breaking-changes.rst @@ -30,6 +30,8 @@ Semantic Only Changes This section lists the changes that are semantic-only, thus potentially hiding new and different behavior in existing code. +.. _state-variable-initialization-order: + - The order of state variable initialization has changed in case of inheritance. The order used to be: diff --git a/libsolidity/analysis/ImmutableValidator.cpp b/libsolidity/analysis/ImmutableValidator.cpp index 8e89c49ab..0f5a2ee2e 100644 --- a/libsolidity/analysis/ImmutableValidator.cpp +++ b/libsolidity/analysis/ImmutableValidator.cpp @@ -18,8 +18,6 @@ #include -#include - #include using namespace solidity::frontend; @@ -27,275 +25,44 @@ using namespace solidity::langutil; void ImmutableValidator::analyze() { - m_inCreationContext = true; - auto linearizedContracts = m_mostDerivedContract.annotation().linearizedBaseContracts | ranges::views::reverse; - for (ContractDefinition const* contract: linearizedContracts) - for (VariableDeclaration const* stateVar: contract->stateVariables()) - if (stateVar->value()) - stateVar->value()->accept(*this); - - for (ContractDefinition const* contract: linearizedContracts) - for (std::shared_ptr const& inheritSpec: contract->baseContracts()) - if (auto args = inheritSpec->arguments()) - ASTNode::listAccept(*args, *this); - for (ContractDefinition const* contract: linearizedContracts) { - for (VariableDeclaration const* stateVar: contract->stateVariables()) - if (stateVar->value()) - m_initializedStateVariables.emplace(stateVar); + for (FunctionDefinition const* function: contract->definedFunctions()) + function->accept(*this); - if (contract->constructor()) - visitCallableIfNew(*contract->constructor()); + for (ModifierDefinition const* modifier: contract->functionModifiers()) + modifier->accept(*this); } - - m_inCreationContext = false; - - for (ContractDefinition const* contract: linearizedContracts) - { - for (auto funcDef: contract->definedFunctions()) - visitCallableIfNew(*funcDef); - - for (auto modDef: contract->functionModifiers()) - visitCallableIfNew(*modDef); - } - - checkAllVariablesInitialized(m_mostDerivedContract.location()); } -bool ImmutableValidator::visit(Assignment const& _assignment) -{ - // Need to visit values first (rhs) as they might access other immutables. - _assignment.rightHandSide().accept(*this); - _assignment.leftHandSide().accept(*this); - return false; -} - - bool ImmutableValidator::visit(FunctionDefinition const& _functionDefinition) { - return analyseCallable(_functionDefinition); + return !_functionDefinition.isConstructor(); } -bool ImmutableValidator::visit(ModifierDefinition const& _modifierDefinition) +void ImmutableValidator::endVisit(MemberAccess const& _memberAccess) { - return analyseCallable(_modifierDefinition); -} - -bool ImmutableValidator::visit(MemberAccess const& _memberAccess) -{ - _memberAccess.expression().accept(*this); - - if (auto contractType = dynamic_cast(_memberAccess.expression().annotation().type)) - if (!contractType->isSuper()) - // external access, no analysis needed. - return false; - - if (auto varDecl = dynamic_cast(_memberAccess.annotation().referencedDeclaration)) - analyseVariableReference(*varDecl, _memberAccess); - else if (auto funcType = dynamic_cast(_memberAccess.annotation().type)) - if (funcType->kind() == FunctionType::Kind::Internal && funcType->hasDeclaration()) - visitCallableIfNew(funcType->declaration()); - - return false; -} - -bool ImmutableValidator::visit(IfStatement const& _ifStatement) -{ - bool prevInBranch = m_inBranch; - - _ifStatement.condition().accept(*this); - - m_inBranch = true; - _ifStatement.trueStatement().accept(*this); - - if (auto falseStatement = _ifStatement.falseStatement()) - falseStatement->accept(*this); - - m_inBranch = prevInBranch; - - return false; -} - -bool ImmutableValidator::visit(WhileStatement const& _whileStatement) -{ - bool prevInLoop = m_inLoop; - m_inLoop = true; - - _whileStatement.condition().accept(*this); - _whileStatement.body().accept(*this); - - m_inLoop = prevInLoop; - - return false; -} - -bool ImmutableValidator::visit(TryStatement const& _tryStatement) -{ - ScopedSaveAndRestore constructorGuard{m_inTryStatement, true}; - - _tryStatement.externalCall().accept(*this); - - for (auto&& clause: _tryStatement.clauses()) - if (clause) - clause->accept(*this); - - return false; -} - -void ImmutableValidator::endVisit(IdentifierPath const& _identifierPath) -{ - if (auto const callableDef = dynamic_cast(_identifierPath.annotation().referencedDeclaration)) - visitCallableIfNew( - *_identifierPath.annotation().requiredLookup == VirtualLookup::Virtual ? - callableDef->resolveVirtual(m_mostDerivedContract) : - *callableDef - ); - - solAssert(!dynamic_cast(_identifierPath.annotation().referencedDeclaration), ""); + analyseVariableReference(_memberAccess.annotation().referencedDeclaration, _memberAccess); } void ImmutableValidator::endVisit(Identifier const& _identifier) { - if (auto const callableDef = dynamic_cast(_identifier.annotation().referencedDeclaration)) - visitCallableIfNew(*_identifier.annotation().requiredLookup == VirtualLookup::Virtual ? callableDef->resolveVirtual(m_mostDerivedContract) : *callableDef); - if (auto const varDecl = dynamic_cast(_identifier.annotation().referencedDeclaration)) - analyseVariableReference(*varDecl, _identifier); + analyseVariableReference(_identifier.annotation().referencedDeclaration, _identifier); } -void ImmutableValidator::endVisit(Return const& _return) +void ImmutableValidator::analyseVariableReference(Declaration const* _reference, Expression const& _expression) { - if (m_currentConstructor != nullptr) - checkAllVariablesInitialized(_return.location()); -} - -bool ImmutableValidator::analyseCallable(CallableDeclaration const& _callableDeclaration) -{ - ScopedSaveAndRestore constructorGuard{m_currentConstructor, {}}; - ScopedSaveAndRestore constructorContractGuard{m_currentConstructorContract, {}}; - - if (FunctionDefinition const* funcDef = dynamic_cast(&_callableDeclaration)) - { - ASTNode::listAccept(funcDef->modifiers(), *this); - - if (funcDef->isConstructor()) - { - m_currentConstructorContract = funcDef->annotation().contract; - m_currentConstructor = funcDef; - } - - if (funcDef->isImplemented()) - funcDef->body().accept(*this); - } - else if (ModifierDefinition const* modDef = dynamic_cast(&_callableDeclaration)) - if (modDef->isImplemented()) - modDef->body().accept(*this); - - return false; -} - -void ImmutableValidator::analyseVariableReference(VariableDeclaration const& _variableReference, Expression const& _expression) -{ - if (!_variableReference.isStateVariable() || !_variableReference.immutable()) + auto const* variable = dynamic_cast(_reference); + if (!variable || !variable->isStateVariable() || !variable->immutable()) return; // If this is not an ordinary assignment, we write and read at the same time. - bool write = _expression.annotation().willBeWrittenTo; - bool read = !_expression.annotation().willBeWrittenTo || !_expression.annotation().lValueOfOrdinaryAssignment; - if (write) - { - if (!m_currentConstructor) - m_errorReporter.typeError( - 1581_error, - _expression.location(), - "Cannot write to immutable here: Immutable variables can only be initialized inline or assigned directly in the constructor." - ); - else if (m_currentConstructor->annotation().contract->id() != _variableReference.annotation().contract->id()) - m_errorReporter.typeError( - 7484_error, - _expression.location(), - "Cannot write to immutable here: Immutable variables must be initialized in the constructor of the contract they are defined in." - ); - else if (m_inLoop) - m_errorReporter.typeError( - 6672_error, - _expression.location(), - "Cannot write to immutable here: Immutable variables cannot be initialized inside a loop." - ); - else if (m_inBranch) - m_errorReporter.typeError( - 4599_error, - _expression.location(), - "Cannot write to immutable here: Immutable variables cannot be initialized inside an if statement." - ); - else if (m_inTryStatement) - m_errorReporter.typeError( - 4130_error, - _expression.location(), - "Cannot write to immutable here: Immutable variables cannot be initialized inside a try/catch statement." - ); - else if (m_initializedStateVariables.count(&_variableReference)) - { - if (!read) - m_errorReporter.typeError( - 1574_error, - _expression.location(), - "Immutable state variable already initialized." - ); - else - m_errorReporter.typeError( - 2718_error, - _expression.location(), - "Immutable variables cannot be modified after initialization." - ); - } - else if (read) - m_errorReporter.typeError( - 3969_error, - _expression.location(), - "Immutable variables must be initialized using an assignment." - ); - m_initializedStateVariables.emplace(&_variableReference); - } - if ( - read && - m_inCreationContext && - !m_initializedStateVariables.count(&_variableReference) - ) + if (_expression.annotation().willBeWrittenTo) m_errorReporter.typeError( - 7733_error, + 1581_error, _expression.location(), - "Immutable variables cannot be read before they are initialized." + "Cannot write to immutable here: Immutable variables can only be initialized inline or assigned directly in the constructor." ); } - -void ImmutableValidator::checkAllVariablesInitialized(solidity::langutil::SourceLocation const& _location) -{ - for (ContractDefinition const* contract: m_mostDerivedContract.annotation().linearizedBaseContracts | ranges::views::reverse) - { - for (VariableDeclaration const* varDecl: contract->stateVariables()) - if (varDecl->immutable()) - if (!util::contains(m_initializedStateVariables, varDecl)) - m_errorReporter.typeError( - 2658_error, - _location, - solidity::langutil::SecondarySourceLocation().append("Not initialized: ", varDecl->location()), - "Construction control flow ends without initializing all immutable state variables." - ); - - // Don't check further than the current c'tors contract - if (contract == m_currentConstructorContract) - break; - } -} - -void ImmutableValidator::visitCallableIfNew(Declaration const& _declaration) -{ - CallableDeclaration const* _callable = dynamic_cast(&_declaration); - solAssert(_callable != nullptr, ""); - - if (m_visitedCallables.emplace(_callable).second) - _declaration.accept(*this); -} diff --git a/libsolidity/analysis/ImmutableValidator.h b/libsolidity/analysis/ImmutableValidator.h index 43a4b5dbf..78d85a61c 100644 --- a/libsolidity/analysis/ImmutableValidator.h +++ b/libsolidity/analysis/ImmutableValidator.h @@ -21,25 +21,15 @@ #include #include -#include - namespace solidity::frontend { /** * Validates access and initialization of immutable variables: - * must be directly initialized in their respective c'tor or inline - * cannot be read before being initialized - * cannot be read when initializing state variables inline - * must be initialized outside loops (only one initialization) - * must be initialized outside ifs (must be initialized unconditionally) - * must be initialized exactly once (no multiple statements) - * must be initialized exactly once (no early return to skip initialization) + * must be directly initialized in a c'tor or inline */ class ImmutableValidator: private ASTConstVisitor { - using CallableDeclarationSet = std::set; - public: ImmutableValidator(langutil::ErrorReporter& _errorReporter, ContractDefinition const& _contractDefinition): m_mostDerivedContract(_contractDefinition), @@ -49,37 +39,15 @@ public: void analyze(); private: - bool visit(Assignment const& _assignment); bool visit(FunctionDefinition const& _functionDefinition); - bool visit(ModifierDefinition const& _modifierDefinition); - bool visit(MemberAccess const& _memberAccess); - bool visit(IfStatement const& _ifStatement); - bool visit(WhileStatement const& _whileStatement); - bool visit(TryStatement const& _tryStatement); - void endVisit(IdentifierPath const& _identifierPath); + void endVisit(MemberAccess const& _memberAccess); void endVisit(Identifier const& _identifier); - void endVisit(Return const& _return); - bool analyseCallable(CallableDeclaration const& _callableDeclaration); - void analyseVariableReference(VariableDeclaration const& _variableReference, Expression const& _expression); - - void checkAllVariablesInitialized(langutil::SourceLocation const& _location); - - void visitCallableIfNew(Declaration const& _declaration); + void analyseVariableReference(Declaration const* _variableReference, Expression const& _expression); ContractDefinition const& m_mostDerivedContract; - CallableDeclarationSet m_visitedCallables; - - std::set m_initializedStateVariables; langutil::ErrorReporter& m_errorReporter; - - FunctionDefinition const* m_currentConstructor = nullptr; - ContractDefinition const* m_currentConstructorContract = nullptr; - bool m_inLoop = false; - bool m_inBranch = false; - bool m_inCreationContext = true; - bool m_inTryStatement = false; }; } diff --git a/test/libsolidity/semanticTests/immutable/delete.sol b/test/libsolidity/semanticTests/immutable/delete.sol new file mode 100644 index 000000000..76e219a77 --- /dev/null +++ b/test/libsolidity/semanticTests/immutable/delete.sol @@ -0,0 +1,15 @@ +contract C { + uint8 immutable public a; + uint8 immutable public b = 0x42; + uint public c; + + constructor() { + delete a; + delete b; + c = b * 2 + a; + } +} +// ---- +// a() -> 0 +// b() -> 0 +// c() -> 0 diff --git a/test/libsolidity/semanticTests/immutable/increment_decrement.sol b/test/libsolidity/semanticTests/immutable/increment_decrement.sol new file mode 100644 index 000000000..14304513a --- /dev/null +++ b/test/libsolidity/semanticTests/immutable/increment_decrement.sol @@ -0,0 +1,18 @@ +contract C { + int immutable x = 1; + int immutable y = 3; + + constructor() { + x--; + --x; + y++; + ++y; + --y; + } + + function f() public view returns (int, int) { + return (x, y); + } +} +// ---- +// f() -> -1, 4 diff --git a/test/libsolidity/semanticTests/immutable/multiple_initializations.sol b/test/libsolidity/semanticTests/immutable/multiple_initializations.sol new file mode 100644 index 000000000..b72f05b11 --- /dev/null +++ b/test/libsolidity/semanticTests/immutable/multiple_initializations.sol @@ -0,0 +1,27 @@ +contract A { + uint immutable x = x + 1; + uint immutable y = x += 2; + + constructor(uint) m(x += 16) m(x += 32) { + x += 64; + x += 128; + } + + modifier m(uint) { + _; + } + + function get() public returns (uint) { + return x; + } +} + +contract B is A(A.x += 8) { + constructor(uint) {} +} + +contract C is B { + constructor() B(x += 4) {} +} +// ---- +// get() -> 0xff diff --git a/test/libsolidity/semanticTests/immutable/uninitialized.sol b/test/libsolidity/semanticTests/immutable/uninitialized.sol new file mode 100644 index 000000000..f6d59ce76 --- /dev/null +++ b/test/libsolidity/semanticTests/immutable/uninitialized.sol @@ -0,0 +1,11 @@ +contract C { + uint immutable u; + bool immutable b; + address immutable a; + + function get() public returns (uint, bool, address) { + return (u, b, a); + } +} +// ---- +// get() -> 0, false, 0x0 diff --git a/test/libsolidity/syntaxTests/immutable/conditional_return_uninitialized.sol b/test/libsolidity/syntaxTests/immutable/conditional_return_uninitialized.sol index 77e73c51f..d2c473fbb 100644 --- a/test/libsolidity/syntaxTests/immutable/conditional_return_uninitialized.sol +++ b/test/libsolidity/syntaxTests/immutable/conditional_return_uninitialized.sol @@ -7,5 +7,3 @@ contract C { x = 1; } } -// ---- -// TypeError 2658: (86-93): Construction control flow ends without initializing all immutable state variables. diff --git a/test/libsolidity/syntaxTests/immutable/conditionally_initialized.sol b/test/libsolidity/syntaxTests/immutable/conditionally_initialized.sol index 052a1b597..312a76083 100644 --- a/test/libsolidity/syntaxTests/immutable/conditionally_initialized.sol +++ b/test/libsolidity/syntaxTests/immutable/conditionally_initialized.sol @@ -5,5 +5,3 @@ contract C { x = 1; } } -// ---- -// TypeError 4599: (86-87): Cannot write to immutable here: Immutable variables cannot be initialized inside an if statement. diff --git a/test/libsolidity/syntaxTests/immutable/ctor_initialization_indirect_reading.sol b/test/libsolidity/syntaxTests/immutable/ctor_initialization_indirect_reading.sol index 1bd0f6b91..b23d161c1 100644 --- a/test/libsolidity/syntaxTests/immutable/ctor_initialization_indirect_reading.sol +++ b/test/libsolidity/syntaxTests/immutable/ctor_initialization_indirect_reading.sol @@ -6,5 +6,3 @@ contract C { function f() public view returns (uint) { return 3 + x; } } -// ---- -// TypeError 7733: (136-137): Immutable variables cannot be read before they are initialized. diff --git a/test/libsolidity/syntaxTests/immutable/ctor_initialization_reading.sol b/test/libsolidity/syntaxTests/immutable/ctor_initialization_reading.sol index 38ff92945..5df8d162f 100644 --- a/test/libsolidity/syntaxTests/immutable/ctor_initialization_reading.sol +++ b/test/libsolidity/syntaxTests/immutable/ctor_initialization_reading.sol @@ -4,5 +4,3 @@ contract C { x = 3 + x; } } -// ---- -// TypeError 7733: (71-72): Immutable variables cannot be read before they are initialized. diff --git a/test/libsolidity/syntaxTests/immutable/ctor_modifier_args.sol b/test/libsolidity/syntaxTests/immutable/ctor_modifier_args.sol index 0a966f7c3..09c3aefa7 100644 --- a/test/libsolidity/syntaxTests/immutable/ctor_modifier_args.sol +++ b/test/libsolidity/syntaxTests/immutable/ctor_modifier_args.sol @@ -9,4 +9,3 @@ contract C { function f(uint a) internal pure {} } // ---- -// TypeError 1581: (59-60): Cannot write to immutable here: Immutable variables can only be initialized inline or assigned directly in the constructor. diff --git a/test/libsolidity/syntaxTests/immutable/ctor_modifier_reading.sol b/test/libsolidity/syntaxTests/immutable/ctor_modifier_reading.sol index 5e3442e55..113cda75f 100644 --- a/test/libsolidity/syntaxTests/immutable/ctor_modifier_reading.sol +++ b/test/libsolidity/syntaxTests/immutable/ctor_modifier_reading.sol @@ -10,5 +10,3 @@ contract C { function f(uint a) internal pure {} } -// ---- -// TypeError 7733: (119-120): Immutable variables cannot be read before they are initialized. diff --git a/test/libsolidity/syntaxTests/immutable/decrement.sol b/test/libsolidity/syntaxTests/immutable/decrement.sol index dd081438a..4931b5f9f 100644 --- a/test/libsolidity/syntaxTests/immutable/decrement.sol +++ b/test/libsolidity/syntaxTests/immutable/decrement.sol @@ -4,5 +4,3 @@ contract C { x--; } } -// ---- -// TypeError 3969: (63-64): Immutable variables must be initialized using an assignment. diff --git a/test/libsolidity/syntaxTests/immutable/delete.sol b/test/libsolidity/syntaxTests/immutable/delete.sol deleted file mode 100644 index bbb418c17..000000000 --- a/test/libsolidity/syntaxTests/immutable/delete.sol +++ /dev/null @@ -1,8 +0,0 @@ -contract C { - uint immutable x; - constructor() { - delete x; - } -} -// ---- -// TypeError 3969: (70-71): Immutable variables must be initialized using an assignment. diff --git a/test/libsolidity/syntaxTests/immutable/delete_and_initialize.sol b/test/libsolidity/syntaxTests/immutable/delete_and_initialize.sol deleted file mode 100644 index 1e55d90ce..000000000 --- a/test/libsolidity/syntaxTests/immutable/delete_and_initialize.sol +++ /dev/null @@ -1,8 +0,0 @@ -contract C { - uint immutable x = 3; - constructor() { - delete x; - } -} -// ---- -// TypeError 2718: (74-75): Immutable variables cannot be modified after initialization. diff --git a/test/libsolidity/syntaxTests/immutable/function_initialization_reading.sol b/test/libsolidity/syntaxTests/immutable/function_initialization_reading.sol index 068688584..e276ba783 100644 --- a/test/libsolidity/syntaxTests/immutable/function_initialization_reading.sol +++ b/test/libsolidity/syntaxTests/immutable/function_initialization_reading.sol @@ -3,5 +3,3 @@ contract C { function f() public view returns (uint) { return 3 + x; } } -// ---- -// TypeError 7733: (99-100): Immutable variables cannot be read before they are initialized. diff --git a/test/libsolidity/syntaxTests/immutable/function_pointer_initializing.sol b/test/libsolidity/syntaxTests/immutable/function_pointer_initializing.sol index 0d9dabf90..cc175d083 100644 --- a/test/libsolidity/syntaxTests/immutable/function_pointer_initializing.sol +++ b/test/libsolidity/syntaxTests/immutable/function_pointer_initializing.sol @@ -11,4 +11,3 @@ contract C is B(C.f) { } // ---- // TypeError 1581: (200-201): Cannot write to immutable here: Immutable variables can only be initialized inline or assigned directly in the constructor. -// TypeError 1574: (109-110): Immutable state variable already initialized. diff --git a/test/libsolidity/syntaxTests/immutable/function_pointer_reading.sol b/test/libsolidity/syntaxTests/immutable/function_pointer_reading.sol index 5c026300c..2658d35d2 100644 --- a/test/libsolidity/syntaxTests/immutable/function_pointer_reading.sol +++ b/test/libsolidity/syntaxTests/immutable/function_pointer_reading.sol @@ -10,4 +10,3 @@ contract C is B(C.f) { function f() internal view returns(uint) { return x + 2; } } // ---- -// TypeError 7733: (205-206): Immutable variables cannot be read before they are initialized. diff --git a/test/libsolidity/syntaxTests/immutable/increment.sol b/test/libsolidity/syntaxTests/immutable/increment.sol index 020620159..62506d88f 100644 --- a/test/libsolidity/syntaxTests/immutable/increment.sol +++ b/test/libsolidity/syntaxTests/immutable/increment.sol @@ -4,5 +4,3 @@ contract C { x++; } } -// ---- -// TypeError 3969: (63-64): Immutable variables must be initialized using an assignment. diff --git a/test/libsolidity/syntaxTests/immutable/increment_decrement.sol b/test/libsolidity/syntaxTests/immutable/increment_decrement.sol deleted file mode 100644 index 7b8092e1e..000000000 --- a/test/libsolidity/syntaxTests/immutable/increment_decrement.sol +++ /dev/null @@ -1,11 +0,0 @@ -contract C { - uint immutable x; - uint immutable y; - constructor() { - ++x; - --y; - } -} -// ---- -// TypeError 3969: (77-78): Immutable variables must be initialized using an assignment. -// TypeError 3969: (86-87): Immutable variables must be initialized using an assignment. diff --git a/test/libsolidity/syntaxTests/immutable/indirect_reading_during_statevar_init.sol b/test/libsolidity/syntaxTests/immutable/indirect_reading_during_statevar_init.sol index ff7927277..985e5d0b3 100644 --- a/test/libsolidity/syntaxTests/immutable/indirect_reading_during_statevar_init.sol +++ b/test/libsolidity/syntaxTests/immutable/indirect_reading_during_statevar_init.sol @@ -5,4 +5,3 @@ contract C { function f() internal pure returns(uint) { return x; } } // ---- -// TypeError 7733: (112-113): Immutable variables cannot be read before they are initialized. diff --git a/test/libsolidity/syntaxTests/immutable/inheritance_ctor_argument.sol b/test/libsolidity/syntaxTests/immutable/inheritance_ctor_argument.sol index bc084400e..025f56161 100644 --- a/test/libsolidity/syntaxTests/immutable/inheritance_ctor_argument.sol +++ b/test/libsolidity/syntaxTests/immutable/inheritance_ctor_argument.sol @@ -10,5 +10,3 @@ contract C is B { uint immutable y; constructor() B(y = 3) { } } -// ---- -// TypeError 1581: (148-149): Cannot write to immutable here: Immutable variables can only be initialized inline or assigned directly in the constructor. diff --git a/test/libsolidity/syntaxTests/immutable/inheritance_ctor_inherit_specifier_argument_init.sol b/test/libsolidity/syntaxTests/immutable/inheritance_ctor_inherit_specifier_argument_init.sol index 503f182d6..f1787ab42 100644 --- a/test/libsolidity/syntaxTests/immutable/inheritance_ctor_inherit_specifier_argument_init.sol +++ b/test/libsolidity/syntaxTests/immutable/inheritance_ctor_inherit_specifier_argument_init.sol @@ -9,5 +9,3 @@ contract B { contract C is B(C.y = 3) { uint immutable y; } -// ---- -// TypeError 1581: (104-107): Cannot write to immutable here: Immutable variables can only be initialized inline or assigned directly in the constructor. diff --git a/test/libsolidity/syntaxTests/immutable/inheritance_ctor_inherit_specifier_argument_reading.sol b/test/libsolidity/syntaxTests/immutable/inheritance_ctor_inherit_specifier_argument_reading.sol index 2c670df6c..0ac37261f 100644 --- a/test/libsolidity/syntaxTests/immutable/inheritance_ctor_inherit_specifier_argument_reading.sol +++ b/test/libsolidity/syntaxTests/immutable/inheritance_ctor_inherit_specifier_argument_reading.sol @@ -12,5 +12,3 @@ contract C is B(C.y) { y = 3; } } -// ---- -// TypeError 7733: (104-107): Immutable variables cannot be read before they are initialized. diff --git a/test/libsolidity/syntaxTests/immutable/inheritance_virtual_functions.sol b/test/libsolidity/syntaxTests/immutable/inheritance_virtual_functions.sol index f33ce4cc4..addd3249c 100644 --- a/test/libsolidity/syntaxTests/immutable/inheritance_virtual_functions.sol +++ b/test/libsolidity/syntaxTests/immutable/inheritance_virtual_functions.sol @@ -16,4 +16,3 @@ contract C is B { } } // ---- -// TypeError 7733: (263-264): Immutable variables cannot be read before they are initialized. diff --git a/test/libsolidity/syntaxTests/immutable/inheritance_virtual_modifiers.sol b/test/libsolidity/syntaxTests/immutable/inheritance_virtual_modifiers.sol index 95ea3e686..31f510dcc 100644 --- a/test/libsolidity/syntaxTests/immutable/inheritance_virtual_modifiers.sol +++ b/test/libsolidity/syntaxTests/immutable/inheritance_virtual_modifiers.sol @@ -17,5 +17,3 @@ contract C is B { _; f(x); } } -// ---- -// TypeError 7733: (245-246): Immutable variables cannot be read before they are initialized. diff --git a/test/libsolidity/syntaxTests/immutable/inheritance_wrong_ctor.sol b/test/libsolidity/syntaxTests/immutable/inheritance_wrong_ctor.sol index 748d9da55..d7586c433 100644 --- a/test/libsolidity/syntaxTests/immutable/inheritance_wrong_ctor.sol +++ b/test/libsolidity/syntaxTests/immutable/inheritance_wrong_ctor.sol @@ -7,5 +7,3 @@ contract C is B { x = 3; } } -// ---- -// TypeError 7484: (88-89): Cannot write to immutable here: Immutable variables must be initialized in the constructor of the contract they are defined in. diff --git a/test/libsolidity/syntaxTests/immutable/init_in_constructor_modifier_param.sol b/test/libsolidity/syntaxTests/immutable/init_in_constructor_modifier_param.sol index d23416942..f638ae7bf 100644 --- a/test/libsolidity/syntaxTests/immutable/init_in_constructor_modifier_param.sol +++ b/test/libsolidity/syntaxTests/immutable/init_in_constructor_modifier_param.sol @@ -4,4 +4,3 @@ contract D { constructor() m(t = 2) {} } // ---- -// TypeError 1581: (83-84): Cannot write to immutable here: Immutable variables can only be initialized inline or assigned directly in the constructor. diff --git a/test/libsolidity/syntaxTests/immutable/init_in_ctor_param.sol b/test/libsolidity/syntaxTests/immutable/init_in_ctor_param.sol index b67d149b2..63c6057d3 100644 --- a/test/libsolidity/syntaxTests/immutable/init_in_ctor_param.sol +++ b/test/libsolidity/syntaxTests/immutable/init_in_ctor_param.sol @@ -3,5 +3,3 @@ contract D is C { uint immutable t; constructor() C(t=2) {} } -// ---- -// TypeError 1581: (92-93): Cannot write to immutable here: Immutable variables can only be initialized inline or assigned directly in the constructor. diff --git a/test/libsolidity/syntaxTests/immutable/init_in_function_modifier_param.sol b/test/libsolidity/syntaxTests/immutable/init_in_function_modifier_param.sol new file mode 100644 index 000000000..b42943959 --- /dev/null +++ b/test/libsolidity/syntaxTests/immutable/init_in_function_modifier_param.sol @@ -0,0 +1,7 @@ +contract D { + uint immutable t; + modifier m(uint) { _; } + function f() public m(t = 2) {} +} +// ---- +// TypeError 1581: (89-90): Cannot write to immutable here: Immutable variables can only be initialized inline or assigned directly in the constructor. diff --git a/test/libsolidity/syntaxTests/immutable/init_in_function_via_contract_name.sol b/test/libsolidity/syntaxTests/immutable/init_in_function_via_contract_name.sol new file mode 100644 index 000000000..01163f2fe --- /dev/null +++ b/test/libsolidity/syntaxTests/immutable/init_in_function_via_contract_name.sol @@ -0,0 +1,11 @@ +contract B { + uint immutable x; +} + +contract C is B { + function f() public { + B.x = 42; + } +} +// ---- +// TypeError 1581: (90-93): Cannot write to immutable here: Immutable variables can only be initialized inline or assigned directly in the constructor. diff --git a/test/libsolidity/syntaxTests/immutable/init_in_function_via_super.sol b/test/libsolidity/syntaxTests/immutable/init_in_function_via_super.sol new file mode 100644 index 000000000..941b5e516 --- /dev/null +++ b/test/libsolidity/syntaxTests/immutable/init_in_function_via_super.sol @@ -0,0 +1,13 @@ +contract B { + uint immutable x; + + function g() public {} +} + +contract C is B { + function f() public { + super.x = 42; + } +} +// ---- +// TypeError 9582: (118-125): Member "x" not found or not visible after argument-dependent lookup in type(contract super C). diff --git a/test/libsolidity/syntaxTests/immutable/init_in_inheritance_specifier_param.sol b/test/libsolidity/syntaxTests/immutable/init_in_inheritance_specifier_param.sol index cc56202e7..f80c238e6 100644 --- a/test/libsolidity/syntaxTests/immutable/init_in_inheritance_specifier_param.sol +++ b/test/libsolidity/syntaxTests/immutable/init_in_inheritance_specifier_param.sol @@ -2,5 +2,3 @@ contract C { constructor(uint) {} } contract D is C(D.t = 2) { uint immutable t; } -// ---- -// TypeError 1581: (52-55): Cannot write to immutable here: Immutable variables can only be initialized inline or assigned directly in the constructor. diff --git a/test/libsolidity/syntaxTests/immutable/loop_initialized.sol b/test/libsolidity/syntaxTests/immutable/loop_initialized.sol index d8c8ca47f..1cbe9add1 100644 --- a/test/libsolidity/syntaxTests/immutable/loop_initialized.sol +++ b/test/libsolidity/syntaxTests/immutable/loop_initialized.sol @@ -5,5 +5,3 @@ contract C { x = 1; } } -// ---- -// TypeError 6672: (88-89): Cannot write to immutable here: Immutable variables cannot be initialized inside a loop. diff --git a/test/libsolidity/syntaxTests/immutable/multiple_inheritance_virtual_functions.sol b/test/libsolidity/syntaxTests/immutable/multiple_inheritance_virtual_functions.sol index 401b068cb..a87ec7680 100644 --- a/test/libsolidity/syntaxTests/immutable/multiple_inheritance_virtual_functions.sol +++ b/test/libsolidity/syntaxTests/immutable/multiple_inheritance_virtual_functions.sol @@ -26,4 +26,3 @@ contract C is A, B { } } // ---- -// TypeError 7733: (499-500): Immutable variables cannot be read before they are initialized. diff --git a/test/libsolidity/syntaxTests/immutable/multiple_inheritance_virtual_functions_with_super.sol b/test/libsolidity/syntaxTests/immutable/multiple_inheritance_virtual_functions_with_super.sol index bf5a1f85b..8b8c5dd28 100644 --- a/test/libsolidity/syntaxTests/immutable/multiple_inheritance_virtual_functions_with_super.sol +++ b/test/libsolidity/syntaxTests/immutable/multiple_inheritance_virtual_functions_with_super.sol @@ -26,4 +26,3 @@ contract C is A, B { } } // ---- -// TypeError 7733: (503-504): Immutable variables cannot be read before they are initialized. diff --git a/test/libsolidity/syntaxTests/immutable/multiple_initializations.sol b/test/libsolidity/syntaxTests/immutable/multiple_initializations.sol index 93e01db30..8fe5ddcfc 100644 --- a/test/libsolidity/syntaxTests/immutable/multiple_initializations.sol +++ b/test/libsolidity/syntaxTests/immutable/multiple_initializations.sol @@ -5,5 +5,3 @@ contract C { x = 4; } } -// ---- -// TypeError 1574: (78-79): Immutable state variable already initialized. diff --git a/test/libsolidity/syntaxTests/immutable/private_state_var.sol b/test/libsolidity/syntaxTests/immutable/private_state_var.sol index 50af6ace8..cce1ca0f5 100644 --- a/test/libsolidity/syntaxTests/immutable/private_state_var.sol +++ b/test/libsolidity/syntaxTests/immutable/private_state_var.sol @@ -16,5 +16,3 @@ contract C is B { function f() internal view override returns(uint) { return readX(); } } -// ---- -// TypeError 7733: (202-203): Immutable variables cannot be read before they are initialized. diff --git a/test/libsolidity/syntaxTests/immutable/read_in_function_before_init.sol b/test/libsolidity/syntaxTests/immutable/read_in_function_before_init.sol index 6e934ff9d..b4f56a269 100644 --- a/test/libsolidity/syntaxTests/immutable/read_in_function_before_init.sol +++ b/test/libsolidity/syntaxTests/immutable/read_in_function_before_init.sol @@ -8,5 +8,3 @@ contract B is A { uint immutable x = 2; function f() override pure internal returns (uint) { return x; } } -// ---- -// TypeError 7733: (223-224): Immutable variables cannot be read before they are initialized. diff --git a/test/libsolidity/syntaxTests/immutable/read_in_function_before_init2.sol b/test/libsolidity/syntaxTests/immutable/read_in_function_before_init2.sol index 6e939b0b2..7234e0ef0 100644 --- a/test/libsolidity/syntaxTests/immutable/read_in_function_before_init2.sol +++ b/test/libsolidity/syntaxTests/immutable/read_in_function_before_init2.sol @@ -3,5 +3,3 @@ contract C { uint x = f(); function f() internal pure returns (uint) { return t; } } -// ---- -// TypeError 7733: (106-107): Immutable variables cannot be read before they are initialized. diff --git a/test/libsolidity/syntaxTests/immutable/reading_after_initialization_function.sol b/test/libsolidity/syntaxTests/immutable/reading_after_initialization_function.sol index 32ac0cceb..618ad36f4 100644 --- a/test/libsolidity/syntaxTests/immutable/reading_after_initialization_function.sol +++ b/test/libsolidity/syntaxTests/immutable/reading_after_initialization_function.sol @@ -13,4 +13,3 @@ contract C { } } // ---- -// TypeError 7733: (141-142): Immutable variables cannot be read before they are initialized. diff --git a/test/libsolidity/syntaxTests/immutable/reading_during_statevar_init.sol b/test/libsolidity/syntaxTests/immutable/reading_during_statevar_init.sol index ae73679ea..755de6481 100644 --- a/test/libsolidity/syntaxTests/immutable/reading_during_statevar_init.sol +++ b/test/libsolidity/syntaxTests/immutable/reading_during_statevar_init.sol @@ -2,5 +2,3 @@ contract C { uint immutable x = 0; uint y = x; } -// ---- -// TypeError 7733: (52-53): Immutable variables cannot be read before they are initialized. diff --git a/test/libsolidity/syntaxTests/immutable/return_uninitialized.sol b/test/libsolidity/syntaxTests/immutable/return_uninitialized.sol index 852b5d350..3a0b3f436 100644 --- a/test/libsolidity/syntaxTests/immutable/return_uninitialized.sol +++ b/test/libsolidity/syntaxTests/immutable/return_uninitialized.sol @@ -7,4 +7,4 @@ contract C { } } // ---- -// TypeError 2658: (63-70): Construction control flow ends without initializing all immutable state variables. +// Warning 5740: (80-85): Unreachable code. diff --git a/test/libsolidity/syntaxTests/immutable/state_var_external_access_read.sol b/test/libsolidity/syntaxTests/immutable/state_var_external_access_read.sol new file mode 100644 index 000000000..64b24b069 --- /dev/null +++ b/test/libsolidity/syntaxTests/immutable/state_var_external_access_read.sol @@ -0,0 +1,13 @@ +contract C { + uint immutable public x = 42; + + function g() external view returns (uint) {} + + function f() public view returns (uint) { + return this.x(); + } + + function h() public view returns (function () external view returns (uint)) { + return this.x; + } +} diff --git a/test/libsolidity/syntaxTests/immutable/state_var_external_access_write.sol b/test/libsolidity/syntaxTests/immutable/state_var_external_access_write.sol new file mode 100644 index 000000000..4baa743cb --- /dev/null +++ b/test/libsolidity/syntaxTests/immutable/state_var_external_access_write.sol @@ -0,0 +1,11 @@ +contract C { + uint immutable public x = 42; + + function g() external view returns (uint) {} + + function f() public view { + this.x = this.g; + } +} +// ---- +// TypeError 4247: (137-143): Expression has to be an lvalue. diff --git a/test/libsolidity/syntaxTests/immutable/try_catch_initialized.sol b/test/libsolidity/syntaxTests/immutable/try_catch_initialized.sol index 9cd18a2b6..fe969a20d 100644 --- a/test/libsolidity/syntaxTests/immutable/try_catch_initialized.sol +++ b/test/libsolidity/syntaxTests/immutable/try_catch_initialized.sol @@ -33,9 +33,3 @@ contract B } // ==== // EVMVersion: >=byzantium -// ---- -// TypeError 4130: (108-116): Cannot write to immutable here: Immutable variables cannot be initialized inside a try/catch statement. -// TypeError 4130: (144-152): Cannot write to immutable here: Immutable variables cannot be initialized inside a try/catch statement. -// TypeError 4130: (216-224): Cannot write to immutable here: Immutable variables cannot be initialized inside a try/catch statement. -// TypeError 4130: (297-305): Cannot write to immutable here: Immutable variables cannot be initialized inside a try/catch statement. -// TypeError 4130: (357-365): Cannot write to immutable here: Immutable variables cannot be initialized inside a try/catch statement. diff --git a/test/libsolidity/syntaxTests/immutable/uninitialized.sol b/test/libsolidity/syntaxTests/immutable/uninitialized.sol index d1791fe0f..bf7c68a84 100644 --- a/test/libsolidity/syntaxTests/immutable/uninitialized.sol +++ b/test/libsolidity/syntaxTests/immutable/uninitialized.sol @@ -1,5 +1,3 @@ contract C { uint immutable x; } -// ---- -// TypeError 2658: (0-36): Construction control flow ends without initializing all immutable state variables. diff --git a/test/libsolidity/syntaxTests/immutable/uninitialized_private_state_var.sol b/test/libsolidity/syntaxTests/immutable/uninitialized_private_state_var.sol index 544111e4c..70bd1448a 100644 --- a/test/libsolidity/syntaxTests/immutable/uninitialized_private_state_var.sol +++ b/test/libsolidity/syntaxTests/immutable/uninitialized_private_state_var.sol @@ -16,6 +16,3 @@ contract C is B { function f() internal view override returns(uint) { return readX(); } } -// ---- -// TypeError 2658: (0-202): Construction control flow ends without initializing all immutable state variables. -// TypeError 2658: (204-361): Construction control flow ends without initializing all immutable state variables. diff --git a/test/libsolidity/syntaxTests/immutable/variable_declaration_already.sol b/test/libsolidity/syntaxTests/immutable/variable_declaration_already.sol index 06d2bfa79..2917f276b 100644 --- a/test/libsolidity/syntaxTests/immutable/variable_declaration_already.sol +++ b/test/libsolidity/syntaxTests/immutable/variable_declaration_already.sol @@ -3,6 +3,3 @@ contract C { uint immutable x = z = y = 3; uint immutable y = 5; } -// ---- -// TypeError 1581: (66-67): Cannot write to immutable here: Immutable variables can only be initialized inline or assigned directly in the constructor. -// TypeError 1581: (62-63): Cannot write to immutable here: Immutable variables can only be initialized inline or assigned directly in the constructor. diff --git a/test/libsolidity/syntaxTests/immutable/variable_declaration_value.sol b/test/libsolidity/syntaxTests/immutable/variable_declaration_value.sol index 2c98ffd79..6451c8e20 100644 --- a/test/libsolidity/syntaxTests/immutable/variable_declaration_value.sol +++ b/test/libsolidity/syntaxTests/immutable/variable_declaration_value.sol @@ -1,5 +1,3 @@ contract C { int immutable x = x = 5; } -// ---- -// TypeError 1581: (35-36): Cannot write to immutable here: Immutable variables can only be initialized inline or assigned directly in the constructor.