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

Implementation for /most/ of SE-0192 (frozen and non-frozen enums) #14945

Merged
merged 12 commits into from
Mar 21, 2018

Conversation

jrose-apple
Copy link
Contributor

An alternative to #11961 that only makes a frozen / non-frozen distinction for imported C enums and for Swift enums in the stdlib/overlays. (Really, it's "libraries compiled with -enable-resilience", and exactly what that means has not been discussed publicly and is not part of SE-0192.)

This does not include the implementation of unknown case, or whatever we end up naming it. That's a big enough change on its own that it deserves its own PR, and this part can land first.

The diagnostics part of this is behind a frontend flag, -enable-nonfrozen-enum-exhaustivity-diagnostics.

@jrose-apple
Copy link
Contributor Author

@swift-ci Please test

@jrose-apple
Copy link
Contributor Author

@swift-ci Please test source compatibility

@jrose-apple
Copy link
Contributor Author

@swift-ci Please test compiler performance

@swift-ci
Copy link
Contributor

swift-ci commented Mar 3, 2018

Build failed
Swift Test Linux Platform
Git Sha - 323abe749e92c655446f025896a21cfc590bbf6c

@swift-ci
Copy link
Contributor

swift-ci commented Mar 3, 2018

Build comment file:

Compilation-performance test failed

@jrose-apple
Copy link
Contributor Author

@swift-ci Please test

@jrose-apple
Copy link
Contributor Author

@swift-ci Please test compiler performance

@jrose-apple
Copy link
Contributor Author

@swift-ci Please test source compatibility

@swift-ci
Copy link
Contributor

swift-ci commented Mar 3, 2018

Build failed
Swift Test OS X Platform
Git Sha - 323abe749e92c655446f025896a21cfc590bbf6c

@jrose-apple
Copy link
Contributor Author

@swift-ci Please test source compatibility

@jrose-apple
Copy link
Contributor Author

@swift-ci Please test compiler performance

@jrose-apple
Copy link
Contributor Author

@swift-ci Please test

@swift-ci
Copy link
Contributor

swift-ci commented Mar 3, 2018

Build failed
Swift Test OS X Platform
Git Sha - 323abe749e92c655446f025896a21cfc590bbf6c

@swift-ci
Copy link
Contributor

swift-ci commented Mar 3, 2018

Build failed
Swift Test Linux Platform
Git Sha - 323abe749e92c655446f025896a21cfc590bbf6c

@swift-ci
Copy link
Contributor

swift-ci commented Mar 3, 2018

Build comment file:

Compilation-performance test failed

@jrose-apple
Copy link
Contributor Author

@swift-ci Please test

@swift-ci
Copy link
Contributor

swift-ci commented Mar 5, 2018

Build failed
Swift Test OS X Platform
Git Sha - 094ea9cc2d9bd12436229dbdfec45dc12ca907da

@swift-ci
Copy link
Contributor

swift-ci commented Mar 5, 2018

Build failed
Swift Test Linux Platform
Git Sha - 094ea9cc2d9bd12436229dbdfec45dc12ca907da

@jrose-apple
Copy link
Contributor Author

@swift-ci Please test

@swift-ci
Copy link
Contributor

swift-ci commented Mar 5, 2018

Build failed
Swift Test Linux Platform
Git Sha - a98032b19ea6c4dc78a3b835b1c6a277f8f48068

@swift-ci
Copy link
Contributor

swift-ci commented Mar 5, 2018

Build failed
Swift Test OS X Platform
Git Sha - a98032b19ea6c4dc78a3b835b1c6a277f8f48068

@jrose-apple
Copy link
Contributor Author

@swift-ci Please clean test macOS

@swift-ci
Copy link
Contributor

swift-ci commented Mar 6, 2018

Build failed
Swift Test OS X Platform
Git Sha - 906af8ee3b9951cee00c26382e8762f8ccde9d1c

@jrose-apple
Copy link
Contributor Author

@swift-ci Please test macOS

@jrose-apple
Copy link
Contributor Author

@swift-ci Please test compiler performance

@jrose-apple
Copy link
Contributor Author

@swift-ci Please test source compatibility

@jrose-apple
Copy link
Contributor Author

@jrose-apple
Copy link
Contributor Author

@swift-ci Please test source compatibility

@jrose-apple jrose-apple changed the title [WIP] Implementation for SE-0192 (frozen and non-frozen enums) Implementation for /most/ of SE-0192 (frozen and non-frozen enums) Mar 20, 2018
Copy link
Member

@DougGregor DougGregor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good. The space engine part is appropriately mind-boggling, but I've convinced myself it looks good. Nice work!

@@ -1101,7 +1101,7 @@ public struct CodingUserInfoKey : RawRepresentable, Equatable, Hashable {
//===----------------------------------------------------------------------===//

/// An error that occurs during the encoding of a value.
@_fixed_layout // FIXME(sil-serialize-all)
@_frozen // FIXME(sil-serialize-all)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a surprise to me; why should encoding and decoding errors be frozen? I'd expect this to grow over time, like most error types.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They'll definitely get un-frozen. This commit did not remove any frozens that were currently there.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... it did in stdlib/public/Platform/POSIXError.swift

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

…oops. Okay, I'll be consistent.

public enum _DebuggerSupport {
@_fixed_layout // FIXME(sil-serialize-all)
@_frozen // FIXME(sil-serialize-all)
@_versioned // FIXME(sil-serialize-all)
internal enum CollectionStatus {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any point to a frozen internal enum?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's versioned, so yes.

Name: EnumExhaustivity
Tags:
- Name: RegularEnumTurnedExhaustiveThenBackViaAPINotes
EnumExtensibility: open
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd never seen this cute "no newline at end of file" GitHub graphic before

@@ -239,6 +242,10 @@ namespace swift {
/// Diagnose uses of NSCoding with classes that have unstable mangled names.
bool EnableNSKeyedArchiverDiagnostics = true;

/// Diagnose switches over non-frozen enums that do not have catch-all
/// cases.
bool EnableNonFrozenEnumExhaustivityDiagnostics = false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is for staging while we settle on the "unknown case" spelling, right? It'll go away then?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's mainly so I can land this part before SE-0192's review period ends, but yes.

Copy link
Contributor

@slavapestov slavapestov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add some code generation (SILGen) tests for -enable-testing. I imagine we'll want to trap if the original library evolves resiliently, right?

Also, library evolution tests for non-frozen @objc enums to ensure the unknown case is handled properly.


// All other checks are use-site specific; with no further information, the
// enum must be treated non-exhaustively.
if (!useDC)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we ever need to check exhaustiveness in SILGen or anything else that runs after Sema? Because we won't have a useDC anymore

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we'll have a DC up through SILGen, but you do have me worried about optimizations. Unfortunately we don't actually the right API for that ("AvailabilityContext"); fortunately, it'll err on the side of "non-exhaustive". (That is, passing nullptr or the containing module or the containing source file might answer "non-exhaustive" when it could be "exhaustive", but never the other way around.)

void AttributeChecker::visitFrozenAttr(FrozenAttr *attr) {
switch (D->getModuleContext()->getResilienceStrategy()) {
case ResilienceStrategy::Default:
// FIXME: Don't warn about the use of this attribute in the standard
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You might be able to get away with removing this now that resilience is on

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, yes, I forgot about this!

@@ -121,25 +127,25 @@ namespace {
// potentially push an enormous fixit on the user.
static const size_t MAX_SPACE_SIZE = 128;

size_t computeSize(TypeChecker &TC,
size_t computeSize(TypeChecker &TC, const DeclContext *DC,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's awkward to plumb the DC (and TC) through everything here -- can't we make them instance variables?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, that makes sense. I'll save it for the next half, though, where I implement unknown:.

@@ -1101,7 +1101,7 @@ public struct CodingUserInfoKey : RawRepresentable, Equatable, Hashable {
//===----------------------------------------------------------------------===//

/// An error that occurs during the encoding of a value.
@_fixed_layout // FIXME(sil-serialize-all)
@_frozen // FIXME(sil-serialize-all)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... it did in stdlib/public/Platform/POSIXError.swift

In theory there could be a "fixed-layout" enum that's not exhaustive
but promises not to add any more cases with payloads, but we don't
need that distinction today.

(Note that @objc enums are still "fixed-layout" in the actual sense of
"having a compile-time known layout". There's just no special way to
spell that.)
Still to do: test and fix up the use of multiple enum_extensibility
annotations, possibly with API notes. This is important because the
definition of NS/CF_ENUM /includes/ enum_extensibility(open) as of
Xcode 9.0; there should be a convenient out people can use to declare
exhaustive enums in C that's backwards-compatible.
Since NS_ENUM has an enum_extensibility(open) in it already, we want
to allow people to undo that by sticking enum_extensibility(closed) on
the end of their enum.
Previously (a03c40c) we assumed all Swift enums were non-frozen in
ObjC, a weird choice in retrospect. Now that we actually distinguish
frozen and non-frozen enums in Swift, we can use the
'enum_extensibility' attribute to mark them as open or closed in ObjC.

Note that this only matters for Swift libraries compiled with
-enable-resilience, i.e. those that might get a new implementation at
runtime. Everyone else is now declaring a "closed" enum, matching the
behavior in Swift.
Error codes, FloatingPointRoundingRule, Mirror.AncestorRepresentation,
Mirror.DisplayStyle, and PlaygroundQuickLook.
That's just ARCamera.TrackingState and DispatchTimeoutResult.
Verified with the framework owners at Apple.
@jrose-apple
Copy link
Contributor Author

We do have the "evolution" tests for non-frozen enums by testing private cases, but I'll add the ones for -enable-testing!

@slavapestov
Copy link
Contributor

@jrose-apple The case I'm thinking of is when you switch over an @objc non-frozen enum, we want to make sure we don't hit UB if you pass in an unknown case

@jrose-apple
Copy link
Contributor Author

Sorry, I forgot that one already landed. :-) See #14724.

@jrose-apple
Copy link
Contributor Author

Addressed feedback.

@swift-ci Please smoke test

@jrose-apple
Copy link
Contributor Author

Merging even though the proposal is still in review in order to get some living-on (and so that I don't have to keep rebasing it). Note that the diagnostics are still off and unknown is not yet implemented. (That's #14382, which I'm currently working on rebasing.)

@ptrkstr
Copy link

ptrkstr commented Jan 8, 2020

Is there a way to suppress the warning this produces if you don't have a @unknown default in your switch?

@jrose-apple
Copy link
Contributor Author

I'm not working on Swift anymore, but people have talked about this for "I know this library is built with library evolution turned on, but I'm embedding it in my app, so it can't possibly change out from under me". It's not clear that such an annotation would really be any better than just writing the @unknown default though.

@jrose-apple
Copy link
Contributor Author

jrose-apple commented Feb 7, 2020

I do suggest taking this discussion to the forums rather than commenting on a two-year-old PR, if you haven't already. (As you noticed, it took a month for me to even see it!)

@AnthonyLatsis AnthonyLatsis added compiler The Swift compiler itself library evolution Feature: library evolution (umbrella feature for features that facilitate resilient libraries) switch exhaustivity Feature: enforcement of exhaustivity in 'switch' statements enum Feature → type declarations: Swift enumeration declarations feature A feature request or implementation swift evolution implemented Flag → feature: A feature that was approved through the Swift evolution process and implemented labels Mar 23, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler The Swift compiler itself enum Feature → type declarations: Swift enumeration declarations feature A feature request or implementation library evolution Feature: library evolution (umbrella feature for features that facilitate resilient libraries) swift evolution implemented Flag → feature: A feature that was approved through the Swift evolution process and implemented switch exhaustivity Feature: enforcement of exhaustivity in 'switch' statements
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants