Allow explicit conversion from address to address payable

This commit is contained in:
Leonardo Alt 2019-09-04 17:45:12 +02:00
parent b6b2a3b8be
commit 5cfe0b7670
23 changed files with 248 additions and 172 deletions

View File

@ -13,6 +13,7 @@ Breaking changes:
Language Features:
* Allow global enums and structs.
* Allow underscores as delimiters in hex strings.
* Allow explicit conversions from ``address`` to ``address payable`` via ``payable(...)``.
Compiler Features:

View File

@ -16,6 +16,8 @@ This section lists purely syntactic changes that do not affect the behavior of e
* Conversions from external function types to ``address`` are now disallowed. Instead external
function types have a member called ``address``, similar to the existing ``selector`` member.
* Conversions from ``address`` to ``address payable`` are now possible via ``payable(x)``, where
``x`` must be of type ``address``.
* New reserved keywords: ``virtual``.

View File

@ -128,3 +128,5 @@ As described in :ref:`address_literals`, hex literals of the correct size that p
test are of ``address`` type. No other literals can be implicitly converted to the ``address`` type.
Explicit conversions from ``bytes20`` or any integer type to ``address`` result in ``address payable``.
An ``address a`` can be converted to ``address payable`` via ``payable(a)``.

View File

@ -171,18 +171,20 @@ while a plain ``address`` cannot be sent Ether.
Type conversions:
Implicit conversions from ``address payable`` to ``address`` are allowed, whereas conversions from ``address`` to ``address payable`` are
not possible (the only way to perform such a conversion is by using an intermediate conversion to ``uint160``).
Implicit conversions from ``address payable`` to ``address`` are allowed, whereas conversions from ``address`` to ``address payable``
must be explicit via ``payable(<address>)``.
:ref:`Address literals<address_literals>` can be implicitly converted to ``address payable``.
Explicit conversions to and from ``address`` are allowed for integers, integer literals, ``bytes20`` and contract types with the following
caveat:
Conversions of the form ``address payable(x)`` are not allowed. Instead the result of a conversion of the form ``address(x)``
The result of a conversion of the form ``address(x)``
has the type ``address payable``, if ``x`` is of integer or fixed bytes type, a literal or a contract with a payable fallback function.
If ``x`` is a contract without payable fallback function, then ``address(x)`` will be of type ``address``.
In external function signatures ``address`` is used for both the ``address`` and the ``address payable`` type.
Only expressions of type ``address`` can be converted to type ``address payable`` via ``payable(<address>)``.
.. note::
It might very well be that you do not need to care about the distinction between ``address``
and ``address payable`` and just use ``address`` everywhere. For example,
@ -310,10 +312,12 @@ Every :ref:`contract<contracts>` defines its own type.
You can implicitly convert contracts to contracts they inherit from.
Contracts can be explicitly converted to and from the ``address`` type.
Explicit conversion to and from the ``address payable`` type
is only possible if the contract type has a payable fallback function.
The conversion is still performed using ``address(x)`` and not
using ``address payable(x)``. You can find more information in the section about
Explicit conversion to and from the ``address payable`` type is only possible
if the contract type has a payable fallback function. The conversion is still
performed using ``address(x)``. If the contract type does not have a payable
fallback function, the conversion to ``address payable`` can be done using
``payable(address(x))``.
You can find more information in the section about
the :ref:`address type<address>`.
.. note::

View File

@ -1527,11 +1527,14 @@ TypePointer TypeChecker::typeCheckTypeConversionAndRetrieveReturnType(
"\"."
);
}
if (resultType->category() == Type::Category::Address)
{
bool const payable = argType->isExplicitlyConvertibleTo(*TypeProvider::payableAddress());
resultType = payable ? TypeProvider::payableAddress() : TypeProvider::address();
}
if (auto addressType = dynamic_cast<AddressType const*>(resultType))
if (addressType->stateMutability() != StateMutability::Payable)
{
bool payable = false;
if (argType->category() != Type::Category::Address)
payable = argType->isExplicitlyConvertibleTo(*TypeProvider::payableAddress());
resultType = payable ? TypeProvider::payableAddress() : TypeProvider::address();
}
}
return resultType;
}
@ -2423,7 +2426,7 @@ bool TypeChecker::visit(Identifier const& _identifier)
void TypeChecker::endVisit(ElementaryTypeNameExpression const& _expr)
{
_expr.annotation().type = TypeProvider::typeType(TypeProvider::fromElementaryTypeName(_expr.typeName()));
_expr.annotation().type = TypeProvider::typeType(TypeProvider::fromElementaryTypeName(_expr.type().typeName(), _expr.type().stateMutability()));
_expr.annotation().isPure = true;
}

View File

@ -1682,16 +1682,21 @@ private:
class ElementaryTypeNameExpression: public PrimaryExpression
{
public:
ElementaryTypeNameExpression(SourceLocation const& _location, ElementaryTypeNameToken const& _type):
PrimaryExpression(_location), m_typeToken(_type)
{}
ElementaryTypeNameExpression(
SourceLocation const& _location,
ASTPointer<ElementaryTypeName> const& _type
):
PrimaryExpression(_location),
m_type(_type)
{
}
void accept(ASTVisitor& _visitor) override;
void accept(ASTConstVisitor& _visitor) const override;
ElementaryTypeNameToken const& typeName() const { return m_typeToken; }
ElementaryTypeName const& type() const { return *m_type; }
private:
ElementaryTypeNameToken m_typeToken;
ASTPointer<ElementaryTypeName> m_type;
};
/**

View File

@ -712,7 +712,7 @@ bool ASTJsonConverter::visit(Identifier const& _node)
bool ASTJsonConverter::visit(ElementaryTypeNameExpression const& _node)
{
std::vector<pair<string, Json::Value>> attributes = {
make_pair(m_legacy ? "value" : "typeName", _node.typeName().toString())
make_pair(m_legacy ? "value" : "typeName", _node.type().typeName().toString())
};
appendExpressionAttributes(attributes, _node.annotation());
setJsonNode(_node, "ElementaryTypeNameExpression", std::move(attributes));

View File

@ -200,7 +200,7 @@ inline T const* TypeProvider::createAndGet(Args&& ... _args)
return static_cast<T const*>(instance().m_generalTypes.back().get());
}
Type const* TypeProvider::fromElementaryTypeName(ElementaryTypeNameToken const& _type)
Type const* TypeProvider::fromElementaryTypeName(ElementaryTypeNameToken const& _type, boost::optional<StateMutability> _stateMutability)
{
solAssert(
TokenTraits::isElementaryTypeName(_type.token()),
@ -233,7 +233,14 @@ Type const* TypeProvider::fromElementaryTypeName(ElementaryTypeNameToken const&
case Token::UFixed:
return fixedPoint(128, 18, FixedPointType::Modifier::Unsigned);
case Token::Address:
{
if (_stateMutability)
{
solAssert(*_stateMutability == StateMutability::Payable, "");
return payableAddress();
}
return address();
}
case Token::Bool:
return boolean();
case Token::Bytes:

View File

@ -54,7 +54,7 @@ public:
/// @name Factory functions
/// Factory functions that convert an AST @ref TypeName to a Type.
static Type const* fromElementaryTypeName(ElementaryTypeNameToken const& _type);
static Type const* fromElementaryTypeName(ElementaryTypeNameToken const& _type, boost::optional<StateMutability> _stateMutability = {});
/// Converts a given elementary type name with optional data location
/// suffix " storage", " calldata" or " memory" to a type pointer. If suffix not given, defaults to " storage".

View File

@ -412,7 +412,9 @@ BoolResult AddressType::isImplicitlyConvertibleTo(Type const& _other) const
BoolResult AddressType::isExplicitlyConvertibleTo(Type const& _convertTo) const
{
if (auto const* contractType = dynamic_cast<ContractType const*>(&_convertTo))
if (_convertTo.category() == category())
return true;
else if (auto const* contractType = dynamic_cast<ContractType const*>(&_convertTo))
return (m_stateMutability >= StateMutability::Payable) || !contractType->isPayable();
return isImplicitlyConvertibleTo(_convertTo) ||
_convertTo.category() == Category::Integer ||

View File

@ -1585,6 +1585,17 @@ ASTPointer<Expression> Parser::parseLeftHandSideExpression(
nodeFactory.markEndPosition();
expression = nodeFactory.createNode<NewExpression>(typeName);
}
else if (m_scanner->currentToken() == Token::Payable)
{
expectToken(Token::Payable);
nodeFactory.markEndPosition();
auto expressionType = nodeFactory.createNode<ElementaryTypeName>(
ElementaryTypeNameToken(Token::Address, 160, 0),
boost::make_optional(StateMutability::Payable)
);
expression = nodeFactory.createNode<ElementaryTypeNameExpression>(expressionType);
expectToken(Token::LParen, false);
}
else
expression = parsePrimaryExpression();
@ -1725,8 +1736,10 @@ ASTPointer<Expression> Parser::parsePrimaryExpression()
unsigned firstSize;
unsigned secondSize;
tie(firstSize, secondSize) = m_scanner->currentTokenInfo();
ElementaryTypeNameToken elementaryExpression(m_scanner->currentToken(), firstSize, secondSize);
expression = nodeFactory.createNode<ElementaryTypeNameExpression>(elementaryExpression);
auto expressionType = nodeFactory.createNode<ElementaryTypeName>(
ElementaryTypeNameToken(m_scanner->currentToken(), firstSize, secondSize)
);
expression = nodeFactory.createNode<ElementaryTypeNameExpression>(expressionType);
m_scanner->next();
}
else
@ -1838,8 +1851,10 @@ Parser::IndexAccessedPath Parser::parseIndexAccessedPath()
unsigned firstNum;
unsigned secondNum;
tie(firstNum, secondNum) = m_scanner->currentTokenInfo();
ElementaryTypeNameToken elemToken(m_scanner->currentToken(), firstNum, secondNum);
iap.path.push_back(ASTNodeFactory(*this).createNode<ElementaryTypeNameExpression>(elemToken));
auto expressionType = ASTNodeFactory(*this).createNode<ElementaryTypeName>(
ElementaryTypeNameToken(m_scanner->currentToken(), firstNum, secondNum)
);
iap.path.push_back(ASTNodeFactory(*this).createNode<ElementaryTypeNameExpression>(expressionType));
m_scanner->next();
}
while (m_scanner->currentToken() == Token::LBrack)
@ -1872,7 +1887,7 @@ ASTPointer<TypeName> Parser::typeNameFromIndexAccessStructure(Parser::IndexAcces
if (auto typeName = dynamic_cast<ElementaryTypeNameExpression const*>(_iap.path.front().get()))
{
solAssert(_iap.path.size() == 1, "");
type = nodeFactory.createNode<ElementaryTypeName>(typeName->typeName());
type = nodeFactory.createNode<ElementaryTypeName>(typeName->type().typeName());
}
else
{

View File

@ -4,10 +4,10 @@
{
"C" :
[
37
39
]
},
"id" : 38,
"id" : 40,
"nodeType" : "SourceUnit",
"nodes" :
[
@ -17,10 +17,10 @@
"contractKind" : "contract",
"documentation" : null,
"fullyImplemented" : true,
"id" : 37,
"id" : 39,
"linearizedBaseContracts" :
[
37
39
],
"name" : "C",
"nodeType" : "ContractDefinition",
@ -32,7 +32,7 @@
"name" : "m",
"nodeType" : "VariableDeclaration",
"overrides" : null,
"scope" : 37,
"scope" : 39,
"src" : "17:44:1",
"stateVariable" : true,
"storageLocation" : "default",
@ -83,7 +83,7 @@
{
"body" :
{
"id" : 35,
"id" : 37,
"nodeType" : "Block",
"src" : "134:122:1",
"statements" :
@ -101,7 +101,7 @@
"name" : "a",
"nodeType" : "VariableDeclaration",
"overrides" : null,
"scope" : 35,
"scope" : 37,
"src" : "144:17:1",
"stateVariable" : false,
"storageLocation" : "default",
@ -242,7 +242,7 @@
"name" : "c",
"nodeType" : "VariableDeclaration",
"overrides" : null,
"scope" : 35,
"scope" : 37,
"src" : "197:9:1",
"stateVariable" : false,
"storageLocation" : "default",
@ -268,7 +268,7 @@
"visibility" : "internal"
}
],
"id" : 26,
"id" : 27,
"initialValue" :
{
"argumentTypes" : null,
@ -276,15 +276,15 @@
[
{
"argumentTypes" : null,
"id" : 24,
"id" : 25,
"name" : "this",
"nodeType" : "Identifier",
"overloadedDeclarations" : [],
"referencedDeclaration" : 66,
"referencedDeclaration" : 68,
"src" : "217:4:1",
"typeDescriptions" :
{
"typeIdentifier" : "t_contract$_C_$37",
"typeIdentifier" : "t_contract$_C_$39",
"typeString" : "contract C"
}
}
@ -294,11 +294,11 @@
"argumentTypes" :
[
{
"typeIdentifier" : "t_contract$_C_$37",
"typeIdentifier" : "t_contract$_C_$39",
"typeString" : "contract C"
}
],
"id" : 23,
"id" : 24,
"isConstant" : false,
"isLValue" : false,
"isPure" : true,
@ -312,7 +312,7 @@
},
"typeName" : "address"
},
"id" : 25,
"id" : 26,
"isConstant" : false,
"isLValue" : false,
"isPure" : false,
@ -334,7 +334,7 @@
"expression" :
{
"argumentTypes" : null,
"id" : 33,
"id" : 35,
"isConstant" : false,
"isLValue" : false,
"isPure" : false,
@ -345,7 +345,7 @@
"baseExpression" :
{
"argumentTypes" : null,
"id" : 27,
"id" : 28,
"name" : "m",
"nodeType" : "Identifier",
"overloadedDeclarations" : [],
@ -357,11 +357,11 @@
"typeString" : "mapping(address => address payable)"
}
},
"id" : 29,
"id" : 30,
"indexExpression" :
{
"argumentTypes" : null,
"id" : 28,
"id" : 29,
"name" : "c",
"nodeType" : "Identifier",
"overloadedDeclarations" : [],
@ -395,7 +395,7 @@
{
"argumentTypes" : null,
"hexValue" : "30",
"id" : 31,
"id" : 33,
"isConstant" : false,
"isLValue" : false,
"isPure" : true,
@ -421,7 +421,7 @@
"typeString" : "int_const 0"
}
],
"id" : 30,
"id" : 32,
"isConstant" : false,
"isLValue" : false,
"isPure" : true,
@ -435,7 +435,7 @@
},
"typeName" : "address"
},
"id" : 32,
"id" : 34,
"isConstant" : false,
"isLValue" : false,
"isPure" : true,
@ -457,14 +457,14 @@
"typeString" : "address payable"
}
},
"id" : 34,
"id" : 36,
"nodeType" : "ExpressionStatement",
"src" : "232:17:1"
}
]
},
"documentation" : null,
"id" : 36,
"id" : 38,
"implemented" : true,
"kind" : "function",
"modifiers" : [],
@ -483,7 +483,7 @@
"name" : "arg",
"nodeType" : "VariableDeclaration",
"overrides" : null,
"scope" : 36,
"scope" : 38,
"src" : "78:19:1",
"stateVariable" : false,
"storageLocation" : "default",
@ -523,7 +523,7 @@
"name" : "r",
"nodeType" : "VariableDeclaration",
"overrides" : null,
"scope" : 36,
"scope" : 38,
"src" : "115:17:1",
"stateVariable" : false,
"storageLocation" : "default",
@ -551,14 +551,14 @@
],
"src" : "114:19:1"
},
"scope" : 37,
"scope" : 39,
"src" : "67:189:1",
"stateMutability" : "nonpayable",
"superFunction" : null,
"visibility" : "public"
}
],
"scope" : 38,
"scope" : 40,
"src" : "0:258:1"
}
],

View File

@ -6,7 +6,7 @@
{
"C" :
[
37
39
]
}
},
@ -28,10 +28,10 @@
"fullyImplemented" : true,
"linearizedBaseContracts" :
[
37
39
],
"name" : "C",
"scope" : 38
"scope" : 40
},
"children" :
[
@ -41,7 +41,7 @@
"constant" : false,
"name" : "m",
"overrides" : null,
"scope" : 37,
"scope" : 39,
"stateVariable" : true,
"storageLocation" : "default",
"type" : "mapping(address => address payable)",
@ -101,7 +101,7 @@
],
"name" : "f",
"overrides" : null,
"scope" : 37,
"scope" : 39,
"stateMutability" : "nonpayable",
"superFunction" : null,
"visibility" : "public"
@ -117,7 +117,7 @@
"constant" : false,
"name" : "arg",
"overrides" : null,
"scope" : 36,
"scope" : 38,
"stateVariable" : false,
"storageLocation" : "default",
"type" : "address payable",
@ -156,7 +156,7 @@
"constant" : false,
"name" : "r",
"overrides" : null,
"scope" : 36,
"scope" : 38,
"stateVariable" : false,
"storageLocation" : "default",
"type" : "address payable",
@ -205,7 +205,7 @@
"constant" : false,
"name" : "a",
"overrides" : null,
"scope" : 35,
"scope" : 37,
"stateVariable" : false,
"storageLocation" : "default",
"type" : "address payable",
@ -358,7 +358,7 @@
"constant" : false,
"name" : "c",
"overrides" : null,
"scope" : 35,
"scope" : 37,
"stateVariable" : false,
"storageLocation" : "default",
"type" : "address",
@ -407,7 +407,7 @@
"argumentTypes" :
[
{
"typeIdentifier" : "t_contract$_C_$37",
"typeIdentifier" : "t_contract$_C_$39",
"typeString" : "contract C"
}
],
@ -418,7 +418,7 @@
"type" : "type(address)",
"value" : "address"
},
"id" : 23,
"id" : 24,
"name" : "ElementaryTypeNameExpression",
"src" : "209:7:1"
},
@ -430,21 +430,21 @@
[
null
],
"referencedDeclaration" : 66,
"referencedDeclaration" : 68,
"type" : "contract C",
"value" : "this"
},
"id" : 24,
"id" : 25,
"name" : "Identifier",
"src" : "217:4:1"
}
],
"id" : 25,
"id" : 26,
"name" : "FunctionCall",
"src" : "209:13:1"
}
],
"id" : 26,
"id" : 27,
"name" : "VariableDeclarationStatement",
"src" : "197:25:1"
},
@ -488,7 +488,7 @@
"type" : "mapping(address => address payable)",
"value" : "m"
},
"id" : 27,
"id" : 28,
"name" : "Identifier",
"src" : "232:1:1"
},
@ -504,12 +504,12 @@
"type" : "address",
"value" : "c"
},
"id" : 28,
"id" : 29,
"name" : "Identifier",
"src" : "234:1:1"
}
],
"id" : 29,
"id" : 30,
"name" : "IndexAccess",
"src" : "232:4:1"
},
@ -548,7 +548,7 @@
"type" : "type(address)",
"value" : "address"
},
"id" : 30,
"id" : 32,
"name" : "ElementaryTypeNameExpression",
"src" : "239:7:1"
},
@ -566,42 +566,42 @@
"type" : "int_const 0",
"value" : "0"
},
"id" : 31,
"id" : 33,
"name" : "Literal",
"src" : "247:1:1"
}
],
"id" : 32,
"id" : 34,
"name" : "FunctionCall",
"src" : "239:10:1"
}
],
"id" : 33,
"id" : 35,
"name" : "Assignment",
"src" : "232:17:1"
}
],
"id" : 34,
"id" : 36,
"name" : "ExpressionStatement",
"src" : "232:17:1"
}
],
"id" : 35,
"id" : 37,
"name" : "Block",
"src" : "134:122:1"
}
],
"id" : 36,
"id" : 38,
"name" : "FunctionDefinition",
"src" : "67:189:1"
}
],
"id" : 37,
"id" : 39,
"name" : "ContractDefinition",
"src" : "0:258:1"
}
],
"id" : 38,
"id" : 40,
"name" : "SourceUnit",
"src" : "0:259:1"
}

View File

@ -4,10 +4,10 @@
{
"c" :
[
14
15
]
},
"id" : 15,
"id" : 16,
"nodeType" : "SourceUnit",
"nodes" :
[
@ -17,10 +17,10 @@
"contractKind" : "contract",
"documentation" : null,
"fullyImplemented" : true,
"id" : 14,
"id" : 15,
"linearizedBaseContracts" :
[
14
15
],
"name" : "c",
"nodeType" : "ContractDefinition",
@ -32,7 +32,7 @@
"name" : "a",
"nodeType" : "VariableDeclaration",
"overrides" : null,
"scope" : 14,
"scope" : 15,
"src" : "13:8:1",
"stateVariable" : true,
"storageLocation" : "default",
@ -71,7 +71,7 @@
{
"body" :
{
"id" : 12,
"id" : 13,
"nodeType" : "Block",
"src" : "43:25:1",
"statements" :
@ -79,17 +79,17 @@
{
"assignments" :
[
9
10
],
"declarations" :
[
{
"constant" : false,
"id" : 9,
"id" : 10,
"name" : "b",
"nodeType" : "VariableDeclaration",
"overrides" : null,
"scope" : 12,
"scope" : 13,
"src" : "45:16:1",
"stateVariable" : false,
"storageLocation" : "storage",
@ -102,7 +102,7 @@
{
"baseType" :
{
"id" : 7,
"id" : 8,
"name" : "uint",
"nodeType" : "ElementaryTypeName",
"src" : "45:4:1",
@ -112,7 +112,7 @@
"typeString" : "uint256"
}
},
"id" : 8,
"id" : 9,
"length" : null,
"nodeType" : "ArrayTypeName",
"src" : "45:6:1",
@ -126,11 +126,11 @@
"visibility" : "internal"
}
],
"id" : 11,
"id" : 12,
"initialValue" :
{
"argumentTypes" : null,
"id" : 10,
"id" : 11,
"name" : "a",
"nodeType" : "Identifier",
"overloadedDeclarations" : [],
@ -148,7 +148,7 @@
]
},
"documentation" : null,
"id" : 13,
"id" : 14,
"implemented" : true,
"kind" : "function",
"modifiers" : [],
@ -169,14 +169,14 @@
"parameters" : [],
"src" : "43:0:1"
},
"scope" : 14,
"scope" : 15,
"src" : "23:45:1",
"stateMutability" : "nonpayable",
"superFunction" : null,
"visibility" : "public"
}
],
"scope" : 15,
"scope" : 16,
"src" : "0:70:1"
}
],

View File

@ -6,7 +6,7 @@
{
"c" :
[
14
15
]
}
},
@ -28,10 +28,10 @@
"fullyImplemented" : true,
"linearizedBaseContracts" :
[
14
15
],
"name" : "c",
"scope" : 15
"scope" : 16
},
"children" :
[
@ -41,7 +41,7 @@
"constant" : false,
"name" : "a",
"overrides" : null,
"scope" : 14,
"scope" : 15,
"stateVariable" : true,
"storageLocation" : "default",
"type" : "uint256[]",
@ -91,7 +91,7 @@
],
"name" : "f",
"overrides" : null,
"scope" : 14,
"scope" : 15,
"stateMutability" : "nonpayable",
"superFunction" : null,
"visibility" : "public"
@ -132,7 +132,7 @@
{
"assignments" :
[
9
10
]
},
"children" :
@ -143,7 +143,7 @@
"constant" : false,
"name" : "b",
"overrides" : null,
"scope" : 12,
"scope" : 13,
"stateVariable" : false,
"storageLocation" : "storage",
"type" : "uint256[]",
@ -166,17 +166,17 @@
"name" : "uint",
"type" : "uint256"
},
"id" : 7,
"id" : 8,
"name" : "ElementaryTypeName",
"src" : "45:4:1"
}
],
"id" : 8,
"id" : 9,
"name" : "ArrayTypeName",
"src" : "45:6:1"
}
],
"id" : 9,
"id" : 10,
"name" : "VariableDeclaration",
"src" : "45:16:1"
},
@ -192,32 +192,32 @@
"type" : "uint256[] storage ref",
"value" : "a"
},
"id" : 10,
"id" : 11,
"name" : "Identifier",
"src" : "64:1:1"
}
],
"id" : 11,
"id" : 12,
"name" : "VariableDeclarationStatement",
"src" : "45:20:1"
}
],
"id" : 12,
"id" : 13,
"name" : "Block",
"src" : "43:25:1"
}
],
"id" : 13,
"id" : 14,
"name" : "FunctionDefinition",
"src" : "23:45:1"
}
],
"id" : 14,
"id" : 15,
"name" : "ContractDefinition",
"src" : "0:70:1"
}
],
"id" : 15,
"id" : 16,
"name" : "SourceUnit",
"src" : "0:71:1"
}

View File

@ -4,10 +4,10 @@
{
"c" :
[
10
11
]
},
"id" : 11,
"id" : 12,
"nodeType" : "SourceUnit",
"nodes" :
[
@ -17,10 +17,10 @@
"contractKind" : "contract",
"documentation" : null,
"fullyImplemented" : true,
"id" : 10,
"id" : 11,
"linearizedBaseContracts" :
[
10
11
],
"name" : "c",
"nodeType" : "ContractDefinition",
@ -29,7 +29,7 @@
{
"body" :
{
"id" : 8,
"id" : 9,
"nodeType" : "Block",
"src" : "33:20:1",
"statements" :
@ -37,17 +37,17 @@
{
"assignments" :
[
6
7
],
"declarations" :
[
{
"constant" : false,
"id" : 6,
"id" : 7,
"name" : "x",
"nodeType" : "VariableDeclaration",
"overrides" : null,
"scope" : 8,
"scope" : 9,
"src" : "35:15:1",
"stateVariable" : false,
"storageLocation" : "memory",
@ -60,7 +60,7 @@
{
"baseType" :
{
"id" : 4,
"id" : 5,
"name" : "uint",
"nodeType" : "ElementaryTypeName",
"src" : "35:4:1",
@ -70,7 +70,7 @@
"typeString" : "uint256"
}
},
"id" : 5,
"id" : 6,
"length" : null,
"nodeType" : "ArrayTypeName",
"src" : "35:6:1",
@ -84,7 +84,7 @@
"visibility" : "internal"
}
],
"id" : 7,
"id" : 8,
"initialValue" : null,
"nodeType" : "VariableDeclarationStatement",
"src" : "35:15:1"
@ -92,7 +92,7 @@
]
},
"documentation" : null,
"id" : 9,
"id" : 10,
"implemented" : true,
"kind" : "function",
"modifiers" : [],
@ -113,14 +113,14 @@
"parameters" : [],
"src" : "33:0:1"
},
"scope" : 10,
"scope" : 11,
"src" : "13:40:1",
"stateMutability" : "nonpayable",
"superFunction" : null,
"visibility" : "public"
}
],
"scope" : 11,
"scope" : 12,
"src" : "0:55:1"
}
],

View File

@ -6,7 +6,7 @@
{
"c" :
[
10
11
]
}
},
@ -28,10 +28,10 @@
"fullyImplemented" : true,
"linearizedBaseContracts" :
[
10
11
],
"name" : "c",
"scope" : 11
"scope" : 12
},
"children" :
[
@ -48,7 +48,7 @@
],
"name" : "f",
"overrides" : null,
"scope" : 10,
"scope" : 11,
"stateMutability" : "nonpayable",
"superFunction" : null,
"visibility" : "public"
@ -89,7 +89,7 @@
{
"assignments" :
[
6
7
],
"initialValue" : null
},
@ -101,7 +101,7 @@
"constant" : false,
"name" : "x",
"overrides" : null,
"scope" : 8,
"scope" : 9,
"stateVariable" : false,
"storageLocation" : "memory",
"type" : "uint256[]",
@ -124,42 +124,42 @@
"name" : "uint",
"type" : "uint256"
},
"id" : 4,
"id" : 5,
"name" : "ElementaryTypeName",
"src" : "35:4:1"
}
],
"id" : 5,
"id" : 6,
"name" : "ArrayTypeName",
"src" : "35:6:1"
}
],
"id" : 6,
"id" : 7,
"name" : "VariableDeclaration",
"src" : "35:15:1"
}
],
"id" : 7,
"id" : 8,
"name" : "VariableDeclarationStatement",
"src" : "35:15:1"
}
],
"id" : 8,
"id" : 9,
"name" : "Block",
"src" : "33:20:1"
}
],
"id" : 9,
"id" : 10,
"name" : "FunctionDefinition",
"src" : "13:40:1"
}
],
"id" : 10,
"id" : 11,
"name" : "ContractDefinition",
"src" : "0:55:1"
}
],
"id" : 11,
"id" : 12,
"name" : "SourceUnit",
"src" : "0:56:1"
}

View File

@ -4,10 +4,10 @@
{
"c" :
[
11
12
]
},
"id" : 12,
"id" : 13,
"nodeType" : "SourceUnit",
"nodes" :
[
@ -17,10 +17,10 @@
"contractKind" : "contract",
"documentation" : null,
"fullyImplemented" : true,
"id" : 11,
"id" : 12,
"linearizedBaseContracts" :
[
11
12
],
"name" : "c",
"nodeType" : "ContractDefinition",
@ -29,7 +29,7 @@
{
"body" :
{
"id" : 9,
"id" : 10,
"nodeType" : "Block",
"src" : "33:25:1",
"statements" :
@ -37,17 +37,17 @@
{
"assignments" :
[
7
8
],
"declarations" :
[
{
"constant" : false,
"id" : 7,
"id" : 8,
"name" : "rows",
"nodeType" : "VariableDeclaration",
"overrides" : null,
"scope" : 9,
"scope" : 10,
"src" : "35:20:1",
"stateVariable" : false,
"storageLocation" : "memory",
@ -62,7 +62,7 @@
{
"baseType" :
{
"id" : 4,
"id" : 5,
"name" : "uint",
"nodeType" : "ElementaryTypeName",
"src" : "35:4:1",
@ -72,7 +72,7 @@
"typeString" : "uint256"
}
},
"id" : 5,
"id" : 6,
"length" : null,
"nodeType" : "ArrayTypeName",
"src" : "35:6:1",
@ -82,7 +82,7 @@
"typeString" : "uint256[]"
}
},
"id" : 6,
"id" : 7,
"length" : null,
"nodeType" : "ArrayTypeName",
"src" : "35:8:1",
@ -96,7 +96,7 @@
"visibility" : "internal"
}
],
"id" : 8,
"id" : 9,
"initialValue" : null,
"nodeType" : "VariableDeclarationStatement",
"src" : "35:20:1"
@ -104,7 +104,7 @@
]
},
"documentation" : null,
"id" : 10,
"id" : 11,
"implemented" : true,
"kind" : "function",
"modifiers" : [],
@ -125,14 +125,14 @@
"parameters" : [],
"src" : "33:0:1"
},
"scope" : 11,
"scope" : 12,
"src" : "13:45:1",
"stateMutability" : "nonpayable",
"superFunction" : null,
"visibility" : "public"
}
],
"scope" : 12,
"scope" : 13,
"src" : "0:60:1"
}
],

View File

@ -6,7 +6,7 @@
{
"c" :
[
11
12
]
}
},
@ -28,10 +28,10 @@
"fullyImplemented" : true,
"linearizedBaseContracts" :
[
11
12
],
"name" : "c",
"scope" : 12
"scope" : 13
},
"children" :
[
@ -48,7 +48,7 @@
],
"name" : "f",
"overrides" : null,
"scope" : 11,
"scope" : 12,
"stateMutability" : "nonpayable",
"superFunction" : null,
"visibility" : "public"
@ -89,7 +89,7 @@
{
"assignments" :
[
7
8
],
"initialValue" : null
},
@ -101,7 +101,7 @@
"constant" : false,
"name" : "rows",
"overrides" : null,
"scope" : 9,
"scope" : 10,
"stateVariable" : false,
"storageLocation" : "memory",
"type" : "uint256[][]",
@ -132,47 +132,47 @@
"name" : "uint",
"type" : "uint256"
},
"id" : 4,
"id" : 5,
"name" : "ElementaryTypeName",
"src" : "35:4:1"
}
],
"id" : 5,
"id" : 6,
"name" : "ArrayTypeName",
"src" : "35:6:1"
}
],
"id" : 6,
"id" : 7,
"name" : "ArrayTypeName",
"src" : "35:8:1"
}
],
"id" : 7,
"id" : 8,
"name" : "VariableDeclaration",
"src" : "35:20:1"
}
],
"id" : 8,
"id" : 9,
"name" : "VariableDeclarationStatement",
"src" : "35:20:1"
}
],
"id" : 9,
"id" : 10,
"name" : "Block",
"src" : "33:25:1"
}
],
"id" : 10,
"id" : 11,
"name" : "FunctionDefinition",
"src" : "13:45:1"
}
],
"id" : 11,
"id" : 12,
"name" : "ContractDefinition",
"src" : "0:60:1"
}
],
"id" : 12,
"id" : 13,
"name" : "SourceUnit",
"src" : "0:61:1"
}

View File

@ -0,0 +1,11 @@
contract C {
function g(address payable _p) internal pure returns (uint) {
return 1;
}
function f(address _a) public pure {
uint x = g(payable(_a));
uint y = g(_a);
}
}
// ----
// TypeError: (169-171): Invalid type for argument in function call. Invalid implicit conversion from address to address payable requested.

View File

@ -0,0 +1,9 @@
contract C {
function f() public view {
address payable p = payable(msg.sender);
address payable q = payable(address(msg.sender));
}
}
// ----
// Warning: (43-60): Unused local variable.
// Warning: (86-103): Unused local variable.

View File

@ -0,0 +1,8 @@
contract C {
function f() public pure {
address payable p = payable(this);
address payable q = payable(address(this));
}
}
// ----
// TypeError: (63-76): Explicit type conversion not allowed from "contract C" to "address payable".

View File

@ -0,0 +1,7 @@
contract C {
function f() public pure {
address payable q = payable;
}
}
// ----
// ParserError: (70-71): Expected '(' but got ';'