Given the following Swift code, saved in bug.swift, and using Xcode 8.2.1 or Xcode 8.3 beta 2:
import Foundation
protocol MyProtocol {
func foo() -> String
}
extension MyProtocol {
func foo() -> String {
return "\(self)"
}
}
extension String: MyProtocol {}
extension NSAttributedString: MyProtocol {}
let normal = "normal".foo()
let attributed = NSAttributedString(string: "attributed", attributes: [:]).foo()
Run the following commands:
swiftc -g bug.swift
lldb bug
LLDB launches. Now, run these commands, and observe the output. Where I pass 9
, pass the line in your bug.swift
that contains return "\(self)"
:
(lldb) target create "bug"
Current executable set to 'bug' (x86_64).
(lldb) b 9
Breakpoint 1: where = bug`(extension in bug):bug.MyProtocol.foo () -> Swift.String + 19 at bug.swift:9, address = 0x0000000100001e53
(lldb) run
Process 16370 launched: '/Users/zev/Desktop/bug' (x86_64)
Process 16370 stopped
* thread #1: tid = 0x31730e, 0x0000000100001e53 bug`MyProtocol.foo(self="normal") -> String + 19 at bug.swift:9, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
frame #0: 0x0000000100001e53 bug`MyProtocol.foo(self="normal") -> String + 19 at bug.swift:9
6
7 extension MyProtocol {
8 func foo() -> String {
-> 9 return "\(self)"
10 }
11 }
12
(lldb) po self
"normal"
(lldb) c
Process 16370 resuming
Process 16370 stopped
* thread #1: tid = 0x31730e, 0x0000000100001e53 bug`MyProtocol.foo(self=0x00007fff5fbff480) -> String + 19 at bug.swift:9, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
frame #0: 0x0000000100001e53 bug`MyProtocol.foo(self=0x00007fff5fbff480) -> String + 19 at bug.swift:9
6
7 extension MyProtocol {
8 func foo() -> String {
-> 9 return "\(self)"
10 }
11 }
12
(lldb) po self
error: <EXPR>:1:11: error: use of undeclared type '$__lldb_context'
extension $__lldb_context {
^~~~~~~~~~~~~~~
error: <EXPR>:18:5: error: use of unresolved identifier '$__lldb_injected_self'
$__lldb_injected_self.$__lldb_wrapped_expr_2(
^~~~~~~~~~~~~~~~~~~~~
The first time we hit the breakpoint, we're in String
's conformance to MyProtocol
, and we can successfully po self
.
However, the second time we hit the breakpoint, we're in NSAttributedString
's conformance to MyProtocol
, and LLDB prints gibberish instead of the expected output from po self
.
Why does LLDB sometimes fail to print anything useful? This is a contrived example, but I run into this all the time in my day-to-day use of LLDB.
According to this answer on the Swift bug reporter, the bug was fixed at some point. I tested in Swift 5.2, and confirmed that it's fixed 🎉