From 8862b3092bcdbcb8314ec27e2b11bf25fcc6346a Mon Sep 17 00:00:00 2001 From: Leonardo Alt Date: Fri, 15 Jun 2018 12:30:28 +0200 Subject: C99 scoping rules by default --- docs/contracts.rst | 1 + docs/control-structures.rst | 99 ++++++++++----------------------------------- 2 files changed, 23 insertions(+), 77 deletions(-) (limited to 'docs') diff --git a/docs/contracts.rst b/docs/contracts.rst index 4dd185aa..5e7eab80 100644 --- a/docs/contracts.rst +++ b/docs/contracts.rst @@ -1323,6 +1323,7 @@ custom types without the overhead of external function calls: if (carry > 0) { // too bad, we have to add a limb uint[] memory newLimbs = new uint[](r.limbs.length + 1); + uint i; for (i = 0; i < r.limbs.length; ++i) newLimbs[i] = r.limbs[i]; newLimbs[i] = carry; diff --git a/docs/control-structures.rst b/docs/control-structures.rst index 7849d15a..cc1f7ca5 100644 --- a/docs/control-structures.rst +++ b/docs/control-structures.rst @@ -325,74 +325,7 @@ is ``false``. The default value for the ``uint`` or ``int`` types is ``0``. For element will be initialized to the default value corresponding to its type. Finally, for dynamically-sized arrays, ``bytes`` and ``string``, the default value is an empty array or string. -A variable declared anywhere within a function will be in scope for the *entire function*, regardless of where it is declared -(this will change soon, see below). -This happens because Solidity inherits its scoping rules from JavaScript. -This is in contrast to many languages where variables are only scoped where they are declared until the end of the semantic block. -As a result, the following code is illegal and cause the compiler to throw an error, ``Identifier already declared``: - -:: - - // This will not compile - - pragma solidity ^0.4.16; - - contract ScopingErrors { - function scoping() public { - uint i = 0; - - while (i++ < 1) { - uint same1 = 0; - } - - while (i++ < 2) { - uint same1 = 0;// Illegal, second declaration of same1 - } - } - - function minimalScoping() public { - { - uint same2 = 0; - } - - { - uint same2 = 0;// Illegal, second declaration of same2 - } - } - - function forLoopScoping() public { - for (uint same3 = 0; same3 < 1; same3++) { - } - - for (uint same3 = 0; same3 < 1; same3++) {// Illegal, second declaration of same3 - } - } - } - -In addition to this, if a variable is declared, it will be initialized at the beginning of the function to its default value. -As a result, the following code is legal, despite being poorly written: - -:: - - pragma solidity ^0.4.0; - - contract C { - function foo() public pure returns (uint) { - // baz is implicitly initialized as 0 - uint bar = 5; - if (true) { - bar += baz; - } else { - uint baz = 10;// never executes - } - return bar;// returns 5 - } - } - -Scoping starting from Version 0.5.0 ------------------------------------ - -Starting from version 0.5.0, Solidity will change to the more widespread scoping rules of C99 +Scoping in Solidity follows the widespread scoping rules of C99 (and many other languages): Variables are visible from the point right after their declaration until the end of a ``{ }``-block. As an exception to this rule, variables declared in the initialization part of a for-loop are only visible until the end of the for-loop. @@ -401,17 +334,12 @@ Variables and other items declared outside of a code block, for example function user-defined types, etc., do not change their scoping behaviour. This means you can use state variables before they are declared and call functions recursively. -These rules are already introduced now as an experimental feature. - As a consequence, the following examples will compile without warnings, since -the two variables have the same name but disjoint scopes. In non-0.5.0-mode, -they have the same scope (the function ``minimalScoping``) and thus it does -not compile there. +the two variables have the same name but disjoint scopes. :: - pragma solidity ^0.4.0; - pragma experimental "v0.5.0"; + pragma solidity >0.4.24; contract C { function minimalScoping() pure public { { @@ -430,8 +358,7 @@ In any case, you will get a warning about the outer variable being shadowed. :: - pragma solidity ^0.4.0; - pragma experimental "v0.5.0"; + pragma solidity >0.4.24; contract C { function f() pure public returns (uint) { uint x = 1; @@ -443,6 +370,24 @@ In any case, you will get a warning about the outer variable being shadowed. } } +.. warning:: + Before version 0.5.0 Solidity followed the same scoping rules as JavaScript, that is, a variable declared anywhere within a function would be in scope + for the entire function, regardless where it was declared. Note that this is a breaking change. The following example shows a code snippet that used + to compile but leads to an error starting from version 0.5.0. + + :: + + // This will not compile + + pragma solidity >0.4.24; + contract C { + function f() pure public returns (uint) { + x = 2; + uint x; + return x; + } + } + .. index:: ! exception, ! throw, ! assert, ! require, ! revert Error handling: Assert, Require, Revert and Exceptions -- cgit v1.2.3