2014-06-16 16 views
11

Hier einige Code:Was ist die Scheibe Vergleichslogik in 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 

Es ist einfach, aber Sie folgenden Code:

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

Warum das Ergebnis "nicht gleich" statt "Equal"? Kann ich den Operator == verwenden, um den Werttyp Inhalt von zwei Arrays oder zwei Slices zu vergleichen? Wenn nicht, warum konnte ich die freigestellten Resultate der ersten zwei if Aussage erhalten?

+1

Vergleich Ich wette, es ist etwas falsch in dem Test war. – chiccodoro

+0

Haben Sie sichergestellt, dass Sie dieses Problem zuverlässig reproduzieren können? Z.B. setze alles in ein Skript, führe es in einem einzigen Schritt aus und erhalte 3 Zeilen Ausgabe. Oder ändern Sie den Inhalt der beiden Arrays und führen Sie den Code erneut aus. – chiccodoro

+6

Ich habe es gerade versucht. Es ist 100% reproduzierbar. Klingt für mich wie ein Compiler-Bug. Sie können ein Radar in [Apples Bug Reporting Tool] (https://bugreport.apple.com) öffnen. – NSAddict

Antwort

3

Ich glaube, das ist ein Compiler Fehler, der nicht die korrekte == Überlastfunktion aufgerufen hat, Slice unter bestimmten Bedingungen zu vergleichen.


dies ist das Mindeste Beispiel I

das Problem zu produzieren kam
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 

Um zu sehen, was passiert ist, ich es als eine Einheit Test in einem Xcode-Projekt setzen und überprüfen Sie die Demontage Code

beginnen Sie mit dem richtigen Code:

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

Xcode gib mir dieses

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 

Es ist nicht schwer, diese Linie zu erkennen

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

überladenen Operator == aufgerufen, um den Wert


jetzt für fehlerhaften Code

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

Xcode zu vergleichen gib mir diese

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 

Ich bin kein Experte von Assembler-Code, sondern ein schneller Scan durch den erzeugten Kommentar, ich kann nicht == überall sehen.

Auch können Sie diese bei der Montage

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

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

so denke ich, es ist die zugrunde liegende Zeigerwert statt den tatsächlichen Inhalt der Scheiben

+0

Ich habe einen Fehlerbericht gesendet: [rdar: // 17340722] (http://openradar.appspot.com/17340722) –