Description
swift reproduce.swift crashes with an assertion failure std::find(Bindings.begin(), Bindings.end(), binding) == Bindings.end() in BindingSet::addBinding at CSBindings.cpp:1681 when the constraint system attempts to solve a tuple variable declaration (some Foo, some Foo) = (123, foo(123)) where foo is overloaded and returns some Foo, and the declaration is inside a local function scope. The constraint solver adds a duplicate binding for a type variable while resolving the overloaded foo(123) call in the context of the opaque return type tuple, triggering the assertion.
Reproducer
func outer() {
protocol Foo {}
extension Int: Foo {}
func foo(_: Int) -> some Foo { return 1738 }
func foo(_: String) -> some Foo { return 679 }
func foo<T: Foo>(_ x: T) -> some Foo { return x }
var globalVarTuple: (some Foo, some Foo) = (123, foo(123))
}
Command
Expected behavior
The compiler should successfully type-check the tuple variable declaration or emit a diagnostic. It should not crash with an assertion failure about duplicate bindings in the constraint system.
Actual behavior
Assertion failed: (std::find(Bindings.begin(), Bindings.end(), binding) == Bindings.end()),
function addBinding at CSBindings.cpp:1681.
While evaluating request TypeCheckFunctionBodyRequest for 'outer()'
While type-checking declaration (var globalVarTuple)
While type-checking expression at [reproduce.swift] RangeText="(123, foo(123)"
While type-checking-target starting at reproduce.swift
Call chain
TypeCheckPrimaryFileRequest::evaluate
→ TypeCheckFunctionBodyRequest::evaluate (outer())
→ typeCheckPatternBinding (var globalVarTuple)
→ typeCheckExpression
→ ConstraintSystem::solve
→ ConstraintSystem::salvage
→ ConstraintSystem::solveImpl
→ ComponentStep::take
→ ConstraintSystem::determineBestBindings
→ BindingSet::BindingSet
→ BindingSet::addBinding ← assertion: duplicate binding
Root cause
When type-checking var globalVarTuple: (some Foo, some Foo) = (123, foo(123)) inside a local function scope, the constraint system generates bindings for the type variables associated with the two some Foo opaque return type positions. The overloaded foo(123) call — which could resolve to foo(_: Int) -> some Foo or foo<T: Foo>(_ x: T) -> some Foo — causes the constraint solver to produce duplicate potential bindings for the same type variable when iterating over disjunction candidates. BindingSet::addBinding asserts that each binding must be unique, but receives the same binding twice. The fix should deduplicate bindings before insertion in BindingSet::addBinding, or prevent the overload resolution from generating duplicate bindings for opaque return type variables in tuple contexts.
Environment
- Compiler: Swift 6.5-dev (LLVM 7c86461e21cca7e, Swift 6da4da7)
- Platform: x86_64 Linux (Ubuntu 24.04.4 LTS)
- Command:
swift reproduce.swift (no special flags required)
- Crash site:
swift/lib/Sema/CSBindings.cpp:1681 (BindingSet::addBinding)
This bug was found by fusion-fuzz
Description
swift reproduce.swiftcrashes with an assertion failurestd::find(Bindings.begin(), Bindings.end(), binding) == Bindings.end()inBindingSet::addBindingatCSBindings.cpp:1681when the constraint system attempts to solve a tuple variable declaration(some Foo, some Foo) = (123, foo(123))wherefoois overloaded and returnssome Foo, and the declaration is inside a local function scope. The constraint solver adds a duplicate binding for a type variable while resolving the overloadedfoo(123)call in the context of the opaque return type tuple, triggering the assertion.Reproducer
Command
Expected behavior
The compiler should successfully type-check the tuple variable declaration or emit a diagnostic. It should not crash with an assertion failure about duplicate bindings in the constraint system.
Actual behavior
Call chain
Root cause
When type-checking
var globalVarTuple: (some Foo, some Foo) = (123, foo(123))inside a local function scope, the constraint system generates bindings for the type variables associated with the twosome Fooopaque return type positions. The overloadedfoo(123)call — which could resolve tofoo(_: Int) -> some Fooorfoo<T: Foo>(_ x: T) -> some Foo— causes the constraint solver to produce duplicate potential bindings for the same type variable when iterating over disjunction candidates.BindingSet::addBindingasserts that each binding must be unique, but receives the same binding twice. The fix should deduplicate bindings before insertion inBindingSet::addBinding, or prevent the overload resolution from generating duplicate bindings for opaque return type variables in tuple contexts.Environment
swift reproduce.swift(no special flags required)swift/lib/Sema/CSBindings.cpp:1681(BindingSet::addBinding)This bug was found by fusion-fuzz