Skip to content

Propagate purity information for member access to foreign pure variables #12928

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Language Features:


Compiler Features:

* TypeChecker: Support using library constants in initializers of other constants.

Bugfixes:

Expand Down
7 changes: 7 additions & 0 deletions libsolidity/analysis/TypeChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3214,6 +3214,13 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess)

annotation.isPure = isPure;
}
if (
auto const* varDecl = dynamic_cast<VariableDeclaration const*>(annotation.referencedDeclaration);
!annotation.isPure.set() &&
varDecl &&
varDecl->isConstant()
)
annotation.isPure = true;

if (auto magicType = dynamic_cast<MagicType const*>(exprType))
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
uint256 constant MAX = 1;

library L1 {
uint256 internal constant INT = 100;
}

contract C1 {
uint256 internal constant CONST1 = L1.INT;

uint256[L1.INT] internal arr1; // error, backward reference
uint256[L2.INT] internal arr2; // error, forward reference
}

contract C2 is C1 {
uint256 internal constant CONST2 = CONST1;

uint256[CONST1] internal arr3; // error, inherited constants
uint256[CONST2] internal arr4; // error, same contract constant
}

library L2 {
uint256 internal constant INT = 100;
}

// ----
// TypeError 5462: (158-164): Invalid array length, expected integer literal or constant expression.
// TypeError 5462: (222-228): Invalid array length, expected integer literal or constant expression.
// TypeError 5462: (356-362): Invalid array length, expected integer literal or constant expression.
// TypeError 5462: (421-427): Invalid array length, expected integer literal or constant expression.
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
uint256 constant MAX = 1;

library L1 {
uint256 internal constant INT = 100;
}

contract C1 {
uint256 internal constant CONST = 20 + L2.INT; // forward reference
uint256 internal constant LIMIT = MAX * L1.INT; // same file & external library constant
uint256 internal constant NESTED = LIMIT + CONST; // nested & same contract constant

uint256[L1.INT] internal arr1; // error, backward reference
uint256[L2.INT] internal arr2; // error, forward reference
}

contract C2 is C1 {
uint256 internal constant INHERITED = NESTED + CONST * LIMIT; // inherited constants
}

contract C3 is C2 {
uint256 internal constant NESTED_INHERITED = INHERITED + NESTED + CONST * LIMIT; // nest-inherited constants

uint256[CONST] internal arr3; // error, nest-inherited constants
uint256[NESTED_INHERITED] internal arr4; // error, same contract constant
}

library L2 {
uint256 internal constant INT = 100;
}

// ----
// TypeError 5462: (366-372): Invalid array length, expected integer literal or constant expression.
// TypeError 5462: (430-436): Invalid array length, expected integer literal or constant expression.
// TypeError 5462: (742-747): Invalid array length, expected integer literal or constant expression.
// TypeError 5462: (822-838): Invalid array length, expected integer literal or constant expression.
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
uint256 constant MAX = 1;

library L1 {
uint256 internal constant INT = 100;
}

contract C1 {
uint256 internal constant CONST = 20 + L2.INT; // forward reference
uint256 internal constant LIMIT = MAX * L1.INT; // same file & external library constant
uint256 internal constant NESTED = LIMIT + CONST; // nested & same contract constant
}

contract C2 is C1 {
uint256 internal constant INHERITED = NESTED + CONST * LIMIT; // inherited constants
}

contract C3 is C2 {
uint256 internal constant NESTED_INHERITED = INHERITED + NESTED + CONST * LIMIT; // nest-inherited constants
}

library L2 {
uint256 internal constant INT = 100;
}

// ----
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
==== Source: A.sol ====
import "B.sol" as B;

uint constant X = 1;
uint constant Y = B.Y;

==== Source: B.sol ====
import "A.sol" as A;

uint constant X = A.X;
uint constant Y = 2;
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
==== Source: A.sol ====
import "B.sol";

library L {
uint constant X = 1;
uint constant Y = K.Y;
}

==== Source: B.sol ====
import "A.sol";

library K {
uint constant X = L.X;
uint constant Y = 2;
}

// ====
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
==== Source: A.sol ====
import "B.sol";

uint256 constant A = B.VAL + 1;

==== Source: B.sol ====
import "A.sol";

library B {
uint256 constant VAL = A + 1;
}

// ----
// TypeError 6161: (B.sol:33-61): The value of the constant VAL has a cyclic dependency via A.
// TypeError 6161: (A.sol:17-47): The value of the constant A has a cyclic dependency via VAL.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
==== Source: A.sol ====
import "B.sol";

uint256 constant A = B + 1;

==== Source: B.sol ====
import "A.sol";

uint256 constant B = A + 1;

// ----
// TypeError 6161: (B.sol:17-43): The value of the constant B has a cyclic dependency via A.
// TypeError 6161: (A.sol:17-43): The value of the constant A has a cyclic dependency via B.
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
library A {
uint256 constant VAL = B.VAL + 1;
}

library B {
uint256 constant VAL = A.VAL + 1;
}

// ----
// TypeError 6161: (16-48): The value of the constant VAL has a cyclic dependency via VAL.
// TypeError 6161: (69-101): The value of the constant VAL has a cyclic dependency via VAL.