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,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 | ||||
| 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``. | ||||
| 
 | ||||
| .. warning: | ||||
| 
 | ||||
|     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())); | ||||
| 	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