mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #8234 from ethereum/contractsAsMappingKeys
Contract types as mapping keys.
This commit is contained in:
commit
8a7e1d651a
@ -1,7 +1,7 @@
|
|||||||
### 0.6.3 (unreleased)
|
### 0.6.3 (unreleased)
|
||||||
|
|
||||||
Language Features:
|
Language Features:
|
||||||
|
* Allow contract types and enums as keys for mappings.
|
||||||
|
|
||||||
|
|
||||||
Compiler Features:
|
Compiler Features:
|
||||||
|
@ -59,7 +59,7 @@ TypeName = ElementaryTypeName
|
|||||||
|
|
||||||
UserDefinedTypeName = Identifier ( '.' Identifier )*
|
UserDefinedTypeName = Identifier ( '.' Identifier )*
|
||||||
|
|
||||||
Mapping = 'mapping' '(' ElementaryTypeName '=>' TypeName ')'
|
Mapping = 'mapping' '(' ( ElementaryTypeName | UserDefinedTypeName ) '=>' TypeName ')'
|
||||||
ArrayTypeName = TypeName '[' Expression? ']'
|
ArrayTypeName = TypeName '[' Expression? ']'
|
||||||
FunctionTypeName = 'function' FunctionTypeParameterList ( 'internal' | 'external' | StateMutability )*
|
FunctionTypeName = 'function' FunctionTypeParameterList ( 'internal' | 'external' | StateMutability )*
|
||||||
( 'returns' FunctionTypeParameterList )?
|
( 'returns' FunctionTypeParameterList )?
|
||||||
|
@ -7,9 +7,8 @@ Mapping Types
|
|||||||
Mapping types use the syntax ``mapping(_KeyType => _ValueType)`` and variables
|
Mapping types use the syntax ``mapping(_KeyType => _ValueType)`` and variables
|
||||||
of mapping type are declared using the syntax ``mapping(_KeyType => _ValueType) _VariableName``.
|
of mapping type are declared using the syntax ``mapping(_KeyType => _ValueType) _VariableName``.
|
||||||
The ``_KeyType`` can be any
|
The ``_KeyType`` can be any
|
||||||
built-in value type plus ``bytes`` and ``string``. User-defined
|
built-in value type, ``bytes``, ``string``, or any contract or enum type. Other user-defined
|
||||||
or complex types such as contract types, enums, mappings, structs or array types
|
or complex types, such as mappings, structs or array types are not allowed.
|
||||||
apart from ``bytes`` and ``string`` are not allowed.
|
|
||||||
``_ValueType`` can be any type, including mappings, arrays and structs.
|
``_ValueType`` can be any type, including mappings, arrays and structs.
|
||||||
|
|
||||||
You can think of mappings as `hash tables <https://en.wikipedia.org/wiki/Hash_table>`_, which are virtually initialised
|
You can think of mappings as `hash tables <https://en.wikipedia.org/wiki/Hash_table>`_, which are virtually initialised
|
||||||
|
@ -2876,6 +2876,25 @@ void TypeChecker::endVisit(Literal const& _literal)
|
|||||||
_literal.annotation().isPure = true;
|
_literal.annotation().isPure = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TypeChecker::visit(Mapping const& _mapping)
|
||||||
|
{
|
||||||
|
if (auto const* keyType = dynamic_cast<UserDefinedTypeName const*>(&_mapping.keyType()))
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
keyType->annotation().type->category() != Type::Category::Contract &&
|
||||||
|
keyType->annotation().type->category() != Type::Category::Enum
|
||||||
|
)
|
||||||
|
m_errorReporter.typeError(
|
||||||
|
keyType->location(),
|
||||||
|
"Only elementary types, contract types or enums are allowed as mapping keys."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
solAssert(dynamic_cast<ElementaryTypeName const*>(&_mapping.keyType()), "");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool TypeChecker::contractDependenciesAreCyclic(
|
bool TypeChecker::contractDependenciesAreCyclic(
|
||||||
ContractDefinition const& _contract,
|
ContractDefinition const& _contract,
|
||||||
std::set<ContractDefinition const*> const& _seenContracts
|
std::set<ContractDefinition const*> const& _seenContracts
|
||||||
|
@ -143,6 +143,7 @@ private:
|
|||||||
bool visit(Identifier const& _identifier) override;
|
bool visit(Identifier const& _identifier) override;
|
||||||
void endVisit(ElementaryTypeNameExpression const& _expr) override;
|
void endVisit(ElementaryTypeNameExpression const& _expr) override;
|
||||||
void endVisit(Literal const& _literal) override;
|
void endVisit(Literal const& _literal) override;
|
||||||
|
bool visit(Mapping const& _mapping) override;
|
||||||
|
|
||||||
bool contractDependenciesAreCyclic(
|
bool contractDependenciesAreCyclic(
|
||||||
ContractDefinition const& _contract,
|
ContractDefinition const& _contract,
|
||||||
|
@ -1152,18 +1152,18 @@ public:
|
|||||||
Mapping(
|
Mapping(
|
||||||
int64_t _id,
|
int64_t _id,
|
||||||
SourceLocation const& _location,
|
SourceLocation const& _location,
|
||||||
ASTPointer<ElementaryTypeName> const& _keyType,
|
ASTPointer<TypeName> const& _keyType,
|
||||||
ASTPointer<TypeName> const& _valueType
|
ASTPointer<TypeName> const& _valueType
|
||||||
):
|
):
|
||||||
TypeName(_id, _location), m_keyType(_keyType), m_valueType(_valueType) {}
|
TypeName(_id, _location), m_keyType(_keyType), m_valueType(_valueType) {}
|
||||||
void accept(ASTVisitor& _visitor) override;
|
void accept(ASTVisitor& _visitor) override;
|
||||||
void accept(ASTConstVisitor& _visitor) const override;
|
void accept(ASTConstVisitor& _visitor) const override;
|
||||||
|
|
||||||
ElementaryTypeName const& keyType() const { return *m_keyType; }
|
TypeName const& keyType() const { return *m_keyType; }
|
||||||
TypeName const& valueType() const { return *m_valueType; }
|
TypeName const& valueType() const { return *m_valueType; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ASTPointer<ElementaryTypeName> m_keyType;
|
ASTPointer<TypeName> m_keyType;
|
||||||
ASTPointer<TypeName> m_valueType;
|
ASTPointer<TypeName> m_valueType;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -511,7 +511,7 @@ ASTPointer<Mapping> ASTJsonImporter::createMapping(Json::Value const& _node)
|
|||||||
{
|
{
|
||||||
return createASTNode<Mapping>(
|
return createASTNode<Mapping>(
|
||||||
_node,
|
_node,
|
||||||
createElementaryTypeName(member(_node, "keyType")),
|
convertJsonToASTNode<TypeName>(member(_node, "keyType")),
|
||||||
convertJsonToASTNode<TypeName>(member(_node, "valueType"))
|
convertJsonToASTNode<TypeName>(member(_node, "valueType"))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -159,6 +159,54 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
|
|||||||
solAssert(!_varDecl.isConstant(), "");
|
solAssert(!_varDecl.isConstant(), "");
|
||||||
solAssert(_varDecl.isStateVariable(), "");
|
solAssert(_varDecl.isStateVariable(), "");
|
||||||
|
|
||||||
|
if (auto const* mappingType = dynamic_cast<MappingType const*>(type))
|
||||||
|
return m_context.functionCollector()->createFunction(functionName, [&]() {
|
||||||
|
pair<u256, unsigned> slot_offset = m_context.storageLocationOfVariable(_varDecl);
|
||||||
|
solAssert(slot_offset.second == 0, "");
|
||||||
|
FunctionType funType(_varDecl);
|
||||||
|
solUnimplementedAssert(funType.returnParameterTypes().size() == 1, "");
|
||||||
|
TypePointer returnType = funType.returnParameterTypes().front();
|
||||||
|
unsigned num_keys = 0;
|
||||||
|
stringstream indexAccesses;
|
||||||
|
string slot = m_context.newYulVariable();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
solUnimplementedAssert(
|
||||||
|
mappingType->keyType()->sizeOnStack() == 1,
|
||||||
|
"Multi-slot mapping key unimplemented - might not be a problem"
|
||||||
|
);
|
||||||
|
indexAccesses <<
|
||||||
|
slot <<
|
||||||
|
" := " <<
|
||||||
|
m_utils.mappingIndexAccessFunction(*mappingType, *mappingType->keyType()) <<
|
||||||
|
"(" <<
|
||||||
|
slot;
|
||||||
|
if (mappingType->keyType()->sizeOnStack() > 0)
|
||||||
|
indexAccesses <<
|
||||||
|
", " <<
|
||||||
|
suffixedVariableNameList("key", num_keys, num_keys + mappingType->keyType()->sizeOnStack());
|
||||||
|
indexAccesses << ")\n";
|
||||||
|
num_keys += mappingType->keyType()->sizeOnStack();
|
||||||
|
}
|
||||||
|
while ((mappingType = dynamic_cast<MappingType const*>(mappingType->valueType())));
|
||||||
|
|
||||||
|
return Whiskers(R"(
|
||||||
|
function <functionName>(<keys>) -> rval {
|
||||||
|
let <slot> := <base>
|
||||||
|
<indexAccesses>
|
||||||
|
rval := <readStorage>(<slot>)
|
||||||
|
}
|
||||||
|
)")
|
||||||
|
("functionName", functionName)
|
||||||
|
("keys", suffixedVariableNameList("key", 0, num_keys))
|
||||||
|
("readStorage", m_utils.readFromStorage(*returnType, 0, false))
|
||||||
|
("indexAccesses", indexAccesses.str())
|
||||||
|
("slot", slot)
|
||||||
|
("base", slot_offset.first.str())
|
||||||
|
.render();
|
||||||
|
});
|
||||||
|
else
|
||||||
|
{
|
||||||
solUnimplementedAssert(type->isValueType(), "");
|
solUnimplementedAssert(type->isValueType(), "");
|
||||||
|
|
||||||
return m_context.functionCollector()->createFunction(functionName, [&]() {
|
return m_context.functionCollector()->createFunction(functionName, [&]() {
|
||||||
@ -175,6 +223,7 @@ string IRGenerator::generateGetter(VariableDeclaration const& _varDecl)
|
|||||||
.render();
|
.render();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
string IRGenerator::constructorCode(ContractDefinition const& _contract)
|
string IRGenerator::constructorCode(ContractDefinition const& _contract)
|
||||||
{
|
{
|
||||||
|
@ -1019,16 +1019,22 @@ ASTPointer<Mapping> Parser::parseMapping()
|
|||||||
ASTNodeFactory nodeFactory(*this);
|
ASTNodeFactory nodeFactory(*this);
|
||||||
expectToken(Token::Mapping);
|
expectToken(Token::Mapping);
|
||||||
expectToken(Token::LParen);
|
expectToken(Token::LParen);
|
||||||
ASTPointer<ElementaryTypeName> keyType;
|
ASTPointer<TypeName> keyType;
|
||||||
Token token = m_scanner->currentToken();
|
Token token = m_scanner->currentToken();
|
||||||
if (!TokenTraits::isElementaryTypeName(token))
|
|
||||||
fatalParserError(string("Expected elementary type name for mapping key type"));
|
|
||||||
unsigned firstSize;
|
unsigned firstSize;
|
||||||
unsigned secondSize;
|
unsigned secondSize;
|
||||||
tie(firstSize, secondSize) = m_scanner->currentTokenInfo();
|
tie(firstSize, secondSize) = m_scanner->currentTokenInfo();
|
||||||
ElementaryTypeNameToken elemTypeName(token, firstSize, secondSize);
|
if (token == Token::Identifier)
|
||||||
keyType = ASTNodeFactory(*this).createNode<ElementaryTypeName>(elemTypeName);
|
keyType = parseUserDefinedTypeName();
|
||||||
|
else if (TokenTraits::isElementaryTypeName(token))
|
||||||
|
{
|
||||||
|
keyType = ASTNodeFactory(*this).createNode<ElementaryTypeName>(
|
||||||
|
ElementaryTypeNameToken{token, firstSize, secondSize}
|
||||||
|
);
|
||||||
m_scanner->next();
|
m_scanner->next();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fatalParserError(string("Expected elementary type name or identifier for mapping key type"));
|
||||||
expectToken(Token::Arrow);
|
expectToken(Token::Arrow);
|
||||||
bool const allowVar = false;
|
bool const allowVar = false;
|
||||||
ASTPointer<TypeName> valueType = parseTypeName(allowVar);
|
ASTPointer<TypeName> valueType = parseTypeName(allowVar);
|
||||||
|
227
test/libsolidity/ASTJSON/mappings.json
Normal file
227
test/libsolidity/ASTJSON/mappings.json
Normal file
@ -0,0 +1,227 @@
|
|||||||
|
{
|
||||||
|
"absolutePath": "a",
|
||||||
|
"exportedSymbols":
|
||||||
|
{
|
||||||
|
"C":
|
||||||
|
[
|
||||||
|
17
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"id": 18,
|
||||||
|
"nodeType": "SourceUnit",
|
||||||
|
"nodes":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"abstract": false,
|
||||||
|
"baseContracts": [],
|
||||||
|
"contractDependencies": [],
|
||||||
|
"contractKind": "contract",
|
||||||
|
"documentation": null,
|
||||||
|
"fullyImplemented": true,
|
||||||
|
"id": 17,
|
||||||
|
"linearizedBaseContracts":
|
||||||
|
[
|
||||||
|
17
|
||||||
|
],
|
||||||
|
"name": "C",
|
||||||
|
"nodeType": "ContractDefinition",
|
||||||
|
"nodes":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"canonicalName": "C.E",
|
||||||
|
"id": 4,
|
||||||
|
"members":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"name": "A",
|
||||||
|
"nodeType": "EnumValue",
|
||||||
|
"src": "26:1:1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"name": "B",
|
||||||
|
"nodeType": "EnumValue",
|
||||||
|
"src": "29:1:1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3,
|
||||||
|
"name": "C",
|
||||||
|
"nodeType": "EnumValue",
|
||||||
|
"src": "32:1:1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "E",
|
||||||
|
"nodeType": "EnumDefinition",
|
||||||
|
"src": "17:18:1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"id": 8,
|
||||||
|
"name": "a",
|
||||||
|
"nodeType": "VariableDeclaration",
|
||||||
|
"overrides": null,
|
||||||
|
"scope": 17,
|
||||||
|
"src": "40:20:1",
|
||||||
|
"stateVariable": true,
|
||||||
|
"storageLocation": "default",
|
||||||
|
"typeDescriptions":
|
||||||
|
{
|
||||||
|
"typeIdentifier": "t_mapping$_t_contract$_C_$17_$_t_bool_$",
|
||||||
|
"typeString": "mapping(contract C => bool)"
|
||||||
|
},
|
||||||
|
"typeName":
|
||||||
|
{
|
||||||
|
"id": 7,
|
||||||
|
"keyType":
|
||||||
|
{
|
||||||
|
"contractScope": null,
|
||||||
|
"id": 5,
|
||||||
|
"name": "C",
|
||||||
|
"nodeType": "UserDefinedTypeName",
|
||||||
|
"referencedDeclaration": 17,
|
||||||
|
"src": "48:1:1",
|
||||||
|
"typeDescriptions":
|
||||||
|
{
|
||||||
|
"typeIdentifier": "t_contract$_C_$17",
|
||||||
|
"typeString": "contract C"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nodeType": "Mapping",
|
||||||
|
"src": "40:18:1",
|
||||||
|
"typeDescriptions":
|
||||||
|
{
|
||||||
|
"typeIdentifier": "t_mapping$_t_contract$_C_$17_$_t_bool_$",
|
||||||
|
"typeString": "mapping(contract C => bool)"
|
||||||
|
},
|
||||||
|
"valueType":
|
||||||
|
{
|
||||||
|
"id": 6,
|
||||||
|
"name": "bool",
|
||||||
|
"nodeType": "ElementaryTypeName",
|
||||||
|
"src": "53:4:1",
|
||||||
|
"typeDescriptions":
|
||||||
|
{
|
||||||
|
"typeIdentifier": "t_bool",
|
||||||
|
"typeString": "bool"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"value": null,
|
||||||
|
"visibility": "internal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"id": 12,
|
||||||
|
"name": "b",
|
||||||
|
"nodeType": "VariableDeclaration",
|
||||||
|
"overrides": null,
|
||||||
|
"scope": 17,
|
||||||
|
"src": "66:26:1",
|
||||||
|
"stateVariable": true,
|
||||||
|
"storageLocation": "default",
|
||||||
|
"typeDescriptions":
|
||||||
|
{
|
||||||
|
"typeIdentifier": "t_mapping$_t_address_$_t_bool_$",
|
||||||
|
"typeString": "mapping(address => bool)"
|
||||||
|
},
|
||||||
|
"typeName":
|
||||||
|
{
|
||||||
|
"id": 11,
|
||||||
|
"keyType":
|
||||||
|
{
|
||||||
|
"id": 9,
|
||||||
|
"name": "address",
|
||||||
|
"nodeType": "ElementaryTypeName",
|
||||||
|
"src": "74:7:1",
|
||||||
|
"typeDescriptions":
|
||||||
|
{
|
||||||
|
"typeIdentifier": "t_address",
|
||||||
|
"typeString": "address"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nodeType": "Mapping",
|
||||||
|
"src": "66:24:1",
|
||||||
|
"typeDescriptions":
|
||||||
|
{
|
||||||
|
"typeIdentifier": "t_mapping$_t_address_$_t_bool_$",
|
||||||
|
"typeString": "mapping(address => bool)"
|
||||||
|
},
|
||||||
|
"valueType":
|
||||||
|
{
|
||||||
|
"id": 10,
|
||||||
|
"name": "bool",
|
||||||
|
"nodeType": "ElementaryTypeName",
|
||||||
|
"src": "85:4:1",
|
||||||
|
"typeDescriptions":
|
||||||
|
{
|
||||||
|
"typeIdentifier": "t_bool",
|
||||||
|
"typeString": "bool"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"value": null,
|
||||||
|
"visibility": "internal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"id": 16,
|
||||||
|
"name": "c",
|
||||||
|
"nodeType": "VariableDeclaration",
|
||||||
|
"overrides": null,
|
||||||
|
"scope": 17,
|
||||||
|
"src": "98:20:1",
|
||||||
|
"stateVariable": true,
|
||||||
|
"storageLocation": "default",
|
||||||
|
"typeDescriptions":
|
||||||
|
{
|
||||||
|
"typeIdentifier": "t_mapping$_t_enum$_E_$4_$_t_bool_$",
|
||||||
|
"typeString": "mapping(enum C.E => bool)"
|
||||||
|
},
|
||||||
|
"typeName":
|
||||||
|
{
|
||||||
|
"id": 15,
|
||||||
|
"keyType":
|
||||||
|
{
|
||||||
|
"contractScope": null,
|
||||||
|
"id": 13,
|
||||||
|
"name": "E",
|
||||||
|
"nodeType": "UserDefinedTypeName",
|
||||||
|
"referencedDeclaration": 4,
|
||||||
|
"src": "106:1:1",
|
||||||
|
"typeDescriptions":
|
||||||
|
{
|
||||||
|
"typeIdentifier": "t_enum$_E_$4",
|
||||||
|
"typeString": "enum C.E"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nodeType": "Mapping",
|
||||||
|
"src": "98:18:1",
|
||||||
|
"typeDescriptions":
|
||||||
|
{
|
||||||
|
"typeIdentifier": "t_mapping$_t_enum$_E_$4_$_t_bool_$",
|
||||||
|
"typeString": "mapping(enum C.E => bool)"
|
||||||
|
},
|
||||||
|
"valueType":
|
||||||
|
{
|
||||||
|
"id": 14,
|
||||||
|
"name": "bool",
|
||||||
|
"nodeType": "ElementaryTypeName",
|
||||||
|
"src": "111:4:1",
|
||||||
|
"typeDescriptions":
|
||||||
|
{
|
||||||
|
"typeIdentifier": "t_bool",
|
||||||
|
"typeString": "bool"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"value": null,
|
||||||
|
"visibility": "internal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"scope": 18,
|
||||||
|
"src": "0:121:1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"src": "0:122:1"
|
||||||
|
}
|
8
test/libsolidity/ASTJSON/mappings.sol
Normal file
8
test/libsolidity/ASTJSON/mappings.sol
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
contract C {
|
||||||
|
enum E { A, B, C }
|
||||||
|
mapping(C => bool) a;
|
||||||
|
mapping(address => bool) b;
|
||||||
|
mapping(E => bool) c;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----
|
248
test/libsolidity/ASTJSON/mappings_legacy.json
Normal file
248
test/libsolidity/ASTJSON/mappings_legacy.json
Normal file
@ -0,0 +1,248 @@
|
|||||||
|
{
|
||||||
|
"attributes":
|
||||||
|
{
|
||||||
|
"absolutePath": "a",
|
||||||
|
"exportedSymbols":
|
||||||
|
{
|
||||||
|
"C":
|
||||||
|
[
|
||||||
|
17
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"children":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"attributes":
|
||||||
|
{
|
||||||
|
"abstract": false,
|
||||||
|
"baseContracts":
|
||||||
|
[
|
||||||
|
null
|
||||||
|
],
|
||||||
|
"contractDependencies":
|
||||||
|
[
|
||||||
|
null
|
||||||
|
],
|
||||||
|
"contractKind": "contract",
|
||||||
|
"documentation": null,
|
||||||
|
"fullyImplemented": true,
|
||||||
|
"linearizedBaseContracts":
|
||||||
|
[
|
||||||
|
17
|
||||||
|
],
|
||||||
|
"name": "C",
|
||||||
|
"scope": 18
|
||||||
|
},
|
||||||
|
"children":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"attributes":
|
||||||
|
{
|
||||||
|
"canonicalName": "C.E",
|
||||||
|
"name": "E"
|
||||||
|
},
|
||||||
|
"children":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"attributes":
|
||||||
|
{
|
||||||
|
"name": "A"
|
||||||
|
},
|
||||||
|
"id": 1,
|
||||||
|
"name": "EnumValue",
|
||||||
|
"src": "26:1:1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attributes":
|
||||||
|
{
|
||||||
|
"name": "B"
|
||||||
|
},
|
||||||
|
"id": 2,
|
||||||
|
"name": "EnumValue",
|
||||||
|
"src": "29:1:1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attributes":
|
||||||
|
{
|
||||||
|
"name": "C"
|
||||||
|
},
|
||||||
|
"id": 3,
|
||||||
|
"name": "EnumValue",
|
||||||
|
"src": "32:1:1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"id": 4,
|
||||||
|
"name": "EnumDefinition",
|
||||||
|
"src": "17:18:1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attributes":
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"name": "a",
|
||||||
|
"overrides": null,
|
||||||
|
"scope": 17,
|
||||||
|
"stateVariable": true,
|
||||||
|
"storageLocation": "default",
|
||||||
|
"type": "mapping(contract C => bool)",
|
||||||
|
"value": null,
|
||||||
|
"visibility": "internal"
|
||||||
|
},
|
||||||
|
"children":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"attributes":
|
||||||
|
{
|
||||||
|
"type": "mapping(contract C => bool)"
|
||||||
|
},
|
||||||
|
"children":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"attributes":
|
||||||
|
{
|
||||||
|
"contractScope": null,
|
||||||
|
"name": "C",
|
||||||
|
"referencedDeclaration": 17,
|
||||||
|
"type": "contract C"
|
||||||
|
},
|
||||||
|
"id": 5,
|
||||||
|
"name": "UserDefinedTypeName",
|
||||||
|
"src": "48:1:1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attributes":
|
||||||
|
{
|
||||||
|
"name": "bool",
|
||||||
|
"type": "bool"
|
||||||
|
},
|
||||||
|
"id": 6,
|
||||||
|
"name": "ElementaryTypeName",
|
||||||
|
"src": "53:4:1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"id": 7,
|
||||||
|
"name": "Mapping",
|
||||||
|
"src": "40:18:1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"id": 8,
|
||||||
|
"name": "VariableDeclaration",
|
||||||
|
"src": "40:20:1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attributes":
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"name": "b",
|
||||||
|
"overrides": null,
|
||||||
|
"scope": 17,
|
||||||
|
"stateVariable": true,
|
||||||
|
"storageLocation": "default",
|
||||||
|
"type": "mapping(address => bool)",
|
||||||
|
"value": null,
|
||||||
|
"visibility": "internal"
|
||||||
|
},
|
||||||
|
"children":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"attributes":
|
||||||
|
{
|
||||||
|
"type": "mapping(address => bool)"
|
||||||
|
},
|
||||||
|
"children":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"attributes":
|
||||||
|
{
|
||||||
|
"name": "address",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
"id": 9,
|
||||||
|
"name": "ElementaryTypeName",
|
||||||
|
"src": "74:7:1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attributes":
|
||||||
|
{
|
||||||
|
"name": "bool",
|
||||||
|
"type": "bool"
|
||||||
|
},
|
||||||
|
"id": 10,
|
||||||
|
"name": "ElementaryTypeName",
|
||||||
|
"src": "85:4:1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"id": 11,
|
||||||
|
"name": "Mapping",
|
||||||
|
"src": "66:24:1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"id": 12,
|
||||||
|
"name": "VariableDeclaration",
|
||||||
|
"src": "66:26:1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attributes":
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"name": "c",
|
||||||
|
"overrides": null,
|
||||||
|
"scope": 17,
|
||||||
|
"stateVariable": true,
|
||||||
|
"storageLocation": "default",
|
||||||
|
"type": "mapping(enum C.E => bool)",
|
||||||
|
"value": null,
|
||||||
|
"visibility": "internal"
|
||||||
|
},
|
||||||
|
"children":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"attributes":
|
||||||
|
{
|
||||||
|
"type": "mapping(enum C.E => bool)"
|
||||||
|
},
|
||||||
|
"children":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"attributes":
|
||||||
|
{
|
||||||
|
"contractScope": null,
|
||||||
|
"name": "E",
|
||||||
|
"referencedDeclaration": 4,
|
||||||
|
"type": "enum C.E"
|
||||||
|
},
|
||||||
|
"id": 13,
|
||||||
|
"name": "UserDefinedTypeName",
|
||||||
|
"src": "106:1:1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attributes":
|
||||||
|
{
|
||||||
|
"name": "bool",
|
||||||
|
"type": "bool"
|
||||||
|
},
|
||||||
|
"id": 14,
|
||||||
|
"name": "ElementaryTypeName",
|
||||||
|
"src": "111:4:1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"id": 15,
|
||||||
|
"name": "Mapping",
|
||||||
|
"src": "98:18:1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"id": 16,
|
||||||
|
"name": "VariableDeclaration",
|
||||||
|
"src": "98:20:1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"id": 17,
|
||||||
|
"name": "ContractDefinition",
|
||||||
|
"src": "0:121:1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"id": 18,
|
||||||
|
"name": "SourceUnit",
|
||||||
|
"src": "0:122:1"
|
||||||
|
}
|
@ -61,10 +61,26 @@ SemanticTest::SemanticTest(string const& _filename, langutil::EVMVersion _evmVer
|
|||||||
}
|
}
|
||||||
m_settings.erase("compileViaYul");
|
m_settings.erase("compileViaYul");
|
||||||
}
|
}
|
||||||
|
if (m_settings.count("ABIEncoderV1Only"))
|
||||||
|
{
|
||||||
|
if (m_settings["ABIEncoderV1Only"] == "true")
|
||||||
|
{
|
||||||
|
m_validatedSettings["ABIEncoderV1Only"] = "true";
|
||||||
|
m_runWithABIEncoderV1Only = true;
|
||||||
|
}
|
||||||
|
m_settings.erase("ABIEncoderV1Only");
|
||||||
|
}
|
||||||
parseExpectations(file);
|
parseExpectations(file);
|
||||||
soltestAssert(!m_tests.empty(), "No tests specified in " + _filename);
|
soltestAssert(!m_tests.empty(), "No tests specified in " + _filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SemanticTest::validateSettings(langutil::EVMVersion _evmVersion)
|
||||||
|
{
|
||||||
|
if (m_runWithABIEncoderV1Only && solidity::test::CommonOptions::get().useABIEncoderV2)
|
||||||
|
return false;
|
||||||
|
return EVMVersionRestrictedTestCase::validateSettings(_evmVersion);
|
||||||
|
}
|
||||||
|
|
||||||
TestCase::TestResult SemanticTest::run(ostream& _stream, string const& _linePrefix, bool _formatted)
|
TestCase::TestResult SemanticTest::run(ostream& _stream, string const& _linePrefix, bool _formatted)
|
||||||
{
|
{
|
||||||
for(bool compileViaYul: set<bool>{!m_runWithoutYul, m_runWithYul})
|
for(bool compileViaYul: set<bool>{!m_runWithoutYul, m_runWithYul})
|
||||||
|
@ -44,6 +44,8 @@ public:
|
|||||||
|
|
||||||
explicit SemanticTest(std::string const& _filename, langutil::EVMVersion _evmVersion);
|
explicit SemanticTest(std::string const& _filename, langutil::EVMVersion _evmVersion);
|
||||||
|
|
||||||
|
bool validateSettings(langutil::EVMVersion _evmVersion) override;
|
||||||
|
|
||||||
TestResult run(std::ostream& _stream, std::string const& _linePrefix = "", bool _formatted = false) override;
|
TestResult run(std::ostream& _stream, std::string const& _linePrefix = "", bool _formatted = false) override;
|
||||||
void printSource(std::ostream &_stream, std::string const& _linePrefix = "", bool _formatted = false) const override;
|
void printSource(std::ostream &_stream, std::string const& _linePrefix = "", bool _formatted = false) const override;
|
||||||
void printUpdatedExpectations(std::ostream& _stream, std::string const& _linePrefix = "") const override;
|
void printUpdatedExpectations(std::ostream& _stream, std::string const& _linePrefix = "") const override;
|
||||||
@ -64,6 +66,7 @@ private:
|
|||||||
std::vector<TestFunctionCall> m_tests;
|
std::vector<TestFunctionCall> m_tests;
|
||||||
bool m_runWithYul = false;
|
bool m_runWithYul = false;
|
||||||
bool m_runWithoutYul = true;
|
bool m_runWithoutYul = true;
|
||||||
|
bool m_runWithABIEncoderV1Only = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
interface A {}
|
||||||
|
contract test {
|
||||||
|
mapping(A => uint8) table;
|
||||||
|
function get(A k) public returns (uint8 v) {
|
||||||
|
return table[k];
|
||||||
|
}
|
||||||
|
function set(A k, uint8 v) public {
|
||||||
|
table[k] = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// compileViaYul: also
|
||||||
|
// ----
|
||||||
|
// get(address): 0 -> 0
|
||||||
|
// get(address): 0x01 -> 0
|
||||||
|
// get(address): 0xa7 -> 0
|
||||||
|
// set(address,uint8): 0x01, 0xa1 ->
|
||||||
|
// get(address): 0 -> 0
|
||||||
|
// get(address): 0x01 -> 0xa1
|
||||||
|
// get(address): 0xa7 -> 0
|
||||||
|
// set(address,uint8): 0x00, 0xef ->
|
||||||
|
// get(address): 0 -> 0xef
|
||||||
|
// get(address): 0x01 -> 0xa1
|
||||||
|
// get(address): 0xa7 -> 0
|
||||||
|
// set(address,uint8): 0x01, 0x05 ->
|
||||||
|
// get(address): 0 -> 0xef
|
||||||
|
// get(address): 0x01 -> 0x05
|
||||||
|
// get(address): 0xa7 -> 0
|
@ -0,0 +1,38 @@
|
|||||||
|
interface A {}
|
||||||
|
contract test {
|
||||||
|
mapping(A => uint8) public table;
|
||||||
|
function set(A k, uint8 v) public {
|
||||||
|
table[k] = v;
|
||||||
|
}
|
||||||
|
function get(A k) public returns (uint8) {
|
||||||
|
return this.table(k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// table(address): 0 -> 0
|
||||||
|
// table(address): 0x01 -> 0
|
||||||
|
// table(address): 0xa7 -> 0
|
||||||
|
// get(address): 0 -> 0
|
||||||
|
// get(address): 0x01 -> 0
|
||||||
|
// get(address): 0xa7 -> 0
|
||||||
|
// set(address,uint8): 0x01, 0xa1 ->
|
||||||
|
// table(address): 0 -> 0
|
||||||
|
// table(address): 0x01 -> 0xa1
|
||||||
|
// table(address): 0xa7 -> 0
|
||||||
|
// get(address): 0 -> 0
|
||||||
|
// get(address): 0x01 -> 0xa1
|
||||||
|
// get(address): 0xa7 -> 0
|
||||||
|
// set(address,uint8): 0x00, 0xef ->
|
||||||
|
// table(address): 0 -> 0xef
|
||||||
|
// table(address): 0x01 -> 0xa1
|
||||||
|
// table(address): 0xa7 -> 0
|
||||||
|
// get(address): 0 -> 0xef
|
||||||
|
// get(address): 0x01 -> 0xa1
|
||||||
|
// get(address): 0xa7 -> 0
|
||||||
|
// set(address,uint8): 0x01, 0x05 ->
|
||||||
|
// table(address): 0 -> 0xef
|
||||||
|
// table(address): 0x01 -> 0x05
|
||||||
|
// table(address): 0xa7 -> 0
|
||||||
|
// get(address): 0 -> 0xef
|
||||||
|
// get(address): 0x01 -> 0x05
|
||||||
|
// get(address): 0xa7 -> 0
|
@ -0,0 +1,35 @@
|
|||||||
|
interface A {}
|
||||||
|
library L {
|
||||||
|
function get(mapping(A => uint8) storage table, A k) external returns (uint8) {
|
||||||
|
return table[k];
|
||||||
|
}
|
||||||
|
function set(mapping(A => uint8) storage table, A k, uint8 v) external {
|
||||||
|
table[k] = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
contract test {
|
||||||
|
mapping(A => uint8) table;
|
||||||
|
function get(A k) public returns (uint8 v) {
|
||||||
|
return L.get(table, k);
|
||||||
|
}
|
||||||
|
function set(A k, uint8 v) public {
|
||||||
|
L.set(table, k, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// library: L
|
||||||
|
// get(address): 0 -> 0
|
||||||
|
// get(address): 0x01 -> 0
|
||||||
|
// get(address): 0xa7 -> 0
|
||||||
|
// set(address,uint8): 0x01, 0xa1 ->
|
||||||
|
// get(address): 0 -> 0
|
||||||
|
// get(address): 0x01 -> 0xa1
|
||||||
|
// get(address): 0xa7 -> 0
|
||||||
|
// set(address,uint8): 0x00, 0xef ->
|
||||||
|
// get(address): 0 -> 0xef
|
||||||
|
// get(address): 0x01 -> 0xa1
|
||||||
|
// get(address): 0xa7 -> 0
|
||||||
|
// set(address,uint8): 0x01, 0x05 ->
|
||||||
|
// get(address): 0 -> 0xef
|
||||||
|
// get(address): 0x01 -> 0x05
|
||||||
|
// get(address): 0xa7 -> 0
|
30
test/libsolidity/semanticTests/types/mapping_enum_key.sol
Normal file
30
test/libsolidity/semanticTests/types/mapping_enum_key.sol
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
enum E { A, B, C }
|
||||||
|
contract test {
|
||||||
|
mapping(E => uint8) table;
|
||||||
|
function get(E k) public returns (uint8 v) {
|
||||||
|
return table[k];
|
||||||
|
}
|
||||||
|
function set(E k, uint8 v) public {
|
||||||
|
table[k] = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// compileViaYul: also
|
||||||
|
// ----
|
||||||
|
// get(uint8): 0 -> 0
|
||||||
|
// get(uint8): 0x01 -> 0
|
||||||
|
// get(uint8): 0x02 -> 0
|
||||||
|
// get(uint8): 0x03 -> FAILURE
|
||||||
|
// get(uint8): 0xa7 -> FAILURE
|
||||||
|
// set(uint8,uint8): 0x01, 0xa1 ->
|
||||||
|
// get(uint8): 0 -> 0
|
||||||
|
// get(uint8): 0x01 -> 0xa1
|
||||||
|
// get(uint8): 0xa7 -> FAILURE
|
||||||
|
// set(uint8,uint8): 0x00, 0xef ->
|
||||||
|
// get(uint8): 0 -> 0xef
|
||||||
|
// get(uint8): 0x01 -> 0xa1
|
||||||
|
// get(uint8): 0xa7 -> FAILURE
|
||||||
|
// set(uint8,uint8): 0x01, 0x05 ->
|
||||||
|
// get(uint8): 0 -> 0xef
|
||||||
|
// get(uint8): 0x01 -> 0x05
|
||||||
|
// get(uint8): 0xa7 -> FAILURE
|
@ -0,0 +1,40 @@
|
|||||||
|
contract test {
|
||||||
|
enum E { A, B, C }
|
||||||
|
mapping(E => uint8) public table;
|
||||||
|
function set(E k, uint8 v) public {
|
||||||
|
table[k] = v;
|
||||||
|
}
|
||||||
|
function get(E k) public returns (uint8) {
|
||||||
|
return this.table(k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// ABIEncoderV1Only: true
|
||||||
|
// ----
|
||||||
|
// table(uint8): 0 -> 0
|
||||||
|
// table(uint8): 0x01 -> 0
|
||||||
|
// table(uint8): 0xa7 -> 0
|
||||||
|
// get(uint8): 0 -> 0
|
||||||
|
// get(uint8): 0x01 -> 0
|
||||||
|
// get(uint8): 0xa7 -> FAILURE
|
||||||
|
// set(uint8,uint8): 0x01, 0xa1 ->
|
||||||
|
// table(uint8): 0 -> 0
|
||||||
|
// table(uint8): 0x01 -> 0xa1
|
||||||
|
// table(uint8): 0xa7 -> 0
|
||||||
|
// get(uint8): 0 -> 0
|
||||||
|
// get(uint8): 0x01 -> 0xa1
|
||||||
|
// get(uint8): 0xa7 -> FAILURE
|
||||||
|
// set(uint8,uint8): 0x00, 0xef ->
|
||||||
|
// table(uint8): 0 -> 0xef
|
||||||
|
// table(uint8): 0x01 -> 0xa1
|
||||||
|
// table(uint8): 0xa7 -> 0
|
||||||
|
// get(uint8): 0 -> 0xef
|
||||||
|
// get(uint8): 0x01 -> 0xa1
|
||||||
|
// get(uint8): 0xa7 -> FAILURE
|
||||||
|
// set(uint8,uint8): 0x01, 0x05 ->
|
||||||
|
// table(uint8): 0 -> 0xef
|
||||||
|
// table(uint8): 0x01 -> 0x05
|
||||||
|
// table(uint8): 0xa7 -> 0
|
||||||
|
// get(uint8): 0 -> 0xef
|
||||||
|
// get(uint8): 0x01 -> 0x05
|
||||||
|
// get(uint8): 0xa7 -> FAILURE
|
@ -0,0 +1,39 @@
|
|||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
contract test {
|
||||||
|
enum E { A, B, C }
|
||||||
|
mapping(E => uint8) public table;
|
||||||
|
function set(E k, uint8 v) public {
|
||||||
|
table[k] = v;
|
||||||
|
}
|
||||||
|
function get(E k) public returns (uint8) {
|
||||||
|
return this.table(k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// table(uint8): 0 -> 0
|
||||||
|
// table(uint8): 0x01 -> 0
|
||||||
|
// table(uint8): 0xa7 -> FAILURE
|
||||||
|
// get(uint8): 0 -> 0
|
||||||
|
// get(uint8): 0x01 -> 0
|
||||||
|
// get(uint8): 0xa7 -> FAILURE
|
||||||
|
// set(uint8,uint8): 0x01, 0xa1 ->
|
||||||
|
// table(uint8): 0 -> 0
|
||||||
|
// table(uint8): 0x01 -> 0xa1
|
||||||
|
// table(uint8): 0xa7 -> FAILURE
|
||||||
|
// get(uint8): 0 -> 0
|
||||||
|
// get(uint8): 0x01 -> 0xa1
|
||||||
|
// get(uint8): 0xa7 -> FAILURE
|
||||||
|
// set(uint8,uint8): 0x00, 0xef ->
|
||||||
|
// table(uint8): 0 -> 0xef
|
||||||
|
// table(uint8): 0x01 -> 0xa1
|
||||||
|
// table(uint8): 0xa7 -> FAILURE
|
||||||
|
// get(uint8): 0 -> 0xef
|
||||||
|
// get(uint8): 0x01 -> 0xa1
|
||||||
|
// get(uint8): 0xa7 -> FAILURE
|
||||||
|
// set(uint8,uint8): 0x01, 0x05 ->
|
||||||
|
// table(uint8): 0 -> 0xef
|
||||||
|
// table(uint8): 0x01 -> 0x05
|
||||||
|
// table(uint8): 0xa7 -> FAILURE
|
||||||
|
// get(uint8): 0 -> 0xef
|
||||||
|
// get(uint8): 0x01 -> 0x05
|
||||||
|
// get(uint8): 0xa7 -> FAILURE
|
@ -0,0 +1,35 @@
|
|||||||
|
enum E { A, B, C }
|
||||||
|
library L {
|
||||||
|
function get(mapping(E => uint8) storage table, E k) external returns (uint8) {
|
||||||
|
return table[k];
|
||||||
|
}
|
||||||
|
function set(mapping(E => uint8) storage table, E k, uint8 v) external {
|
||||||
|
table[k] = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
contract test {
|
||||||
|
mapping(E => uint8) table;
|
||||||
|
function get(E k) public returns (uint8 v) {
|
||||||
|
return L.get(table, k);
|
||||||
|
}
|
||||||
|
function set(E k, uint8 v) public {
|
||||||
|
L.set(table, k, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// library: L
|
||||||
|
// get(uint8): 0 -> 0
|
||||||
|
// get(uint8): 0x01 -> 0
|
||||||
|
// get(uint8): 0xa7 -> FAILURE
|
||||||
|
// set(uint8,uint8): 0x01, 0xa1 ->
|
||||||
|
// get(uint8): 0 -> 0
|
||||||
|
// get(uint8): 0x01 -> 0xa1
|
||||||
|
// get(uint8): 0xa7 -> FAILURE
|
||||||
|
// set(uint8,uint8): 0x00, 0xef ->
|
||||||
|
// get(uint8): 0 -> 0xef
|
||||||
|
// get(uint8): 0x01 -> 0xa1
|
||||||
|
// get(uint8): 0xa7 -> FAILURE
|
||||||
|
// set(uint8,uint8): 0x01, 0x05 ->
|
||||||
|
// get(uint8): 0 -> 0xef
|
||||||
|
// get(uint8): 0x01 -> 0x05
|
||||||
|
// get(uint8): 0xa7 -> FAILURE
|
@ -0,0 +1,26 @@
|
|||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
contract test {
|
||||||
|
enum E { A, B, C }
|
||||||
|
mapping(E => uint8) public table;
|
||||||
|
function set(E k, uint8 v) public {
|
||||||
|
table[k] = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// compileViaYul: also
|
||||||
|
// ----
|
||||||
|
// table(uint8): 0 -> 0
|
||||||
|
// table(uint8): 0x01 -> 0
|
||||||
|
// table(uint8): 0xa7 -> FAILURE
|
||||||
|
// set(uint8,uint8): 0x01, 0xa1 ->
|
||||||
|
// table(uint8): 0 -> 0
|
||||||
|
// table(uint8): 0x01 -> 0xa1
|
||||||
|
// table(uint8): 0xa7 -> FAILURE
|
||||||
|
// set(uint8,uint8): 0x00, 0xef ->
|
||||||
|
// table(uint8): 0 -> 0xef
|
||||||
|
// table(uint8): 0x01 -> 0xa1
|
||||||
|
// table(uint8): 0xa7 -> FAILURE
|
||||||
|
// set(uint8,uint8): 0x01, 0x05 ->
|
||||||
|
// table(uint8): 0 -> 0xef
|
||||||
|
// table(uint8): 0x01 -> 0x05
|
||||||
|
// table(uint8): 0xa7 -> FAILURE
|
40
test/libsolidity/semanticTests/viaYul/mapping_getters.sol
Normal file
40
test/libsolidity/semanticTests/viaYul/mapping_getters.sol
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
contract test {
|
||||||
|
mapping(uint256 => uint256) public m1;
|
||||||
|
mapping(uint256 => mapping(uint256 => uint256)) public m2;
|
||||||
|
function set(uint256 k, uint256 v) public {
|
||||||
|
m1[k] = v;
|
||||||
|
}
|
||||||
|
function set(uint256 k1, uint256 k2, uint256 v) public {
|
||||||
|
m2[k1][k2] = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// compileViaYul: also
|
||||||
|
// ----
|
||||||
|
// m1(uint256): 0 -> 0
|
||||||
|
// m1(uint256): 0x01 -> 0
|
||||||
|
// m1(uint256): 0xa7 -> 0
|
||||||
|
// set(uint256,uint256): 0x01, 0xa1 ->
|
||||||
|
// m1(uint256): 0 -> 0
|
||||||
|
// m1(uint256): 0x01 -> 0xa1
|
||||||
|
// m1(uint256): 0xa7 -> 0
|
||||||
|
// set(uint256,uint256): 0x00, 0xef ->
|
||||||
|
// m1(uint256): 0 -> 0xef
|
||||||
|
// m1(uint256): 0x01 -> 0xa1
|
||||||
|
// m1(uint256): 0xa7 -> 0
|
||||||
|
// set(uint256,uint256): 0x01, 0x05 ->
|
||||||
|
// m1(uint256): 0 -> 0xef
|
||||||
|
// m1(uint256): 0x01 -> 0x05
|
||||||
|
// m1(uint256): 0xa7 -> 0
|
||||||
|
// m2(uint256,uint256): 0, 0 -> 0
|
||||||
|
// m2(uint256,uint256): 0, 0x01 -> 0
|
||||||
|
// m2(uint256,uint256): 0xa7, 0 -> 0
|
||||||
|
// m2(uint256,uint256): 0xa7, 0x01 -> 0
|
||||||
|
// set(uint256,uint256,uint256): 0xa7, 0x01, 0x23
|
||||||
|
// m2(uint256,uint256): 0, 0x01 -> 0
|
||||||
|
// m2(uint256,uint256): 0xa7, 0 -> 0
|
||||||
|
// m2(uint256,uint256): 0xa7, 0x01 -> 0x23
|
||||||
|
// set(uint256,uint256,uint256): 0, 0x01, 0xef
|
||||||
|
// m2(uint256,uint256): 0, 0x01 -> 0xef
|
||||||
|
// m2(uint256,uint256): 0xa7, 0 -> 0
|
||||||
|
// m2(uint256,uint256): 0xa7, 0x01 -> 0x23
|
@ -0,0 +1,9 @@
|
|||||||
|
interface I {}
|
||||||
|
contract J {}
|
||||||
|
contract C {
|
||||||
|
mapping(I => bool) i;
|
||||||
|
mapping(J => bool) j;
|
||||||
|
function f(I x, J y) public view returns (bool, bool) {
|
||||||
|
return (i[x], j[y]);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
interface I {}
|
||||||
|
contract J {}
|
||||||
|
contract C {
|
||||||
|
mapping(I => bool) i;
|
||||||
|
mapping(J => bool) j;
|
||||||
|
function f(I x, J y, address z) public view returns (bool, bool, bool) {
|
||||||
|
return (i[y], j[x], i[z]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// TypeError: (189-190): Type contract J is not implicitly convertible to expected type contract I.
|
||||||
|
// TypeError: (195-196): Type contract I is not implicitly convertible to expected type contract J.
|
||||||
|
// TypeError: (201-202): Type address is not implicitly convertible to expected type contract I.
|
7
test/libsolidity/syntaxTests/mappings/enum_mapping.sol
Normal file
7
test/libsolidity/syntaxTests/mappings/enum_mapping.sol
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
enum E { A, B, C }
|
||||||
|
contract C {
|
||||||
|
mapping(E => bool) e;
|
||||||
|
function f(E v) public view returns (bool, bool) {
|
||||||
|
return (e[v], e[E.A]);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
enum E { A, B, C }
|
||||||
|
contract C {
|
||||||
|
mapping(E => bool) e;
|
||||||
|
function f(uint256 a, uint8 b) public view returns (bool, bool) {
|
||||||
|
return (e[a], e[b]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// TypeError: (146-147): Type uint256 is not implicitly convertible to expected type enum E.
|
||||||
|
// TypeError: (152-153): Type uint8 is not implicitly convertible to expected type enum E.
|
@ -5,4 +5,4 @@ contract c {
|
|||||||
mapping(S => uint) data;
|
mapping(S => uint) data;
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// ParserError: (47-48): Expected elementary type name for mapping key type
|
// TypeError: (47-48): Only elementary types, contract types or enums are allowed as mapping keys.
|
||||||
|
@ -5,4 +5,4 @@ contract c {
|
|||||||
mapping(S => uint) data;
|
mapping(S => uint) data;
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// ParserError: (49-50): Expected elementary type name for mapping key type
|
// TypeError: (49-50): Only elementary types, contract types or enums are allowed as mapping keys.
|
||||||
|
@ -4,4 +4,4 @@ contract test {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// ParserError: (44-47): Expected elementary type name for mapping key type
|
// ParserError: (44-47): Expected elementary type name or identifier for mapping key type
|
||||||
|
Loading…
Reference in New Issue
Block a user