2014-06-16 91 views
11
比較邏輯

下面是一些代碼:什麼是分層的斯威夫特

var arr1 = [1, 2, 3, 4] 
var arr2 = [1, 2, 3, 4] 

if arr1 == arr2 { 
    println("Equal") 
} else { 
    println("Not Equal") 
} 
// console output: Equal 

let slice1 = arr1[0..4] 
let slice2 = arr2[0..4] 

if slice1 == slice2 { 
    println("Equal") 
} else { 
    println("Not Equal") 
} 
// console output: Equal 

它的簡單,但代碼如下:

if arr1[0..4] == arr2[0..4] { 
    println("Equal") 
} else { 
    println("Not Equal") 
} 
// console output: Not Equal 

爲什麼結果是「不等於」,而不是「平等」? 我可以使用==運算符來比較兩個數組或兩個切片的值類型內容嗎?如果沒有,爲什麼我可以得到前兩個if聲明的例外結果?

+1

我敢打賭,有一些錯誤的測試的實際內容。 – chiccodoro

+0

您確定可以可靠地重現此問題嗎?例如。將所有內容放在一個腳本中,一步執行,獲得3行輸出。或者更改兩個數組的內容並再次運行代碼。 – chiccodoro

+6

我剛試過。它是100%可重複的。聽起來像是一個編譯器bug。您可以在[Apple的Bug報告工具](https://bugreport.apple.com)上打開雷達。 – NSAddict

回答

3

我相信這是一個編譯器bug,在某些情況下,它沒有調用正確的==過載函數來比較Slice


這是我出來後,產生問題

let s1 : Slice<Int> = Slice(count: 1, repeatedValue:1) 
let s2 : Slice<Int> = Slice(count: 1, repeatedValue:1) 

var b1 = s1[0..1] == s2 // false 
var b2 = s1 == s2  // true 

爲了看看發生了什麼,我把它作爲一個Xcode項目單元測試和檢查的反彙編代碼的最低例子

開始用正確的代碼:

func testSlice2() { 
    b2 = s1 == s2 
} 

的Xcode給我這個

test2Tests`test2Tests.VariableTests.testSlice2 (test2Tests.VariableTests)() ->() at test2Tests.swift:38: 
0x1000ec120: pushq %rbp 
0x1000ec121: movq %rsp, %rbp 
0x1000ec124: subq $0x80, %rsp 
0x1000ec12b: movq %rdi, -0x8(%rbp) 
0x1000ec12f: movq %rdi, -0x10(%rbp) 
0x1000ec133: callq 0x1000efd86    ; symbol stub for: objc_retain 
0x1000ec138: movq -0x10(%rbp), %rdi 
0x1000ec13c: movq %rax, -0x18(%rbp) 
0x1000ec140: callq 0x1000efd8c    ; symbol stub for: object_getClass 
0x1000ec145: movq -0x10(%rbp), %rdi 
0x1000ec149: callq *0x50(%rax) 
0x1000ec14c: movq -0x10(%rbp), %rdi 
0x1000ec150: movq %rax, -0x20(%rbp) 
0x1000ec154: movq %rdx, -0x28(%rbp) 
0x1000ec158: movq %rcx, -0x30(%rbp) 
0x1000ec15c: callq 0x1000efd86    ; symbol stub for: objc_retain 
0x1000ec161: movq -0x10(%rbp), %rcx 
0x1000ec165: movq %rcx, %rdi 
0x1000ec168: movq %rax, -0x38(%rbp) 
0x1000ec16c: callq 0x1000efd8c    ; symbol stub for: object_getClass 
0x1000ec171: movq 0x4ed8(%rip), %rcx  ; (void *)0x00000001047bd8b0: direct type metadata for Swift.Int 
0x1000ec178: addq $0x8, %rcx 
0x1000ec17f: movq 0x4ef2(%rip), %rdx  ; (void *)0x00000001047b6fc8: protocol witness table for Swift.Int : Swift.Equatable 
0x1000ec186: movq -0x10(%rbp), %rdi 
0x1000ec18a: movq %rdx, -0x40(%rbp) 
0x1000ec18e: movq %rcx, -0x48(%rbp) 
0x1000ec192: callq *0x58(%rax) 
0x1000ec195: movq -0x20(%rbp), %rdi 
0x1000ec199: movq -0x28(%rbp), %rsi 
0x1000ec19d: movq -0x30(%rbp), %r8 
0x1000ec1a1: movq %rdx, -0x50(%rbp) 
0x1000ec1a5: movq %r8, %rdx 
0x1000ec1a8: movq %rcx, -0x58(%rbp) 
0x1000ec1ac: movq %rax, %rcx 
0x1000ec1af: movq -0x50(%rbp), %r8 
0x1000ec1b3: movq -0x58(%rbp), %r9 
0x1000ec1b7: movq -0x48(%rbp), %rax 
0x1000ec1bb: movq %rax, (%rsp) 
0x1000ec1bf: movq -0x40(%rbp), %r10 
0x1000ec1c3: movq %r10, 0x8(%rsp) 
0x1000ec1c8: callq 0x1000efc3c    ; symbol stub for: Swift.== @infix <A : Swift.Equatable>(Swift.Slice<A>, Swift.Slice<A>) -> Swift.Bool 
0x1000ec1cd: movq -0x10(%rbp), %rdi 
0x1000ec1d1: movb %al, -0x59(%rbp) 
0x1000ec1d4: callq 0x1000efd86    ; symbol stub for: objc_retain 
0x1000ec1d9: movb -0x59(%rbp), %r11b 
0x1000ec1dd: movzbl %r11b, %edi 
0x1000ec1e1: movq %rax, -0x68(%rbp) 
0x1000ec1e5: callq 0x1000efdb0    ; symbol stub for: ObjectiveC._convertBoolToObjCBool (Swift.Bool) -> ObjectiveC.ObjCBool 
0x1000ec1ea: movq 0x552f(%rip), %rsi  ; "setB2:" 
0x1000ec1f1: movq -0x10(%rbp), %rcx 
0x1000ec1f5: movq %rcx, %rdi 
0x1000ec1f8: movzbl %al, %edx 
0x1000ec1fb: callq 0x1000efd6e    ; symbol stub for: objc_msgSend 
0x1000ec200: movq -0x10(%rbp), %rdi 
0x1000ec204: callq 0x1000efd80    ; symbol stub for: objc_release 
0x1000ec209: movq -0x10(%rbp), %rdi 
0x1000ec20d: callq 0x1000efd80    ; symbol stub for: objc_release 
0x1000ec212: addq $0x80, %rsp 
0x1000ec219: popq %rbp 
0x1000ec21a: retq 

這是不難發現這條線

0x1000ec1c8: callq 0x1000efc3c    ; symbol stub for: Swift.== @infix <A : Swift.Equatable>(Swift.Slice<A>, Swift.Slice<A>) -> Swift.Bool 

重載運營商==被調用,以價值


比較現在對於bug的代碼

func testSlice1() { 
    b1 = s1[0..1] == s2 
} 

的Xcode給我這個

test2Tests`test2Tests.VariableTests.testSlice1 (test2Tests.VariableTests)() ->() at test2Tests.swift:34: 
0x1000ebec0: pushq %rbp 
0x1000ebec1: movq %rsp, %rbp 
0x1000ebec4: pushq %r14 
0x1000ebec6: pushq %rbx 
0x1000ebec7: subq $0xf0, %rsp 
0x1000ebece: movq %rdi, -0x18(%rbp) 
0x1000ebed2: movq %rdi, -0x40(%rbp) 
0x1000ebed6: callq 0x1000efd86    ; symbol stub for: objc_retain 
0x1000ebedb: movq -0x40(%rbp), %rdi 
0x1000ebedf: movq %rax, -0x48(%rbp) 
0x1000ebee3: callq 0x1000efd8c    ; symbol stub for: object_getClass 
0x1000ebee8: movq 0x5161(%rip), %rdi  ; (void *)0x00000001006cb8b0: direct type metadata for Swift.Int 
0x1000ebeef: addq $0x8, %rdi 
0x1000ebef6: movq 0x5163(%rip), %r8   ; (void *)0x00000001006c5158: protocol witness table for Swift.Int : Swift.ForwardIndex 
0x1000ebefd: movq 0x5164(%rip), %rcx  ; (void *)0x00000001006c5120: protocol witness table for Swift.Int : Swift._SignedInteger 
0x1000ebf04: movq 0x5165(%rip), %rdx  ; (void *)0x00000001006c4f90: protocol witness table for Swift.Int : Swift._BuiltinIntegerLiteralConvertible 
0x1000ebf0b: leaq -0x38(%rbp), %rsi 
0x1000ebf0f: leaq -0x28(%rbp), %r9 
0x1000ebf13: leaq -0x20(%rbp), %r10 
0x1000ebf17: movq -0x40(%rbp), %r11 
0x1000ebf1b: movq %rdi, -0x50(%rbp) 
0x1000ebf1f: movq %r11, %rdi 
0x1000ebf22: movq %r10, -0x58(%rbp) 
0x1000ebf26: movq %r8, -0x60(%rbp) 
0x1000ebf2a: movq %rcx, -0x68(%rbp) 
0x1000ebf2e: movq %rdx, -0x70(%rbp) 
0x1000ebf32: movq %rsi, -0x78(%rbp) 
0x1000ebf36: movq %r9, -0x80(%rbp) 
0x1000ebf3a: callq *0x50(%rax) 
0x1000ebf3d: movq $0x0, -0x20(%rbp) 
0x1000ebf45: movq $0x1, -0x28(%rbp) 
0x1000ebf4d: movq -0x58(%rbp), %rsi 
0x1000ebf51: movq -0x80(%rbp), %rdi 
0x1000ebf55: movq -0x78(%rbp), %r8 
0x1000ebf59: movq %rdi, -0x88(%rbp) 
0x1000ebf60: movq %r8, %rdi 
0x1000ebf63: movq -0x88(%rbp), %r8 
0x1000ebf6a: movq %rdx, -0x90(%rbp) 
0x1000ebf71: movq %r8, %rdx 
0x1000ebf74: movq -0x50(%rbp), %r9 
0x1000ebf78: movq %rcx, -0x98(%rbp) 
0x1000ebf7f: movq %r9, %rcx 
0x1000ebf82: movq -0x60(%rbp), %r8 
0x1000ebf86: movq -0x68(%rbp), %r10 
0x1000ebf8a: movq %r10, (%rsp) 
0x1000ebf8e: movq -0x50(%rbp), %r11 
0x1000ebf92: movq %r11, 0x8(%rsp) 
0x1000ebf97: movq %r11, 0x10(%rsp) 
0x1000ebf9c: movq -0x70(%rbp), %rbx 
0x1000ebfa0: movq %rbx, 0x18(%rsp) 
0x1000ebfa5: movq %rax, -0xa0(%rbp) 
0x1000ebfac: callq 0x1000ecac0    ; Swift... @infix <A : Swift.ForwardIndex>(A, A) -> Swift.Range<A> 
0x1000ebfb1: movq 0x5098(%rip), %rax  ; (void *)0x00000001006cb8b0: direct type metadata for Swift.Int 
0x1000ebfb8: addq $0x8, %rax 
0x1000ebfbe: movq -0x38(%rbp), %rdi 
0x1000ebfc2: movq -0x30(%rbp), %rsi 
0x1000ebfc6: movq -0xa0(%rbp), %rdx 
0x1000ebfcd: movq -0x90(%rbp), %rcx 
0x1000ebfd4: movq -0x98(%rbp), %r8 
0x1000ebfdb: movq %rax, %r9 
0x1000ebfde: callq 0x1000efc72    ; symbol stub for: Swift.Slice.subscript.getter (Swift.Range<Swift.Int>) -> Swift.Slice<A> 
0x1000ebfe3: movq 0x5066(%rip), %rsi  ; (void *)0x00000001006cb8b0: direct type metadata for Swift.Int 
0x1000ebfea: addq $0x8, %rsi 
0x1000ebff1: movq %rax, %rdi 
0x1000ebff4: movq %rsi, -0xa8(%rbp) 
0x1000ebffb: movq %rdx, %rsi 
0x1000ebffe: movq %rcx, %rdx 
0x1000ec001: movq -0xa8(%rbp), %rcx 
0x1000ec008: callq 0x1000ec910    ; Swift.Slice.__conversion <A>(Swift.Slice<A>)() -> Swift.CConstVoidPointer 
0x1000ec00d: movq -0x40(%rbp), %rdi 
0x1000ec011: movq %rax, -0xb0(%rbp) 
0x1000ec018: movq %rdx, -0xb8(%rbp) 
0x1000ec01f: callq 0x1000efd86    ; symbol stub for: objc_retain 
0x1000ec024: movq -0x40(%rbp), %rcx 
0x1000ec028: movq %rcx, %rdi 
0x1000ec02b: movq %rax, -0xc0(%rbp) 
0x1000ec032: callq 0x1000efd8c    ; symbol stub for: object_getClass 
0x1000ec037: movq 0x5012(%rip), %rcx  ; (void *)0x00000001006cb8b0: direct type metadata for Swift.Int 
0x1000ec03e: addq $0x8, %rcx 
0x1000ec045: movq -0x40(%rbp), %rdi 
0x1000ec049: movq %rcx, -0xc8(%rbp) 
0x1000ec050: callq *0x58(%rax) 
0x1000ec053: movq %rax, %rdi 
0x1000ec056: movq %rdx, %rsi 
0x1000ec059: movq %rcx, %rdx 
0x1000ec05c: movq -0xc8(%rbp), %rcx 
0x1000ec063: callq 0x1000ec910    ; Swift.Slice.__conversion <A>(Swift.Slice<A>)() -> Swift.CConstVoidPointer 
0x1000ec068: movq -0xb8(%rbp), %rcx 
0x1000ec06f: cmpq %rdx, %rcx 
0x1000ec072: sete %r14b 
0x1000ec076: movq %rax, %rdi 
0x1000ec079: movb %r14b, -0xc9(%rbp) 
0x1000ec080: callq 0x1000efd80    ; symbol stub for: objc_release 
0x1000ec085: movq -0xb0(%rbp), %rdi 
0x1000ec08c: callq 0x1000efd80    ; symbol stub for: objc_release 
0x1000ec091: movq -0x40(%rbp), %rdi 
0x1000ec095: callq 0x1000efd86    ; symbol stub for: objc_retain 
0x1000ec09a: movb -0xc9(%rbp), %r14b 
0x1000ec0a1: movzbl %r14b, %edi 
0x1000ec0a5: movq %rax, -0xd8(%rbp) 
0x1000ec0ac: callq 0x1000efdb0    ; symbol stub for: ObjectiveC._convertBoolToObjCBool (Swift.Bool) -> ObjectiveC.ObjCBool 
0x1000ec0b1: movq 0x5660(%rip), %rsi  ; "setB1:" 
0x1000ec0b8: movq -0x40(%rbp), %rcx 
0x1000ec0bc: movq %rcx, %rdi 
0x1000ec0bf: movzbl %al, %edx 
0x1000ec0c2: callq 0x1000efd6e    ; symbol stub for: objc_msgSend 
0x1000ec0c7: movq -0x40(%rbp), %rdi 
0x1000ec0cb: callq 0x1000efd80    ; symbol stub for: objc_release 
0x1000ec0d0: movq -0x40(%rbp), %rdi 
0x1000ec0d4: callq 0x1000efd80    ; symbol stub for: objc_release 
0x1000ec0d9: addq $0xf0, %rsp 
0x1000ec0e0: popq %rbx 
0x1000ec0e1: popq %r14 
0x1000ec0e3: popq %rbp 
0x1000ec0e4: retq 

我不是專家的彙編代碼,但通過生成的評論快速掃描,我看不到==任何地方。

你也可以將這些組件中

0x1000ec008: callq 0x1000ec910    ; Swift.Slice.__conversion <A>(Swift.Slice<A>)() -> Swift.CConstVoidPointer 

0x1000ec063: callq 0x1000ec910    ; Swift.Slice.__conversion <A>(Swift.Slice<A>)() -> Swift.CConstVoidPointer 

所以我認爲這是比較底層的指針值而不是切片

+0

我已提交錯誤報告:[rdar:// 17340722](http://openradar.appspot.com/17340722) –