Ternary in if statement - ternary-operator

Have looked at this question: To ternary or not to ternary?, however it didn't really provide me with an answer to this situation.
I've been using ternary in if statements, as it, according to me, provides more logic and requires less operations to actually work. An example of such statement is: if (a == 'foo' ? b != 'poo' : true), which of course can be replaced by if ((a == 'foo' && b != 'poo') || a != 'foo'). If comparing the number of operations - between 1 and 2 for ternary and 2 and 3 for non (of course this is a trivial example - I can as well create an example where the difference is greater than 1), it's also a cleaner than the non-ternary (at least for me); however my co-workers have been asking why have I adopted such convention.
Are there any caveats of using ternaries within conditionals (apart for readability - I'm still considering a ? b ? c ? d : e : f : g inhumane thing to parse)?

Using ternaries in an if statement is a bad idea, if for no other reason than it's unexpected. It's also logically more difficult to follow - I mentally converted your ternary to a conditional, as it makes more sense thinking about it that way. If I think of the conditions, I'm going to think in terms of "and" and "or", not "if ... then ... else," and I think most devs will agree with me on that.
Finally, look at the disassembly. Using clang on OSX, they are identical except the ternary has one more jmp. Your "fewer operations" argument is wrong.
Ternary
_ternary: ## #ternary
.cfi_startproc
## BB#0:
pushq %rbp
Ltmp2:
.cfi_def_cfa_offset 16
Ltmp3:
.cfi_offset %rbp, -16
movq %rsp, %rbp
Ltmp4:
.cfi_def_cfa_register %rbp
subq $16, %rsp
movl %edi, -4(%rbp)
movl %esi, -8(%rbp)
movl %edx, -12(%rbp)
cmpl $102, -4(%rbp)
jne LBB0_2
## BB#1:
cmpl $111, -8(%rbp)
je LBB0_3
jmp LBB0_4
LBB0_2:
cmpl $111, -12(%rbp)
jne LBB0_4
LBB0_3:
leaq L_.str(%rip), %rdi
callq _puts
movl %eax, -16(%rbp) ## 4-byte Spill
LBB0_4:
movl $0, %eax
addq $16, %rsp
popq %rbp
ret
.cfi_endproc
Logical
_logical: ## #logical
.cfi_startproc
## BB#0:
pushq %rbp
Ltmp7:
.cfi_def_cfa_offset 16
Ltmp8:
.cfi_offset %rbp, -16
movq %rsp, %rbp
Ltmp9:
.cfi_def_cfa_register %rbp
subq $16, %rsp
movl %edi, -4(%rbp)
movl %esi, -8(%rbp)
movl %edx, -12(%rbp)
cmpl $102, -4(%rbp)
jne LBB1_2
## BB#1:
cmpl $111, -8(%rbp)
je LBB1_3
LBB1_2:
cmpl $111, -12(%rbp)
jne LBB1_4
LBB1_3:
leaq L_.str1(%rip), %rdi
callq _puts
movl %eax, -16(%rbp) ## 4-byte Spill
LBB1_4:
movl $0, %eax
addq $16, %rsp
popq %rbp
ret
.cfi_endproc
Diff, excluding naming (< = ternary)
20,22c20,21
< jmp LBB0_4
---

Related

App crashing when fetching > 800 contacts using iOS 9 Contacts framework

Trying to fetch all the unified contacts on a device using the iOS 9 Contacts framework. The app is crashing when trying to fetch > 800 contacts.
I think this is a memory issue.
Below is my implementation
#objc func searchContacts(searchText: String?, callback: (NSObject) -> ()) -> Void {
let contactStore = CNContactStore()
let keysToFetch = [ CNContactGivenNameKey, CNContactFamilyNameKey, CNContactImageDataAvailableKey, CNContactThumbnailImageDataKey ]
do {
var cNContacts = [CNContact]()
let fetchRequest = CNContactFetchRequest(keysToFetch: keysToFetch)
fetchRequest.sortOrder = CNContactSortOrder.GivenName
try contactStore.enumerateContactsWithFetchRequest(fetchRequest) { (cNContact, pointer) -> Void in
if !cNContact.givenName.isEmpty { // Ignore any Contacts that don't have a Given Name. Garbage Contact.
if searchText == nil {
// Add all Contacts if no searchText is provided.
cNContacts.append(cNContact)
}
else {
// If the Contact contains the search string then add it.
if self.contactContainsText( cNContact, searchText: searchText! ) {
cNContacts.append(cNContact)
}
}
}
}
var contacts = [NSDictionary]();
for cNContact in cNContacts {
contacts.append( convertCNContactToDictionary(cNContact) )
}
callback([NSNull(), contacts])
}
catch let error as NSError {
NSLog("Problem getting unified Contacts")
NSLog(error.localizedDescription)
callback([error.localizedDescription, NSNull()])
}
}
and here is the dictionary converter:
func convertCNContactToDictionary(cNContact: CNContact) -> NSDictionary {
var contact = [String: AnyObject]()
let phoneNumbers = NSMutableArray()
contact["identifier"] = cNContact.identifier
contact["givenName"] = cNContact.givenName
contact["familyName"] = cNContact.familyName
contact["imageDataAvailable"] = cNContact.imageDataAvailable
if (cNContact.imageDataAvailable) {
let thumbnailImageDataAsBase64String = cNContact.thumbnailImageData!.base64EncodedStringWithOptions([])
contact["thumbnailImageData"] = thumbnailImageDataAsBase64String
// let imageDataAsBase64String = cNContact.imageData!.base64EncodedStringWithOptions([])
// contact["imageData"] = imageDataAsBase64String
}
if (cNContact.isKeyAvailable(CNContactPhoneNumbersKey)) {
for number in cNContact.phoneNumbers {
var numbers = [String: AnyObject]()
let phoneNumber = (number.value as! CNPhoneNumber).valueForKey("digits") as! String
let countryCode = (number.value as! CNPhoneNumber).valueForKey("countryCode") as? String
let label = CNLabeledValue.localizedStringForLabel(number.label)
numbers["number"] = phoneNumber
numbers["countryCode"] = countryCode
numbers["label"] = label
phoneNumbers.addObject(numbers)
}
contact["phoneNumbers"] = phoneNumbers
}
let contactAsNSDictionary = contact as NSDictionary
return contactAsNSDictionary;
}
EDIT
So I add a bunch of contacts in my simulator and can reproduce the crash.
Here is the stacktrace:
libswiftCore.dylib`function signature specialization <Arg[0] = Exploded, Arg[1] = Exploded, Arg[2] = Dead, Arg[3] = Dead> of Swift._fatalErrorMessage (Swift.StaticString, Swift.StaticString, Swift.StaticString, Swift.UInt) -> ():
0x107e73180 <+0>: pushq %rbp
0x107e73181 <+1>: movq %rsp, %rbp
0x107e73184 <+4>: pushq %rbx
0x107e73185 <+5>: pushq %rax
0x107e73186 <+6>: movq %rcx, %r10
0x107e73189 <+9>: testb $0x1, %dl
0x107e7318c <+12>: jne 0x107e731aa ; <+42>
0x107e7318e <+14>: testq %rsi, %rsi
0x107e73191 <+17>: js 0x107e731f9 ; <+121>
0x107e73193 <+19>: addq %rdi, %rsi
0x107e73196 <+22>: movzbl %r9b, %eax
0x107e7319a <+26>: movq %r10, %rdx
0x107e7319d <+29>: movq %r8, %rcx
0x107e731a0 <+32>: movl %eax, %r8d
0x107e731a3 <+35>: callq 0x107eccea0 ; function signature specialization <Arg[0] = Exploded, Arg[1] = Exploded> of Swift.(_fatalErrorMessage (Swift.StaticString, Swift.StaticString, Swift.StaticString, Swift.UInt) -> ()).(closure #2)
-> 0x107e731a8 <+40>: ud2
0x107e731aa <+42>: movq $0x0, -0x10(%rbp)
0x107e731b2 <+50>: movl %edi, %eax
0x107e731b4 <+52>: cmpq %rax, %rdi
0x107e731b7 <+55>: jne 0x107e73303 ; <+387>
0x107e731bd <+61>: cmpl $0xd7ff, %edi ; imm = 0xD7FF
0x107e731c3 <+67>: ja 0x107e73222 ; <+162>
0x107e731c5 <+69>: xorl %esi, %esi
0x107e731c7 <+71>: cmpl $0x80, %edi
0x107e731cd <+77>: movl $0x0, %r11d
0x107e731d3 <+83>: jb 0x107e732f6 ; <+374>
0x107e731d9 <+89>: movl %edi, %r11d
0x107e731dc <+92>: shrl $0x6, %r11d
0x107e731e0 <+96>: cmpl $0x800, %edi ; imm = 0x800
0x107e731e6 <+102>: jae 0x107e7329b ; <+283>
0x107e731ec <+108>: orb $-0x40, %r11b
0x107e731f0 <+112>: xorl %esi, %esi
0x107e731f2 <+114>: xorl %ebx, %ebx
0x107e731f4 <+116>: jmp 0x107e732c6 ; <+326>
0x107e731f9 <+121>: leaq 0xd3d92(%rip), %rdi ; "fatal error"
0x107e73200 <+128>: leaq 0xd3f89(%rip), %rcx ; "UnsafeBufferPointer with negative count"
0x107e73207 <+135>: movl $0xb, %esi
0x107e7320c <+140>: movl $0x2, %edx
0x107e73211 <+145>: movl $0x27, %r8d
0x107e73217 <+151>: movl $0x2, %r9d
0x107e7321d <+157>: callq 0x107e73180 ; <+0>
0x107e73222 <+162>: cmpl $0xe000, %edi ; imm = 0xE000
0x107e73228 <+168>: jb 0x107e73272 ; <+242>
0x107e7322a <+170>: cmpl $0x110000, %edi ; imm = 0x110000
0x107e73230 <+176>: jae 0x107e73352 ; <+466>
0x107e73236 <+182>: movl %edi, %r11d
0x107e73239 <+185>: shrl $0x6, %r11d
0x107e7323d <+189>: movl %edi, %eax
0x107e7323f <+191>: shrl $0xc, %eax
0x107e73242 <+194>: cmpl $0xffff, %edi ; imm = 0xFFFF
0x107e73248 <+200>: jbe 0x107e732a0 ; <+288>
0x107e7324a <+202>: movl %edi, %ecx
0x107e7324c <+204>: shrl $0x12, %ecx
0x107e7324f <+207>: orl $0xf0, %ecx
0x107e73255 <+213>: movzbl %cl, %edx
0x107e73258 <+216>: cmpl %edx, %ecx
0x107e7325a <+218>: jne 0x107e73303 ; <+387>
0x107e73260 <+224>: andb $0x3f, %al
0x107e73262 <+226>: orb $-0x80, %al
0x107e73264 <+228>: movzbl %cl, %edx
0x107e73267 <+231>: movq %rdx, -0x10(%rbp)
0x107e7326b <+235>: movl $0x1, %esi
0x107e73270 <+240>: jmp 0x107e732a6 ; <+294>
0x107e73272 <+242>: leaq 0xd3d19(%rip), %rdi ; "fatal error"
0x107e73279 <+249>: leaq 0xd4a80(%rip), %rcx ; "high- and low-surrogate code points are not valid Unicode scalar values"
0x107e73280 <+256>: movl $0xb, %esi
0x107e73285 <+261>: movl $0x2, %edx
0x107e7328a <+266>: movl $0x47, %r8d
0x107e73290 <+272>: movl $0x2, %r9d
0x107e73296 <+278>: callq 0x107e73180 ; <+0>
0x107e7329b <+283>: movl %edi, %eax
0x107e7329d <+285>: shrl $0xc, %eax
0x107e732a0 <+288>: orb $-0x20, %al
0x107e732a2 <+290>: xorl %esi, %esi
0x107e732a4 <+292>: xorl %edx, %edx
0x107e732a6 <+294>: leaq (,%rsi,8), %rcx
0x107e732ae <+302>: andb $0x3f, %r11b
0x107e732b2 <+306>: orb $-0x80, %r11b
0x107e732b6 <+310>: movzbl %al, %ebx
0x107e732b9 <+313>: shlq %cl, %rbx
0x107e732bc <+316>: orq %rdx, %rbx
0x107e732bf <+319>: movq %rbx, -0x10(%rbp)
0x107e732c3 <+323>: incq %rsi
0x107e732c6 <+326>: movl $0x8, %ecx
0x107e732cb <+331>: movq %rsi, %rax
0x107e732ce <+334>: mulq %rcx
0x107e732d1 <+337>: jo 0x107e73303 ; <+387>
0x107e732d3 <+339>: cmpq $0x3f, %rax
0x107e732d7 <+343>: ja 0x107e73329 ; <+425>
0x107e732d9 <+345>: andl $0x3f, %edi
0x107e732dc <+348>: orq $0x80, %rdi
0x107e732e3 <+355>: movzbl %r11b, %r11d
0x107e732e7 <+359>: movb %al, %cl
0x107e732e9 <+361>: shlq %cl, %r11
0x107e732ec <+364>: orq %rbx, %r11
0x107e732ef <+367>: movq %r11, -0x10(%rbp)
0x107e732f3 <+371>: incq %rsi
0x107e732f6 <+374>: movl $0x8, %ecx
0x107e732fb <+379>: movq %rsi, %rax
0x107e732fe <+382>: mulq %rcx
0x107e73301 <+385>: jno 0x107e73305 ; <+389>
0x107e73303 <+387>: ud2
0x107e73305 <+389>: cmpq $0x40, %rax
0x107e73309 <+393>: jae 0x107e73329 ; <+425>
0x107e7330b <+395>: movzbl %dil, %edx
0x107e7330f <+399>: movb %al, %cl
0x107e73311 <+401>: shlq %cl, %rdx
0x107e73314 <+404>: orq %r11, %rdx
0x107e73317 <+407>: movq %rdx, -0x10(%rbp)
0x107e7331b <+411>: leaq -0x10(%rbp), %rdi
0x107e7331f <+415>: leaq 0x1(%rsi,%rdi), %rsi
0x107e73324 <+420>: jmp 0x107e73196 ; <+22>
0x107e73329 <+425>: leaq 0xd3c62(%rip), %rdi ; "fatal error"
0x107e73330 <+432>: leaq 0xd3df9(%rip), %rcx ; "shift amount is larger than type size in bits"
0x107e73337 <+439>: movl $0xb, %esi
0x107e7333c <+444>: movl $0x2, %edx
0x107e73341 <+449>: movl $0x2d, %r8d
0x107e73347 <+455>: movl $0x2, %r9d
0x107e7334d <+461>: callq 0x107e73180 ; <+0>
0x107e73352 <+466>: leaq 0xd3c39(%rip), %rdi ; "fatal error"
0x107e73359 <+473>: leaq 0xd49f0(%rip), %rcx ; "value is outside of Unicode codespace"
0x107e73360 <+480>: movl $0xb, %esi
0x107e73365 <+485>: movl $0x2, %edx
0x107e7336a <+490>: movl $0x25, %r8d
0x107e73370 <+496>: movl $0x2, %r9d
0x107e73376 <+502>: callq 0x107e73180 ; <+0>
0x107e7337b <+507>: nopl (%rax,%rax)
I don't know why this happens though.
I would check if thumbnailImageData is nil and ignore it in that case. It's possible that a record is marked as having a thumbnail but it can't be loaded for some reason, like an incompatible image type.
I tried your code and was able to get it to load over 1200 records quickly and without any issues. I didn't really modify your code at all at first, so I'm not sure why you're getting a crash. I did have a few thoughts though. First, why not use the predicate field on your CNContactFetchRequest? I think that makes things much faster and you get a subset. I realize that may not work for your needs as you may want to search more than the name field. However, here's what it looks like with the refactoring I tried:
func searchContacts(searchText: String?, callback: (NSArray) -> ()) -> Void {
let contactStore = CNContactStore()
let keysToFetch = [ CNContactGivenNameKey, CNContactFamilyNameKey, CNContactImageDataAvailableKey, CNContactThumbnailImageDataKey ]
do {
var contacts = [NSDictionary]();
let fetchRequest = CNContactFetchRequest(keysToFetch: keysToFetch)
fetchRequest.sortOrder = CNContactSortOrder.GivenName
// Create a predicate here based on the search text passed in
fetchRequest.predicate = CNContact.predicateForContactsMatchingName(searchText!)
try contactStore.enumerateContactsWithFetchRequest(fetchRequest) { (cNContact, pointer) -> Void in
// Just append the contact because we won't have any that don't
// contain the search string since we used a predicate.
// The .dictionary property is from our extension and it converts
// the CNContact object to a dictionary
contacts.append(cNContact.dictionary)
}
callback([NSNull(), contacts])
}
catch let error as NSError {
NSLog("Problem getting unified Contacts")
NSLog(error.localizedDescription)
callback([error.localizedDescription, NSNull()])
}
}
Note that I created an extension on CNContact to convert the contact to a dictionary. That code is identical to your conversion code except in a self (CNContact) context:
extension CNContact {
var dictionary : NSDictionary {
var contact = [String: AnyObject]()
let phoneNumbers = NSMutableArray()
contact["identifier"] = self.identifier
contact["givenName"] = self.givenName
contact["familyName"] = self.familyName
contact["imageDataAvailable"] = self.imageDataAvailable
if (self.imageDataAvailable) {
let thumbnailImageDataAsBase64String = self.thumbnailImageData!.base64EncodedStringWithOptions([])
contact["thumbnailImageData"] = thumbnailImageDataAsBase64String
}
if (self.isKeyAvailable(CNContactPhoneNumbersKey)) {
for number in self.phoneNumbers {
var numbers = [String: AnyObject]()
let phoneNumber = (number.value as! CNPhoneNumber).valueForKey("digits") as! String
let countryCode = (number.value as! CNPhoneNumber).valueForKey("countryCode") as? String
let label = CNLabeledValue.localizedStringForLabel(number.label)
numbers["number"] = phoneNumber
numbers["countryCode"] = countryCode
numbers["label"] = label
phoneNumbers.addObject(numbers)
}
contact["phoneNumbers"] = phoneNumbers
}
let contactAsNSDictionary = contact as NSDictionary
return contactAsNSDictionary;
}
}
Out of curiosity I threw your code into a boiler plate master detail table view project that searches contacts and applied my refactoring. You can grab it from here: https://github.com/perlmunger/MemoryContacts . (The search bar in the sample project requires you type at least 3 letters before it tries to search, btw.)

In Rust, is Option compiled to a runtime check or an instruction jump?

In Rust, Option is defined as:
pub enum Option<T> {
None,
Some(T),
}
Used like so:
fn may_return_none() -> Option<i32> {
if is_full_moon {
None
} else {
Some(1)
}
}
fn main() {
let optional = may_return_none();
match optional {
None => println!("None"),
Some(v) => println!("Some"),
}
}
I'm not familiar with Rust internals, but initially I assumed it might work similar to Nullable in .NET, so the compiled logic of my above Rust code would be like so:
// occupies `sizeof(T) + 1` memory space, possibly more depending on `Bool`'s alignment, so `Nullable<Int32>` consumes 5 bytes.
struct Nullable<T> {
Bool hasValue;
T value;
}
Nullable<Int32> MayReturnNone() {
if( isFullMoon )
// as a `struct`, the Nullable<Int32> instance is returned via the stack
return Nullable<Int32>() { HasValue = false }
else
return Nullable<Int32>() { HasValue = true, Value = 1 }
}
void Test() {
Nullable<Int32> optional = may_return_none();
if( !optional.HasValue ) println("None");
else println("Some");
}
However this isn't a zero-cost abstraction because of the space required for the Bool hasValue flag - and Rust makes a point of providing zero-cost abstractions.
I realise that Option could be implemented via a direct return-jump by the compiler, though it would need the exact jump-to values to be provided as arguments on the stack - as though you can push multiple return addresses:
(Psuedocode)
mayReturnNone(returnToIfNone, returnToIfHasValue) {
if( isFullMoon ) {
cleanup-current-stackframe
jump-to returnToIfNone
else {
cleanup-current-stackframe
push-stack 1
jump-to returnToIfHasValue
}
test() {
mayReturnNone( instructionAddressOf( ifHasValue ), instructionAddressOf( ifNoValue ) )
ifHasValue:
println("Some")
ifNoValue:
println("None")
}
Is this how it's implemented? This approach also works for other enum types in Rust - but this specific application I've demonstrated is very brittle and breaks if you want to execute code in-between the call to mayReturnNone and the match statement, for example (as mayReturnNone will jump directly to the match, skipping intermediate instructions).
It depends entirely on optimization. Consider this implementation (playground):
#![feature(asm)]
extern crate rand;
use rand::Rng;
#[inline(never)]
fn is_full_moon() -> bool {
rand::thread_rng().gen()
}
fn may_return_none() -> Option<i32> {
if is_full_moon() { None } else { Some(1) }
}
#[inline(never)]
fn usage() {
let optional = may_return_none();
match optional {
None => unsafe { asm!("nop") },
Some(v) => unsafe { asm!("nop; nop") },
}
}
fn main() {
usage();
}
Here, I've used inline assembly instead of printing because it doesn't clutter up the resulting output as much. Here's the assembly for usage when compiled in release mode:
.section .text._ZN10playground5usage17hc2760d0a512fe6f1E,"ax",#progbits
.p2align 4, 0x90
.type _ZN10playground5usage17hc2760d0a512fe6f1E,#function
_ZN10playground5usage17hc2760d0a512fe6f1E:
.cfi_startproc
pushq %rax
.Ltmp6:
.cfi_def_cfa_offset 16
callq _ZN10playground12is_full_moon17h78e56c4ffd6b7730E
testb %al, %al
je .LBB1_2
#APP
nop
#NO_APP
popq %rax
retq
.LBB1_2:
#APP
nop
nop
#NO_APP
popq %rax
retq
.Lfunc_end1:
.size _ZN10playground5usage17hc2760d0a512fe6f1E, .Lfunc_end1-_ZN10playground5usage17hc2760d0a512fe6f1E
.cfi_endproc
The quick rundown is:
It calls the is_full_moon function (callq _ZN10playground12is_full_moon17h78e56c4ffd6b7730E).
The result of the random value is tested (testb %al, %al)
One branch goes to the nop, the other goes to the nop; nop
Everything else has been optimized out. The function may_return_none basically never exists; no Option was ever created, the value of 1 was never materialized.
I'm sure that various people have different opinions, but I don't think I could have written this any more optimized.
Likewise, if we use the value in the Some (which I changed to 42 to find easier):
Some(v) => unsafe { asm!("nop; nop" : : "r"(v)) },
Then the value is inlined in the branch that uses it:
.section .text._ZN10playground5usage17hc2760d0a512fe6f1E,"ax",#progbits
.p2align 4, 0x90
.type _ZN10playground5usage17hc2760d0a512fe6f1E,#function
_ZN10playground5usage17hc2760d0a512fe6f1E:
.cfi_startproc
pushq %rax
.Ltmp6:
.cfi_def_cfa_offset 16
callq _ZN10playground12is_full_moon17h78e56c4ffd6b7730E
testb %al, %al
je .LBB1_2
#APP
nop
#NO_APP
popq %rax
retq
.LBB1_2:
movl $42, %eax ;; Here it is
#APP
nop
nop
#NO_APP
popq %rax
retq
.Lfunc_end1:
.size _ZN10playground5usage17hc2760d0a512fe6f1E, .Lfunc_end1-_ZN10playground5usage17hc2760d0a512fe6f1E
.cfi_endproc
However, nothing can "optimize" around a contractural obligation; if a function has to return an Option, it has to return an Option:
#[inline(never)]
pub fn may_return_none() -> Option<i32> {
if is_full_moon() { None } else { Some(42) }
}
This makes some Deep Magic assembly:
.section .text._ZN10playground15may_return_none17ha1178226d153ece2E,"ax",#progbits
.p2align 4, 0x90
.type _ZN10playground15may_return_none17ha1178226d153ece2E,#function
_ZN10playground15may_return_none17ha1178226d153ece2E:
.cfi_startproc
pushq %rax
.Ltmp6:
.cfi_def_cfa_offset 16
callq _ZN10playground12is_full_moon17h78e56c4ffd6b7730E
movabsq $180388626432, %rdx
leaq 1(%rdx), %rcx
testb %al, %al
cmovneq %rdx, %rcx
movq %rcx, %rax
popq %rcx
retq
.Lfunc_end1:
.size _ZN10playground15may_return_none17ha1178226d153ece2E, .Lfunc_end1-_ZN10playground15may_return_none17ha1178226d153ece2E
.cfi_endproc
Let's hope I get this right...
Load the 64-bit value 0x2A00000000 to %rdx. 0x2A is 42. This is our Option being built; it's the None variant.
Load %rdx + 1 into %rcx. This is the Some variant.
We test the random value
Depending on the result of the test, move the invalid value to %rcx or not
Move %rcx to %rax - the return register
The main point here is that regardless of optimization, a function that says it's going to return data in a specific format has to do so. Only when it's inlined with other code is it valid to remove that abstraction.
Warning: this comes from the debug build, not release. See the other answer for an optimised version which behaves differently.
You can check the code on the Rust playground
The function compiles to:
.cfi_startproc
pushq %rbp
.Ltmp6:
.cfi_def_cfa_offset 16
.Ltmp7:
.cfi_offset %rbp, -16
movq %rsp, %rbp
.Ltmp8:
.cfi_def_cfa_register %rbp
subq $16, %rsp
.Ltmp9:
.loc 1 6 0 prologue_end
callq is_full_moon#PLT
movb %al, -9(%rbp)
movb -9(%rbp), %al
testb $1, %al
jne .LBB1_3
jmp .LBB1_4
.LBB1_3:
.loc 1 7 0
movl $0, -8(%rbp)
.loc 1 6 0
jmp .LBB1_5
.LBB1_4:
.loc 1 10 0
movl $1, -8(%rbp)
movl $1, -4(%rbp)
.LBB1_5:
.loc 1 12 0
movq -8(%rbp), %rax
addq $16, %rsp
popq %rbp
retq
.Ltmp10:
.Lfunc_end1:
.size _ZN8rust_out15may_return_none17hb9719b83eae05d85E, .Lfunc_end1-_ZN8rust_out15may_return_none17hb9719b83eae05d85E
.cfi_endproc
Which isn't really returning to different places. The space for Option<i32> contains the i32 value as well. That means your function is writing either just the None/Some marker:
movl $0, -8(%rbp)
Or the value as well:
movl $1, -8(%rbp)
movl $1, -4(%rbp)
So I guess the answer to your question is that this:
Rust makes a point of providing zero-cost abstractions
is an assumption that doesn't apply to every single case.

App is crashing without showing any error

CoreFoundation`__CFTypeCollectionRetain:
0x10fd3d830 <+0>: pushq %rbp
0x10fd3d831 <+1>: movq %rsp, %rbp
0x10fd3d834 <+4>: testq %rsi, %rsi
0x10fd3d837 <+7>: je 0x10fd3d842 ; <+18>
0x10fd3d839 <+9>: movq %rsi, %rdi
0x10fd3d83c <+12>: popq %rbp
0x10fd3d83d <+13>: jmp 0x10fd3ac80 ; CFRetain
0x10fd3d842 <+18>: leaq 0x337eed(%rip), %rax ; "*** __CFTypeCollectionRetain() called with NULL; likely a collection has been corrupted ***"
0x10fd3d849 <+25>: movq %rax, 0x368378(%rip) ; gCRAnnotations + 8
0x10fd3d850 <+32>: int3
-> 0x10fd3d851 <+33>: callq 0x10fed9cec ; symbol stub for: getpid
0x10fd3d856 <+38>: movl $0x9, %esi
0x10fd3d85b <+43>: movl %eax, %edi
0x10fd3d85d <+45>: callq 0x10fed9d46 ; symbol stub for: kill
0x10fd3d862 <+50>: nopw %cs:(%rax,%rax)
Log:
objc[24778]: Class MFData is implemented in both /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/PrivateFrameworks/MIME.framework/MIME and /Users/hemang/Library/Developer/CoreSimulator/Devices/8B9DCA42-1446-4D56-871A-2CFBC43DF81A/data/Containers/Bundle/Application/5CAB5F60-AF92-4986-98EC-8F0614619365/Q Hamp.app/Dee Q’s/Q Hamp. One of the two will be used. Which one is undefined.
Please use Exceptional break point to find where app is crashing
#bbum, it was a bad mistake, don't know from whom? (me or Apple). By mistake, I changed Product Name inside Build Settings. Before it was "DeeQHamp", but then I changed it to "DeeQ's/Hamp" and then the problem started. I reverse it to an original name and now its working fine.

Ionic app Crashes giving javascriptcore wtfcrash

Hi am new to this build of an ios app with the ionic, below crash code its populating while testing in the emulator, am not getting what the issues is this, please suggest me what the wrong is going on what this crash states thank you
JavaScriptCore`WTFCrash:
0x11347a090 <+0>: pushq %rbp
0x11347a091 <+1>: movq %rsp, %rbp
0x11347a094 <+4>: subq $0x110, %rsp
0x11347a09b <+11>: movq 0xb6446(%rip), %rax ; globalHook
0x11347a0a2 <+18>: testq %rax, %rax
0x11347a0a5 <+21>: je 0x11347a0a9 ; <+25>
0x11347a0a7 <+23>: callq *%rax
0x11347a0a9 <+25>: leaq -0x110(%rbp), %rdi
0x11347a0b0 <+32>: movl $0x21, %esi
0x11347a0b5 <+37>: callq 0x1134bbae0 ; symbol stub for: backtrace
0x11347a0ba <+42>: leaq -0x100(%rbp), %rdi
0x11347a0c1 <+49>: leal -0x2(%rax), %esi
0x11347a0c4 <+52>: callq 0x113479fc0 ; WTFPrintBacktrace
0x11347a0c9 <+57>: movl $0xbbadbeef, %eax
-> 0x11347a0ce <+62>: movl $0x0, (%rax) //here am getting crash stating bad access
0x11347a0d4 <+68>: ud2
0x11347a0d6 <+70>: nopw %cs:(%rax,%rax)

getting error “dyld_sim`dyld_fatal_error” after app starts

dyld_sim`dyld_fatal_error:
0x103e63000 <+0>: int3
-> 0x103e63001 <+1>: nop
My app is compile & build successfully but it ends with above error.
There're no other messages (error logs).
I set breakpoints in AppDelegate's didFinishLaunghingWithOptions method and in main.m also. But it never stops there.
My app's first view is always visible and error is coming only after it.
I couldn't find anything regarding this error – how can I solve it? Any specific suggestions.
I also tried this,
change frameworks type from Required to Optional.
But nothing works !!
And yes, I'm using CocoaPods.
Update:
My question isn't matched with any other questions, as both having contradict in titles.
Error which I'm getting - dyld_sim`dyld_fatal_error
Error in duplicate (suggestion) question - dyld`dyld_fatal_error:
Update 2:
Update 3:
Crash log
dyld_sim`dyldbootstrap::rebaseDyld:
0x10f95c002 <+0>: pushq %rbp
0x10f95c003 <+1>: movq %rsp, %rbp
0x10f95c006 <+4>: pushq %r15
0x10f95c008 <+6>: pushq %r14
0x10f95c00a <+8>: pushq %r13
0x10f95c00c <+10>: pushq %r12
0x10f95c00e <+12>: pushq %rbx
0x10f95c00f <+13>: subq $0x18, %rsp
0x10f95c013 <+17>: movq %rsi, %rbx
0x10f95c016 <+20>: movq %rdi, %r14
0x10f95c019 <+23>: movl 0x10(%r14), %r13d
0x10f95c01d <+27>: addq $0x20, %r14
0x10f95c021 <+31>: xorl %eax, %eax
0x10f95c023 <+33>: movq %rax, -0x30(%rbp)
0x10f95c027 <+37>: xorl %eax, %eax
0x10f95c029 <+39>: movq %rax, -0x38(%rbp)
0x10f95c02d <+43>: xorl %r12d, %r12d
0x10f95c030 <+46>: xorl %r15d, %r15d
-> 0x10f95c033 <+49>: movl (%r14), %eax
0x10f95c036 <+52>: cmpl $0xb, %eax
0x10f95c039 <+55>: jne 0x10f95c043 ; <+65>
0x10f95c03b <+57>: movq %r14, %r12
0x10f95c03e <+60>: jmp 0x10f95c0cc ; <+202>
0x10f95c043 <+65>: cmpl $0x19, %eax
0x10f95c046 <+68>: jne 0x10f95c0cc ; <+202>
0x10f95c04c <+74>: leaq 0x8(%r14), %rdi
0x10f95c050 <+78>: leaq 0x192c0(%rip), %rsi ; "__LINKEDIT"
0x10f95c057 <+85>: callq 0x10f9751a2 ; strcmp
0x10f95c05c <+90>: testl %eax, %eax
0x10f95c05e <+92>: movq -0x30(%rbp), %rax
0x10f95c062 <+96>: cmoveq %r14, %rax
0x10f95c066 <+100>: movq %rax, -0x30(%rbp)
0x10f95c06a <+104>: leaq 0x48(%r14), %rax
0x10f95c06e <+108>: movl 0x40(%r14), %ecx
0x10f95c072 <+112>: leaq (%rcx,%rcx,4), %rcx
0x10f95c076 <+116>: shlq $0x4, %rcx
0x10f95c07a <+120>: leaq 0x48(%r14,%rcx), %rcx
0x10f95c07f <+125>: jmp 0x10f95c085 ; <+131>
0x10f95c081 <+127>: addq $0x50, %rax
0x10f95c085 <+131>: cmpq %rcx, %rax
0x10f95c088 <+134>: jae 0x10f95c0b3 ; <+177>
0x10f95c08a <+136>: movzbl 0x40(%rax), %edx
0x10f95c08e <+140>: cmpl $0x6, %edx
0x10f95c091 <+143>: jne 0x10f95c081 ; <+127>
0x10f95c093 <+145>: movq 0x28(%rax), %rdx
0x10f95c097 <+149>: shrq $0x3, %rdx
0x10f95c09b <+153>: testl %edx, %edx
0x10f95c09d <+155>: je 0x10f95c081 ; <+127>
0x10f95c09f <+157>: movq 0x20(%rax), %rsi
0x10f95c0a3 <+161>: addq %rbx, %rsi
0x10f95c0a6 <+164>: addq %rbx, (%rsi)
0x10f95c0a9 <+167>: addq $0x8, %rsi
0x10f95c0ad <+171>: decl %edx
0x10f95c0af <+173>: jne 0x10f95c0a6 ; <+164>
0x10f95c0b1 <+175>: jmp 0x10f95c081 ; <+127>
0x10f95c0b3 <+177>: cmpq $0x0, -0x38(%rbp)
0x10f95c0b8 <+182>: jne 0x10f95c0cc ; <+202>
0x10f95c0ba <+184>: testb $0x2, 0x3c(%r14)
0x10f95c0bf <+189>: movl $0x0, %eax
0x10f95c0c4 <+194>: cmovneq %r14, %rax
0x10f95c0c8 <+198>: movq %rax, -0x38(%rbp)
0x10f95c0cc <+202>: movl 0x4(%r14), %eax
0x10f95c0d0 <+206>: addq %rax, %r14
0x10f95c0d3 <+209>: incl %r15d
0x10f95c0d6 <+212>: cmpl %r13d, %r15d
0x10f95c0d9 <+215>: jne 0x10f95c033 ; <+49>
0x10f95c0df <+221>: movl 0x48(%r12), %esi
0x10f95c0e4 <+226>: movl 0x4c(%r12), %edx
0x10f95c0e9 <+231>: testq %rdx, %rdx
0x10f95c0ec <+234>: je 0x10f95c13d ; <+315>
0x10f95c0ee <+236>: movq -0x38(%rbp), %rax
0x10f95c0f2 <+240>: movq 0x18(%rax), %rax
0x10f95c0f6 <+244>: addq %rbx, %rax
0x10f95c0f9 <+247>: movq -0x30(%rbp), %rcx
0x10f95c0fd <+251>: movq %rcx, %rdi
0x10f95c100 <+254>: movq 0x18(%rdi), %rcx
0x10f95c104 <+258>: addq %rbx, %rcx
0x10f95c107 <+261>: addq %rsi, %rcx
0x10f95c10a <+264>: subq 0x28(%rdi), %rcx
0x10f95c10e <+268>: leaq (%rcx,%rdx,8), %rdx
0x10f95c112 <+272>: movl 0x4(%rcx), %esi
0x10f95c115 <+275>: movl %esi, %edi
0x10f95c117 <+277>: andl $0x6000000, %edi
0x10f95c11d <+283>: cmpl $0x6000000, %edi
0x10f95c123 <+289>: jne 0x10f95c14c ; <+330>
0x10f95c125 <+291>: cmpl $0x10000000, %esi
0x10f95c12b <+297>: jae 0x10f95c15f ; <+349>
0x10f95c12d <+299>: movslq (%rcx), %rsi
0x10f95c130 <+302>: addq %rbx, (%rax,%rsi)
0x10f95c134 <+306>: addq $0x8, %rcx
0x10f95c138 <+310>: cmpq %rdx, %rcx
0x10f95c13b <+313>: jb 0x10f95c112 ; <+272>
0x10f95c13d <+315>: addq $0x18, %rsp
0x10f95c141 <+319>: popq %rbx
0x10f95c142 <+320>: popq %r12
0x10f95c144 <+322>: popq %r13
0x10f95c146 <+324>: popq %r14
0x10f95c148 <+326>: popq %r15
0x10f95c14a <+328>: popq %rbp
0x10f95c14b <+329>: retq
0x10f95c14c <+330>: movl $0x8, %edi
0x10f95c151 <+335>: callq 0x10f9710ea ; __cxa_allocate_exception
0x10f95c156 <+340>: leaq 0x191c5(%rip), %rcx ; "relocation in dyld has wrong size"
0x10f95c15d <+347>: jmp 0x10f95c170 ; <+366>
0x10f95c15f <+349>: movl $0x8, %edi
0x10f95c164 <+354>: callq 0x10f9710ea ; __cxa_allocate_exception
0x10f95c169 <+359>: leaq 0x191d4(%rip), %rcx ; "relocation in dyld has wrong type"
0x10f95c170 <+366>: movq %rcx, (%rax)
0x10f95c173 <+369>: leaq 0x24c56(%rip), %rcx ; typeinfo for char const*
0x10f95c17a <+376>: xorl %edx, %edx
0x10f95c17c <+378>: movq %rax, %rdi
0x10f95c17f <+381>: movq %rcx, %rsi
0x10f95c182 <+384>: callq 0x10f971354 ; __cxa_throw
I had this issue after deleting a bunch of things to try and fix another issue. I was able to fix it by reverting the following:
In Project>Build Settings>Runpath Search Paths, add the following (using the + icon, values are comma separated):
$(inherited), #executable_path/Frameworks, #loader_path/Frameworks
Unfortunately, SO text editor made me write it in a code block.

Resources