Description
swift reproduce.swift crashes with an assertion failure in NamingPatternRequest::evaluate (TypeCheckDecl.cpp:2766) when the type checker attempts to resolve the type of a top-level variable fusion_0e59 that references c, which is itself declared in a later TopLevelCodeDecl (separated by a func declaration) and depends on a guard let b binding from an earlier TopLevelCodeDecl. The type checker queries b's type before its parent guard statement has been type-checked, violating the ordering invariant.
Reproducer
var fusion_0e59 = c
let a: Int? = fusion_0e59
guard let b = a else {
fatalError()
}
func foo() {}
let c = b
Command
Expected behavior
The compiler should emit a diagnostic about the use of c before it is declared, or handle the forward reference gracefully. It should not crash with an assertion failure.
Actual behavior
Assertion failed: (Context.SourceMgr.hasIDEInspectionTargetBuffer() ||
Context.LangOpts.IsForSourceKit ||
Context.TypeCheckerOpts.EnableLazyTypecheck ||
inSecondaryScriptFile() &&
"Querying VarDecl's type before type-checking parent stmt"),
function evaluate at TypeCheckDecl.cpp:2766.
While evaluating request TypeCheckPrimaryFileRequest(source_file "reproduce.swift")
While type-checking declaration (at reproduce.swift:1:1) [var fusion_0e59]
While evaluating request PatternBindingEntryRequest
While evaluating request InterfaceTypeRequest [c]
While evaluating request NamingPatternRequest [c]
While evaluating request PatternBindingEntryRequest
While type-checking expression [c = b]
While evaluating request InterfaceTypeRequest [b]
While evaluating request NamingPatternRequest [b]
← assertion failure
Call chain
TypeCheckPrimaryFileRequest::evaluate
→ typeCheckTopLevelCodeDecl
→ typeCheckPatternBinding (var fusion_0e59 = c)
→ PatternBindingEntryRequest (fusion_0e59)
→ InterfaceTypeRequest (c)
→ NamingPatternRequest (c)
→ PatternBindingEntryRequest (let c = b)
→ InterfaceTypeRequest (b)
→ NamingPatternRequest (b) ← assertion: parent stmt not yet type-checked
Root cause
func foo() interrupts the top-level code, splitting it into separate TopLevelCodeDecl nodes. let c = b is in a later TopLevelCodeDecl than guard let b = a. When var fusion_0e59 = c triggers type resolution of c, which requires b's type, the type checker queries b's NamingPattern before the guard let b statement has been type-checked. This violates the invariant that VarDecl::getInterfaceType() must not be called before the parent statement is type-checked. The fix should either detect the forward reference and emit a diagnostic before attempting type resolution, or ensure that cross-TopLevelCodeDecl variable references do not trigger out-of-order type-checking.
Environment
- Compiler: Swift 6.4-dev (LLVM d2079213f1d4451, Swift 82b7720)
- Platform: x86_64 Linux (Ubuntu 24.04.4 LTS)
- Command:
swift reproduce.swift (no special flags required)
- Crash site:
swift/lib/Sema/TypeCheckDecl.cpp:2766 (NamingPatternRequest::evaluate)
This bug was found by fusion-fuzz
Description
swift reproduce.swiftcrashes with an assertion failure inNamingPatternRequest::evaluate(TypeCheckDecl.cpp:2766) when the type checker attempts to resolve the type of a top-level variablefusion_0e59that referencesc, which is itself declared in a laterTopLevelCodeDecl(separated by afuncdeclaration) and depends on aguard let bbinding from an earlierTopLevelCodeDecl. The type checker queriesb's type before its parentguardstatement has been type-checked, violating the ordering invariant.Reproducer
Command
Expected behavior
The compiler should emit a diagnostic about the use of
cbefore it is declared, or handle the forward reference gracefully. It should not crash with an assertion failure.Actual behavior
Call chain
Root cause
func foo()interrupts the top-level code, splitting it into separateTopLevelCodeDeclnodes.let c = bis in a laterTopLevelCodeDeclthanguard let b = a. Whenvar fusion_0e59 = ctriggers type resolution ofc, which requiresb's type, the type checker queriesb'sNamingPatternbefore theguard let bstatement has been type-checked. This violates the invariant thatVarDecl::getInterfaceType()must not be called before the parent statement is type-checked. The fix should either detect the forward reference and emit a diagnostic before attempting type resolution, or ensure that cross-TopLevelCodeDeclvariable references do not trigger out-of-order type-checking.Environment
swift reproduce.swift(no special flags required)swift/lib/Sema/TypeCheckDecl.cpp:2766(NamingPatternRequest::evaluate)This bug was found by fusion-fuzz