Skip to content

Commit dae3218

Browse files
committed
Propagate purity information for member access to foreign pure variables
1 parent 2159153 commit dae3218

8 files changed

+110
-0
lines changed

Changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Language Features:
88
Compiler Features:
99
* LSP: Add rudimentary support for semantic highlighting.
1010
* Yul Optimizer: Improve inlining heuristics for via IR code generation and pure Yul compilation.
11+
* TypeChecker: Support using library constants in initializers of other constants
1112

1213

1314
Bugfixes:

libsolidity/analysis/TypeChecker.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3158,6 +3158,13 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess)
31583158

31593159
annotation.isPure = isPure;
31603160
}
3161+
if (
3162+
auto const* varDecl = dynamic_cast<VariableDeclaration const*>(annotation.referencedDeclaration);
3163+
!annotation.isPure.set() &&
3164+
varDecl &&
3165+
varDecl->isConstant()
3166+
)
3167+
annotation.isPure = true;
31613168

31623169
if (auto magicType = dynamic_cast<MagicType const*>(exprType))
31633170
{
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
uint256 constant MAX = 1;
2+
3+
library L1 {
4+
uint256 internal constant INT = 100;
5+
}
6+
7+
contract C1 {
8+
uint256 internal constant CONST = 20 + L2.INT; // forward reference
9+
uint256 internal constant LIMIT = MAX * L1.INT; // same file & external library constant
10+
uint256 internal constant NESTED = LIMIT + CONST; // nested & same contract constant
11+
12+
uint256[L1.INT] internal arr1; // error, backward reference
13+
uint256[L2.INT] internal arr2; // error, forward reference
14+
}
15+
16+
contract C2 is C1 {
17+
uint256 internal constant INHERITED = NESTED + CONST * LIMIT; // inherited constants
18+
}
19+
20+
contract C3 is C2 {
21+
uint256 internal constant NESTED_INHERITED = INHERITED + NESTED + CONST * LIMIT; // nest-inherited constants
22+
23+
uint256[CONST] internal arr3; // error, nest-inherited constants
24+
uint256[NESTED_INHERITED] internal arr4; // error, same contract constant
25+
}
26+
27+
library L2 {
28+
uint256 internal constant INT = 100;
29+
}
30+
31+
// ----
32+
// TypeError 5462: (366-372): Invalid array length, expected integer literal or constant expression.
33+
// TypeError 5462: (430-436): Invalid array length, expected integer literal or constant expression.
34+
// TypeError 5462: (742-747): Invalid array length, expected integer literal or constant expression.
35+
// TypeError 5462: (822-838): Invalid array length, expected integer literal or constant expression.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
==== Source: A.sol ====
2+
import "B.sol" as B;
3+
4+
uint constant X = 1;
5+
uint constant Y = B.Y;
6+
7+
==== Source: B.sol ====
8+
import "A.sol" as A;
9+
10+
uint constant X = A.X;
11+
uint constant Y = 2;
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
==== Source: A.sol ====
2+
import "B.sol";
3+
4+
library L {
5+
uint constant X = 1;
6+
uint constant Y = K.Y;
7+
}
8+
9+
==== Source: B.sol ====
10+
import "A.sol";
11+
12+
library K {
13+
uint constant X = L.X;
14+
uint constant Y = 2;
15+
}
16+
17+
// ====
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
==== Source: A.sol ====
2+
import "B.sol";
3+
4+
uint256 constant A = B.VAL + 1;
5+
6+
==== Source: B.sol ====
7+
import "A.sol";
8+
9+
library B {
10+
uint256 constant VAL = A + 1;
11+
}
12+
13+
// ----
14+
// TypeError 6161: (B.sol:33-61): The value of the constant VAL has a cyclic dependency via A.
15+
// TypeError 6161: (A.sol:17-47): The value of the constant A has a cyclic dependency via VAL.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
==== Source: A.sol ====
2+
import "B.sol";
3+
4+
uint256 constant A = B + 1;
5+
6+
==== Source: B.sol ====
7+
import "A.sol";
8+
9+
uint256 constant B = A + 1;
10+
11+
// ----
12+
// TypeError 6161: (B.sol:17-43): The value of the constant B has a cyclic dependency via A.
13+
// TypeError 6161: (A.sol:17-43): The value of the constant A has a cyclic dependency via B.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
library A {
2+
uint256 constant VAL = B.VAL + 1;
3+
}
4+
5+
library B {
6+
uint256 constant VAL = A.VAL + 1;
7+
}
8+
9+
// ----
10+
// TypeError 6161: (16-48): The value of the constant VAL has a cyclic dependency via VAL.
11+
// TypeError 6161: (69-101): The value of the constant VAL has a cyclic dependency via VAL.

0 commit comments

Comments
 (0)