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