Merge pull request #4731 from ethereum/interface-enum

Allow enums in interfaces
This commit is contained in:
chriseth 2018-08-07 17:20:05 +02:00 committed by GitHub
commit d7756322c0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 93 additions and 9 deletions

View File

@ -69,6 +69,7 @@ Language Features:
* General: Allow appending ``calldata`` keyword to types, to explicitly specify data location for arguments of external functions.
* General: Support ``pop()`` for storage arrays.
* General: Scoping rules now follow the C99-style.
* General: Allow ``enum``s in interfaces.
Compiler Features:
* C API (``libsolc``): Export the ``solidity_license``, ``solidity_version`` and ``solidity_compile`` methods.

View File

@ -751,13 +751,6 @@ bool TypeChecker::visit(VariableDeclaration const& _variable)
return false;
}
bool TypeChecker::visit(EnumDefinition const& _enum)
{
if (m_scope->contractKind() == ContractDefinition::ContractKind::Interface)
m_errorReporter.typeError(_enum.location(), "Enumerable cannot be declared in interfaces.");
return false;
}
void TypeChecker::visitManually(
ModifierInvocation const& _modifier,
vector<ContractDefinition const*> const& _bases

View File

@ -96,7 +96,6 @@ private:
virtual bool visit(StructDefinition const& _struct) override;
virtual bool visit(FunctionDefinition const& _function) override;
virtual bool visit(VariableDeclaration const& _variable) override;
virtual bool visit(EnumDefinition const& _enum) override;
/// We need to do this manually because we want to pass the bases of the current contract in
/// case this is a base constructor call.
void visitManually(ModifierInvocation const& _modifier, std::vector<ContractDefinition const*> const& _bases);

View File

@ -4577,6 +4577,50 @@ BOOST_AUTO_TEST_CASE(constructing_enums_from_ints)
ABI_CHECK(callContractFunction("test()"), encodeArgs(1));
}
BOOST_AUTO_TEST_CASE(enum_referencing)
{
char const* sourceCode = R"(
interface I {
enum Direction { A, B, Left, Right }
}
library L {
enum Direction { Left, Right }
function f() public pure returns (Direction) {
return Direction.Right;
}
function g() public pure returns (I.Direction) {
return I.Direction.Right;
}
}
contract C is I {
function f() public pure returns (Direction) {
return Direction.Right;
}
function g() public pure returns (I.Direction) {
return I.Direction.Right;
}
function h() public pure returns (L.Direction) {
return L.Direction.Right;
}
function x() public pure returns (L.Direction) {
return L.f();
}
function y() public pure returns (I.Direction) {
return L.g();
}
}
)";
compileAndRun(sourceCode, 0, "L");
ABI_CHECK(callContractFunction("f()"), encodeArgs(1));
ABI_CHECK(callContractFunction("g()"), encodeArgs(3));
compileAndRun(sourceCode, 0, "C", bytes(), map<string, Address>{{"L", m_contractAddress}});
ABI_CHECK(callContractFunction("f()"), encodeArgs(3));
ABI_CHECK(callContractFunction("g()"), encodeArgs(3));
ABI_CHECK(callContractFunction("h()"), encodeArgs(1));
ABI_CHECK(callContractFunction("x()"), encodeArgs(1));
ABI_CHECK(callContractFunction("y()"), encodeArgs(3));
}
BOOST_AUTO_TEST_CASE(inline_member_init)
{
char const* sourceCode = R"(

View File

@ -2,4 +2,3 @@ interface I {
enum A { B, C }
}
// ----
// TypeError: (18-33): Enumerable cannot be declared in interfaces.

View File

@ -0,0 +1,9 @@
interface I {
enum Direction { Left, Right }
}
contract D {
function f() public pure returns (I.Direction) {
return I.Direction.Left;
}
}

View File

@ -0,0 +1,12 @@
interface I {
enum Direction { Left, Right }
}
library L {
function f() public pure returns (I.Direction) {
return I.Direction.Left;
}
function g() internal pure returns (I.Direction) {
return I.Direction.Left;
}
}

View File

@ -0,0 +1,9 @@
library L {
enum Direction { Left, Right }
}
contract D {
function f() public pure returns (L.Direction) {
return L.Direction.Left;
}
}

View File

@ -0,0 +1,9 @@
contract C {
enum Direction { Left, Right }
}
contract D is C {
function f() public pure returns (Direction) {
return Direction.Left;
}
}

View File

@ -0,0 +1,9 @@
interface I {
enum Direction { Left, Right }
}
contract D is I {
function f() public pure returns (Direction) {
return Direction.Left;
}
}