2014-06-16 2 views
11

Ecco un po 'di codice:Qual è la fetta confrontare logica a Swift

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 

E' semplice, ma il codice seguendo:

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

Perché il risultato è "diverso" piuttosto che "Equal"? Posso usare l'operatore == per confrontare il contenuto del tipo di valore di due array o due slice? In caso contrario, perché potrei ottenere i risultati esenti delle prime due dichiarazioni if?

+1

Scommetto che c'era qualcosa di sbagliato nel test. – chiccodoro

+0

Ti sei assicurato di poter riprodurre questo problema in modo affidabile? Per esempio. metti tutto in uno script, eseguilo in un unico passaggio, ottenendo 3 righe di output. O modificare il contenuto dei due array ed eseguire nuovamente il codice. – chiccodoro

+6

L'ho appena provato. È riproducibile al 100%. Mi sembra un errore del compilatore. Puoi aprire un radar su [Segnalazione bug di Apple] (https://bugreport.apple.com). – NSAddict

risposta

3

Credo che questo sia un errore del compilatore che non ha chiamato la corretta funzione di sovraccarico == per confrontare Slice in alcune condizioni.


questo è l'esempio minima sono uscito per produrre il problema

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 

Per vedere quello che è successo, l'ho messo come una prova di unità in un progetto Xcode e controllare il codice di smontaggio

Inizia con il codice corretto:

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

Xcode dammi di quest'acqua

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 

Non è difficile da individuare questa linea

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

sovraccaricato operatore == è chiamato a confrontare il valore


Ora il codice buggy

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

Xcode dammi questo

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 

io non sono esperto di codice assembly, ma una scansione rapida attraverso il commento generato, non riesco a vedere == ovunque.

Inoltre è possibile questi nell'assemblea

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

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

quindi penso che è confrontare il valore del puntatore sottostante al posto del contenuto effettivo delle fette

+0

Ho inviato una segnalazione di errore: [rdar: // 17340722] (http://openradar.appspot.com/17340722) –