Skip to content

SILOptimizer: add a diagnostics pass to warn about lifetime issues with weak references. #35918

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 1 commit into from
Feb 15, 2021

Conversation

eeckstein
Copy link
Contributor

The DiagnoseLifetimeIssuesPass pass prints a warning if an object is stored to a weak property (or is weakly captured) and destroyed before the property (or captured reference) is ever used again.
This can happen if the programmer relies on the lexical scope to keep an object alive, but copy-propagation can shrink the object's lifetime to its last use.
For example:

  func test() {
    let k = Klass()
      // k is deallocated immediately after the closure capture (a store_weak).
      functionWithClosure({ [weak k] in
                            // crash!
                            k!.foo()
                          })
    }

Unfortunately this pass can only catch simple cases, but it's better than nothing.

rdar://73910632

@eeckstein eeckstein requested a review from atrick February 11, 2021 12:39
@eeckstein
Copy link
Contributor Author

@swift-ci test

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - 514bd26f913d6ea4da2ad34294b9f39c79be0fc2

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - 514bd26f913d6ea4da2ad34294b9f39c79be0fc2

@eeckstein eeckstein force-pushed the diagnose-lifetime-issues branch from 514bd26 to d37a352 Compare February 11, 2021 17:16
@eeckstein
Copy link
Contributor Author

@swift-ci test

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - d37a3529e2e7da265806e3cf46a4edb117114691

@atrick
Copy link
Contributor

atrick commented Feb 12, 2021

@eeckstein We should probably have another iteration of this diagnostic after you merge this that recurses through all ForwardingConsumes, not just Enum. There is a ForwardingOperand abstraction that's close to what you need for that. Without that, I think we could have false positive warnings.

@atrick
Copy link
Contributor

atrick commented Feb 12, 2021

We may also want to be more conservative in the OperandOwnership::DestroyingConsume case. That only destroys the OSSA value, but could actually forward the reference through a store.

Copy link
Contributor

@atrick atrick left a comment

Choose a reason for hiding this comment

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

I'm concerned about false positive warnings in two case: ForwardingConsume and DestroyingConsume. For forwarding operations, we should be able to recognize most and look through them. For DestroyingConsume, the question is how conservative we want to be for stores, calls, and things we don't recognize. It may be good enough to just warn when the only destroys are actual Destroys.

I spent most of my time reviewing just trying to figure out what the Demangle nodes really mean. I could not find documentation anywhere in the source. I can guess what they mean but it would be helpful if you add comments with precise definitions.

It's up to you whether you want to address improvements in another PR later.

@atrick
Copy link
Contributor

atrick commented Feb 12, 2021

@eeckstein in general this looks really great!

@atrick
Copy link
Contributor

atrick commented Feb 12, 2021

@swift-ci smoke test linux

@atrick
Copy link
Contributor

atrick commented Feb 12, 2021

@swift-ci smoke test windows

@eeckstein
Copy link
Contributor Author

eeckstein commented Feb 12, 2021

It may be good enough to just warn when the only destroys are actual Destroys.

You are right. I'll change that

Update: Actually that's the case right now. Everything else than destroy_values are considered as "normal" uses and extend the lifetime, which prevents the warning.

@eeckstein
Copy link
Contributor Author

@swift-ci smoke test linux

1 similar comment
@eeckstein
Copy link
Contributor Author

@swift-ci smoke test linux

@atrick
Copy link
Contributor

atrick commented Feb 13, 2021

@eeckstein I'm referring to cases like this

%0 = alloc_ref
%copy = copy_value %0
store %copy to ...
store_weak %0 to ...

or

%0 = alloc_ref
%copy = copy_value %0
%cast = cast %copy
store_weak %0 to ...
... = %cast

…th weak references.

The DiagnoseLifetimeIssuesPass pass prints a warning if an object is stored to a weak property (or is weakly captured) and destroyed before the property (or captured reference) is ever used again.
This can happen if the programmer relies on the lexical scope to keep an object alive, but copy-propagation can shrink the object's lifetime to its last use.
For example:

  func test() {
    let k = Klass()
      // k is deallocated immediately after the closure capture (a store_weak).
      functionWithClosure({ [weak k] in
                            // crash!
                            k!.foo()
                          })
    }

Unfortunately this pass can only catch simple cases, but it's better than nothing.

rdar://73910632
@eeckstein eeckstein force-pushed the diagnose-lifetime-issues branch from d37a352 to a17f8c2 Compare February 15, 2021 10:12
@eeckstein
Copy link
Contributor Author

Ah, you are right. I fixed this.

@eeckstein
Copy link
Contributor Author

@swift-ci smoke test

Copy link
Contributor

@atrick atrick left a comment

Choose a reason for hiding this comment

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

Thanks. It would be pretty easy to handle casts at some point.

@eeckstein eeckstein merged commit 841e4ee into swiftlang:main Feb 15, 2021
@eeckstein eeckstein deleted the diagnose-lifetime-issues branch February 15, 2021 17:11
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.

3 participants