Uploaded image for project: 'Swift'
  1. Swift
  2. SR-2942

Errant ambiguous overloaded method when return type optionality differs

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Open
    • Priority: Medium
    • Resolution: Unresolved
    • Component/s: Compiler
    • Labels:
    • Environment:

      Xcode 8, macOS 10.11.6

      Description

      The attached Xcode playground demonstrates this behavior. If two versions of a method exist that differ only in the optionality of the return type, the compiler should be able to choose the optional one when called within an if-let context. In Xcode 8 (8A218a), it's ambiguous without more context.

      import Foundation
      
      extension
      String
      {
          public
          func
          deleting(prefix inPrefix: String)
              -> String
          {
              //  If it's not a substring, return self…
              
              guard
                  let r = self.range(of: inPrefix)
              else
              {
                  return self
              }
              
              //  If it's not the prefix, return self…
              
              if r.lowerBound != self.startIndex
              {
                  return self
              }
              
              return self.substring(from: r.upperBound)
          }
      
          public
          func
          deleting(prefix inPrefix: String)
              -> String?
          {
              //  If it's not a substring, return self…
              
              guard
                  let r = self.range(of: inPrefix)
              else
              {
                  return nil
              }
              
              //  If it's not the prefix, return self…
              
              if r.lowerBound != self.startIndex
              {
                  return nil
              }
              
              return self.substring(from: r.upperBound)
          }
      }
      
      let s = "Hello there"
      
      //  Case 1 (works)
      
      let a: String = s.deleting(prefix: "Hello ")
      print("a: \(a)")
      
      //  Case 2 (works)
      
      if let b: String = s.deleting(prefix: "Bar")
      {
          print("b: \(b) (Oops)")
      }
      else
      {
          print("b: \(s) (Correct)")
      }
      
      //  Case 3 (ambiguous, but shouldn’t be)
      
      if let c = s.deleting(prefix: "Bar")
      {
          print("b: \(b) (Oops)")
      }
      else
      {
          print("b: \(s) (Correct)")
      }
      

        Attachments

          Activity

            People

            • Assignee:
              Unassigned
              Reporter:
              rmann Rick M
            • Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

              • Created:
                Updated: