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

EXC_BAD_ACCESS stemming from protocol definition not including class, but including class-based restraint

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Resolved
    • Priority: Medium
    • Resolution: Done
    • Component/s: Compiler
    • Environment:
      • Xcode 10.1 (10B61)
      • Swift 4.2.1
      • macOS 10.13.6 (17G5019)

      Description

      A crash named EXC_BAD_ACCESS occurs with the following setup:

      • Swift 4.2.1 (as bundled with Xcode 10.1)
      • A protocol which is not class-bound, but which has a where clause requiring it to inherit from any other class
        • At least one function or variable requirement of that protocol
      • A class which conforms to the aforementioned protocol
      • A variable or constant whose type is explicitly the aforementioned protocol, and whose instance is of the aforementioned class
      • A call to the protocol-required function or variable of the aforementioned variable

      Expected outcome

      Calling the function or variable requirement on the implementation instance will actually call said function or variable

      Actual outcome

      Attempting to perform such a call results in EXC_BAD_ACCESS

      Known workarounds

      1. On the protocol, add : class to make it class-bound. This is not always possible as it results in a Swift compiler warning, and some projects/businesses require "Treat Warnings As Errors" be set to "Yes", which will cause this to fail a compile attempt
      2. On the variable declaration, explicitly type it to the implementation class' type. This is not always possible as that type is not always knowable at that time of writing (e.g. implementation class might be internal to some other framework)

      SSCCE

      open class Bar {}
      
      
      
      protocol Foo where Self : Bar { // Fix 1: change this to `protocol Foo : class where Self : Bar {`
          func bar()
          var baz: Any { get }
      }
      
      
      
      class FooImpl : Bar, Foo {
          func bar() {
              print("You called bar!")
          }
          
          let baz: Any = "This is baz"
      }
      
      
      
      let myFoo: Foo // Fix 2: change this to `let myFoo: FooImpl`
      myFoo = FooImpl()
      
      myFoo.bar() // crash: EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
      print(myFoo.baz) // if the previous line is commented-out, crash: EXC_BAD_ACCESS (code=1, address=0xfffffffffffffff8)
      

        Attachments

          Activity

            People

            Assignee:
            Unassigned Unassigned
            Reporter:
            BenLeggiero Ben Leggiero
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Dates

              Created:
              Updated:
              Resolved: