Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SR-13090] Runtime crash when conforming to unavailable protocol (Identifiable) #55536

Closed
robmaceachern opened this issue Jun 26, 2020 · 4 comments

Comments

@robmaceachern
Copy link

robmaceachern commented Jun 26, 2020

Previous ID SR-13090
Radar rdar://problem/64953120
Original Reporter @robmaceachern
Type Bug
Status Resolved
Resolution Done

Attachment: Download

Environment

Xcode 11.5 and Xcode 12 beta 1

Swift 5.1 and 5.3

Additional Detail from JIRA
Votes 1
Component/s Compiler
Labels Bug, TypeChecker
Assignee None
Priority Medium

md5: fb7f8d30c8452a22e9ddddbf84515984

Issue Description:

It's possible to build and run code (without warnings) where a type conforms to a protocol that isn't available for a deployment target which then crashes at runtime.

My example uses an `Identifiable` conformance in an app with an iOS 12 deployment target.

It seems like the line `struct Store<T> where T: Animal` should be generating a compile error like: `'Animal' is only available in iOS 13 or newer`.

Edit: See sample project. Couldn't get code formatted properly. The app crashes when run on the iOS 12 simulator.

@typesanitizer
Copy link

typesanitizer commented Jun 26, 2020

Confirming that I can reproduce using an iPhone 8 Plus iOS 12.4 simulator + Xcode 12 beta 1 toolchain. With a master compiler + Xcode 12 beta 1, lldb itself crashes.

@swift-ci create

@theblixguy
Copy link
Collaborator

theblixguy commented Jul 15, 2020

Looks like the compiler isn't checking for availability in certain contexts. Here's an example that doesn't rely on a stdlib protocol.

// Xcode 12 beta 1
// Deployment target: iOS 14
// -------------------------------------
@available(iOS 15.0, *)
protocol Foo {}

class A: Foo {} // This doesn't trigger an error

class B {}
extension B: Foo {} // No error

class C {
    let foo: Foo! // 'Foo' is only available in iOS 15.0 or newer
    init() {
        fatalError()
    }
}

let a1 = A() // No error

let a2: Foo = A() // ''Foo' is only available in iOS 15.0 or newer'

func foo1<T: Foo>() -> T { fatalError() } // ''Foo' is only available in iOS 15.0 or newer'

func foo2(arg: Foo) { fatalError() } // ''Foo' is only available in iOS 15.0 or newer'

I suppose this is fine because the error is eventually trigger later on (such as in the a2: Foo case). It looks like this is one scenario where it doesn't trigger:

@available(iOS 15, *)
protocol P {
  var foo: Int { get }
}

protocol Q: P {}
struct S: Q { let foo = 0 }
class C<T: Q> {}

let s = C<S>()

@theblixguy
Copy link
Collaborator

theblixguy commented Jul 15, 2020

I did a little bit of research and found this comment here:

// We allow a type to conform to a protocol that is less available than
// the type itself. This enables a type to retroactively model or directly
// conform to a protocol only available on newer OSes and yet still be used on
// older OSes.
// To support this, inside inheritance clauses we allow references to
// protocols that are unavailable in the current type refinement context.

@slavapestov
Copy link
Member

slavapestov commented Feb 25, 2022

Swift 5.5 checks conformance availability.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants