C99 scoping rules by default

This commit is contained in:
Leonardo Alt
2018-06-20 12:53:38 +02:00
parent ba7fbf11e7
commit 8862b3092b
35 changed files with 85 additions and 219 deletions
+1
View File
@@ -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;
+22 -77
View File
@@ -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