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-2970] @noescape local variable closures will no longer be possible once @noescape is fully removed from the language #45560

Closed
hamishknight opened this issue Oct 16, 2016 · 4 comments
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself regression swift 3.0

Comments

@hamishknight
Copy link
Collaborator

Previous ID SR-2970
Radar None
Original Reporter @hamishknight
Type Bug
Status Resolved
Resolution Won't Do
Environment

Xcode 8 (8A218a) Apple Swift version 3.0 (swiftlang-800.0.46.2 clang-800.0.38)
Target: x86_64-apple-macosx10.9

Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug, 3.0Regression
Assignee None
Priority Medium

md5: b5605ab57aaec004648adef2dce69be4

Issue Description:

Currently in Swift 3.0, although @NoEscape is deprecated, and to be removed - you can mark a local variable closure in a function with the @NoEscape attribute, allowing it to capture other non-escaping closures.

// the function parameter is non-escaping by default
func foo(_ function: () -> ()) {
    let f : @noescape () -> () = { function() }
    f()
}

Removing the @NoEscape attribute will trigger a compiler error stating that the non-escaping parameter cannot be captured in a potentially escaping closure.

With the @NoEscape attribute present, the compiler will correctly enforce that f is non-escaping, by preventing it from escaping the lifetime of the function foo:

func foo(_ function: () -> ()) -> () -> () {
    let f : @noescape () -> () = { function() }
    f()
    return f // Invalid conversion from non-escaping function of type '() -> ()' to potentially escaping function type () -> ()
}

However, once @NoEscape is fully removed from the language, this will no longer be possible.

@rintaro
Copy link
Mannequin

rintaro mannequin commented Oct 18, 2016

CC/ @lattner
I think accepting let f: @noescape () -> () = { function() }; is an unintentional side-effect of SE-0049.

@belkadan
Copy link
Contributor

cc @milseman. This was definitely unintentional, but Hamish is demonstrating that people are using it.

Ideally we'd handle this without any annotations at all using a DI-like escape analysis. That would handle the local function case as well. But I don't know if that's (1) worth the effort, and (2) too complicated a language model.

@rintaro
Copy link
Mannequin

rintaro mannequin commented Oct 21, 2016

FYI, here's another escaping @noescape value problem:

class C {
    let foo: @noescape () -> ()
    
    init(_ function: () -> ()) {
        foo = { function() }
    }
}

let c = C({ print("foo") })
c.foo()

@belkadan
Copy link
Contributor

The latter should definitely be illegal. Arguably the former is permissible, though.

@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
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself regression swift 3.0
Projects
None yet
Development

No branches or pull requests

3 participants