Browse Source

Allow types to be called error (#843)

solc allows this too.

Found in https://github.com/hyperledger-labs/solang/pull/787

Signed-off-by: Sean Young <sean@mess.org>
Sean Young 3 years ago
parent
commit
000a509e81

+ 18 - 6
solang-parser/src/solidity.lalrpop

@@ -74,7 +74,7 @@ NoFunctionType: Type = {
     Bytes => Type::Bytes(<>),
     // prior to 0.8.0 `byte` used to be an alias for `bytes1`
     "byte" => Type::Bytes(1),
-    <l:@L> "mapping" "(" <k:Precedence0> "=>" <v:Precedence0> ")" <r:@R> => {
+    <l:@L> "mapping" "(" <k:AnyType> "=>" <v:AnyType> ")" <r:@R> => {
         Type::Mapping(Loc::File(file_no, l, r), Box::new(k), Box::new(v))
     },
 }
@@ -139,7 +139,7 @@ SolIdentifierPath: IdentifierPath = {
 }
 
 VariableDeclaration: VariableDeclaration = {
-    <l:@L> <ty:Precedence0> <storage:StorageLocation?> <name:SolIdentifier> <r:@R> => VariableDeclaration {
+    <l:@L> <ty:AnyType> <storage:StorageLocation?> <name:SolIdentifier> <r:@R> => VariableDeclaration {
         loc: Loc::File(file_no, l, r), ty, storage, name
     },
 }
@@ -195,13 +195,13 @@ ContractDefinition: Box<ContractDefinition> = {
 }
 
 EventParameter: EventParameter = {
-    <l:@L> <ty:Precedence0> <i:"indexed"?> <name:SolIdentifier?> <r:@R> => EventParameter{
+    <l:@L> <ty:AnyType> <i:"indexed"?> <name:SolIdentifier?> <r:@R> => EventParameter{
         loc: Loc::File(file_no, l, r), ty, indexed: i.is_some(), name
     }
 }
 
 ErrorParameter: ErrorParameter = {
-    <l:@L> <ty:Precedence0> <name:SolIdentifier?> <r:@R> => ErrorParameter{
+    <l:@L> <ty:AnyType> <name:SolIdentifier?> <r:@R> => ErrorParameter{
         loc: Loc::File(file_no, l, r), ty, name
     }
 }
@@ -234,6 +234,13 @@ VariableDefinition: Box<VariableDefinition> = {
             loc: Loc::File(file_no, l, r), ty, attrs, name, initializer: e,
         })
     },
+    <l:@L> "error" <er:@R> <attrs:VariableAttribute*> <name:SolIdentifier> <e:("=" <Expression>)?> <r:@R> ";" => {
+        let ty = Expression::Variable(Identifier{loc: Loc::File(file_no, l, r), name: "error".to_string()});
+
+        Box::new(VariableDefinition{
+            loc: Loc::File(file_no, l, r), ty, attrs, name, initializer: e,
+        })
+    },
     // attributes cause shift-reduce errors with function type, since a function type contract variable can be declare as
     // contract foo {
     //     // f is a variable with internal visibility referencing an external function
@@ -247,7 +254,7 @@ VariableDefinition: Box<VariableDefinition> = {
 }
 
 TypeDefinition: Box<TypeDefinition> = {
-    <l:@L> "type" <name:SolIdentifier> "is" <ty:Precedence0> <r:@R> ";" => {
+    <l:@L> "type" <name:SolIdentifier> "is" <ty:AnyType> <r:@R> ";" => {
         Box::new(TypeDefinition{
             loc: Loc::File(file_no, l, r), name, ty
         })
@@ -391,6 +398,11 @@ FunctionCallPrecedence: Expression = {
     <l:@L> "type" <r:@R> => Expression::Variable(Identifier{loc: Loc::File(file_no, l, r), name: "type".to_string()}),
 }
 
+AnyType: Expression = {
+    <l:@L> "error" <r:@R> => Expression::Variable(Identifier{loc: Loc::File(file_no, l, r), name: "error".to_string()}),
+    Precedence0
+}
+
 Precedence0: Expression = {
     NoFunctionTyPrecedence0,
     FunctionTyPrecedence0
@@ -629,7 +641,7 @@ FunctionDefinition: Box<FunctionDefinition> = {
 }
 
 Using: Box<Using> = {
-    <l:@L> "using" <list:UsingList> "for" <ty:Precedence0> <global:SolIdentifier?> <r:@R> ";" => Box::new(Using {
+    <l:@L> "using" <list:UsingList> "for" <ty:AnyType> <global:SolIdentifier?> <r:@R> ";" => Box::new(Using {
         loc: Loc::File(file_no, l, r),
         list,
         ty: Some(ty),

+ 38 - 0
tests/contract_testcases/solana/type_called_error.dot

@@ -0,0 +1,38 @@
+strict digraph "tests/contract_testcases/solana/type_called_error.sol" {
+	error [label="name:error\ntests/contract_testcases/solana/type_called_error.sol:1:8-13\nfield name:f1 ty:int256"]
+	contract [label="contract c\ntests/contract_testcases/solana/type_called_error.sol:8:1-9:12"]
+	var [label="variable v1\nvisibility public\ntests/contract_testcases/solana/type_called_error.sol:10:2-17"]
+	v1 [label="function v1\ncontract: c\ntests/contract_testcases/solana/type_called_error.sol:10:15-17\nsignature v1()\nvisibility public\nmutability view"]
+	returns [label="returns\nstruct error "]
+	return [label="return\nimplicit"]
+	storage_load [label="storage load struct error\nimplicit"]
+	storage_var [label="storage variable\nc.v1\nstruct error storage\nimplicit"]
+	test [label="function test\ncontract: c\ntests/contract_testcases/solana/type_called_error.sol:12:2-54\nsignature test((int256))\nvisibility internal\nmutability pure"]
+	parameters [label="parameters\nstruct error e"]
+	returns_12 [label="returns\nstruct error "]
+	expr [label="expression\ntests/contract_testcases/solana/type_called_error.sol:13:3-13"]
+	call_internal_function [label="call internal function\ntests/contract_testcases/solana/type_called_error.sol:13:3-13"]
+	internal_function [label="function(struct error) internal pure returns (void)\nfree function member\ntests/contract_testcases/solana/type_called_error.sol:13:3-13"]
+	variable [label="variable: e\nstruct error\ntests/contract_testcases/solana/type_called_error.sol:13:3-4"]
+	return_17 [label="return\ntests/contract_testcases/solana/type_called_error.sol:14:3-11"]
+	variable_18 [label="variable: e\nstruct error\ntests/contract_testcases/solana/type_called_error.sol:14:10-11"]
+	diagnostic [label="found contract 'c'\nlevel Debug\ntests/contract_testcases/solana/type_called_error.sol:8:1-9:12"]
+	structs -> error
+	contracts -> contract
+	contract -> var [label="variable"]
+	contract -> v1 [label="function"]
+	v1 -> returns [label="returns"]
+	v1 -> return [label="body"]
+	return -> storage_load [label="expr"]
+	storage_load -> storage_var [label="expr"]
+	contract -> test [label="function"]
+	test -> parameters [label="parameters"]
+	test -> returns_12 [label="returns"]
+	test -> expr [label="body"]
+	expr -> call_internal_function [label="expr"]
+	call_internal_function -> internal_function [label="function"]
+	call_internal_function -> variable [label="arg #0"]
+	expr -> return_17 [label="next"]
+	return_17 -> variable_18 [label="expr"]
+	diagnostics -> diagnostic [label="Debug"]
+}

+ 16 - 0
tests/contract_testcases/solana/type_called_error.sol

@@ -0,0 +1,16 @@
+struct error { int f1; }
+
+function member(error e) pure returns (int) {
+	return e.f1;
+}
+
+using {member} for error;
+
+contract c {
+	error public v1;
+
+	function test(error e) internal pure returns (error) {
+		e.member();
+		return e;
+	}
+}