Skip to content

[Swift][Specialization] Assertion std::find(conformsTo) != conformsTo.end() in getTypeForSymbolRange when serializing @_specialize generic signature with ambiguous type used in associated type chain #89154

@YuanchengJiang

Description

@YuanchengJiang

Description

Description

swift reproduce.swift crashes with an assertion failure std::find(conformsTo.begin(), conformsTo.end(), symbol.getProtocol()) != conformsTo.end() in getTypeForSymbolRange at InterfaceType.cpp:365 when serializing the generic signature of a @_specialize attribute on a function whose where clause references a type (MyStruct4) whose associated type (DP2) resolves to a type (MyStruct3) that is ambiguous due to a second declaration of the same name. The ambiguity corrupts the protocol conformance lookup during specialization signature serialization, causing the assertion to fire when a conformance symbol's protocol is not found in the expected conformance list.

Reproducer

public protocol P1 {
    associatedtype DP1
    associatedtype DP11
}

public protocol P2 {
    associatedtype DP2: P1
}

public struct H<T> {}

public struct MyStruct3: P1 {
    public typealias DP1 = Int
    public typealias DP11 = H<Int>
}

public struct MyStruct4: P2 {
    public typealias DP2 = MyStruct3
}

@_specialize(where T == MyStruct4)
public func foo<T: P2>(_ t: T) where T.DP2.DP11 == H<T.DP2.DP1> {}

struct MyStruct3 {}

Command

swift reproduce.swift

Expected behavior

The compiler should emit a diagnostic about the ambiguous MyStruct3 and the resulting conformance failure, then exit gracefully. It should not crash with an assertion failure during @_specialize signature serialization.

Actual behavior

reproduce.swift: error: 'MyStruct3' is ambiguous for type lookup in this context

Assertion failed: (std::find(conformsTo.begin(), conformsTo.end(), symbol.getProtocol()) != conformsTo.end()),
function getTypeForSymbolRange at InterfaceType.cpp:365.

While evaluating request TypeCheckPrimaryFileRequest(source_file "reproduce.swift")
While type-checking 'foo(_:)'
While evaluating request SerializeAttrGenericSignatureRequest(foo, @_specialize(...))

💣 Program crashed: Bad pointer dereference at 0x0000000000000048

Call chain

TypeCheckPrimaryFileRequest::evaluate
  → typeCheckDecl (foo(_:))
    → SerializeAttrGenericSignatureRequest::evaluate
      → AbstractSpecializeAttr::getSpecializedSignature
        → getTypeForSymbolRange              (InterfaceType.cpp:365)
          ← assertion: protocol not found in conformsTo list

Root cause

@_specialize(where T == MyStruct4) on foo<T: P2> requires serializing a specialized generic signature that includes the chain T.DP2.DP11 == H<T.DP2.DP1>. MyStruct4.DP2 resolves to MyStruct3, but because MyStruct3 is declared twice (making it ambiguous), the conformance of MyStruct3 to P1 is not reliably resolved. During signature serialization, getTypeForSymbolRange looks up the protocol of a conformance symbol in the conformsTo list of the associated type's interface type, but the ambiguity causes the wrong or missing conformance to be stored, so the protocol is not found and the assertion fires. The fix should guard getTypeForSymbolRange against missing conformances in error recovery situations, or ensure that SerializeAttrGenericSignatureRequest bails out gracefully when the specialized type's conformances are in an error state due to ambiguity.

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/AST/InterfaceType.cpp:365 (getTypeForSymbolRange)
  • Affected pass: SerializeAttrGenericSignatureRequest in swift/lib/Sema/

This bug was found by fusion-fuzz

Metadata

Metadata

Assignees

No one assigned

    Labels

    crashBug: A crash, i.e., an abnormal termination of softwaretriage neededThis issue needs more specific labels

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions