Skip to content

[SIL] Fix Diagnosing Never-returning functions that don't call other Never-returning functions #4393

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
merged 2 commits into from
Aug 19, 2016

Conversation

CodaFi
Copy link
Contributor

@CodaFi CodaFi commented Aug 19, 2016

What's in this pull request?

A more principled fix than #4365. It turns out we have never handled this kind of thing correctly in the SIL Optimizer. Previous versions of Swift even allowed this to work before the uninhabited changes went through.

enum X {}
@noreturn func foo() -> X {}

The SIL Optimizer now understands that Void is the only case where a missing return is acceptable and correctly diagnoses failing to call other Never-returning functions from all paths in Never-returning functions.

@slavapestov can you review?


Before merging this pull request to apple/swift repository:

  • Test pull request on Swift continuous integration.

Triggering Swift CI

The swift-ci is triggered by writing a comment on this PR addressed to the GitHub user @swift-ci. Different tests will run depending on the specific comment that you use. The currently available comments are:

Smoke Testing

Platform Comment
All supported platforms @swift-ci Please smoke test
All supported platforms @swift-ci Please smoke test and merge
OS X platform @swift-ci Please smoke test OS X platform
Linux platform @swift-ci Please smoke test Linux platform

A smoke test on macOS does the following:

  1. Builds the compiler incrementally.
  2. Builds the standard library only for macOS. Simulator standard libraries and
    device standard libraries are not built.
  3. lldb is not built.
  4. The test and validation-test targets are run only for macOS. The optimized
    version of these tests are not run.

A smoke test on Linux does the following:

  1. Builds the compiler incrementally.
  2. Builds the standard library incrementally.
  3. lldb is built incrementally.
  4. The swift test and validation-test targets are run. The optimized version of these
    tests are not run.
  5. lldb is tested.

Validation Testing

Platform Comment
All supported platforms @swift-ci Please test
All supported platforms @swift-ci Please test and merge
OS X platform @swift-ci Please test OS X platform
OS X platform @swift-ci Please benchmark
Linux platform @swift-ci Please test Linux platform

Lint Testing

Language Comment
Python @swift-ci Please Python lint

Note: Only members of the Apple organization can trigger swift-ci.

Previously, isNever would return true for an equivalence class of
uninhabited enums.  The rest of the compiler, however, is using this in
places that actually expect just the Never type.  This means that code
like this would compile properly

enum Uninhabited {}
func do() -> Uninhabited { /* No body here */ }

and we wouldn’t diagnose the missing return.
@CodaFi CodaFi changed the title Never say never [SIL] Fix Diagnosing Never-returning functions that don't call other Never-returning functions Aug 19, 2016
@CodaFi
Copy link
Contributor Author

CodaFi commented Aug 19, 2016

@swift-ci please test.

ERROR(missing_never_call,none,
"never-returning %select{function|closure}0 is missing call to "
"another never-returning function on all paths.",
(unsigned))
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 don't like the wording of this diagnostic.

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 if I change isNever to isUninhabited and put back the original implementation I can make this

function with uninhabited return type is missing call to never-returning function on all paths

@swift-ci
Copy link
Contributor

Build failed
Jenkins build - Swift Test OS X Platform
Git Commit - f6f609b9744b1169437211b74cf21b8d31a561bf
Test requested by - @CodaFi

ERROR(non_exhaustive_switch,none,
ERROR(missing_never_call,none,
"never-returning %select{function|closure}0 is missing call to "
"another never-returning function on all paths.",
Copy link
Contributor

Choose a reason for hiding this comment

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

Don't end diagnostic with '.'.

@CodaFi
Copy link
Contributor Author

CodaFi commented Aug 19, 2016

@swift-ci please test macOS platform. CI Job is here

@CodaFi
Copy link
Contributor Author

CodaFi commented Aug 19, 2016

@slavapestov bump for re-review.

// function is marked 'noreturn'.
if (ResTy->isVoid() || F->isNoReturnFunction())
// No action required if the function returns 'Void'.
if (ResTy->isVoid())
Copy link
Contributor

Choose a reason for hiding this comment

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

Is even this necessary? SILGen ought to emit the return implicitly already if it's emitting a void function. We'd still want to diagnose things like guard or switch exhaustiveness where we use unreachables to indicate control flow that should be unreachable.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hm... I'm seeing what effect removing this would have, but you're right it seems this code path is unexercised.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Looks like nothing exploded.

@swift-ci
Copy link
Contributor

Build failed
Jenkins build - Swift Test OS X Platform
Git Commit - f6f609b9744b1169437211b74cf21b8d31a561bf
Test requested by - @CodaFi

Turn on the noreturn diagnostic for cases where a reachable unreachable
could be encountered.  Previously, the diagnostic would not fire if the
function was marked noreturn and any of its reachable unreachable calls
were around.  While this makes sense from a SILGen perspective (it Just
Crashes tm), it is still wrong.  We need to diagnose *everything* that
has reachable unreachables.
@slavapestov
Copy link
Contributor

@CodaFi Looks good, thanks for seeing this through. Can you cherry-pick this over to the 3.0 branch as well?

@CodaFi
Copy link
Contributor Author

CodaFi commented Aug 19, 2016

Can do.

@CodaFi
Copy link
Contributor Author

CodaFi commented Aug 19, 2016

@swift-ci please test macOS platform. Build status

@CodaFi
Copy link
Contributor Author

CodaFi commented Aug 19, 2016

It passed

@CodaFi
Copy link
Contributor Author

CodaFi commented Aug 19, 2016

@swift-ci please test macOS platform.

@CodaFi CodaFi merged commit 7f3f0f8 into swiftlang:master Aug 19, 2016
@CodaFi CodaFi deleted the never-say-never branch August 19, 2016 14:41
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.

4 participants