Merge pull request #4093 from ethereum/prepareDropConstantKeyword

Prepare drop constant keyword.
This commit is contained in:
chriseth 2018-05-14 12:47:07 +02:00 committed by GitHub
commit ab63ab1cbb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 110 additions and 125 deletions

View File

@ -1,6 +1,7 @@
### 0.4.24 (unreleased) ### 0.4.24 (unreleased)
Features: Features:
* Remove deprecated ``constant`` as function state modifier from documentation and tests (but still leave it as a valid feature).
* Build System: Update internal dependency of jsoncpp to 1.8.4, which introduces more strictness and reduces memory usage. * Build System: Update internal dependency of jsoncpp to 1.8.4, which introduces more strictness and reduces memory usage.
* Code Generator: Use native shift instructions on target Constantinople. * Code Generator: Use native shift instructions on target Constantinople.
* Gas Estimator: Only explore paths with higher gas costs. This reduces accuracy but greatly improves the speed of gas estimation. * Gas Estimator: Only explore paths with higher gas costs. This reduces accuracy but greatly improves the speed of gas estimation.

View File

@ -473,7 +473,7 @@ The following statements are considered modifying the state:
} }
.. note:: .. note::
``constant`` on functions is an alias to ``view``, but this is deprecated and is planned to be dropped in version 0.5.0. ``constant`` on functions is an alias to ``view``, but this is deprecated and will be dropped in version 0.5.0.
.. note:: .. note::
Getter methods are marked ``view``. Getter methods are marked ``view``.

View File

@ -25,7 +25,7 @@ Storage
storedData = x; storedData = x;
} }
function get() public constant returns (uint) { function get() public view returns (uint) {
return storedData; return storedData;
} }
} }

View File

@ -120,7 +120,7 @@ Gas Limit and Loops
Loops that do not have a fixed number of iterations, for example, loops that depend on storage values, have to be used carefully: Loops that do not have a fixed number of iterations, for example, loops that depend on storage values, have to be used carefully:
Due to the block gas limit, transactions can only consume a certain amount of gas. Either explicitly or just due to Due to the block gas limit, transactions can only consume a certain amount of gas. Either explicitly or just due to
normal operation, the number of iterations in a loop can grow beyond the block gas limit which can cause the complete normal operation, the number of iterations in a loop can grow beyond the block gas limit which can cause the complete
contract to be stalled at a certain point. This may not apply to ``constant`` functions that are only executed contract to be stalled at a certain point. This may not apply to ``view`` functions that are only executed
to read data from the blockchain. Still, such functions may be called by other contracts as part of on-chain operations to read data from the blockchain. Still, such functions may be called by other contracts as part of on-chain operations
and stall those. Please be explicit about such cases in the documentation of your contracts. and stall those. Please be explicit about such cases in the documentation of your contracts.

View File

@ -269,7 +269,7 @@ Functions should be grouped according to their visibility and ordered:
- internal - internal
- private - private
Within a grouping, place the ``constant`` functions last. Within a grouping, place the ``view`` and ``pure`` functions last.
Yes:: Yes::
@ -285,7 +285,10 @@ Yes::
// External functions // External functions
// ... // ...
// External functions that are constant // External functions that are view
// ...
// External functions that are pure
// ... // ...
// Public functions // Public functions

View File

@ -13,11 +13,11 @@ contract StandardToken is Token {
balance[_initialOwner] = _supply; balance[_initialOwner] = _supply;
} }
function balanceOf(address _account) constant public returns (uint) { function balanceOf(address _account) view public returns (uint) {
return balance[_account]; return balance[_account];
} }
function totalSupply() constant public returns (uint) { function totalSupply() view public returns (uint) {
return supply; return supply;
} }
@ -53,7 +53,7 @@ contract StandardToken is Token {
return true; return true;
} }
function allowance(address _owner, address _spender) constant public returns (uint256) { function allowance(address _owner, address _spender) view public returns (uint256) {
return m_allowance[_owner][_spender]; return m_allowance[_owner][_spender];
} }
} }

View File

@ -4,10 +4,10 @@ contract Token {
event Transfer(address indexed _from, address indexed _to, uint256 _value); event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value); event Approval(address indexed _owner, address indexed _spender, uint256 _value);
function totalSupply() constant public returns (uint256 supply); function totalSupply() view public returns (uint256 supply);
function balanceOf(address _owner) constant public returns (uint256 balance); function balanceOf(address _owner) view public returns (uint256 balance);
function transfer(address _to, uint256 _value) public returns (bool success); function transfer(address _to, uint256 _value) public returns (bool success);
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success); function transferFrom(address _from, address _to, uint256 _value) public returns (bool success);
function approve(address _spender, uint256 _value) public returns (bool success); function approve(address _spender, uint256 _value) public returns (bool success);
function allowance(address _owner, address _spender) constant public returns (uint256 remaining); function allowance(address _owner, address _spender) view public returns (uint256 remaining);
} }

View File

@ -2105,7 +2105,7 @@ BOOST_AUTO_TEST_CASE(packed_keccak256_complex_types)
char const* sourceCode = R"( char const* sourceCode = R"(
contract test { contract test {
uint120[3] x; uint120[3] x;
function f() view returns (bytes32 hash1, bytes32 hash2, bytes32 hash3) { function f() returns (bytes32 hash1, bytes32 hash2, bytes32 hash3) {
uint120[] memory y = new uint120[](3); uint120[] memory y = new uint120[](3);
x[0] = y[0] = uint120(-2); x[0] = y[0] = uint120(-2);
x[1] = y[1] = uint120(-3); x[1] = y[1] = uint120(-3);
@ -10877,9 +10877,9 @@ BOOST_AUTO_TEST_CASE(negative_stack_height)
bool Aboolc; bool Aboolc;
bool exists; bool exists;
} }
function nredit(uint startindex) public constant returns(uint[500] CIDs, uint[500] dates, uint[500] RIDs, bool[500] Cboolas, uint[500] amounts){} function nredit(uint startindex) public pure returns(uint[500] CIDs, uint[500] dates, uint[500] RIDs, bool[500] Cboolas, uint[500] amounts){}
function return500InvoicesByDates(uint begindate, uint enddate, uint startindex) public constant returns(uint[500] AIDs, bool[500] Aboolas, uint[500] dates, bytes32[3][500] Abytesas, bytes32[3][500] bytesbs, bytes32[2][500] bytescs, uint[500] amounts, bool[500] Aboolbs, bool[500] Aboolcs){} function return500InvoicesByDates(uint begindate, uint enddate, uint startindex) public view returns(uint[500] AIDs, bool[500] Aboolas, uint[500] dates, bytes32[3][500] Abytesas, bytes32[3][500] bytesbs, bytes32[2][500] bytescs, uint[500] amounts, bool[500] Aboolbs, bool[500] Aboolcs){}
function return500PaymentsByDates(uint begindate, uint enddate, uint startindex) public constant returns(uint[500] BIDs, uint[500] dates, uint[500] RIDs, bool[500] Bboolas, bytes32[3][500] bytesbs,bytes32[2][500] bytescs, uint[500] amounts, bool[500] Bboolbs){} function return500PaymentsByDates(uint begindate, uint enddate, uint startindex) public view returns(uint[500] BIDs, uint[500] dates, uint[500] RIDs, bool[500] Bboolas, bytes32[3][500] bytesbs,bytes32[2][500] bytescs, uint[500] amounts, bool[500] Bboolbs){}
} }
)"; )";
compileAndRun(sourceCode, 0, "C"); compileAndRun(sourceCode, 0, "C");
@ -11065,13 +11065,13 @@ BOOST_AUTO_TEST_CASE(bare_call_invalid_address)
char const* sourceCode = R"( char const* sourceCode = R"(
contract C { contract C {
/// Calling into non-existant account is successful (creates the account) /// Calling into non-existant account is successful (creates the account)
function f() external view returns (bool) { function f() external returns (bool) {
return address(0x4242).call(); return address(0x4242).call();
} }
function g() external view returns (bool) { function g() external returns (bool) {
return address(0x4242).callcode(); return address(0x4242).callcode();
} }
function h() external view returns (bool) { function h() external returns (bool) {
return address(0x4242).delegatecall(); return address(0x4242).delegatecall();
} }
} }
@ -11093,13 +11093,13 @@ BOOST_AUTO_TEST_CASE(delegatecall_return_value)
function get() external view returns (uint) { function get() external view returns (uint) {
return value; return value;
} }
function get_delegated() external view returns (bool) { function get_delegated() external returns (bool) {
return this.delegatecall(bytes4(sha3("get()"))); return this.delegatecall(bytes4(sha3("get()")));
} }
function assert0() external view { function assert0() external view {
assert(value == 0); assert(value == 0);
} }
function assert0_delegated() external view returns (bool) { function assert0_delegated() external returns (bool) {
return this.delegatecall(bytes4(sha3("assert0()"))); return this.delegatecall(bytes4(sha3("assert0()")));
} }
} }
@ -11560,7 +11560,7 @@ BOOST_AUTO_TEST_CASE(abi_encode_v2)
require(y[0] == "e"); require(y[0] == "e");
} }
S s; S s;
function f4() public view returns (bytes r) { function f4() public returns (bytes r) {
string memory x = "abc"; string memory x = "abc";
s.a = 7; s.a = 7;
s.b.push(2); s.b.push(2);

View File

@ -831,24 +831,6 @@ BOOST_AUTO_TEST_CASE(illegal_override_visibility)
CHECK_ERROR(text, TypeError, "Overriding function visibility differs"); CHECK_ERROR(text, TypeError, "Overriding function visibility differs");
} }
BOOST_AUTO_TEST_CASE(illegal_override_remove_constness)
{
char const* text = R"(
contract B { function f() constant {} }
contract C is B { function f() public {} }
)";
CHECK_ERROR(text, TypeError, "Overriding function changes state mutability from \"view\" to \"nonpayable\".");
}
BOOST_AUTO_TEST_CASE(illegal_override_add_constness)
{
char const* text = R"(
contract B { function f() public {} }
contract C is B { function f() constant {} }
)";
CHECK_ERROR(text, TypeError, "Overriding function changes state mutability from \"nonpayable\" to \"view\".");
}
BOOST_AUTO_TEST_CASE(complex_inheritance) BOOST_AUTO_TEST_CASE(complex_inheritance)
{ {
char const* text = R"( char const* text = R"(
@ -993,19 +975,6 @@ BOOST_AUTO_TEST_CASE(private_state_variable)
BOOST_CHECK_MESSAGE(function == nullptr, "Accessor function of an internal variable should not exist"); BOOST_CHECK_MESSAGE(function == nullptr, "Accessor function of an internal variable should not exist");
} }
BOOST_AUTO_TEST_CASE(missing_state_variable)
{
char const* text = R"(
contract Scope {
function getStateVar() constant public returns (uint stateVar) {
stateVar = Scope.stateVar; // should fail.
}
}
)";
CHECK_ERROR(text, TypeError, "Member \"stateVar\" not found or not visible after argument-dependent lookup in type(contract Scope)");
}
BOOST_AUTO_TEST_CASE(base_class_state_variable_accessor) BOOST_AUTO_TEST_CASE(base_class_state_variable_accessor)
{ {
// test for issue #1126 https://github.com/ethereum/cpp-ethereum/issues/1126 // test for issue #1126 https://github.com/ethereum/cpp-ethereum/issues/1126
@ -1119,17 +1088,6 @@ BOOST_AUTO_TEST_CASE(fallback_function_with_return_parameters)
CHECK_ERROR(text, TypeError, "Fallback function cannot return values."); CHECK_ERROR(text, TypeError, "Fallback function cannot return values.");
} }
BOOST_AUTO_TEST_CASE(fallback_function_with_constant_modifier)
{
char const* text = R"(
contract C {
uint x;
function() constant { x = 2; }
}
)";
CHECK_ERROR(text, TypeError, "Fallback function must be payable or non-payable");
}
BOOST_AUTO_TEST_CASE(fallback_function_twice) BOOST_AUTO_TEST_CASE(fallback_function_twice)
{ {
char const* text = R"( char const* text = R"(
@ -2327,30 +2285,6 @@ BOOST_AUTO_TEST_CASE(constant_string_literal_disallows_assignment)
CHECK_ERROR(text, TypeError, "Index access for string is not possible."); CHECK_ERROR(text, TypeError, "Index access for string is not possible.");
} }
BOOST_AUTO_TEST_CASE(assign_constant_function_value_to_constant_0_4_x)
{
char const* text = R"(
contract C {
function () constant returns (uint) x;
uint constant y = x();
}
)";
CHECK_WARNING(text, "Initial value for constant variable has to be compile-time constant.");
}
BOOST_AUTO_TEST_CASE(assign_constant_function_value_to_constant)
{
char const* text = R"(
pragma experimental "v0.5.0";
contract C {
function () constant returns (uint) x;
uint constant y = x();
}
)";
CHECK_ERROR(text, TypeError, "Initial value for constant variable has to be compile-time constant.");
}
BOOST_AUTO_TEST_CASE(assignment_to_const_var_involving_conversion) BOOST_AUTO_TEST_CASE(assignment_to_const_var_involving_conversion)
{ {
char const* text = R"( char const* text = R"(

View File

@ -838,40 +838,6 @@ BOOST_AUTO_TEST_CASE(multiple_visibility_specifiers)
CHECK_PARSE_ERROR(text, "Visibility already specified as \"private\"."); CHECK_PARSE_ERROR(text, "Visibility already specified as \"private\".");
} }
BOOST_AUTO_TEST_CASE(multiple_statemutability_specifiers)
{
char const* text = R"(
contract c {
function f() payable payable {}
})";
CHECK_PARSE_ERROR(text, "State mutability already specified as \"payable\".");
text = R"(
contract c {
function f() constant constant {}
})";
CHECK_PARSE_ERROR(text, "State mutability already specified as \"view\".");
text = R"(
contract c {
function f() constant view {}
})";
CHECK_PARSE_ERROR(text, "State mutability already specified as \"view\".");
text = R"(
contract c {
function f() payable constant {}
})";
CHECK_PARSE_ERROR(text, "State mutability already specified as \"payable\".");
text = R"(
contract c {
function f() pure payable {}
})";
CHECK_PARSE_ERROR(text, "State mutability already specified as \"pure\".");
text = R"(
contract c {
function f() pure constant {}
})";
CHECK_PARSE_ERROR(text, "State mutability already specified as \"pure\".");
}
BOOST_AUTO_TEST_CASE(literal_constants_with_ether_subdenominations) BOOST_AUTO_TEST_CASE(literal_constants_with_ether_subdenominations)
{ {
char const* text = R"( char const* text = R"(

View File

@ -0,0 +1,6 @@
contract C {
function () pure returns (uint) x;
uint constant y = x();
}
// ----
// Warning: (74-77): Initial value for constant variable has to be compile-time constant. This will fail to compile with the next breaking version change.

View File

@ -0,0 +1,8 @@
pragma experimental "v0.5.0";
contract C {
function () pure returns (uint) x;
uint constant y = x();
}
// ----
// TypeError: (105-108): Initial value for constant variable has to be compile-time constant.

View File

@ -0,0 +1,6 @@
contract C {
uint x;
function() pure { x = 2; }
}
// ----
// TypeError: (29-55): Fallback function must be payable or non-payable, but is "pure".

View File

@ -0,0 +1,6 @@
contract C {
uint x;
function() view { x = 2; }
}
// ----
// TypeError: (29-55): Fallback function must be payable or non-payable, but is "view".

View File

@ -0,0 +1,4 @@
contract B { function f() public {} }
contract C is B { function f() view {} }
// ----
// TypeError: (56-76): Overriding function changes state mutability from "nonpayable" to "view".

View File

@ -0,0 +1,4 @@
contract B { function f() view {} }
contract C is B { function f() public {} }
// ----
// TypeError: (54-76): Overriding function changes state mutability from "view" to "nonpayable".

View File

@ -0,0 +1,7 @@
contract Scope {
function getStateVar() view public returns (uint stateVar) {
stateVar = Scope.stateVar; // should fail.
}
}
// ----
// TypeError: (101-115): Member "stateVar" not found or not visible after argument-dependent lookup in type(contract Scope)

View File

@ -0,0 +1,7 @@
contract C {
uint s;
// this test should fail starting from 0.5.0
function f() public constant returns (uint) {
return s;
}
}

View File

@ -1,10 +1,10 @@
contract test { contract test {
uint256 stateVar; uint256 stateVar;
function functionName(bytes20 arg1, address addr) constant returns (int id) { } function functionName(bytes20 arg1, address addr) view returns (int id) { }
} }
// ---- // ----
// Warning: (36-115): No visibility specified. Defaulting to "public". // Warning: (36-111): No visibility specified. Defaulting to "public".
// Warning: (58-70): Unused function parameter. Remove or comment out the variable name to silence this warning. // Warning: (58-70): Unused function parameter. Remove or comment out the variable name to silence this warning.
// Warning: (72-84): Unused function parameter. Remove or comment out the variable name to silence this warning. // Warning: (72-84): Unused function parameter. Remove or comment out the variable name to silence this warning.
// Warning: (104-110): Unused function parameter. Remove or comment out the variable name to silence this warning. // Warning: (100-106): Unused function parameter. Remove or comment out the variable name to silence this warning.
// Warning: (36-115): Function state mutability can be restricted to pure // Warning: (36-111): Function state mutability can be restricted to pure

View File

@ -0,0 +1,33 @@
contract c1 {
function f() payable payable {}
}
contract c2 {
function f() view view {}
}
contract c3 {
function f() pure pure {}
}
contract c4 {
function f() pure view {}
}
contract c5 {
function f() payable view {}
}
contract c6 {
function f() pure payable {}
}
contract c7 {
function f() pure constant {}
}
contract c8 {
function f() view constant {}
}
// ----
// ParserError: (39-46): State mutability already specified as "payable".
// ParserError: (88-92): State mutability already specified as "view".
// ParserError: (134-138): State mutability already specified as "pure".
// ParserError: (180-184): State mutability already specified as "pure".
// ParserError: (229-233): State mutability already specified as "payable".
// ParserError: (275-282): State mutability already specified as "pure".
// ParserError: (324-332): State mutability already specified as "pure".
// ParserError: (374-382): State mutability already specified as "view".