Эх сурвалжийг харах

Sema test for casting destructure values is broken

When the left hand side of a destructure statements is a structure
member or array element, the test incorrectly assumed the value was not
assignable.

Fixes issue #731.

Signed-off-by: Sean Young <sean@mess.org>
Sean Young 3 жил өмнө
parent
commit
431acb3893

+ 1 - 1
src/sema/statements.rs

@@ -1413,7 +1413,7 @@ fn destructure_values(
             let loc = field.loc().unwrap();
             let _ = Expression::FunctionArg(loc, right_tys[i].clone(), i).cast(
                 &loc,
-                left_ty,
+                left_ty.deref_memory(),
                 true,
                 ns,
                 diagnostics,

+ 52 - 0
tests/contract_testcases/solana/destructure_assign_struct_member.dot

@@ -0,0 +1,52 @@
+strict digraph "tests/contract_testcases/solana/destructure_assign_struct_member.sol" {
+	Data [label="name:Data\ncontract: TestContract\ntests/contract_testcases/solana/destructure_assign_struct_member.sol:3:12-16\nfield name:a1 ty:bytes32\nfield name:a2 ty:bytes32"]
+	contract [label="contract TestContract\ntests/contract_testcases/solana/destructure_assign_struct_member.sol:1:57-2:23"]
+	var [label="variable Hashes\nvisibility internal\ntests/contract_testcases/solana/destructure_assign_struct_member.sol:8:5-39"]
+	node_5 [label="constructor \ncontract: TestContract\ntests/contract_testcases/solana/destructure_assign_struct_member.sol:10:5-19\nsignature ()\nvisibility public\nmutability nonpayable"]
+	getdata [label="function getdata\ncontract: TestContract\ntests/contract_testcases/solana/destructure_assign_struct_member.sol:12:5-84\nsignature getdata(uint176,bool)\nvisibility public\nmutability view"]
+	parameters [label="parameters\nuint176 id\nbool needHash"]
+	returns [label="returns\nstruct TestContract.Data g"]
+	destructure [label="destructure\ntests/contract_testcases/solana/destructure_assign_struct_member.sol:13:9-52"]
+	structmember [label="struct member #0 bytes32\ntests/contract_testcases/solana/destructure_assign_struct_member.sol:13:12-14"]
+	variable [label="variable: g\nstruct TestContract.Data\ntests/contract_testcases/solana/destructure_assign_struct_member.sol:13:10-11"]
+	structmember_12 [label="struct member #1 bytes32\ntests/contract_testcases/solana/destructure_assign_struct_member.sol:13:18-20"]
+	variable_13 [label="variable: g\nstruct TestContract.Data\ntests/contract_testcases/solana/destructure_assign_struct_member.sol:13:16-17"]
+	list [label="list\ntests/contract_testcases/solana/destructure_assign_struct_member.sol:13:9-52"]
+	subscript [label="subscript mapping(uint176 => bytes32) storage\ntests/contract_testcases/solana/destructure_assign_struct_member.sol:13:25-37"]
+	storage_var [label="storage variable\nTestContract.Hashes\nmapping(uint176 => bytes32) storage\ntests/contract_testcases/solana/destructure_assign_struct_member.sol:13:25-31"]
+	add [label="add\nuint176\ntests/contract_testcases/solana/destructure_assign_struct_member.sol:13:34-35"]
+	variable_18 [label="variable: id\nuint176\ntests/contract_testcases/solana/destructure_assign_struct_member.sol:13:32-34"]
+	number_literal [label="uint176 literal: 1\ntests/contract_testcases/solana/destructure_assign_struct_member.sol:13:35-36"]
+	subscript_20 [label="subscript mapping(uint176 => bytes32) storage\ntests/contract_testcases/solana/destructure_assign_struct_member.sol:13:39-51"]
+	storage_var_21 [label="storage variable\nTestContract.Hashes\nmapping(uint176 => bytes32) storage\ntests/contract_testcases/solana/destructure_assign_struct_member.sol:13:39-45"]
+	add_22 [label="add\nuint176\ntests/contract_testcases/solana/destructure_assign_struct_member.sol:13:48-49"]
+	variable_23 [label="variable: id\nuint176\ntests/contract_testcases/solana/destructure_assign_struct_member.sol:13:46-48"]
+	number_literal_24 [label="uint176 literal: 2\ntests/contract_testcases/solana/destructure_assign_struct_member.sol:13:49-50"]
+	diagnostic [label="found contract ‘TestContract’\nlevel Debug\ntests/contract_testcases/solana/destructure_assign_struct_member.sol:1:57-2:23"]
+	diagnostic_27 [label="function parameter ‘needHash‘ has never been read\nlevel Warning\ntests/contract_testcases/solana/destructure_assign_struct_member.sol:12:39-47"]
+	structs -> Data
+	contracts -> contract
+	contract -> var [label="variable"]
+	contract -> node_5 [label="constructor"]
+	contract -> getdata [label="function"]
+	getdata -> parameters [label="parameters"]
+	getdata -> returns [label="returns"]
+	getdata -> destructure [label="body"]
+	destructure -> structmember [label="arg #0"]
+	structmember -> variable [label="var"]
+	destructure -> structmember_12 [label="arg #1"]
+	structmember_12 -> variable_13 [label="var"]
+	destructure -> list [label="expr"]
+	list -> subscript [label="entry #0"]
+	subscript -> storage_var [label="array"]
+	subscript -> add [label="index"]
+	add -> variable_18 [label="left"]
+	add -> number_literal [label="right"]
+	list -> subscript_20 [label="entry #1"]
+	subscript_20 -> storage_var_21 [label="array"]
+	subscript_20 -> add_22 [label="index"]
+	add_22 -> variable_23 [label="left"]
+	add_22 -> number_literal_24 [label="right"]
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_27 [label="Warning"]
+}

+ 15 - 0
tests/contract_testcases/solana/destructure_assign_struct_member.sol

@@ -0,0 +1,15 @@
+// https://github.com/hyperledger-labs/solang/issues/731
+contract TestContract {
+    struct Data {
+        bytes32 a1;
+        bytes32 a2;
+    }
+
+    mapping(uint176 => bytes32) Hashes;
+
+    constructor() {}
+
+    function getdata(uint176 id, bool needHash) public view returns (Data memory g) {
+        (g.a1, g.a2) = (Hashes[id+1], Hashes[id+2]);
+    }
+}

+ 64 - 0
tests/contract_testcases/solana/destructure_assign_struct_member_2.dot

@@ -0,0 +1,64 @@
+strict digraph "tests/contract_testcases/solana/destructure_assign_struct_member_2.sol" {
+	Struct1 [label="name:Struct1\ncontract: Contract\ntests/contract_testcases/solana/destructure_assign_struct_member_2.sol:11:12-19\nfield name:a ty:uint256\nfield name:b ty:uint256"]
+	contract [label="contract IUniswapV2Pair\ntests/contract_testcases/solana/destructure_assign_struct_member_2.sol:3:1-4:26"]
+	getReserves [label="function getReserves\ncontract: IUniswapV2Pair\ntests/contract_testcases/solana/destructure_assign_struct_member_2.sol:5:5-113\nsignature getReserves()\nvisibility external\nmutability view\nvirtual"]
+	returns [label="returns\nuint112 reserve0\nuint112 reserve1\nuint32 blockTimestampLast"]
+	contract_6 [label="contract Contract\ntests/contract_testcases/solana/destructure_assign_struct_member_2.sol:8:1-9:19"]
+	test [label="function test\ncontract: Contract\ntests/contract_testcases/solana/destructure_assign_struct_member_2.sol:16:5-56\nsignature test(bytes32[])\nvisibility public\nmutability view"]
+	parameters [label="parameters\naddress[] _tokens"]
+	var_decl [label="variable decl struct Contract.Struct1[] struct_1\ntests/contract_testcases/solana/destructure_assign_struct_member_2.sol:19:9-53"]
+	alloc_array [label="alloc array struct Contract.Struct1[]\ntests/contract_testcases/solana/destructure_assign_struct_member_2.sol:19:37-53"]
+	number_literal [label="uint32 literal: 3\ntests/contract_testcases/solana/destructure_assign_struct_member_2.sol:19:51-52"]
+	destructure [label="destructure\ntests/contract_testcases/solana/destructure_assign_struct_member_2.sol:21:9-83"]
+	structmember [label="struct member #0 uint256\ntests/contract_testcases/solana/destructure_assign_struct_member_2.sol:21:22-23"]
+	subscript [label="subscript struct Contract.Struct1[]\ntests/contract_testcases/solana/destructure_assign_struct_member_2.sol:21:10-21"]
+	variable [label="variable: struct_1\nstruct Contract.Struct1[]\ntests/contract_testcases/solana/destructure_assign_struct_member_2.sol:21:10-18"]
+	number_literal_16 [label="uint32 literal: 0\ntests/contract_testcases/solana/destructure_assign_struct_member_2.sol:21:19-20"]
+	structmember_17 [label="struct member #1 uint256\ntests/contract_testcases/solana/destructure_assign_struct_member_2.sol:21:37-38"]
+	subscript_18 [label="subscript struct Contract.Struct1[]\ntests/contract_testcases/solana/destructure_assign_struct_member_2.sol:21:25-36"]
+	variable_19 [label="variable: struct_1\nstruct Contract.Struct1[]\ntests/contract_testcases/solana/destructure_assign_struct_member_2.sol:21:25-33"]
+	number_literal_20 [label="uint32 literal: 0\ntests/contract_testcases/solana/destructure_assign_struct_member_2.sol:21:34-35"]
+	none [label="none"]
+	call_external_function [label="call external function\ntests/contract_testcases/solana/destructure_assign_struct_member_2.sol:21:43-83"]
+	external_function [label="function() external view returns (uint112,uint112,uint32)\nIUniswapV2Pair.getReserves\ntests/contract_testcases/solana/destructure_assign_struct_member_2.sol:21:43-83"]
+	cast [label="cast contract IUniswapV2Pair\ntests/contract_testcases/solana/destructure_assign_struct_member_2.sol:21:43-69"]
+	load [label="load address\ntests/contract_testcases/solana/destructure_assign_struct_member_2.sol:21:43-69"]
+	subscript_26 [label="subscript address[]\ntests/contract_testcases/solana/destructure_assign_struct_member_2.sol:21:58-68"]
+	variable_27 [label="variable: _tokens\naddress[]\ntests/contract_testcases/solana/destructure_assign_struct_member_2.sol:21:58-65"]
+	number_literal_28 [label="uint32 literal: 0\ntests/contract_testcases/solana/destructure_assign_struct_member_2.sol:21:66-67"]
+	diagnostic [label="pragma ‘solidity’ is ignored\nlevel Debug\ntests/contract_testcases/solana/destructure_assign_struct_member_2.sol:1:57-2:23"]
+	diagnostic_31 [label="found interface ‘IUniswapV2Pair’\nlevel Debug\ntests/contract_testcases/solana/destructure_assign_struct_member_2.sol:3:1-4:26"]
+	diagnostic_32 [label="found contract ‘Contract’\nlevel Debug\ntests/contract_testcases/solana/destructure_assign_struct_member_2.sol:8:1-9:19"]
+	diagnostic_33 [label="local variable ‘struct_1‘ has been assigned, but never read\nlevel Warning\ntests/contract_testcases/solana/destructure_assign_struct_member_2.sol:19:26-34"]
+	structs -> Struct1
+	contracts -> contract
+	contract -> getReserves [label="function"]
+	getReserves -> returns [label="returns"]
+	contracts -> contract_6
+	contract_6 -> test [label="function"]
+	test -> parameters [label="parameters"]
+	test -> var_decl [label="body"]
+	var_decl -> alloc_array [label="init"]
+	alloc_array -> number_literal [label="length"]
+	var_decl -> destructure [label="next"]
+	destructure -> structmember [label="arg #0"]
+	structmember -> subscript [label="var"]
+	subscript -> variable [label="array"]
+	subscript -> number_literal_16 [label="index"]
+	destructure -> structmember_17 [label="arg #1"]
+	structmember_17 -> subscript_18 [label="var"]
+	subscript_18 -> variable_19 [label="array"]
+	subscript_18 -> number_literal_20 [label="index"]
+	destructure -> none [label="arg #2"]
+	destructure -> call_external_function [label="expr"]
+	call_external_function -> external_function [label="function"]
+	external_function -> cast [label="address"]
+	cast -> load [label="expr"]
+	load -> subscript_26 [label="expr"]
+	subscript_26 -> variable_27 [label="array"]
+	subscript_26 -> number_literal_28 [label="index"]
+	diagnostics -> diagnostic [label="Debug"]
+	diagnostics -> diagnostic_31 [label="Debug"]
+	diagnostics -> diagnostic_32 [label="Debug"]
+	diagnostics -> diagnostic_33 [label="Warning"]
+}

+ 24 - 0
tests/contract_testcases/solana/destructure_assign_struct_member_2.sol

@@ -0,0 +1,24 @@
+// https://github.com/hyperledger-labs/solang/issues/731
+pragma solidity 0.6.12;
+
+interface IUniswapV2Pair {
+    function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);   
+}
+
+
+contract Contract {
+   
+    struct Struct1 {
+        uint256 a;
+        uint256 b;
+    }
+
+    function test(address[] memory _tokens) public view {
+
+        // get shares and eth required for each share
+        Struct1[] memory struct_1 = new Struct1[](3);
+
+        (struct_1[0].a, struct_1[0].b,) = IUniswapV2Pair(_tokens[0]).getReserves();
+
+    }
+}