LLDB Negative Cache

In Xcode, the LLDB variables view always beachballs for a bit when debugging a Swift file with type aliases referencing other typealiases.

Here’s the relevant source code:

open class SomeWorkflowStep<A, B> {}

public typealias SomeParameterType = Bool
public typealias SomeReferencingAliasV3 = SomeWorkflowStep<SomeParameterType, Bool>

class ReproV2 {
    let someReferencingAlias: SomeReferencingAliasV3?
    init(someReferencingAlias: SomeReferencingAliasV3? = nil) {
        self.someReferencingAlias = someReferencingAlias // breakpoint was added on this line.
    }
}

LLDB type logs show:

SwiftASTContextForModule("MyApplication")::SwiftDWARFImporterDelegate::lookupValue("SomeReferencingAliasV3")
TypeSystemSwiftTypeRef("MyApplication")::SwiftDWARFImporterForClangTypes::lookupValue("SomeReferencingAliasV3")
SwiftDWARFImporterDelegate::lookupValue() -- imported 0 types from debug info.
ReconstructTypeImpl("$s21MyApplicationMainLib22SomeReferencingAliasV3aSgD") -- not found
ReconstructTypeImpl("$s21MyApplicationMainLib22SomeReferencingAliasV3aSgD") -- found in the negative cache

Since its not able to find the type, it does a global lookup which takes significant time in our setup given ours is a heavy application.

Couldn't compute size of type $s21MyApplicationMainLib22SomeReferencingAliasV3aSgD using SwiftLanguageRuntime.
 SwiftASTContextForModule("MyApplication")::ReconstructTypeImpl("$s21MyApplicationMainLib22SomeReferencingAliasV3aSgD") -- found in the negative cache
 SwiftASTContextForModule("MyApplication")::GetBitSize() -- Input type is nullptr, bailing out.
 SwiftASTContextForModule("MyApplication")::ReconstructTypeImpl("$s21MyApplicationMainLib22SomeReferencingAliasV3aSgD") -- found in the negative cache
 SwiftASTContextForModule("MyApplication")::ReconstructTypeImpl("$s21MyApplicationMainLib22SomeReferencingAliasV3aSgD") -- found in the negative cache
 Couldn't compute size of type $s21MyApplicationMainLib22SomeReferencingAliasV3aSgD using SwiftLanguageRuntime.
 SwiftASTContextForModule("MyApplication")::ReconstructTypeImpl("$s21MyApplicationMainLib22SomeReferencingAliasV3aSgD") -- found in the negative cache
 SwiftASTContextForModule("MyApplication")::GetBitSize() -- Input type is nullptr, bailing out.
 SwiftASTContextForModule("MyApplication")::ReconstructTypeImpl("$s21MyApplicationMainLib22SomeReferencingAliasV3aSgD") -- found in the negative cache
 SwiftASTContextForModule("MyApplication")::ReconstructTypeImpl("$s21MyApplicationMainLib22SomeReferencingAliasV3aSgD") -- found in the negative cache
 Couldn't compute size of type $s21MyApplicationMainLib22SomeReferencingAliasV3aSgD using SwiftLanguageRuntime.
 SwiftASTContextForModule("MyApplication")::ReconstructTypeImpl("$s21MyApplicationMainLib22SomeReferencingAliasV3aSgD") -- found in the negative cache
 SwiftASTContextForModule("MyApplication")::GetBitSize() -- Input type is nullptr, bailing out.
 SwiftASTContextForModule("MyApplication")::ReconstructTypeImpl("$s21MyApplicationMainLib22SomeReferencingAliasV3aSgD") -- found in the negative cache
 SwiftASTContextForModule("MyApplication")::ReconstructTypeImpl("$s21MyApplicationMainLib22SomeReferencingAliasV3aSgD") -- found in the negative cache
 SwiftASTContextForModule("MyApplication")::ReconstructTypeImpl("$s21MyApplicationMainLib22SomeReferencingAliasV3aSgD") -- found in the negative cache
 SwiftASTContextForModule("MyApplication")::ReconstructTypeImpl("$s21MyApplicationMainLib22SomeReferencingAliasV3aSgD") -- found in the negative cache
 SwiftASTContextForModule("MyApplication")::ReconstructTypeImpl("$s21MyApplicationMainLib22SomeReferencingAliasV3aSgD") -- found in the negative cache
 SwiftASTContextForModule("MyApplication")::ReconstructTypeImpl("$s21MyApplicationMainLib22SomeReferencingAliasV3aSgD") -- found in the negative cache
 SwiftASTContextForModule("MyApplication")::ReconstructTypeImpl("$s21MyApplicationMainLib22SomeReferencingAliasV3aSgD") -- found in the negative cache
 SwiftASTContextForModule("MyApplication")::ReconstructTypeImpl("$s21MyApplicationMainLib22SomeReferencingAliasV3aSgD") -- found in the negative cache
 SwiftASTContextForModule("MyApplication")::ReconstructTypeImpl("$s21MyApplicationMainLib22SomeReferencingAliasV3aSgD") -- found in the negative cache
 SwiftASTContextForModule("MyApplication")::ReconstructTypeImpl("$s21MyApplicationMainLib22SomeReferencingAliasV3aSgD") -- found in the negative cache
 SwiftASTContextForModule("MyApplication")::ReconstructTypeImpl("$s21MyApplicationMainLib22SomeReferencingAliasV3aSgD") -- found in the negative cache
 SwiftASTContextForModule("MyApplication")::ReconstructTypeImpl("$s21MyApplicationMainLib22SomeReferencingAliasV3aSgD") -- found in the negative cache
 SwiftASTContextForModule("MyApplication")::ReconstructTypeImpl("$s21MyApplicationMainLib22SomeReferencingAliasV3aSgD") -- found in the negative cache
 SwiftASTContextForModule("MyApplication")::ReconstructTypeImpl("$s21MyApplicationMainLib22SomeReferencingAliasV3aSgD") -- found in the negative cache
 SwiftASTContextForModule("MyApplication")::ReconstructTypeImpl("$s21MyApplicationMainLib22SomeReferencingAliasV3aSgD") -- found in the negative cache
 SwiftASTContextForModule("MyApplication")::ReconstructTypeImpl("$s21MyApplicationMainLib22SomeReferencingAliasV3aSgD") -- found in the negative cache
 SwiftASTContextForModule("MyApplication")::ReconstructTypeImpl("$s21MyApplicationMainLib22SomeReferencingAliasV3aSgD") -- found in the negative cache
 TypeSystemSwiftTypeRefForExpressions::TypeSystemSwiftTypeRefForExpressions()
 returned project-wide scratch context
 returned project-wide scratch context
 returned project-wide scratch context
 dynamic type of instance_ptr 0x600000213620 is $s21MyApplicationMainLib7ReproV2CD
 [self 0x5cdf30e00] might have a dynamic type
 [self 0x5cdf30e00] has a new dynamic type MyApplicationMainLib.ReproV2
 returned project-wide scratch context
 dynamic type of instance_ptr 0x600000213620 is $s21MyApplicationMainLib7ReproV2CD
 dynamic type of instance_ptr 0x600000213620 is $s21MyApplicationMainLib7ReproV2CD
 dynamic type of instance_ptr 0x600000213620 is $s21MyApplicationMainLib7ReproV2CD
 dynamic type of instance_ptr 0x600000213620 is $s21MyApplicationMainLib7ReproV2CD
 dynamic type of instance_ptr 0x600000213620 is $s21MyApplicationMainLib7ReproV2CD
 dynamic type of instance_ptr 0x600000213620 is $s21MyApplicationMainLib7ReproV2CD
 returned project-wide scratch context
 returned project-wide scratch context
 SwiftASTContextForModule("MyApplication")::ReconstructTypeImpl("$s21MyApplicationMainLib22SomeReferencingAliasV3aSgD") -- found in the negative cache
 SwiftASTContextForModule("MyApplication")::ReconstructTypeImpl("$s21MyApplicationMainLib22SomeReferencingAliasV3aSgD") -- found in the negative cache
 SwiftASTContextForModule("MyApplication")::ReconstructTypeImpl("$s21MyApplicationMainLib22SomeReferencingAliasV3aSgD") -- found in the negative cache
 SwiftASTContextForModule("MyApplication")::ReconstructTypeImpl("$s21MyApplicationMainLib22SomeReferencingAliasV3aSgD") -- found in the negative cache
 SwiftASTContextForModule("MyApplication")::ReconstructTypeImpl("$s21MyApplicationMainLib22SomeReferencingAliasV3aSgD") -- found in the negative cache
 SwiftASTContextForModule("MyApplication")::ReconstructTypeImpl("$s21MyApplicationMainLib22SomeReferencingAliasV3aSgD") -- found in the negative cache
 SwiftASTContextForModule("MyApplication")::ReconstructTypeImpl("$s21MyApplicationMainLib22SomeReferencingAliasV3aSgD") -- found in the negative cache

  1. -ast-paths are valid, and the module is found as per LLDB logs.
    • SwiftASTContextForModule("MyApplication")::GetASTBuffersFromModule() -- Found 1189 AST file data entries in .../../MyApplication
  2. When I replace the typealias refereing other typealias with a Bool, or a struct, class - it all works fine and there are no negative cache issues reported in the lldb logs. The beachballing issue resolves, and the variables view loads seamlessly without any noticeable delays.
  3. swift-healthcheck is all okay.
  4. I believe this might be specific to our project, but if anyone has any insights or suggestions, that would be super helpful.

Is the code you posted representative of the actual problem?
I recently added some missing functionality to support type aliases for associated types in [lldb] Resolve typealias information for assiciated types via reflection by adrian-prantl · Pull Request #9768 · swiftlang/llvm-project · GitHub but this seems to be a much simpler global type alias.

1 Like

Looks like I can reproduce the type reconstruction failure from this alone! Thanks, I'll let you know when I found out more!

2 Likes

Thank you so much, @Adrian_Prantl!

I fixed 50% of the problem here: [lldb] Recursively resolve type aliases when canonicalizing types by adrian-prantl · Pull Request #9883 · swiftlang/llvm-project · GitHub
The other bug is in the compiler, it doesn't emit debug info for the inner type alias since it's not directly used in a variable. In the LLDB test I worked around it with the anchor variable.

1 Like

Here's the compiler side: [Debug info] Retain all type aliases in asttypes mode by adrian-prantl · Pull Request #78901 · swiftlang/swift · GitHub

2 Likes

Thank you @Adrian_Prantl :pray:t3: This pattern is quite common in our monorepo, so these fixes will be very helpful to us.

@Adrian_Prantl
Would it be possible to extract all types that make up a binary and query the Swift runtime (or other necessary components) to determine if they can be reconstructed, as required by LLDB to proactively avoid above negative cache issues? Are there existing tools or approaches that could facilitate this?

If this is feasible, we can then even explore adding it as a CI step when a developer creates a PR in-house - with an intent to provide an early detection mechanism for potential debugging regressions.