From 036c60cbc66a51851bea3ad1287e4d5a8a3b7c19 Mon Sep 17 00:00:00 2001 From: genisis0x Date: Fri, 15 May 2026 15:27:13 +0530 Subject: [PATCH] Type Checker: skip zero-param bindings in operatorDefinitions matching scan When a using-for directive contains both a valid operator binding (e.g. `f as -`, two parameters) and a zero-parameter binding (e.g. `g as -`), TypeChecker::endVisit(UsingForDirective) reports the per-binding fatal error 4731 for the zero-parameter function, but only after the matching binding has already triggered the cross-binding scan in Type::operatorDefinitions(). That scan asserted on `!functionType->parameterTypes().empty()` and aborted with an internal compiler error before the user-visible 4731 was emitted. Skip such entries explicitly inside operatorDefinitions(); the TypeChecker still reports the visibility error from the offending binding itself, and the matching scan no longer reaches the assertion. Fixes #16613 --- libsolidity/ast/Types.cpp | 8 +++++++- ...operator_zero_param_alongside_valid_binding_no_ice.sol | 6 ++++++ 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 test/libsolidity/syntaxTests/operators/userDefined/operator_zero_param_alongside_valid_binding_no_ice.sol diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 3fa068491d9f..76c4b7c3f762 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -404,7 +404,13 @@ std::set Type::operatorDefiniti *identifierPath->annotation().referencedDeclaration ); auto const* functionType = dynamic_cast(functionDefinition.typeWhenAttached()); - solAssert(functionType && !functionType->parameterTypes().empty()); + solAssert(functionType); + // Zero-parameter functions are rejected by TypeChecker::endVisit(UsingForDirective) + // with error 4731, but that fatal fires per-binding and the matching scan below + // still revisits sibling bindings. Skip them here so that we do not assert on an + // already-reported invalid binding (#16613). + if (functionType->parameterTypes().empty()) + continue; size_t parameterCount = functionDefinition.parameterList().parameters().size(); if (*this == *functionType->parameterTypes().front() && (_unary ? parameterCount == 1 : parameterCount == 2)) diff --git a/test/libsolidity/syntaxTests/operators/userDefined/operator_zero_param_alongside_valid_binding_no_ice.sol b/test/libsolidity/syntaxTests/operators/userDefined/operator_zero_param_alongside_valid_binding_no_ice.sol new file mode 100644 index 000000000000..7d011492540c --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/userDefined/operator_zero_param_alongside_valid_binding_no_ice.sol @@ -0,0 +1,6 @@ +type T is int256; +function f(T a, T b) pure returns (T) {} +function g() pure returns (T) {} +using {f as -, g as -} for T global; +// ---- +// TypeError 4731: (107-108): The function "g" does not have any parameters, and therefore cannot be attached to the type "T".