Propagate purity information for member access to foreign pure variables

This commit is contained in:
Ryan 2022-04-11 21:45:20 -05:00 committed by nishant-sachdeva
parent f904bb0615
commit 3b2c6de61c
10 changed files with 164 additions and 1 deletions

View File

@ -4,7 +4,7 @@ Language Features:
Compiler Features: Compiler Features:
* TypeChecker: Support using library constants in initializers of other constants.
Bugfixes: Bugfixes:

View File

@ -3214,6 +3214,13 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess)
annotation.isPure = isPure; 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)) if (auto magicType = dynamic_cast<MagicType const*>(exprType))
{ {

View File

@ -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.

View File

@ -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.

View File

@ -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;
}
// ----

View File

@ -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;

View File

@ -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;
}
// ====

View File

@ -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.

View File

@ -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.

View File

@ -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.