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
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
Description
swift reproduce.swiftcrashes with an assertion failure(allowTypeParameters || !firstType->hasTypeParameter()) && "must take a contextual type..."incheckRequirementsImplatRequirement.cpp:283when type-checking a structrdar27680407Structthat conforms to a protocol with an associated typeT, where the struct'sinit(value:)usesrdar27680407Struct.Tto name the associated type, and all of this is nested inside a generic functionfoo<T>that also has a generic parameter namedT. The associated type inference engine passes a type parameter (the outerTfromfoo<T>) tocheckRequirementswithout substituting it to a contextual type, triggering the assertion.Reproducer
Command
Expected behavior
The compiler should emit diagnostics about the name shadowing between the outer
Tgeneric parameter and the associated typeT, or about the invalid nesting, then exit gracefully. It should not crash with an assertion failure during associated type inference.Actual behavior
Call chain
Root cause
When
rdar27680407Structis nested insidefunc foo<T>, the outer generic parameterTis in scope. The struct declaresinit(value: rdar27680407Struct.T)where.Trefers to the protocol's associated typeT. During associated type inference infindSolutionsRec, when validating candidate solutions by callingcheckRequirements, the outer generic parameterTfromfoo<T>leaks into the requirement check as an unsubstituted type parameter.checkRequirementsImplasserts that all types must be contextual (i.e. fully substituted), but the leakedTis not, triggering the crash. The fix should ensure that associated type inference substitutes or filters out outer generic parameters before callingcheckRequirements.Environment
swift reproduce.swift(no special flags required)swift/lib/AST/Requirement.cpp:283(checkRequirementsImpl)swift/lib/Sema/AssociatedTypeInference.cpp(findSolutionsRec)This bug was found by fusion-fuzz