Guard Let throws warnings but Let does not (Swift 5.2)

I'm perplexed on this one. The only difference between these two code examples is that one uses let, and the other uses guard let.

.readObjects returns [Any]? which may be causing the compiler to get confused and this looks like a bug.

The first example produces [URL]? successfully. The second example with the same code but using guard instead (which you assume would unwrap the optional array to produce [URL]), fails to compile.

Swift 5.2, Xcode 11.3.1

This compiles:

override func performDragOperation(_ sender: NSDraggingInfo) -> Bool {
    let files = sender
        .draggingPasteboard
        .readObjects(forClasses: [NSURL.self])?
        .compactMap { $0 as? URL }
    
    print(files)
    
    return true
}

This does NOT compile:

override func performDragOperation(_ sender: NSDraggingInfo) -> Bool {
    guard let files = sender
        .draggingPasteboard
        .readObjects(forClasses: [NSURL.self])?
        .compactMap { $0 as? URL }
    else { return false }
    
    print(files)
    
    return true
}

Compiler is confused by the trailing closure. Try surrounding your sender.draggingblahblahblah.compactMap { $0 as? URL } in parentheses, or don't use trailing closures, so that it's clear where it ends

https://bugs.swift.org/browse/SR-7503

1 Like

Thanks, that seems to resolve it but you'd never guess from the warnings.

Added parens to the compactMap closure as suggested:

override func performDragOperation(_ sender: NSDraggingInfo) -> Bool {
    guard let files = sender
        .draggingPasteboard
        .readObjects(forClasses: [NSURL.self])?
        .compactMap({ $0 as? URL })
    else { return false }
    
    print(files)
    
    return true
}
1 Like

The behavior is exactly the same with Xcode 12b3.

Terms of Service

Privacy Policy

Cookie Policy