From 55b344f8e4fcec9fc6949fb7a44b4936e34ae8f3 Mon Sep 17 00:00:00 2001 From: genisis0x Date: Thu, 14 May 2026 12:47:07 +0530 Subject: [PATCH] TypeChecker: skip external free functions in `using for` resolution When a free function declared `external` is referenced from a `using for` directive, SyntaxChecker emits error 4126 ("Free functions cannot have visibility.") but the error is not fatal, so type checking continues into endVisit(UsingForDirective). The resolution there calls `FunctionDefinition::type()` for the non-library branch, which asserts `visibility() != External` and triggers an ICE. Skip such entries explicitly under `solAssert(hasErrors())`. The user still receives the visibility error from the function definition itself, and the directive no longer reaches the assertion. Fixes #16620 --- libsolidity/analysis/TypeChecker.cpp | 14 ++++++++++++++ .../syntaxTests/using/external_free_function.sol | 7 +++++++ 2 files changed, 21 insertions(+) create mode 100644 test/libsolidity/syntaxTests/using/external_free_function.sol diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 25bd4a915197..89395aeb73ef 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -4052,6 +4052,20 @@ void TypeChecker::endVisit(UsingForDirective const& _usingFor) FunctionDefinition const& functionDefinition = dynamic_cast(*path->annotation().referencedDeclaration); + // Free functions with an explicit visibility were already flagged by the + // SyntaxChecker (error 4126). That error is not fatal, so resolution + // continues into this directive and calls `functionDefinition.type()`, + // which asserts non-external. Skip the entry to avoid the ICE; the user + // will still see the visibility error from the function definition. + if ( + !functionDefinition.libraryFunction() && + functionDefinition.visibility() == Visibility::External + ) + { + solAssert(m_errorReporter.hasErrors()); + continue; + } + FunctionType const* functionType = dynamic_cast( functionDefinition.libraryFunction() ? functionDefinition.typeViaContractName() : diff --git a/test/libsolidity/syntaxTests/using/external_free_function.sol b/test/libsolidity/syntaxTests/using/external_free_function.sol new file mode 100644 index 000000000000..3cb57697bb3f --- /dev/null +++ b/test/libsolidity/syntaxTests/using/external_free_function.sol @@ -0,0 +1,7 @@ +// Used to cause ICE in FunctionDefinition::type() when an external free +// function (already a syntax error) was bound via `using for`. +function f(int) external; +using {f} for int global; +// ---- +// SyntaxError 4126: (0-26): Free functions cannot have visibility. +// TypeError 4668: (0-26): Free functions must be implemented.