Merge pull request #12836 from ethereum/fixUsingGlobal

Fix using global with libraries.
This commit is contained in:
chriseth 2022-05-02 12:41:34 +02:00 committed by GitHub
commit df29ea72f0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 122 additions and 24 deletions

View File

@ -11,6 +11,7 @@ Compiler Features:
Bugfixes:
* Type Checker: Properly check restrictions of ``using ... global`` in conjunction with libraries.
* Assembly-Json: Fix assembly json export to store jump types of operations in `jumpType` field instead of `value`.
* TypeChecker: Convert parameters of function type to how they would be called for ``abi.encodeCall``.
* View Pure Checker: Mark ``returndatasize`` and ``returndatacopy`` as view to disallow them in inline assembly blocks in pure functions.

View File

@ -3638,11 +3638,36 @@ void TypeChecker::endVisit(Literal const& _literal)
void TypeChecker::endVisit(UsingForDirective const& _usingFor)
{
if (_usingFor.global())
{
if (m_currentContract || !_usingFor.typeName())
{
solAssert(m_errorReporter.hasErrors());
return;
}
solAssert(_usingFor.typeName()->annotation().type);
if (Declaration const* typeDefinition = _usingFor.typeName()->annotation().type->typeDefinition())
{
if (typeDefinition->scope() != m_currentSourceUnit)
m_errorReporter.typeError(
4117_error,
_usingFor.location(),
"Can only use \"global\" with types defined in the same source unit at file level."
);
}
else
m_errorReporter.typeError(
8841_error,
_usingFor.location(),
"Can only use \"global\" with user-defined types."
);
}
if (!_usingFor.usesBraces())
{
solAssert(_usingFor.functionsOrLibrary().size() == 1);
ContractDefinition const* library = dynamic_cast<ContractDefinition const*>(
_usingFor.functionsOrLibrary().front()->annotation().referencedDeclaration
_usingFor.functionsOrLibrary().front()->annotation().referencedDeclaration
);
solAssert(library && library->isLibrary());
// No type checking for libraries
@ -3662,28 +3687,6 @@ void TypeChecker::endVisit(UsingForDirective const& _usingFor)
);
solAssert(normalizedType);
if (_usingFor.global())
{
if (m_currentContract)
solAssert(m_errorReporter.hasErrors());
if (Declaration const* typeDefinition = _usingFor.typeName()->annotation().type->typeDefinition())
{
if (typeDefinition->scope() != m_currentSourceUnit)
m_errorReporter.typeError(
4117_error,
_usingFor.location(),
"Can only use \"global\" with types defined in the same source unit at file level."
);
}
else
m_errorReporter.typeError(
8841_error,
_usingFor.location(),
"Can only use \"global\" with user-defined types."
);
}
for (ASTPointer<IdentifierPath> const& path: _usingFor.functionsOrLibrary())
{
solAssert(path->annotation().referencedDeclaration);

View File

@ -0,0 +1,18 @@
using L for I;
interface I { function f() external pure returns (uint); }
library L {
function execute(I i) internal pure returns (uint) {
return i.f();
}
}
contract C is I {
function x() public view returns (uint) {
I i = this;
return i.execute();
}
function f() public pure returns (uint) { return 7; }
}
// ====
// compileViaYul: also
// ----
// x() -> 7

View File

@ -0,0 +1,38 @@
==== Source: A ====
enum E {A, B}
struct S { uint x; }
type T is uint;
using L for E global;
using L for S global;
using L for T global;
library L {
function f(E e) internal pure returns (uint) {
return uint(e);
}
function f(S memory s) internal pure returns (uint) {
return s.x;
}
function f(T t) internal pure returns (uint) {
return T.unwrap(t);
}
}
==== Source: B ====
contract C {
function f() public pure returns (uint a, uint b, uint c) {
E e = E.B;
a = e.f();
S memory s;
s.x = 7;
b = s.f();
T t = T.wrap(9);
c = t.f();
}
}
import {E, S, T} from "A";
// ====
// compileViaYul: also
// ----
// f() -> 1, 7, 9

View File

@ -4,4 +4,3 @@ contract C {
function f(uint) pure{}
// ----
// SyntaxError 3367: (17-43): "global" can only be used at file level.
// TypeError 8841: (17-43): Can only use "global" with user-defined types.

View File

@ -0,0 +1,9 @@
using L for uint global;
using L for uint[] global;
using L for function() returns (uint) global;
library L {
}
// ----
// TypeError 8841: (0-24): Can only use "global" with user-defined types.
// TypeError 8841: (25-51): Can only use "global" with user-defined types.
// TypeError 8841: (52-97): Can only use "global" with user-defined types.

View File

@ -0,0 +1,6 @@
using L for L.S global;
library L {
struct S { uint x; }
}
// ----
// TypeError 4117: (0-23): Can only use "global" with types defined in the same source unit at file level.

View File

@ -0,0 +1,6 @@
interface I {}
using L for I global;
library L {
}
// ----
// TypeError 8841: (15-36): Can only use "global" with user-defined types.

View File

@ -0,0 +1,8 @@
==== Source: A ====
struct S { uint x; }
==== Source: B ====
library L {}
using L for S global;
import {S} from "A";
// ----
// TypeError 4117: (B:13-34): Can only use "global" with types defined in the same source unit at file level.

View File

@ -0,0 +1,5 @@
using L for * global;
library L {}
// ----
// SyntaxError 8118: (0-21): The type has to be specified explicitly at file level (cannot use '*').
// SyntaxError 2854: (0-21): Can only globally bind functions to specific types.

View File

@ -0,0 +1,5 @@
using {f} for * global;
function f(uint) pure{}
// ----
// SyntaxError 8118: (0-23): The type has to be specified explicitly at file level (cannot use '*').
// SyntaxError 2854: (0-23): Can only globally bind functions to specific types.