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

Generic function taking closure with inout parameter can result in a variety of compiler errors or EXC_BAD_ACCESS

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Resolved
    • Priority: Medium
    • Resolution: Done
    • Component/s: Compiler
    • Labels:
      None
    • Environment:

      OS X 10.11.6
      Xcode 8.2.1 (8C1002)

      Description

      There are several related bug reports, but the following example may possibly help toward a fix. The lines which provoke errors all have appended comments. Lines without comments are free of problems.

      func with<T>(_ item: T, _ update: (inout T) -> Void) -> T {
          var this = item
          update(&this)
          return this
      }
      
      
      let i = Int()
      
      _ = with(i) { $0 += 3 }                                   // Compiler error: Ambiguous use of operator '+='
      _ = with(i) { $0 += 3; true }                             // Compiler error: Left side of mutating operator isn't mutable: '$0' is immutable
      _ = with(i) { true; $0 += 3 }                             // Compiler error: Left side of mutating operator isn't mutable: '$0' is immutable
      _ = with(i) { $0 = Int() }
      _ = with(i) { $0 = Int(); true }                          // Compiler error: Cannot assign to value: '$0' is immutable
      _ = with(i) { true; $0 = Int() }                          // Compiler error: Cannot assign to value: '$0' is immutable
      _ = with(i) { (a: inout Int) in a += 3 }
      _ = with(i) { (a: inout Int) in a += 3; true }
      _ = with(i) { (a: inout Int) in true; a += 3 }
      
      
      let s = String()
      
      _ = with(s) { $0.append("Swift") }                        // Compiler error: Type of expression is ambiguous without more context
      _ = with(s) { $0.append("Swift"); true }                  // Compiler error: Cannot use mutating member on immutable value: '$0' is immutable
      _ = with(s) { true; $0.append("Swift") }                  // Compiler error: Cannot use mutating member on immutable value: '$0' is immutable
      _ = with(s) { $0 = String() }
      _ = with(s) { $0 = String(); true }                       // Compiler error: Cannot assign to value: '$0' is immutable
      _ = with(s) { true; $0 = String() }                       // Compiler error: Cannot assign to value: '$0' is immutable
      _ = with(s) { (a: inout String) in a.append("Swift") }
      _ = with(s) { (a: inout String) in a.append("Swift"); true }
      _ = with(s) { (a: inout String) in true; a.append("Swift") }
      
      
      let a = [Int]()
      
      _ = with(a) { $0.append(3) }                              // Compiler error: Type of expression is ambiguous without more context
      _ = with(a) { $0.append(3); true }                        // Compiler error: Cannot use mutating member on immutable value: '$0' is immutable
      _ = with(a) { true; $0.append(3) }                        // Compiler error: Cannot use mutating member on immutable value: '$0' is immutable
      _ = with(a) { $0 = [Int]() }
      _ = with(a) { $0 = [Int](); true }                        // Compiler error: Cannot assign to value: '$0' is immutable
      _ = with(a) { true; $0 = [Int]() }                        // Compiler error: Cannot assign to value: '$0' is immutable
      _ = with(a) { (a: inout [Int]) in a.append(3) }
      _ = with(a) { (a: inout [Int]) in a.append(3); true }
      _ = with(a) { (a: inout [Int]) in true; a.append(3) }
      
      
      let sn = NSMutableString()
      
      _ = with(sn) { $0.append("Swift") }                       // EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
      _ = with(sn) { $0.append("Swift"); true }                 // EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
      _ = with(sn) { true; $0.append("Swift") }                 // EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
      _ = with(sn) { $0 = NSMutableString() }
      _ = with(sn) { $0 = NSMutableString(); true }             // Compiler error: Cannot assign to value: '$0' is immutable
      _ = with(sn) { true; $0 = NSMutableString() }             // Compiler error: Cannot assign to value: '$0' is immutable
      _ = with(sn) { (a: inout NSMutableString) in a.append("Swift") }
      _ = with(sn) { (a: inout NSMutableString) in a.append("Swift"); true }
      _ = with(sn) { (a: inout NSMutableString) in true; a.append("Swift") }
      
      
      let an = NSMutableArray()
      
      _ = with(an) { $0.add(3) }                                // EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
      _ = with(an) { $0.add(3); true }                          // EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
      _ = with(an) { true; $0.add(3) }                          // EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
      _ = with(an) { $0 = NSMutableArray() }
      _ = with(an) { $0 = NSMutableArray(); true }              // Compiler error: Cannot assign to value: '$0' is immutable
      _ = with(an) { true; $0 = NSMutableArray() }              // Compiler error: Cannot assign to value: '$0' is immutable
      _ = with(an) { (a: inout NSMutableArray) in a.add(3) }
      _ = with(an) { (a: inout NSMutableArray) in a.add(3); true }
      _ = with(an) { (a: inout NSMutableArray) in true; a.add(3) }
      
      
      var vi = Int()
      
      vi = with(vi) { $0 += 3 }                                 // Compiler error: parameters may not have the 'var' specifier
      vi = with(vi) { $0 = Int(0) }
      
      
      var vs = String()
      
      vs = with(vs) { $0.append("Swift") }                      // Compiler error: parameters may not have the 'var' specifier
      vs = with(vs) { $0 = String() }
      
      
      var va = [Int]()
      
      va = with(va) { $0.append(3) }                            // Compiler error: parameters may not have the 'var' specifier
      va = with(va) { $0 = [Int]() }
      
      
      var vsn = NSMutableString()
      
      vsn = with(vsn) { $0.append("Swift") }                    // EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
      vsn = with(vsn) { $0 = NSMutableString() }
      
      
      var van = NSMutableArray()
      
      van = with(van) { $0.add(3) }                             // EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
      van = with(van) { $0 = NSMutableArray() }
      
      

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              goldsdad Owen Roberts
              Reporter:
              goldsdad Owen Roberts
              Votes:
              1 Vote for this issue
              Watchers:
              10 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved: