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:
|
Language Features:
|
||||||
* Allow accessing external functions via contract and interface names to obtain their selector.
|
* Allow accessing external functions via contract and interface names to obtain their selector.
|
||||||
* Inline Assembly: Support literals ``true`` and ``false``.
|
* Inline Assembly: Support literals ``true`` and ``false``.
|
||||||
|
* Allow interfaces to inherit from other interfaces
|
||||||
|
|
||||||
|
|
||||||
Compiler Features:
|
Compiler Features:
|
||||||
|
@ -8,7 +8,7 @@ Interfaces
|
|||||||
|
|
||||||
Interfaces are similar to abstract contracts, but they cannot have any functions implemented. There are further restrictions:
|
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.
|
- All declared functions must be external.
|
||||||
- They cannot declare a constructor.
|
- They cannot declare a constructor.
|
||||||
- They cannot declare state variables.
|
- They cannot declare state variables.
|
||||||
@ -37,10 +37,31 @@ they can be overridden. This does not automatically mean that an overriding func
|
|||||||
can be overridden again - this is only possible if the overriding
|
can be overridden again - this is only possible if the overriding
|
||||||
function is marked ``virtual``.
|
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
|
Types defined inside interfaces and other contract-like structures
|
||||||
can be accessed from other contracts: ``Token.TokenType`` or ``Token.Coin``.
|
can be accessed from other contracts: ``Token.TokenType`` or ``Token.Coin``.
|
||||||
|
|
||||||
.. warning:
|
.. warning:
|
||||||
|
|
||||||
Interfaces have supported ``enum`` types since :doc:`Solidity version 0.5.0 <050-breaking-changes>`, make
|
Interfaces have supported ``enum`` types since :doc:`Solidity version 0.5.0 <050-breaking-changes>`, make
|
||||||
sure the pragma version specifies this version as a minimum.
|
sure the pragma version specifies this version as a minimum.
|
||||||
|
@ -237,8 +237,8 @@ void TypeChecker::endVisit(InheritanceSpecifier const& _inheritance)
|
|||||||
auto base = dynamic_cast<ContractDefinition const*>(&dereference(_inheritance.name()));
|
auto base = dynamic_cast<ContractDefinition const*>(&dereference(_inheritance.name()));
|
||||||
solAssert(base, "Base contract not available.");
|
solAssert(base, "Base contract not available.");
|
||||||
|
|
||||||
if (m_scope->isInterface())
|
if (m_scope->isInterface() && !base->isInterface())
|
||||||
m_errorReporter.typeError(_inheritance.location(), "Interfaces cannot inherit.");
|
m_errorReporter.typeError(_inheritance.location(), "Interfaces can only inherit from other interfaces.");
|
||||||
|
|
||||||
if (base->isLibrary())
|
if (base->isLibrary())
|
||||||
m_errorReporter.typeError(_inheritance.location(), "Libraries cannot be inherited from.");
|
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 {
|
interface I is A {
|
||||||
}
|
}
|
||||||
// ----
|
|
||||||
// TypeError: (31-32): Interfaces cannot inherit.
|
|
||||||
|
Loading…
Reference in New Issue
Block a user