Skip to content

[Swift][AssociatedTypeInference] Assertion allowTypeParameters || !firstType->hasTypeParameter() in checkRequirementsImpl .. #89238

@YuanchengJiang

Description

@YuanchengJiang

Description

swift reproduce.swift crashes with an assertion failure (allowTypeParameters || !firstType->hasTypeParameter()) && "must take a contextual type..." in checkRequirementsImpl at Requirement.cpp:283 when type-checking a struct rdar27680407Struct that conforms to a protocol with an associated type T, where the struct's init(value:) uses rdar27680407Struct.T to name the associated type, and all of this is nested inside a generic function foo<T> that also has a generic parameter named T. The associated type inference engine passes a type parameter (the outer T from foo<T>) to checkRequirements without substituting it to a contextual type, triggering the assertion.

Reproducer

func foo<T>(x: T) {
    protocol rdar27680407Proto {
        associatedtype T
        init(value: T)
    }
    struct rdar27680407Struct: rdar27680407Proto {
        init(value: rdar27680407Struct.T) {}
    }
}

Command

swift reproduce.swift

Expected behavior

The compiler should emit diagnostics about the name shadowing between the outer T generic parameter and the associated type T, or about the invalid nesting, then exit gracefully. It should not crash with an assertion failure during associated type inference.

Actual behavior

Assertion failed: ((allowTypeParameters || !firstType->hasTypeParameter()) &&
  "must take a contextual type. if you really are ok with an indefinite answer
  (and usually YOU ARE NOT), then consider whether you really, definitely are
  ok with an indefinite answer, and use `checkRequirementsWithoutContext` instead"),
function checkRequirementsImpl at Requirement.cpp:283.

While type-checking 'rdar27680407Struct'
While type-checking 'init(value:)'
While evaluating request TypeWitnessRequest(rdar27680407Struct: rdar27680407Proto, T)
While evaluating request ResolveTypeWitnessesRequest(rdar27680407Struct: rdar27680407Proto)

Call chain

TypeCheckPrimaryFileRequest::evaluate
  → TypeCheckFunctionBodyRequest::evaluate  (foo<T>(x:))
    → typeCheckDecl  (rdar27680407Struct)
      → ResolveTypeWitnessesRequest::evaluate
        → AssociatedTypeInference::solve
          → findSolutions
            → findSolutionsRec
              → checkRequirements           ← called with unsubstituted T
                → checkRequirementsImpl     ← assertion: hasTypeParameter()

Root cause

When rdar27680407Struct is nested inside func foo<T>, the outer generic parameter T is in scope. The struct declares init(value: rdar27680407Struct.T) where .T refers to the protocol's associated type T. During associated type inference in findSolutionsRec, when validating candidate solutions by calling checkRequirements, the outer generic parameter T from foo<T> leaks into the requirement check as an unsubstituted type parameter. checkRequirementsImpl asserts that all types must be contextual (i.e. fully substituted), but the leaked T is not, triggering the crash. The fix should ensure that associated type inference substitutes or filters out outer generic parameters before calling checkRequirements.

Environment

  • Compiler: Swift 6.5-dev (LLVM c612996be917903, Swift acb09e2)
  • Platform: x86_64 Linux (Ubuntu 24.04.4 LTS)
  • Command: swift reproduce.swift (no special flags required)
  • Crash site: swift/lib/AST/Requirement.cpp:283 (checkRequirementsImpl)
  • Affected code: swift/lib/Sema/AssociatedTypeInference.cpp (findSolutionsRec)

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