Skip to content

CSGen, SILGen: Fix delegations to Optional initializers #59171

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

Merged

Conversation

AnthonyLatsis
Copy link
Collaborator

Resolves #57012 and more.

There remains a family of malfunctioning edge cases that I'm not sure what to make of. Specifically, when the constructed Optional value is force-unwrapped:

extension Optional {
  init(nonFailable: Void) { ... }
  init?(failable: Void) { ... }

  init(delegation1: Void) {
    self.init(nonFailable: ())! // this
  }

   init(delegation2: Void) {
    self.init(failable: ())!! // or this
  }
}

extension Optional where Wrapped == Optional<Bool> {
  init(delegation3: Void) {
    self.init(nonFailable: ())!! // or this
  }
}

I guess we should either deal with them using optional injections or ban them.

@AnthonyLatsis AnthonyLatsis requested review from jckarter and hborla May 31, 2022 15:03
@AnthonyLatsis
Copy link
Collaborator Author

@swift-ci please smoke test macOS

@AnthonyLatsis
Copy link
Collaborator Author

@swift-ci please test source compatibility

@AnthonyLatsis
Copy link
Collaborator Author

@jckarter ping

…zers

Using `replaceCovariantResultType`, which looks through optionals, to
substitute the container type for the result type would add an extra
level of optionality to the result type whenever the container type was
`Optional`, causing a crash later in the game. Besides, we don't have to
do this in the first place, because we know these types match in the case
of an initializer (neglecting optionality).
Relying on the optionality depth of the 'new self' value to flatten
an extra level of optionality or handle a failure is not sufficient,
because we may be delegating to an `Optional` initializer.
Instead, flattening should occur if the result type of the enclosing
initializer is less optional than 'new self', and failure handling —
if the enclosing initializer is failable and its result type is as
optional as the potentially flattened 'new self' value.
…onal` initializers

We need the extra level of optionality here to discern between failures
and constructed values.
@AnthonyLatsis AnthonyLatsis force-pushed the init-delegation-optional branch from 9eaa365 to 1842772 Compare June 25, 2022 16:17
@jckarter
Copy link
Contributor

jckarter commented Jul 1, 2022

I think we should reject those other cases involving Optional that unwrap into the constructed value itself. The ! as part of a self.init(...)! is really only intended to let us delegate from a non-failable to a failable initializer of the same type. It shouldn't be possible to force-unwrap into the constructed value itself in the case where self is Optional.

@jckarter
Copy link
Contributor

jckarter commented Jul 1, 2022

@swift-ci Please test

@AnthonyLatsis
Copy link
Collaborator Author

Thanks! Will put the addition of a tailored diagnostic for these force-unwraps on my radar.

@AnthonyLatsis
Copy link
Collaborator Author

@jckarter Could this (or maybe just the parts that resolve #57012) be nominated for inclusion in the release at this point?

@AnthonyLatsis AnthonyLatsis merged commit f1207ff into swiftlang:main Jul 1, 2022
@AnthonyLatsis AnthonyLatsis deleted the init-delegation-optional branch July 1, 2022 23:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[SR-14660] Swift Compiler Crashes When Compiling Extensions to Optional
2 participants