Debugging error: circular reference

I’m stumped… I have a new project (SPM based) that wraps a very complex cpp codebase. I’ve made a module that creates cpp wrappers around heavily templated code, and in turn I’m extending those wrapper types in swift. This all seemingly works great - but while writing test coverage I’ve started getting the following errors:

<unknown>:0: error: circular reference
<unknown>:0: note: through reference here
<unknown>:0: note: through reference here
<unknown>:0: error: circular reference
<unknown>:0: note: through reference here
<unknown>:0: note: through reference here
<unknown>:0: error: circular reference
<unknown>:0: note: through reference here
<unknown>:0: note: through reference here
<unknown>:0: error: circular reference
<unknown>:0: note: through reference here
<unknown>:0: note: through reference here
<unknown>:0: error: circular reference
<unknown>:0: note: through reference here
<unknown>:0: note: through reference here
<unknown>:0: error: circular reference
<unknown>:0: note: through reference here
<unknown>:0: note: through reference here
<unknown>:0: error: circular reference
<unknown>:0: note: through reference here
<unknown>:0: note: through reference here
<unknown>:0: error: circular reference
<unknown>:0: note: through reference here
<unknown>:0: note: through reference here
<unknown>:0: error: circular reference
<unknown>:0: note: through reference here
<unknown>:0: note: through reference here

I can’t find any annotations to where this error is, what here is, or what reference its referring to. I’ve commented out all the code in my tests and the error goes away. at this point I've removed almost all the code in the triggering test file. here’s what remains:

import Testing
@testable import HalideSwift

struct HalideMetalTests {

     @Test func testCreateAndWrapMetalBuffer() {
        let c =  255 * 255
     }

}

commenting out the assignment line resolves the errors, but seemingly any additional code in this project triggers it again. how can I figure out where to even begin to look for the root cause of this issue?

Mike

2 Likes

Try passing the -debug-cycles compiler flag, it will dump the request stack upon encountering a cycle.

1 Like

What toolchain version are you using? What does swift --version at the command line say?

1 Like

swift-driver version: 1.127.14.1 Apple Swift version 6.2.1 (swiftlang-6.2.1.4.8 clang-1700.4.4.1)
Target: arm64-apple-macosx26.0

1 Like

ok, so here’s the result of the first error… having a hard time making sense of it

===CYCLE DETECTED===
 `--TypeCheckPrimaryFileRequest(source_file "/Users/mike/Development/Hedge/HalideSwift/Tests/HalideSwiftTests/HalideMetalTests.swift")
     `--TypeCheckFunctionBodyRequest(HalideSwiftTests.(file).HalideMetalTests.testCreateAndWrapMetalBuffer()@/Users/mike/Development/Hedge/HalideSwift/Tests/HalideSwiftTests/HalideMetalTests.swift:18:17)
         `--PatternBindingEntryRequest((unknown decl)@/Users/mike/Development/Hedge/HalideSwift/Tests/HalideSwiftTests/HalideMetalTests.swift:23:9, 0)
             `--UnqualifiedLookupRequest(looking up '*' from 0x840e2f298 AbstractFunctionDecl name=testCreateAndWrapMetalBuffer() : (HalideMetalTests) -> () -> () with options { AllowProtocolMembers, IncludeOuterResults })
                 `--LookupInModuleRequest(0x840d64008 FileUnit file="/Users/mike/Development/Hedge/HalideSwift/Tests/HalideSwiftTests/HalideMetalTests.swift", '*', UnqualifiedLookup, Overloadable, 0x840d64008 FileUnit file="/Users/mike/Development/Hedge/HalideSwift/Tests/HalideSwiftTests/HalideMetalTests.swift", { NL_RemoveNonVisible, NL_RemoveOverridden })
                     `--ModuleQualifiedLookupRequest(0x83eddb868 Module name=HalideWrappers, HalideWrappers, 'HalideExpr', { NL_RemoveOverridden })
                         `--LookupInModuleRequest(0x83eddb868 Module name=HalideWrappers, 'HalideExpr', QualifiedLookup, Overloadable, 0x83eddb868 Module name=HalideWrappers, { NL_RemoveOverridden })
                             `--LookupConformanceInModuleRequest(looking up conformance to Swift.(file).Copyable for HalideExpr)
                                 `--ModuleQualifiedLookupRequest(0x83eddb868 Module name=HalideWrappers, HalideWrappers, 'HalideExpr', { NL_RemoveOverridden }) (cyclic dependency)
1 Like

The cycle appears to be just the last four lines. It looks like it's getting stuck in a loop looking up overloads of * inside the module HalideWrappers? Very weird.

It looks like a bug in the ClangImporter, because it’s looking up a conformance of a C++ type to Copyable, but that triggers a recursive name lookup. The request evaluator stops the infinite recursion and emits the diagnostic instead. Do you mind filing a bug? It would be nice if both the underlying issue was solved, and the diagnostic fixed to point to a source location in a synthesized buffer if a circular reference is diagnosed for some other reason in imported declarations.

3 Likes

I’m happy to file a bug… what info do you need besides that log?

1 Like

If you could share either the whole project or a standalone reproducer, that would be ideal.

1 Like