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-8546] Enforce @escaping for for all but the most trivial uses of captured variables. #51064

Closed
atrick opened this issue Aug 16, 2018 · 4 comments

Comments

@atrick
Copy link
Member

atrick commented Aug 16, 2018

Previous ID SR-8546
Radar rdar://problem/43355341
Original Reporter @atrick
Type Bug
Status Resolved
Resolution Done

Attachment: Download

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

md5: 5633bcbc0929418f15d8bc331f63f2ed

relates to:

  • SR-9043 Missing checks of inout/mutating captures

Issue Description:

This is a source compatibility bug.

A nested function used in an @escaping context must produce a type
checker error. In the example below, we expect a diagnostic:

error: nested function with an implicitly captured inout parameter can only be used as a non-escaping argument

Instead we get an error in diagnose exclusivity, but only in asserts builds, which is not good enough to protect against undefined behavior.

Applied argument must be @noescape function type: %21 = argument of bb3 : $@callee_guaranteed () -> ()
A partial_apply with @inout_aliasable may only be used as a @noescape function type argument.
UNREACHABLE executed at /s/s/swift/lib/SILOptimizer/Mandatory/DiagnoseStaticExclusivity.cpp:1085!
func doit(_ f: @escaping ()->()) { f() }

public func outerFoo1(x: inout Int) {
 func innerFoo1() {
  x = 1
 }
 func innerFoo2() {
  x = 2
 }
 doit(x == 0 ? innerFoo1 : innerFoo2)
}
@atrick
Copy link
Member Author

atrick commented Aug 16, 2018

@swift-ci create.

@rudkx
Copy link
Member

rudkx commented Sep 13, 2018

The analysis being done for this at the moment seems like it's just fundamentally broken in that it looks at the direct arguments of the function to see if they are DeclRefs that capture inouts.

Here are two more (similar) examples that currently assert rather than getting flagged by type checking.

doit{ innerFoo1() } 

and

let fn = { innerFoo1() }
doit(fn) 

@atrick
Copy link
Member Author

atrick commented Dec 22, 2018

Here's another obvious type checker failure:

var globalf: ()->() = {}

func testEscapeToGlobal(x: inout Int) {
 globalf = { defer { x = 5 } }
}

These are miscompiles and source compatibility issues. The only reason that we're catching them now is that I added complex verification in the optimizer.

@slavapestov
Copy link
Member

slavapestov commented Apr 11, 2019

#23923

@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

3 participants