diff --git a/libsolidity/analysis/DeclarationTypeChecker.cpp b/libsolidity/analysis/DeclarationTypeChecker.cpp index d5392ef84..076155366 100644 --- a/libsolidity/analysis/DeclarationTypeChecker.cpp +++ b/libsolidity/analysis/DeclarationTypeChecker.cpp @@ -437,14 +437,16 @@ void DeclarationTypeChecker::endVisit(VariableDeclaration const& _variable) type = TypeProvider::withLocation(ref, typeLoc, isPointer); } - if (_variable.isConstant() && !type->isValueType()) - { - bool allowed = false; - if (auto arrayType = dynamic_cast(type)) - allowed = arrayType->isByteArray(); - if (!allowed) - m_errorReporter.fatalDeclarationError(9259_error, _variable.location(), "Constants of non-value type not yet implemented."); - } + if ( + _variable.isConstant() && + !dynamic_cast(type) && + type->containsNestedMapping() + ) + m_errorReporter.fatalDeclarationError( + 3530_error, + _variable.location(), + "The type contains a (nested) mapping and therefore cannot be a constant." + ); _variable.annotation().type = type; } diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 83a9da55c..05fdc489b 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -530,6 +530,15 @@ bool TypeChecker::visit(VariableDeclaration const& _variable) } if (_variable.isConstant()) { + if (!varType->isValueType()) + { + bool allowed = false; + if (auto arrayType = dynamic_cast(varType)) + allowed = arrayType->isByteArray(); + if (!allowed) + m_errorReporter.fatalTypeError(9259_error, _variable.location(), "Constants of non-value type not yet implemented."); + } + if (!_variable.value()) m_errorReporter.typeError(4266_error, _variable.location(), "Uninitialized \"constant\" variable."); else if (!*_variable.value()->annotation().isPure) diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 334e69ba1..b08694820 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -1124,6 +1124,8 @@ public: bool containsNestedMapping() const override { solAssert(nameable(), "Called for a non nameable type."); + // DeclarationTypeChecker::endVisit(VariableDeclaration const&) + // assumes that this will never be true. solAssert(!underlyingType().containsNestedMapping(), ""); return false; } diff --git a/test/libsolidity/syntaxTests/constantEvaluator/type_reference.sol b/test/libsolidity/syntaxTests/constantEvaluator/type_reference.sol index 4ad0a0c4b..585c005f6 100644 --- a/test/libsolidity/syntaxTests/constantEvaluator/type_reference.sol +++ b/test/libsolidity/syntaxTests/constantEvaluator/type_reference.sol @@ -1,4 +1,3 @@ int[L] constant L = 6; // ---- // TypeError 5462: (4-5): Invalid array length, expected integer literal or constant expression. -// DeclarationError 9259: (0-21): Constants of non-value type not yet implemented. diff --git a/test/libsolidity/syntaxTests/constantEvaluator/type_reference_in_contract.sol b/test/libsolidity/syntaxTests/constantEvaluator/type_reference_in_contract.sol index 7ce1a7ad3..9073f6ac1 100644 --- a/test/libsolidity/syntaxTests/constantEvaluator/type_reference_in_contract.sol +++ b/test/libsolidity/syntaxTests/constantEvaluator/type_reference_in_contract.sol @@ -3,4 +3,3 @@ contract C { } // ---- // TypeError 5462: (21-22): Invalid array length, expected integer literal or constant expression. -// DeclarationError 9259: (17-38): Constants of non-value type not yet implemented. diff --git a/test/libsolidity/syntaxTests/constants/mapping_constant.sol b/test/libsolidity/syntaxTests/constants/mapping_constant.sol index 5821d0d56..4d80fb43e 100644 --- a/test/libsolidity/syntaxTests/constants/mapping_constant.sol +++ b/test/libsolidity/syntaxTests/constants/mapping_constant.sol @@ -1,3 +1,3 @@ mapping(uint => uint) constant b = b; // ---- -// DeclarationError 9259: (0-36): Constants of non-value type not yet implemented. +// DeclarationError 3530: (0-36): The type contains a (nested) mapping and therefore cannot be a constant. diff --git a/test/libsolidity/syntaxTests/constants/struct_constant.sol b/test/libsolidity/syntaxTests/constants/struct_constant.sol index 42f4584ed..8d750beb6 100644 --- a/test/libsolidity/syntaxTests/constants/struct_constant.sol +++ b/test/libsolidity/syntaxTests/constants/struct_constant.sol @@ -1,4 +1,4 @@ struct S { uint x; } S constant s; // ---- -// DeclarationError 9259: (21-33): Constants of non-value type not yet implemented. +// TypeError 9259: (21-33): Constants of non-value type not yet implemented. diff --git a/test/libsolidity/syntaxTests/iceRegressionTests/const_struct_with_mapping.sol b/test/libsolidity/syntaxTests/iceRegressionTests/const_struct_with_mapping.sol index 2ee03b09e..f8e0896c3 100644 --- a/test/libsolidity/syntaxTests/iceRegressionTests/const_struct_with_mapping.sol +++ b/test/libsolidity/syntaxTests/iceRegressionTests/const_struct_with_mapping.sol @@ -5,4 +5,4 @@ contract C { S public constant e = 0x1212121212121212121212121212121212121212; } // ---- -// DeclarationError 9259: (71-135): Constants of non-value type not yet implemented. +// DeclarationError 3530: (71-135): The type contains a (nested) mapping and therefore cannot be a constant. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/105_constant_input_parameter.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/105_constant_input_parameter.sol index cac87c3dd..aaf6f620a 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/105_constant_input_parameter.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/105_constant_input_parameter.sol @@ -3,4 +3,3 @@ contract test { } // ---- // DeclarationError 1788: (31-55): The "constant" keyword can only be used for state variables or variables at file level. -// DeclarationError 9259: (31-55): Constants of non-value type not yet implemented. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/171_assignment_to_const_array_vars.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/171_assignment_to_const_array_vars.sol index cb39b004b..81b9eab8a 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/171_assignment_to_const_array_vars.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/171_assignment_to_const_array_vars.sol @@ -2,4 +2,4 @@ contract C { uint[3] constant x = [uint(1), 2, 3]; } // ---- -// DeclarationError 9259: (17-53): Constants of non-value type not yet implemented. +// TypeError 9259: (17-53): Constants of non-value type not yet implemented. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/173_constant_struct.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/173_constant_struct.sol index b9b798431..d32dd2768 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/173_constant_struct.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/173_constant_struct.sol @@ -3,4 +3,4 @@ contract C { S constant x = S(5, new uint[](4)); } // ---- -// DeclarationError 9259: (52-86): Constants of non-value type not yet implemented. +// TypeError 9259: (52-86): Constants of non-value type not yet implemented. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/constant_mapping.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/constant_mapping.sol index 12d2d9105..7539a99cb 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/constant_mapping.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/constant_mapping.sol @@ -1,7 +1,5 @@ contract C { - // This should probably have a better error message at some point. - // Constant mappings should not be possible in general. mapping(uint => uint) constant x; } // ---- -// DeclarationError 9259: (148-180): Constants of non-value type not yet implemented. +// DeclarationError 3530: (17-49): The type contains a (nested) mapping and therefore cannot be a constant. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/constant_nested_mapping.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/constant_nested_mapping.sol index fcc8a432b..81e6e6b15 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/constant_nested_mapping.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/constant_nested_mapping.sol @@ -5,4 +5,4 @@ contract C { S public constant c; } // ---- -// DeclarationError 9259: (71-90): Constants of non-value type not yet implemented. +// DeclarationError 3530: (71-90): The type contains a (nested) mapping and therefore cannot be a constant. diff --git a/test/libsolidity/syntaxTests/parsing/location_specifiers_for_params.sol b/test/libsolidity/syntaxTests/parsing/location_specifiers_for_params.sol index 8e1ca503c..7d3dd5640 100644 --- a/test/libsolidity/syntaxTests/parsing/location_specifiers_for_params.sol +++ b/test/libsolidity/syntaxTests/parsing/location_specifiers_for_params.sol @@ -3,4 +3,3 @@ contract Foo { } // ---- // DeclarationError 1788: (30-55): The "constant" keyword can only be used for state variables or variables at file level. -// DeclarationError 9259: (30-55): Constants of non-value type not yet implemented. diff --git a/test/libsolidity/syntaxTests/userDefinedValueType/forward_reference_constant_variable_declaration.sol b/test/libsolidity/syntaxTests/userDefinedValueType/forward_reference_constant_variable_declaration.sol new file mode 100644 index 000000000..a459698a7 --- /dev/null +++ b/test/libsolidity/syntaxTests/userDefinedValueType/forward_reference_constant_variable_declaration.sol @@ -0,0 +1,2 @@ +MyInt constant x = MyInt.wrap(20); +type MyInt is int;