Skip to content

Commit

Permalink
Allow mapping returns from library functions.
Browse files Browse the repository at this point in the history
  • Loading branch information
ekpyron committed Nov 9, 2018
1 parent a154a52 commit 416aef9
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 28 deletions.
38 changes: 12 additions & 26 deletions libsolidity/analysis/TypeChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -695,14 +695,19 @@ bool TypeChecker::visit(FunctionDefinition const& _function)
if (!_function.isConstructor() && !_function.isFallback() && !_function.isPartOfExternalInterface())
m_errorReporter.typeError(_function.location(), "Internal functions cannot be payable.");
}
const auto checkArgumentsAndReturnParameters = [&](ASTPointer<VariableDeclaration> const& var) {
if (
type(*var)->category() == Type::Category::Mapping &&
!type(*var)->dataStoredIn(DataLocation::Storage)
)
for (ASTPointer<VariableDeclaration> const& var: _function.parameters() + _function.returnParameters())
{
if (type(*var)->category() == Type::Category::Mapping)
{
if (!type(*var)->dataStoredIn(DataLocation::Storage))
m_errorReporter.typeError(var->location(), "Mapping types can only have a data location of \"storage\"." );
if (
type(*var)->category() != Type::Category::Mapping &&
else if (
!isLibraryFunction &&
_function.visibility() > FunctionDefinition::Visibility::Internal
)
m_errorReporter.typeError(var->location(), "Type is required to live outside storage.");
}
else if (
!type(*var)->canLiveOutsideStorage() &&
_function.visibility() > FunctionDefinition::Visibility::Internal
)
Expand All @@ -721,25 +726,6 @@ bool TypeChecker::visit(FunctionDefinition const& _function)
);

var->accept(*this);
};
for (ASTPointer<VariableDeclaration> const& var: _function.parameters())
{
if (
type(*var)->category() == Type::Category::Mapping &&
!isLibraryFunction &&
_function.visibility() > FunctionDefinition::Visibility::Internal
)
m_errorReporter.typeError(var->location(), "Type is required to live outside storage.");
checkArgumentsAndReturnParameters(var);
}
for (ASTPointer<VariableDeclaration> const& var: _function.returnParameters())
{
if (
type(*var)->category() == Type::Category::Mapping &&
_function.visibility() > FunctionDefinition::Visibility::Internal
)
m_errorReporter.typeError(var->location(), "Type is required to live outside storage.");
checkArgumentsAndReturnParameters(var);
}
set<Declaration const*> modifiers;
for (ASTPointer<ModifierInvocation> const& modifier: _function.modifiers())
Expand Down
1 change: 1 addition & 0 deletions libsolidity/ast/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -1205,6 +1205,7 @@ class MappingType: public Type
{
return _inLibrary ? shared_from_this() : TypePointer();
}
virtual unsigned calldataEncodedSize(bool) const override { return 32; }
virtual bool dataStoredIn(DataLocation _location) const override { return _location == DataLocation::Storage; }
/// Cannot be stored in memory, but just in case.
virtual bool hasSimpleZeroValueInMemory() const override { solAssert(false, ""); }
Expand Down
25 changes: 25 additions & 0 deletions test/libsolidity/SolidityEndToEndTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8717,6 +8717,31 @@ BOOST_AUTO_TEST_CASE(using_library_mappings_external)
ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(2), u256(0), u256(84), u256(46), u256(0), u256(198)));
}

BOOST_AUTO_TEST_CASE(using_library_mappings_return)
{
char const* sourceCode = R"(
library Lib {
function choose(mapping(uint => mapping(uint => uint)) storage m, uint key) external returns (mapping(uint => uint) storage) {
return m[key];
}
}
contract Test {
mapping(uint => mapping(uint => uint)) m;
function f() public returns (uint, uint, uint, uint, uint, uint)
{
Lib.choose(m, 0)[0] = 1;
Lib.choose(m, 0)[2] = 42;
Lib.choose(m, 1)[0] = 23;
Lib.choose(m, 1)[2] = 99;
return (m[0][0], m[0][1], m[0][2], m[1][0], m[1][1], m[1][2]);
}
}
)";
compileAndRun(sourceCode, 0, "Lib");
compileAndRun(sourceCode, 0, "Test", bytes(), map<string, Address>{{"Lib", m_contractAddress}});
ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(1), u256(0), u256(42), u256(23), u256(0), u256(99)));
}

BOOST_AUTO_TEST_CASE(using_library_structs)
{
char const* sourceCode = R"(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,3 @@ library L
}
}
// ----
// TypeError: (123-152): Type is required to live outside storage.
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,3 @@ library L
}
}
// ----
// TypeError: (121-150): Type is required to live outside storage.

0 comments on commit 416aef9

Please sign in to comment.