mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #8091 from random-internet-cat/interface-inheritance
Interface inheritance
This commit is contained in:
commit
641bb815e8
@ -3,6 +3,7 @@
|
||||
Language Features:
|
||||
* Allow accessing external functions via contract and interface names to obtain their selector.
|
||||
* Inline Assembly: Support literals ``true`` and ``false``.
|
||||
* Allow interfaces to inherit from other interfaces
|
||||
|
||||
|
||||
Compiler Features:
|
||||
|
@ -8,7 +8,7 @@ Interfaces
|
||||
|
||||
Interfaces are similar to abstract contracts, but they cannot have any functions implemented. There are further restrictions:
|
||||
|
||||
- They cannot inherit other contracts or interfaces.
|
||||
- They cannot inherit from other contracts, but they can inherit from other interfaces.
|
||||
- All declared functions must be external.
|
||||
- They cannot declare a constructor.
|
||||
- They cannot declare state variables.
|
||||
@ -37,6 +37,27 @@ they can be overridden. This does not automatically mean that an overriding func
|
||||
can be overridden again - this is only possible if the overriding
|
||||
function is marked ``virtual``.
|
||||
|
||||
Interfaces can inherit from other interfaces. This has the same rules as normal
|
||||
inheritance.
|
||||
|
||||
::
|
||||
|
||||
pragma solidity >0.6.1 <0.7.0;
|
||||
|
||||
interface ParentA {
|
||||
function test() external returns (uint256);
|
||||
}
|
||||
|
||||
interface ParentB {
|
||||
function test() external returns (uint256);
|
||||
}
|
||||
|
||||
interface SubInterface is ParentA, ParentB {
|
||||
// Must redefine test in order to assert that the parent
|
||||
// meanings are compatible.
|
||||
function test() external override(ParentA, ParentB) returns (uint256);
|
||||
}
|
||||
|
||||
Types defined inside interfaces and other contract-like structures
|
||||
can be accessed from other contracts: ``Token.TokenType`` or ``Token.Coin``.
|
||||
|
||||
|
@ -237,8 +237,8 @@ void TypeChecker::endVisit(InheritanceSpecifier const& _inheritance)
|
||||
auto base = dynamic_cast<ContractDefinition const*>(&dereference(_inheritance.name()));
|
||||
solAssert(base, "Base contract not available.");
|
||||
|
||||
if (m_scope->isInterface())
|
||||
m_errorReporter.typeError(_inheritance.location(), "Interfaces cannot inherit.");
|
||||
if (m_scope->isInterface() && !base->isInterface())
|
||||
m_errorReporter.typeError(_inheritance.location(), "Interfaces can only inherit from other interfaces.");
|
||||
|
||||
if (base->isLibrary())
|
||||
m_errorReporter.typeError(_inheritance.location(), "Libraries cannot be inherited from.");
|
||||
|
@ -0,0 +1,39 @@
|
||||
interface Parent {
|
||||
function parentFun() external returns (uint256);
|
||||
}
|
||||
|
||||
interface SubA is Parent {
|
||||
function subAFun() external returns (uint256);
|
||||
}
|
||||
|
||||
interface SubB is Parent {
|
||||
function subBFun() external returns (uint256);
|
||||
}
|
||||
|
||||
contract Impl is SubA, SubB {
|
||||
function parentFun() override external returns (uint256) { return 1; }
|
||||
function subAFun() override external returns (uint256) { return 2; }
|
||||
function subBFun() override external returns (uint256) { return 3; }
|
||||
}
|
||||
|
||||
contract C {
|
||||
function convertParent() public returns (uint256) {
|
||||
Parent p = new Impl();
|
||||
return p.parentFun();
|
||||
}
|
||||
|
||||
function convertSubA() public returns (uint256, uint256) {
|
||||
SubA sa = new Impl();
|
||||
return (sa.parentFun(), sa.subAFun());
|
||||
}
|
||||
|
||||
function convertSubB() public returns (uint256, uint256) {
|
||||
SubB sb = new Impl();
|
||||
return (sb.parentFun(), sb.subBFun());
|
||||
}
|
||||
}
|
||||
|
||||
// ----
|
||||
// convertParent() -> 1
|
||||
// convertSubA() -> 1, 2
|
||||
// convertSubB() -> 1, 3
|
@ -0,0 +1,5 @@
|
||||
contract C {}
|
||||
interface I is C {}
|
||||
|
||||
// ----
|
||||
// TypeError: (29-30): Interfaces can only inherit from other interfaces.
|
@ -0,0 +1,10 @@
|
||||
interface Parent {
|
||||
function test() external returns (uint256);
|
||||
}
|
||||
|
||||
interface SubA is Parent {}
|
||||
interface SubB is Parent {}
|
||||
|
||||
contract C is SubA, SubB {
|
||||
function test() external override returns (uint256) { return 42; }
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
interface Parent {
|
||||
function test() external returns (uint256);
|
||||
}
|
||||
|
||||
interface SubA is Parent {
|
||||
function test() external override returns (uint256);
|
||||
}
|
||||
|
||||
interface SubB is Parent {
|
||||
function test() external override returns (uint256);
|
||||
}
|
||||
|
||||
contract C is SubA, SubB {
|
||||
function test() external override(SubA, SubB) returns (uint256) { return 42; }
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
interface ParentA {
|
||||
function testA() external returns (uint256);
|
||||
}
|
||||
|
||||
interface ParentB {
|
||||
function testB() external returns (uint256);
|
||||
}
|
||||
|
||||
interface Sub is ParentA, ParentB {
|
||||
function testSub() external returns (uint256);
|
||||
}
|
||||
|
||||
contract SubImpl is Sub {
|
||||
function testA() external override returns (uint256) { return 12; }
|
||||
function testB() external override(ParentB) returns (uint256) { return 42; }
|
||||
function testSub() external override returns (uint256) { return 99; }
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
interface ParentA {
|
||||
function testA() external returns (uint256);
|
||||
}
|
||||
|
||||
interface ParentB {
|
||||
function testB() external returns (uint256);
|
||||
}
|
||||
|
||||
interface Sub is ParentA, ParentB {
|
||||
function testSub() external returns (uint256);
|
||||
}
|
||||
|
||||
contract SubImpl is Sub {
|
||||
function testA() external override returns (uint256) { return 12; }
|
||||
function testSub() external override returns (uint256) { return 99; }
|
||||
}
|
||||
|
||||
// ----
|
||||
// TypeError: (234-407): Contract "SubImpl" should be marked as abstract.
|
@ -0,0 +1,8 @@
|
||||
interface ParentA {}
|
||||
interface ParentB {}
|
||||
interface Sub is ParentA, ParentB {}
|
||||
|
||||
contract ListsA is Sub, ParentA {}
|
||||
|
||||
// ----
|
||||
// TypeError: (80-114): Linearization of inheritance graph impossible
|
@ -0,0 +1,8 @@
|
||||
interface ParentA {}
|
||||
interface ParentB {}
|
||||
interface Sub is ParentA, ParentB {}
|
||||
|
||||
contract ListsB is Sub, ParentB {}
|
||||
|
||||
// ----
|
||||
// TypeError: (80-114): Linearization of inheritance graph impossible
|
@ -0,0 +1,8 @@
|
||||
interface ParentA {}
|
||||
interface ParentB {}
|
||||
interface Sub is ParentA, ParentB {}
|
||||
|
||||
contract ListsBoth is Sub, ParentA, ParentB {}
|
||||
|
||||
// ----
|
||||
// TypeError: (80-126): Linearization of inheritance graph impossible
|
@ -0,0 +1,7 @@
|
||||
interface ParentA {}
|
||||
interface ParentB {}
|
||||
interface Sub is ParentA, ParentB {}
|
||||
|
||||
contract ListsA is ParentA, Sub {}
|
||||
contract ListsB is ParentB, Sub {}
|
||||
contract ListsBoth is ParentA, ParentB, Sub {}
|
@ -0,0 +1,15 @@
|
||||
interface SuperA {
|
||||
function test() external returns (uint256);
|
||||
function testA() external returns (int128);
|
||||
}
|
||||
|
||||
interface SuperB {
|
||||
function test() external returns (uint256);
|
||||
function testB() external returns (int256);
|
||||
}
|
||||
|
||||
interface Sub is SuperA, SuperB {
|
||||
}
|
||||
|
||||
// ----
|
||||
// TypeError: (236-271): Derived contract must override function "test". Two or more base classes define function with same name and parameter types.
|
@ -0,0 +1,31 @@
|
||||
interface SuperA {
|
||||
function test1() external returns (uint256);
|
||||
function test2() external returns (uint256);
|
||||
function test3() external returns (uint256);
|
||||
function test4() external returns (uint256);
|
||||
function test5() external returns (uint256);
|
||||
}
|
||||
|
||||
interface SuperB {
|
||||
function test1() external returns (uint256);
|
||||
function test2() external returns (uint256);
|
||||
function test3() external returns (uint256);
|
||||
function test4() external returns (uint256);
|
||||
function test5() external returns (uint256);
|
||||
}
|
||||
|
||||
interface Sub is SuperA, SuperB {
|
||||
function test1() external returns (uint256);
|
||||
function test2() external override returns (uint256);
|
||||
function test3() external override(SuperA) returns (uint256);
|
||||
function test4() external override(SuperB) returns (uint256);
|
||||
function test5() external override(SuperA, SuperB) returns (uint256);
|
||||
}
|
||||
|
||||
// ----
|
||||
// TypeError: (572-616): Overriding function is missing "override" specifier.
|
||||
// TypeError: (572-616): Overriding function is missing "override" specifier.
|
||||
// TypeError: (572-616): Function needs to specify overridden contracts "SuperA" and "SuperB".
|
||||
// TypeError: (647-655): Function needs to specify overridden contracts "SuperA" and "SuperB".
|
||||
// TypeError: (705-721): Function needs to specify overridden contract "SuperB".
|
||||
// TypeError: (771-787): Function needs to specify overridden contract "SuperA".
|
@ -0,0 +1,14 @@
|
||||
interface Super {
|
||||
function test1() external returns (uint256);
|
||||
function test2() external returns (uint256);
|
||||
function test3() external returns (uint256);
|
||||
}
|
||||
|
||||
interface Sub is Super {
|
||||
function test1() external returns (uint256);
|
||||
function test2() external override returns (uint256);
|
||||
function test3() external override(Super) returns (uint256);
|
||||
}
|
||||
|
||||
// ----
|
||||
// TypeError: (197-241): Overriding function is missing "override" specifier.
|
@ -0,0 +1,5 @@
|
||||
interface Super {
|
||||
function test() external returns (uint256);
|
||||
}
|
||||
|
||||
interface Sub is Super {}
|
@ -2,5 +2,3 @@ interface A {
|
||||
}
|
||||
interface I is A {
|
||||
}
|
||||
// ----
|
||||
// TypeError: (31-32): Interfaces cannot inherit.
|
||||
|
Loading…
Reference in New Issue
Block a user