Merge pull request #9422 from ethereum/typeCheckerFunctionNamedArgsFix

[TypeChecker] Do not allow function application with named arguments on the result of a conditional operator
This commit is contained in:
chriseth 2020-07-23 15:22:26 +02:00 committed by GitHub
commit 1a4c896775
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 125 additions and 3 deletions

View File

@ -32,6 +32,7 @@ Bugfixes:
* NatSpec: Constructors and functions have consistent userdoc output.
* Inheritance: Disallow public state variables overwriting ``pure`` functions.
* State Mutability: Constant public state variables are considered ``pure`` functions.
* Type Checker: Fixing deduction issues on function types when function call has named arguments.
### 0.6.12 (2020-07-22)

View File

@ -1293,9 +1293,9 @@ bool TypeChecker::visit(Conditional const& _conditional)
if (_conditional.annotation().willBeWrittenTo)
m_errorReporter.typeError(
2212_error,
_conditional.location(),
"Conditional expression as left value is not supported yet."
2212_error,
_conditional.location(),
"Conditional expression as left value is not supported yet."
);
return false;

View File

@ -3425,6 +3425,28 @@ TypeResult FunctionType::interfaceType(bool /*_inLibrary*/) const
return TypeResult::err("Internal type is not allowed for public or external functions.");
}
TypePointer FunctionType::mobileType() const
{
if (m_valueSet || m_gasSet || m_saltSet || m_bound)
return nullptr;
// return function without parameter names
return TypeProvider::function(
m_parameterTypes,
m_returnParameterTypes,
strings(m_parameterTypes.size()),
strings(m_returnParameterNames.size()),
m_kind,
m_arbitraryParameters,
m_stateMutability,
m_declaration,
m_gasSet,
m_valueSet,
m_bound,
m_saltSet
);
}
bool FunctionType::canTakeArguments(
FuncCallArguments const& _arguments,
Type const* _selfType

View File

@ -1234,6 +1234,7 @@ public:
MemberList::MemberMap nativeMembers(ASTNode const* _currentScope) const override;
TypePointer encodingType() const override;
TypeResult interfaceType(bool _inLibrary) const override;
TypePointer mobileType() const override;
/// @returns TypePointer of a new FunctionType object. All input/return parameters are an
/// appropriate external types (i.e. the interfaceType()s) of input/return parameters of

View File

@ -0,0 +1,12 @@
contract C {
function g(int x, int y) public pure returns (int) { return x - y; }
function h(int y, int x) public pure returns (int) { return y - x; }
function f() public pure returns (int) {
return (false ? g : h)(2, 1);
}
}
// ====
// compileViaYul: also
// ----
// f() -> 1

View File

@ -0,0 +1,10 @@
contract C {
function f() external payable returns (uint) { assert(msg.value > 0); return 1; }
function g() external payable returns (uint) { assert(msg.value > 0); return 2; }
function h() public payable returns (uint) {
return [this.f, this.g][0]{value: 1}();
}
}
// ----
// h(), 1 ether -> 1

View File

@ -0,0 +1,14 @@
contract C {
function g(int x, int y) public pure returns (int) { return x - y; }
function h(int y, int x) public pure returns (int) { return y - x; }
function f() public pure {
(true ? g : h)({x : 1, y : 2});
[g, h][1]({x : 1, y : 2});
}
}
// ----
// TypeError 4974: (199-229): Named argument "x" does not match function declaration.
// TypeError 4974: (199-229): Named argument "y" does not match function declaration.
// TypeError 4974: (239-264): Named argument "x" does not match function declaration.
// TypeError 4974: (239-264): Named argument "y" does not match function declaration.

View File

@ -0,0 +1,9 @@
contract C {
function f() pure public {
function(uint a) returns (uint) x;
x({a:2});
}
}
// ----
// Warning 6162: (61-67): Naming function type parameters is deprecated.
// TypeError 4974: (95-103): Named argument "a" does not match function declaration.

View File

@ -0,0 +1,13 @@
library L {
function f(uint a) internal pure {}
function g(uint a) internal pure {}
}
contract C {
using L for *;
function f() pure public {
uint t = 8;
[t.f, t.g][0]();
}
}
// ----
// TypeError 9563: (186-189): Invalid mobile type.

View File

@ -0,0 +1,13 @@
library L {
function f(uint a) internal pure {}
}
contract C {
using L for *;
function f() pure public {
uint t;
function() pure x;
[t.f, x][0]({a: 8});
}
}
// ----
// TypeError 9563: (169-172): Invalid mobile type.

View File

@ -0,0 +1,13 @@
contract D {
function f(uint a) external payable {}
function g(uint a) external {}
}
contract C {
function f() public {
D d;
[d.f{value: 1}, d.g][0](8);
}
}
// ----
// TypeError 9563: (155-168): Invalid mobile type.

View File

@ -0,0 +1,14 @@
library L {
function f(uint a) internal pure {}
function g(uint a) internal pure {}
}
contract C {
using L for *;
function f(bool x) pure public {
uint t = 8;
(x ? t.f : t.g)();
}
}
// ----
// TypeError 9717: (196-199): Invalid mobile type in true expression.
// TypeError 3703: (202-205): Invalid mobile type in false expression.