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-9043] Missing checks of inout/mutating captures #51546

Closed
swift-ci opened this issue Oct 19, 2018 · 4 comments
Closed

[SR-9043] Missing checks of inout/mutating captures #51546

swift-ci opened this issue Oct 19, 2018 · 4 comments

Comments

@swift-ci
Copy link
Collaborator

swift-ci commented Oct 19, 2018

Previous ID SR-9043
Radar rdar://problem/45511834
Original Reporter koher (JIRA User)
Type Bug
Status Resolved
Resolution Done
Environment

Xcode Version 10.0 (10A255)

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

md5: 23f0e6aa3983c486dcd3930dc0b1232d

relates to:

  • SR-8546 Enforce @escaping for for all but the most trivial uses of captured variables.

Issue Description:

The following code causes a compile-time error correctly.

func run(_ body: @escaping () -> Void) { body() }


struct S {
    var a: Int = 3
    
    mutating func foo() {
        func _foo() {
            if a == 0 { return }
            a -= 1
            print(a)
            run(_foo)
        }
        _foo()
    }
}


var s = S()
s.foo()
error: nested function with an implicitly captured inout parameter can only be used as a non-escaping argument
             run(_foo)
             ^

However, when `run(_foo)` is changed to `run { _foo() }`, it can be compiled. I guess the compiler lacks some checks.

@rintaro
Copy link
Mannequin

rintaro mannequin commented Oct 19, 2018

Crash in master:

$ cat test.swift
func run(_ body: @escaping () -> Void) { }

struct S {
    var a: Int
    mutating func foo() {
        func _foo() {
            _ = a
            run { _foo() }
        }
    }
}
$ ../build/Ninja-ReleaseAssert/swift-macosx-x86_64/bin/swift test.swift
Applied argument must be @noescape function type:   %11 = partial_apply [callee_guaranteed] %10(%0) : $@convention(thin) (@inout_aliasable S) -> () // users: %14, %13
A partial_apply with @inout_aliasable may only be used as a @noescape function type argument.
UNREACHABLE executed at /Users/rintaro/Repositories/swift-oss/swift/lib/SILOptimizer/Mandatory/DiagnoseStaticExclusivity.cpp:1078!
Stack dump:
0.  Program arguments: /Users/rintaro/Repositories/swift-oss/build/Ninja-ReleaseAssert/swift-macosx-x86_64/bin/swift -frontend -interpret test.swift -enable-objc-interop -sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk -color-diagnostics -module-name test 
1.  While running pass #​7 SILFunctionTransform "DiagnoseStaticExclusivity" on SILFunction "@$s4test1SV3fooyyF01_B0L_yyF".
 for '_foo()' at test.swift:6:9
0  swift                    0x000000010a44e2b8 llvm::sys::PrintStackTrace(llvm::raw_ostream&) + 40
1  swift                    0x000000010a44d288 llvm::sys::RunSignalHandlers() + 248
2  swift                    0x000000010a44e8d2 SignalHandler(int) + 258
3  libsystem_platform.dylib 0x00007fff6e3ceb3d _sigtramp + 29
4  swift                    0x000000010b717678 llvm::dbgs()::thestrm + 16
5  libsystem_c.dylib        0x00007fff6e28d1c9 abort + 127
6  swift                    0x000000010a3e14ee llvm::llvm_unreachable_internal(char const*, char const*, unsigned int) + 542
7  swift                    0x0000000107141d12 checkStaticExclusivity(swift::SILFunction&, swift::PostOrderFunctionInfo*, swift::AccessSummaryAnalysis*) + 13298
8  swift                    0x000000010715e905 swift::SILPassManager::runPassOnFunction(unsigned int, swift::SILFunction*) + 1925
9  swift                    0x000000010715fab3 swift::SILPassManager::runFunctionPasses(unsigned int, unsigned int) + 1299
10 swift                    0x0000000107160bdf swift::SILPassManager::execute() + 607
11 swift                    0x000000010673336b swift::SILPassManager::executePassPipelinePlan(swift::SILPassPipelinePlan const&) + 187
12 swift                    0x00000001071695b4 swift::runSILDiagnosticPasses(swift::SILModule&) + 132
13 swift                    0x00000001065c01db performCompile(swift::CompilerInstance&, swift::CompilerInvocation&, llvm::ArrayRef<char const*>, int&, swift::FrontendObserver*, swift::UnifiedStatsReporter*) + 10923
14 swift                    0x00000001065bc69d swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 3021
15 swift                    0x000000010656ea8e main + 686
16 libdyld.dylib            0x00007fff6e1e50a5 start + 1
Abort trap: 6

@belkadan
Copy link
Contributor

belkadan commented Oct 22, 2018

@swift-ci create

@atrick
Copy link
Member

atrick commented Oct 25, 2018

Note that the closure

{ _foo }

captures inout self, then is passed as an @escaping closure. This clearly violates the type system but the type checker can't catch it. Asserting in a diagnostic pass is better than nothing, until the type checker is fixed. We can't easily convert the assert into a diagnostic (even if we wanted to), because the code doing the verification is only run in the asserts compiler.

Hopefully, the fix for SR-8546 will cover this.

SR-8546: Enforce @escaping for nested functions named inside conditional expressions.

But the test case is sufficiently different that it should probably be two bugs.

@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

4 participants