Evaluate Swift expressions in LLDB - swift

I want to define a Swift extension, including a method / computed var, only for LLDB debugging purposes. Here is the regular Swift code:
extension Collection where Self.Element == Int {
var elementsOver30: [Self.Element]? {
return self.filter { $0 > 30 }
}
}
How can I define elementsOver30 in this example in pure LLDB? I think expression command is the right tool to use, but I sometimes get parsing errors.
Also, is there an equivalent syntax for other Swift symbols in LLDB, like structs?

Working with Swift code in LLDB 📺
Most Swift code can be executed as part of LLDB if it's part of the stdlib with the right syntax. The key is to prefix type names with the symbol identifier $. I've used $ even for variable names here (new LLDB improvements make this unnecessary) because I prefer to distinguish LLDB definitions.
Extensions 📏
With improvements to LLDB, you can actually copy-paste the Swift code directly after expression.
I've added an example for your extension with $ symbols for clarity:
(lldb) expression
extension Collection where Self.Element == Int {
var $elementsOver30: [Self.Element]? {
return self.filter { $0 > 30 }
}
}
(lldb) po [32,31,4].$elementsOver30
▿ Optional<Array<Int>>
▿ some : 2 elements
- 0 : 32
- 1 : 31
Pressing Enter after expression prompts a multi-line evaluation where we can input the remaining Swift code.
Structs/Class definitions 🧱
(lldb) expression
struct $Person {
let name: String
}
(lldb) po let $pranav = $Person.init(name: "pranav")
(lldb) po $pranav
▿ $Person
- name : "pranav"
Reading a Swift instance from memory
Sometimes, we need to read Swift code using Objective-C in LLDB. For example, if we have a Swift file with a View Controller:
class LoginViewController: UIViewController {
...
}
We can print the dynamic type of the result of a memory address as follows:
(lldb) expr -O --language objc -- 0x14160c260
<SharedSettings.LoginViewController: 0x14160c260>
View Swift docs 📝
Use type lookup to read a minified version of the type definitions:
(lldb) type lookup Equatable
protocol Equatable {
static func == (lhs: Self, rhs: Self) -> Swift.Bool
}
extension Swift.Equatable {
static func != (lhs: Self, rhs: Self) -> Swift.Bool
}

Related

Workaround for conditional conformance in Swift (was: Adding protocol to a constrained generic types)

The code snippet below demonstrates the problem I am trying to solve.
import Foundation
protocol Printable {
func className() -> String
}
class SomeType: Printable {
func className() -> String {
return "SomeType"
}
}
class List<T> {
}
extension List where T: SomeType {
func className() -> String {
return "List<SomeType>"
}
}
func test(type: Any, message: String) {
guard type is Printable else {
print("\(message): ERROR")
return
}
print("\(message): SUCCESS")
}
let s: Any = SomeType()
test(type: s, message: "#1")
let slist1: Any = List<Any>()
test(type: slist1, message: "#2")
let slist2: Any = List<SomeType>()
test(type: slist2, message: "#3")
How can I get this:
> #1: SUCCESS <--- as expected
> #2: ERROR <--- it's okay
> #3: SUCCESS <--- I am getting ERROR instead
It seems that adding a protocol to this line would do the trick:
extension List: Printable where T: SomeType { // COMPILE ERROR
But unfortunately, this is not allowed.
Another way to do it could be to use:
extension List where T: Printable { // COMPILES OK in Swift 2.3 but doesn't work. COMPILE ERROR in Swift 3.0
But again, no luck passing the test.
What else can I do to add a protocol to a constrained generic type?
An updated answer now that we have Swift 4.2, conditional conformance is now added as a feature.
From their spec on Github, this sort of code is now valid
extension List : Printable where T: SomeType {
func className() -> String {
return "List<SomeType>"
}
}
Okay so in your guard you're asking "if this is Printable then print success else print Error" and with your first example you have s which is SomeType which is printable. That's fine.
After that you have slist1 which is type List<Any> which is definitely not of type printable and you get "Error". That's fine
Next you have List<SomeType>. Now you have a class extension that defines T to be SomeType, correct? But you're only defining T to be SomeType and not the actual List so when you pass the entire List into the test function you're not going to get your test to pass because List<AnyTypeHere> is not Printable because the list itself doesn't implement Printable.
Now the question is, do you want the entire list to be printable? If so, then just make it conform to the SomeType or Printable protocol. That's the only way you'll get that to pass other than you passing individual List<SomeType> elements into the function. Your function logic is correct but it's just a misuse of the concept.
So if you want the List<SomeType> to make that pass then you could do something like
class List<T> : Printable where T:SomeType {
//Add code here that conforms to protocol
}
Doing that will make your second test fail because Any doesn't inherit from SomeType but it'll make your third test pass because now List<T> is Printable and T is also of type SomeType. I mean, that's just a real quick way to get what it looked like you wanted to begin with. You're not going to have the second and third tests pass at the same time unless you add something extra because the second test is List being of type Any while the third is List being of type Printable. So either one of them will throw an error (because List isn't of type Printable) or all tests show success (because List is of type Printable)

Optional Binding, Capturing References and Closures [possible bug]

I have been trying to get myself acquainted with Swift, but I recently came across this peculiar problem involving Optional Bindings and capturing references within the context of Closures.
Given the following declarations (code abbreviated for clarity; full code provided at the end):
class Thing
{
func giveNameIfSize() -> String? {
/.../
}
}
typealias IterationBlock = (Thing) -> Bool
class Iterable
{
func iterate(block: IterationBlock) {
/.../
}
}
An Iterable object can store a collection of Things and can iterate through them using a closure. Now say we wanted to find the name of the Thing object that has a size property set up. We could do something like this:
var name: String?
iterable.iterate { (someThing) -> Bool in
/*
Assigning the result of the giveNameIfSize() function to
a variable 'name' declared outside of the closure and
captured by reference
*/
if name = someThing.giveNameIfSize() {
return true
}
return false
}
However, the code above generates the following compiler error:
Cannot assign to immutable value of type 'String?'
Curiously enough, the problem disappears when we use another variable in the optional binding:
iterable.iterate { (someThing) -> Bool in
if var tempResult = someThing.giveNameIfSize() {
name = tempResult
return true
}
return false
} /* COMPILES AND RUNS */
The problem is also resolved if we assign a value to the externally declared variable name outside of the optional binding:
iterable.iterate { (someThing) -> Bool in
name = someThing.giveNameIfSize()
if name != nil {
return true
}
return false
} /* ALSO COMPILES AND RUNS */
Full source code here.
Obs.: Tested this code with Swift 1.2, not 2.0.
====
Is this a bug? Or am I missing something?
The error you're receiving is a little misleading, but the underlying problem here is that you're trying to do something that Swift doesn't support. In Swift, you can't use the result of assignment in a condition.
That being said, both of your proposed alternative methods will work, although I tend to think that the first of the two is a little more Swifty.

Extending Swift's Dictionary to conform to Protocol that requires the use of subscript causes Linker Error

The title says it all, but I have a protocol like:
protocol MyProtocol {
typealias KeyType
typealias ValueType
subscript(key: KeyType) -> ValueType? { get set }
}
And trying to make Dictionary conform to MyProtocol like:
extension Dictionary: MyProtocol {
}
results in the Linker Error:
Undefined symbols for architecture x86_64:
"__TFVSs10Dictionarym9subscriptFQ_GSqQ0__", referenced from:
__TTWUSs8Hashable___GVSs10DictionaryQ_Q0__18ProjectName11MyProtocolS1_FS2_m9subscriptFQQPS2_12KeyTypeGSqQS3_15ValueType_ in Searcher.o
Now, the interesting part is that if I reimplement subscript, the error goes away, but I don't know how to reimplement it without causing infinite recursion.
If instead of { get set }, the protocol requires { get } the error also goes away and the extension works as desired.
So I imagine the issue must be in the set side of things, trying to require { get mutating set } also doesn't work.
Does anyone know (a) what's going on and (b) how to make Dictionary conform to MyProtocol, without having to resort to drastic solutions like reimplementing subscript?
At first I was convinced it was a bug with Swift, but after probing it a bit, I am not so sure.
I'm using Swift 1.2
Edit: I managed to make it work by doing the following:
extension Dictionary: MyProtocol {
subscript(key: Key) -> Value? {
get {
let index = self.indexForKey(key)
if let i = index {
return self[i].1
}
return nil
}
set {
if let value = newValue {
self.updateValue(value, forKey: key)
} else {
self.removeValueForKey(key)
}
}
}
}
But re-implementing the Dictionary's subscript really doesn't seem like a good idea to me.
Edit 2: Clearer Question.
Edit 3: Tried the same code out in Swift 2.0 and it still doesn't work. Curiously the linker error is different this time:
Undefined symbols for architecture x86_64:
"Swift.Dictionary.subscript.materializeForSet : (A) -> B?", referenced from:
protocol witness for _Test.MyProtocol.subscript.materializeForSet : (A.KeyType) -> A.ValueType? in conformance <A, B where A: Swift.Hashable> [A : B] : _Test.MyProtocol in _Test in TestFile.o

Swift compiler segmentation fault when building

Adding a (convenient) computed height property to UIView in my UIViewExtension.swift file is causing the Swift compiler to segfault... What could possibly be going wrong here?
0 swift 0x00000001061e5608 llvm::sys::PrintStackTrace(__sFILE*) + 40
1 swift 0x00000001061e5af4 SignalHandler(int) + 452
2 libsystem_platform.dylib 0x00007fff894da5aa _sigtramp + 26
3 libsystem_platform.dylib 0xb03939841e997c88 _sigtramp + 2504775416
4 swift 0x00000001064c8bb9 swift::NominalTypeDecl::getMembers(bool) const + 41
5 swift 0x00000001055efab9 swift::irgen::ClassMetadataLayout<(anonymous namespace)::FindClassMethodIndex>::addClassMembers(swift::ClassDecl*) + 329
6 swift 0x00000001055e97b2 swift::irgen::emitVirtualMethodValue(swift::irgen::IRGenFunction&, llvm::Value*, swift::SILType, swift::SILDeclRef, swift::CanTypeWrapper<swift::SILFunctionType>, swift::ResilienceExpansion) + 434
7 swift 0x00000001056550d3 swift::SILVisitor<(anonymous namespace)::IRGenSILFunction, void>::visit(swift::ValueBase*) + 42611
8 swift 0x000000010564a266 swift::irgen::IRGenModule::emitSILFunction(swift::SILFunction*) + 8678
9 swift 0x00000001055cb6f8 swift::irgen::IRGenModule::emitGlobalTopLevel() + 184
10 swift 0x00000001056376e3 performIRGeneration(swift::IRGenOptions&, swift::Module*, swift::SILModule*, llvm::StringRef, llvm::LLVMContext&, swift::SourceFile*, unsigned int) + 1859
11 swift 0x0000000105638033 swift::performIRGeneration(swift::IRGenOptions&, swift::SourceFile&, swift::SILModule*, llvm::StringRef, llvm::LLVMContext&, unsigned int) + 51
12 swift 0x00000001055aa65a frontend_main(llvm::ArrayRef<char const*>, char const*, void*) + 4842
13 swift 0x00000001055a935d main + 1533
14 libdyld.dylib 0x00007fff8a82e5fd start + 1
 
1. While emitting IR SIL function #_TFCSo6UIViewg6heightSd for 'anonname=0x7ff422892fd0' at <path redacted>/UIViewExtension.swift:60:5
<unknown>:0: error: unable to execute command: Segmentation fault: 11
<unknown>:0: error: swift frontend command failed due to signal (use -v to see invocation)
Command /Applications/Xcode6-Beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift failed with exit code 254
If more information is needed to crack this, just comment. Thanks!
Edit:
Here's a related .xcodeproj that returns this question's compiler error. Download here
I had this error because I was doing this :
if(currentMeal?.State == .Deleted){
}
instead of
if(currentMeal!.State == .Deleted){
}
so I think optional not unwrapped in if condition can cause this error
When you run into a compiler segfault in Swift, you don't get a handy line number and error message. Here's how you can track the problem down:
Create a new file called SegFaultDebugger.swift in your project.
In this new file, define an extension to the class that's giving you problems.
Move a group of methods from the main file to SegFaultDebugger.swift.
Compile.
At this point, one of three things happens:
You still get the segfault in the original file: Move the methods from SegFaultDebugger.swift back to the original file and move a different set of methods into SegFaultDebugger.swift. Repeat
You get a segfault in SegFaultDebugger.swift: Great! Now use binary search to pin the segfault down to a specific method until you can figure out what construct is causing it.
You get meaningful compiler errors: Great! Fix the errors. Once everything compiles, move your methods back into the original file.
I got this error while extending one of my protocols and mistyped and optional type argument.
protocol SomeProtocolName: class {
var someProtocolVariable: String { get set }
func someProtocolFunction(someProtocolVariable: String)
}
// MARK:
extension SomeProtocolName {
func someProtocolFunction(someProtocolVariable: String?) {
self.someProtocolVariable = someProtocolVariable
}
}
The difference in function arguments String in prototype and String? in extension caused Segmentation Fault 11.
In Xcode 7, you can click on the error in the Debug Navigator and you'll be shown an expanded view of the crashes. Clicking on the hamburger button on the right expands the error, and if you scroll all the way down to the bottom of the expanded error message, you will see where it comes from.
For me, I had two of those segmentation fault errors. In the picture above, the first one is what it looks like when collapsed, the second is when you expand the hamburger button. At the very bottom of the expanded gray box, you'll see a message that says where the compiler crashed.
Note however that the error message may at times be not informative enough, so while it tells you where it crashed, it doesn't always say why and how to fix it. Getting rid of this error is still very much a matter of guesswork.
I had this error too, and I fixed it like this:
Check your project and find out which files are used twice and remove one, or delete and re-add them all.
Errors in my Xcode:
:0: error: filename "AttributedString.swift" used twice:
'/Users/.../CNJOB/CNJOB/AttributedString.swift' and
'/Users/.../CNJOB/CNJOB/AttributedString.swift'
:0: note: filenames are used to distinguish private
declarations with the same name
:0: error: filename "APIClient.swift" used twice:
'/Users/.../CNJOB/CNJOB/APIClient.swift' and
'/Users/.../CNJOB/CNJOB/APIClient.swift'
:0: note: filenames are used to distinguish private
declarations with the same name
Command /Applications/Xcode
3.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc
failed with exit code 1
I’ve discovered a simple workaround until the problem is fixed in a future Xcode/Swift build:
Simply place all extensions causing the issue in the .swift file that it’s being used.
In the example project you provided, place the contents of UIViewExtension.swift and CALayerExtension.swift above AppDelegate.swift
Hopefully this can get us to write working Swift code until the problem’s cleared up.
As for me, adding private to static var fixed clang crash:
private static var taskId = 0
I had a compiler segmentation fault on a statement like this:
someFunction(isFlagged ? "String1" : "String2")
I just did a if-else statement instead and it works.
This typically happens when the compiler does not have enough information (despite what you think) to guarantee/determine the state of a statement or a variable within a statement.
For example, imagine you have a dictionary of type [String: String] which you populate with city names as keys and a comma separated list of corresponding zip codes/post codes.
Imagine that somewhere in your code you want to update the list of corresponding codes:
myDict[town] += newZipCode + ","
In this case, the compiler will respond with segmentation fault as town might not be in the dictionary and therefore it cannot guarantee that the above statement will have a valid value.
To resolve this, you should store the current state of myDict[town] in a separate variable allowing you to handle the case of key not in dict and then update the value for the given key:
myDict[town] = guaranteedValue + "," newZipCode + ","
Unfortunately, it is not always straightforward to determine the root cause so I hope this simple example helps.
You can also have this problem if you declare a condition with an unwrapped Bool as a property
In my case, a misplaced colon during string interpolation broke mine (XCode 6.1.1).
Example:
println("\(value1:value2)")
when I meant to do:
println("\(value1) : \(value2)")
This error happened to me when I tried to override weak variable from parent class.
In base class:
weak var stripeViewDelegate : StripeViewDelegate? = nil
Derived class:
override weak var stripeViewDelegate : StripeViewDelegate? = nil {
didSet {
self.stripeView.delegate = stripeViewDelegate
}
The error disappeared when I removed =nil from derived class.
I catch some exception today
class func createByAny(instance: Any?) -> ApiCollectionResponse { ... }
and this solved it:
class func createByAny(instance: Any) -> ApiCollectionResponse { ... }
Because "Any" type is any type event "nil", "AnyObject", optional, ... :)
It is cannot be optional, it is already optional.
typealias Any = protocol<>
This error happens also if you accidentally declare a variable with a type matching its name:
var sectionGroup: sectionGroup? { ... }
Ran into this error because of an extraneous generic type on an operator function, e.g.
func ==<T>(lhs: Foo, rhs: Foo) -> Bool {
return lhs.bar == rhs.bar
}
In my case, removing <T> resolved the issue.
In my case I had declared a struct inside a func. Moving the struct to class level solved the issue.
Now that I write this I remember having had issues with struct inside funcs before. It was something else than the segmentation fault (which seems to become notorious with the Swift 1.2 beta). OMG Apple, what are you doing there?
In my case, this error because I use Class name for variable
var MYClass : MYClass {
get {
return.....
}
}
And this fixes my problem
var myClass : MYClass {
get {
return.....
}
}
Im my case, this happened when I did incorrect static initialization in a protocol. I found a way to get around, but a compiler should never produce a segmentation fault while building.
There are three files involved. A protocol NamedSegues.swift, a custom TableViewController that among other things implements the protocol which contains a callback, a custom TableViewCell that holds reference to this protocol to call the callback.
//file1
import Foundation
protocol NamedSegues {
func executeSegueWithId(id: String) -> Void
static func getDefault() -> NamedSegues // This was required because of init requirement in CustomCellView
}
//file2
class CustomController: UITableViewController, NamedSegues {
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("CustomCellID", forIndexPath: indexPath ) as! CustomCellView
// Configure the cell...
//App logic...
cell.parent = self
}
//Mark: NamedSegues
func executeSegueWithId(id: String) ->() {
NSLog("Received callback to execute segue: \(id)")
//
}
static func getDefault() -> NamedSegues { // I think this must be where it threw up.
return self as! NamedSegues
}
}
//file3
import UIKit
class CustomCellView: UITableViewCell {
var id: String = "NoName"
var parent: NamedSegues = NamedSegues.getDefault() // This is where it was needed.
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
NSLog("Touched id: \(id)")
parent.executeSegueWithId(id) // This is where parent was used.
}
}
I got around it by using ?
In the protocol file, file1: delete the declaration of getDefault()
In the CustomController file2: delete the implementation of getDefault.
In the CustomCellView, file3:
var parent: NamedSegues?
...
parent?.executeSegueWithId(id)
The compiler should have caught this and given some error message instead of throwing a segmentation fault during build!
Seems like the Swift 2 compiler might not have been quite ready for prime-time! In case this helps anyone, I was getting a segmentation fault: 11 due to a mismatch with the variable type in a closure header, specifically in a Parse method, PFQuery.query.findObjectsInBackgroundWithBlock.
You can see the issue in more detail here:
https://github.com/ParsePlatform/Parse-SDK-iOS-OSX/issues/280
Like #Fjohn said, this was an issue related to unwrapping an optional for me (broke in both Xcode 7.0 beta 6 and Xcode 7). In my case, I was not unwrapping optional of the optional (what tipped me off was double ?? in the descriptor. Using if let solved the issue
As others wrote above, for me this happened when I'm using an extension over a protocol but the signature of methods in the protocol don't match the implementations in an extension.
In my case, I had added a new parameter to the implementation (in the extension) but forgot to also add it to the method's signature in the protocol.
in my case, I tried to add a function parameter after a variadic parameter.
Reversing parameter sequence and making the variadic parameter the last parameter in the parameter list fixed it.
Swift 3.0 (Xcode 8.1) exhibits this issue when a protocol declares an optional variable, and an implementer implements that variable as a lazy initialised one.
Bug is reported here:
https://bugs.swift.org/browse/SR-1825
Xcode 8.2.
Adding #nonobjc protocol implementation into extension causing segmentation faults.
Move #nonobjc protocol implementation into class implementation.
In my case the culprit was accidentally overloading a function expecting an array argument with one with a variadic argument:
public required init(_ args: Node...) {
}
When the superclass had it defined as an array:
public required init(_ args: [Node]) {
}
For me the following caused a segfault while type is an optional:
switch type {
case .aType:
// Do Something
default:
break
}
and this solved it:
switch type {
case .Some(.aType):
// Do Something
default:
break
}
I got this error with the following method signature in a custom UITableViewController.
func filterContentForSearchText(searchText: String)
changing to:
func filterContentForSearchText(searchText: String!)
fixed the problem.
I had the same problem in an extension. My extension had two convenience initializers:
convenience init(context: NSManagedObjectContext) {
let entityDescription = NSEntityDescription.entityForName("PropertyEntity", inManagedObjectContext: context)!
self.init(entity: entityDescription, insertIntoManagedObjectContext: context)
}
convenience init(dictionary: NSDictionary, context: NSManagedObjectContext) {
self.init(context: context)
property1 = (dictionary["key"] as? String) ?? ""
// More properties...
}
To get rid of the error I added an instance method map(dictionary: NSDictionary) and the segmentation fault error disappeared.
convenience init(dictionary: NSDictionary, context: NSManagedObjectContext) {
self.init(context: context)
map(dictionary)
}
For me the issue was having my architectures not set to the standard. I had added i386 or something, just set it back to default xcodeproject arch and it compiled fine.
I had the same problem in a swift project. The issue was a function that should have returned an object, but didn't have a return in it. This sort of error used to be signaled while editing with Obj-C. It seems like t isn't the case in Swift.

Swift Generics issue

Right now I want to be able to see if an object is included inside an Array so:
func isIncluded<U:Comparable>(isIncluded : U) -> Bool
{
for item in self
{
if (item == isIncluded)
{
return true
}
}
return false
}
If you notice this function belongs to an Array extension. The problem is if add it to this:
extension Array{
}
I receive the following error:
Could not find an overload for '==' that accepts the supplied arguments
I understand that I could probably need to tell what kind of objects should be inside the Array like so: T[] <T.GeneratorType.Element: Comparable>. But it doesn't work as well:
Braced block of statements is an unused closure
Non-nominal type 'T[]' cannot be extended
Expected '{' in extension
With Swift, we'll need to think whether there's a function that can do the trick -- outside the methods of a class.
Just like in our case here:
contains(theArray, theItem)
You can try it in a playground:
let a = [1, 2, 3, 4, 5]
contains(a, 3)
contains(a, 6)
I discover a lot of these functions by cmd-clicking on a Swift symbol (example: Array) and then by looking around in that file (which seems to be the global file containing all declarations for Swift general classes and functions).
Here's a little extension that will add the "contains" method to all arrays:
extension Array {
func contains<T: Equatable>(item: T) -> Bool {
for i in self {
if item == (i as T) { return true }
}
return false
}
}
To add, the problem is that T is already defined and the Array's definition of T does not conform to Equatable. You can either accomplish what you want by casting (like the accepted answer), and risking an invalid cast, or you could pass in a delegate where no casting would be required.
Consider modifying like so:
extension Array {
func contains(comparator: (T)->Bool) -> Bool {
for item in self {
if comparator(item) {
return true
}
}
return false
}
}
Example usage:
class Test {
func arrayContains(){
var test: Int[] = [0,1,3,4,5]
//should be true
var exists = test.contains({(item)->Bool in item == 0});
}
}
Not to say that it's impossible, but I haven't yet seen a way to extend structs or classes to put conditions on the original generics, for instance to guarantee Equatable or Comparable on an Array. However, for your particular issue, instead of extending, you can do something like the following:
var arr = [1, 2, 3]
var isIncluded : Bool = arr.bridgeToObjectiveC().doesContain(1)