2014-06-06 3 views
3

다음 코드는 WWDC의 중급 스위프트 토크 예제에서 파생 된 것입니다. 내가 뭘하려고하는지 API 클래스의 일종에서 온 키 속성 목록에서 모델 클래스를 초기화하는 것입니다. 나는이 컴파일 할 때스위프트 스위치 케이스 컴파일러 오류

class Movie { 
    var title: String 

    init(title: String) { 
    self.title = title 
    } 
} 

func movieFromDictionary(dict: Dictionary<String, AnyObject>) -> Movie? { 
    switch dict["title"] { 
    case .Some(let movieTitle as String): 
    return Movie(title: movieTitle) 
    default: 
    return nil 
    } 
} 

, 나는 다음과 같은 오류가 발생합니다 :

Bitcast requires both operands to be pointer or neither 
    %38 = bitcast i8* %37 to %SS, !dbg !161 
Invalid operand types for ICmp instruction 
    %39 = icmp ne %SS %38, null, !dbg !161 
PHI nodes must have at least one entry. If the block is dead, the PHI should be removed! 
    %42 = phi i64 , !dbg !161 
PHI node operands are not the same type as the result! 
    %41 = phi i8* [ %38, %34 ], !dbg !161 
LLVM ERROR: Broken function found, compilation aborted! 
Command /Applications/Xcode6-Beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift failed with exit code 1 

흥미롭게 편집기 코드로 확인 될 것으로 보인다. 이것은 컴파일러 버그 또는 코드에 문제가 있습니까?

+2

이것은 확실히 컴파일러 버그입니다. – rightfold

+1

코드가 맞는지 여부에 관계없이 이것은 컴파일러 버그입니다. 컴파일러는 코드를 분석하고 코드가 올바른지 아닌지를 결정할 수 있어야합니다. 잘못된 코드 일 경우 오류를 발생 시키거나 올바른 경우 유효한 코드를 생성 할 수 있어야합니다. 이 경우에는 올바른 것으로 결정한 다음 __invalid__ 낮은 수준의 코드가 생성되어서는 안됩니다. 사과에게이 사실을보고해야합니다. –

답변

1

의견 작성자는 apple에게 신고해야하는 컴파일러 버그임을 동의합니다.

func movieFromDictionary(dict: Dictionary<String, AnyObject>) -> Movie? { 
    if let title = dict["title"] as? String { 
    return Movie(title: title) 
    } 
    else { 
    return nil 
    } 
} 
+0

당신 말이 맞아요. 그러나 내가 뭘했는지 실제로 하나 이상의 필드를 초기화하려고합니다. 그래서 "제목"속성뿐만 아니라 그 중 몇 가지. 하나의 스위치에서 속성을 패턴 일치와 일치 시키려면 훨씬 더 짧습니다. 그것은 작동하지 않았기 때문에 어디에서 문제가 발생했는지 알아보기 위해 하나의 속성 만 사용했습니다. – Haldun

0

내가 유사한 문제가 있고, 내가 일을 추출하면 내가 처음에 전환 된 것으로 나타났습니다, 그것은 모든 : 그러나, 당신은 또한 그것을 간단하고 잘 작동합니다이 방법을 구현할 수 있습니다 즉 잘 작동했다.

대신으로도 유사한

let s:AnyObject = segue.sourceViewController 
switch s { 
    case let c as XYZAddToDoItemViewController where c.toDoItem.name.utf16count > 0 : toDoItems.append(c.toDoItem) 
     tableView.reloadData() 
    default: println("Unexpected source controller") 
} 
0
switch dict["title"] { 
case .Some(let movieTitle as String): 

난 그냥 발생 뭔가를 당신은 당신이 처음에 전환하고있는 것을 선언한다 (그리고이 AnyObject 주장)

switch segue.sourceViewController { 
    case let c as XYZAddToDoItemViewController where c.toDoItem.name.utf16count > 0 : toDoItems.append(c.toDoItem) 
     tableView.reloadData() 
    default: println("Unexpected source controller") 
} 

의 사전. 문제는 내가 더블 캐스트라고 부르는 것 같다. dict["title"]AnyObject!입니다. 즉, 선택 사항입니다. 그것이 암묵적으로 풀리지 않는다는 사실은 지금 당장은 무의미합니다. 이제 당신은 그것을 String으로 던지려고합니다. 그래서 당신은 한 번에 두 주조 조치를 취하고 있습니다 :

  • 당신은 당신은 AnyObject로 입력되는 선택 사양은 문자열
에 주조로 내부에 무엇이 원하는 옵션
  • 랩을 해제하려면

    컴파일러 문제를 일으키는 것은이 이중 캐스트입니다. 더 나은 오류 메시지를 제공해야하며이 문제는 쉽게 재현 할 수 있으므로 버그를 신고해야합니다. 그럼에도 불구하고 이런 종류의 더블 캐스팅은 잘못되었다고 생각합니다. 위의 글 머리 기호와 같이 두 단계로 수행해야합니다. 먼저 dict["title"]이 nil인지 확인한 다음, 그렇지 않은 경우에만 펼치고 문자열로 캐스트 할 수 있는지 확인합니다.

    (상황은 NSDictionary와 Dictionary 사이의 상호 작용이 깨끗하지 못하기 때문에 도움이되지 않습니다. 제 경우에는 사전이 사용자 기본값에서 벗어나기 때문에 상황이 훨씬 복잡해졌습니다. 그 자체은 선택 사항입니다.