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-9991] It is possible to forward @autoclosure in a tuple #52395

Closed
swift-ci opened this issue Feb 23, 2019 · 9 comments
Closed

[SR-9991] It is possible to forward @autoclosure in a tuple #52395

swift-ci opened this issue Feb 23, 2019 · 9 comments
Assignees
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself crash Bug: A crash, i.e., an abnormal termination of software

Comments

@swift-ci
Copy link
Collaborator

Previous ID SR-9991
Radar None
Original Reporter polac24 (JIRA User)
Type Bug
Status Resolved
Resolution Done
Environment

Apple Swift version 4.2.1 (swiftlang-1000.11.42 clang-1000.11.45.1)

Target: x86_64-apple-darwin18.5.0

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

md5: 2d9abebffa6f6c5993f5446f37e30268

Issue Description:

SR-9494 mentions that @autoclosure shouldn't forward, however it is still possible to do that by wrapping it in a tuple and use type interference:

func copyType<I,O> (_ function: (I) -> (O)) -> (I) -> (O) {
    fatalError("Never called")
}

class Class {
    lazy var storage = copyType(takeFunction) // storage is "autoclosured"
    func takeFunction(_ autoString: @autoclosure () -> String, other: String) {
    }
}

let c = Class()
c.storage = { _ in }

print(type(of: c.storage)) // (() -> String, String) -> ()
// c.storage(({"A"},"b")) // error: function produces expected type 'String'; did you mean to call it with '()'?
c.storage(("A","b")) // only that compiles

Output from 5.0 snapshot

$ /Library/Developer/Toolchains/swift-5.0-DEVELOPMENT-SNAPSHOT-2019-02-20-a.xctoolchain/usr/bin/swift autoclosure.swift 
Assertion failed: (flags.isNone()), function appendTypeList, file /Users/buildnode/jenkins/workspace/oss-swift-5.0-package-osx/swift/lib/AST/ASTMangler.cpp, line 1829.
Stack dump:
0.  Program arguments: /Library/Developer/Toolchains/swift-5.0-DEVELOPMENT-SNAPSHOT-2019-02-20-a.xctoolchain/usr/bin/swift -frontend -interpret autoclosure.swift -enable-objc-interop -sdk /Applications/Xcode_1010.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk -color-diagnostics -module-name autoclosure 
0  swift                    0x0000000108c11c85 llvm::sys::PrintStackTrace(llvm::raw_ostream&) + 37
1  swift                    0x0000000108c10f25 llvm::sys::RunSignalHandlers() + 85
2  swift                    0x0000000108c12272 SignalHandler(int) + 258
3  libsystem_platform.dylib 0x00007fff69079b5d _sigtramp + 29
4  libsystem_malloc.dylib   0x00007fff69040796 tiny_malloc_from_free_list + 444
5  libsystem_c.dylib        0x00007fff68f396a6 abort + 127
6  libsystem_c.dylib        0x00007fff68f0220d basename_r + 0
7  swift                    0x00000001062c11bb swift::Mangle::ASTMangler::appendTypeList(swift::Type) + 523
8  swift                    0x00000001062bd1cf swift::Mangle::ASTMangler::appendType(swift::Type) + 1055
9  swift                    0x00000001062c373c swift::Mangle::ASTMangler::appendTypeListElement(swift::Identifier, swift::Type, swift::ParameterTypeFlags) + 140
10 swift                    0x00000001062c3582 swift::Mangle::ASTMangler::appendFunctionInputType(llvm::ArrayRef<swift::AnyFunctionType::Param>) + 146
11 swift                    0x00000001062c33ea swift::Mangle::ASTMangler::appendFunctionSignature(swift::AnyFunctionType*) + 58
12 swift                    0x00000001062c18f2 swift::Mangle::ASTMangler::appendFunctionType(swift::AnyFunctionType*, bool) + 50
13 swift                    0x00000001062bf6b0 swift::Mangle::ASTMangler::appendDeclType(swift::ValueDecl const*, bool) + 192
14 swift                    0x00000001062bacfe swift::Mangle::ASTMangler::appendAccessorEntity(llvm::StringRef, swift::AbstractStorageDecl const*, bool) + 142
15 swift                    0x00000001062b9db0 swift::Mangle::ASTMangler::mangleEntity(swift::ValueDecl const*, bool, swift::Mangle::ASTMangler::SymbolKind) + 48
16 swift                    0x0000000105dfd24f swift::SILDeclRef::mangle(swift::SILDeclRef::ManglingKind) const + 1775
17 swift                    0x0000000105e4c677 swift::SILFunctionBuilder::getOrCreateFunction(swift::SILLocation, swift::SILDeclRef, swift::ForDefinition_t, swift::ProfileCounter) + 55
18 swift                    0x00000001058b5f9c swift::Lowering::SILGenModule::getFunction(swift::SILDeclRef, swift::ForDefinition_t) + 348
19 swift                    0x000000010599c47e swift::Lowering::SILGenModule::emitVTableMethod(swift::ClassDecl*, swift::SILDeclRef, swift::SILDeclRef) + 430
20 swift                    0x000000010599eab1 (anonymous namespace)::SILGenType::emitType() + 1025
21 swift                    0x000000010599e6a9 swift::Lowering::SILGenModule::visitNominalTypeDecl(swift::NominalTypeDecl*) + 25
22 swift                    0x00000001058bbe16 swift::Lowering::SILGenModule::emitSourceFile(swift::SourceFile*) + 822
23 swift                    0x00000001058bcd78 swift::SILModule::constructSIL(swift::ModuleDecl*, swift::SILOptions&, swift::FileUnit*) + 376
24 swift                    0x00000001058bd270 swift::performSILGeneration(swift::ModuleDecl*, swift::SILOptions&) + 16
25 swift                    0x0000000105046717 performCompile(swift::CompilerInstance&, swift::CompilerInvocation&, llvm::ArrayRef<char const*>, int&, swift::FrontendObserver*, swift::UnifiedStatsReporter*) + 9943
26 swift                    0x00000001050432d8 swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 3000
27 swift                    0x0000000104ff5152 main + 690
28 libdyld.dylib            0x00007fff68e943ed start + 1
29 libdyld.dylib            0x000000000000000a start + 2534849566
Abort trap: 6

Practical problem
If the @autoclosure behaviour is forwarded without error, it leads to a crash when I try to record the argument:

func mock<I,O> (for function: (I) -> (O), alwaysReturn: O) -> (I) -> (O) {
    return { p in
        return alwaysReturn
    }
}

class Class {
    lazy var storage = mock(for: takeFunction, alwaysReturn: Void())
    func takeFunction(_ autoString: @autoclosure () -> String, other: String) {
        storage((autoString(), other))
    }
}

class ArrayClass<T> {
    var s:[T] = []
}
func spyMockCalls<I,O>(of stub: inout (I) -> (O)) -> ArrayClass<I> {
    let records = ArrayClass<I>()
    let originalStub = stub
    stub = { [weak weakRecords = records] arg in
        weakRecords?.s.append(arg)
        return originalStub(arg)
    }
    return records
}

let c = Class()
let args = spyMockCalls(of: &c.storage)
c.takeFunction("example", other: "other")
print(args.s[0].0())// Crash
@belkadan
Copy link
Contributor

Hm, I can't reproduce it in my local build of Swift 5, which admittedly isn't as new as the snapshot you tried. @xedin, did something just change here?

@swift-ci
Copy link
Collaborator Author

Comment by Bartosz Polaczyk (JIRA)

I downloaded swift-5.0-DEVELOPMENT-SNAPSHOT-2019-02-24-a and here is the smallest snippet to reproduce a crash on compilation:

func copyType<I,O> (_ function: (I) -> (O)) -> (I) -> (O) {
    fatalError("Never called")
}

class Class {
    lazy var storage = copyType(takeFunction) // storage is "autoclosured"
    func takeFunction(_ autoString: @autoclosure () -> String, other: String) {
    }
}
/Library/Developer/Toolchains/swift-5.0-DEVELOPMENT-SNAPSHOT-2019-02-24-a.xctoolchain/usr/bin/swiftc autoclosure.swift -v 
Apple Swift version 5.0-dev (LLVM 3207a50965, Clang 72dde1b133, Swift a8126fb484)
Target: x86_64-apple-darwin18.5.0
/Library/Developer/Toolchains/swift-5.0-DEVELOPMENT-SNAPSHOT-2019-02-24-a.xctoolchain/usr/bin/swift -frontend -c -primary-file autoclosure.swift -target x86_64-apple-darwin18.5.0 -enable-objc-interop -color-diagnostics -module-name autoclosure -o /var/folders/3v/2ymlw0cd53q9k8qsr1vg45gh0000gn/T/autoclosure-58c714.o
Assertion failed: (flags.isNone()), function appendTypeList, file /Users/buildnode/jenkins/workspace/oss-swift-5.0-package-osx/swift/lib/AST/ASTMangler.cpp, line 1829.
Stack dump:
0.  Program arguments: /Library/Developer/Toolchains/swift-5.0-DEVELOPMENT-SNAPSHOT-2019-02-24-a.xctoolchain/usr/bin/swift -frontend -c -primary-file autoclosure.swift -target x86_64-apple-darwin18.5.0 -enable-objc-interop -color-diagnostics -module-name autoclosure -o /var/folders/3v/2ymlw0cd53q9k8qsr1vg45gh0000gn/T/autoclosure-58c714.o 
0  swift                    0x000000010afa1c45 llvm::sys::PrintStackTrace(llvm::raw_ostream&) + 37
1  swift                    0x000000010afa0ee5 llvm::sys::RunSignalHandlers() + 85
2  swift                    0x000000010afa2232 SignalHandler(int) + 258
3  libsystem_platform.dylib 0x00007fff7f1e5b5d _sigtramp + 29
4  libsystem_platform.dylib 0x00007f9e930a1b48 _sigtramp + 334217224
5  libsystem_c.dylib        0x00007fff7f0a56a6 abort + 127
6  libsystem_c.dylib        0x00007fff7f06e20d basename_r + 0
7  swift                    0x000000010865117b swift::Mangle::ASTMangler::appendTypeList(swift::Type) + 523
8  swift                    0x000000010864d18f swift::Mangle::ASTMangler::appendType(swift::Type) + 1055
9  swift                    0x00000001086536fc swift::Mangle::ASTMangler::appendTypeListElement(swift::Identifier, swift::Type, swift::ParameterTypeFlags) + 140
10 swift                    0x0000000108653542 swift::Mangle::ASTMangler::appendFunctionInputType(llvm::ArrayRef<swift::AnyFunctionType::Param>) + 146
11 swift                    0x00000001086533aa swift::Mangle::ASTMangler::appendFunctionSignature(swift::AnyFunctionType*) + 58
12 swift                    0x00000001086518b2 swift::Mangle::ASTMangler::appendFunctionType(swift::AnyFunctionType*, bool) + 50
13 swift                    0x000000010864e638 swift::Mangle::ASTMangler::appendType(swift::Type) + 6344
14 swift                    0x000000010864f67d swift::Mangle::ASTMangler::appendDeclType(swift::ValueDecl const*, bool) + 205
15 swift                    0x000000010864b04a swift::Mangle::ASTMangler::appendEntity(swift::ValueDecl const*, llvm::StringRef, bool) + 58
16 swift                    0x000000010864b292 swift::Mangle::ASTMangler::mangleInitializerEntity(swift::VarDecl const*, swift::Mangle::ASTMangler::SymbolKind) + 66
17 swift                    0x000000010818cfb6 swift::SILDeclRef::mangle(swift::SILDeclRef::ManglingKind) const + 1446
18 swift                    0x00000001081dc527 swift::SILFunctionBuilder::getOrCreateFunction(swift::SILLocation, swift::SILDeclRef, swift::ForDefinition_t, swift::ProfileCounter) + 55
19 swift                    0x0000000107c45eac swift::Lowering::SILGenModule::getFunction(swift::SILDeclRef, swift::ForDefinition_t) + 348
20 swift                    0x0000000107c49683 swift::Lowering::SILGenModule::emitStoredPropertyInitialization(swift::PatternBindingDecl*, unsigned int) + 867
21 swift                    0x0000000107d2e76d (anonymous namespace)::SILGenType::emitType() + 429
22 swift                    0x0000000107d2e5b9 swift::Lowering::SILGenModule::visitNominalTypeDecl(swift::NominalTypeDecl*) + 25
23 swift                    0x0000000107c4bd26 swift::Lowering::SILGenModule::emitSourceFile(swift::SourceFile*) + 822
24 swift                    0x0000000107c4cc35 swift::SILModule::constructSIL(swift::ModuleDecl*, swift::SILOptions&, swift::FileUnit*) + 293
25 swift                    0x0000000107c4d1b9 swift::performSILGeneration(swift::FileUnit&, swift::SILOptions&) + 41
26 swift                    0x00000001073d5a9c performCompile(swift::CompilerInstance&, swift::CompilerInvocation&, llvm::ArrayRef<char const*>, int&, swift::FrontendObserver*, swift::UnifiedStatsReporter*) + 8012
27 swift                    0x00000001073d2de8 swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 3000
28 swift                    0x0000000107384c62 main + 690
29 libdyld.dylib            0x00007fff7f0003ed start + 1
30 libdyld.dylib            0x000000000000000d start + 2164259873
<unknown>:0: error: unable to execute command: Abort trap: 6
<unknown>:0: error: compile command failed due to signal 6 (use -v to see invocation)

@xedin
Copy link
Member

xedin commented Feb 26, 2019

@slavapestov Looks like `flag.isNone()` assert added by d31d35a, might be too strict for this case since we allow `@autoclosure` marked parameters inside of optional container like in the example code. Type of the `storage` declaration is a follows:

(bound_generic_enum_type decl=Swift.(file).Optional
  (function_type escaping
    (input=function_params num_params=1
      (param
        (tuple_type num_elements=2
          (tuple_type_elt autoclosure
            (function_type
              (input=function_params num_params=0)
              (output=struct_type decl=Swift.(file).String)))
          (tuple_type_elt
            (struct_type decl=Swift.(file).String)))))
    (output=tuple_type num_elements=0)))

WDYT?

@xedin
Copy link
Member

xedin commented Feb 26, 2019

Or maybe if we should just disallow assigning tuples with @autoclosure flag to generic parameters in the solver, jut like we do for @escaping I think...

@xedin
Copy link
Member

xedin commented Feb 26, 2019

Hm, I though that we disallowed @escaping in situations like this, but then I tried this example with @escaping instead of @autoclosure `Class` declaration and it compiled just fine...

@slavapestov
Copy link
Member

I think the call `copyType(takeFunction)` should be rejected. We should not do the 'tuple splat' when the argument list contains an autoclosure.

@slavapestov
Copy link
Member

@xedin The closest analogy here is not @escaping but varargs. If you change the type of takeFunction() to take a vararg parameter instead of an autoclosure, we reject the code instead of forming a tuple type with a vararg element. This is an easy fix, I'll take it.

@slavapestov
Copy link
Member

We also allow splatting tuples containing noescape function types, which isn't sound either:

public func foo<T>(_ fn: (T) -> (), _ t: T) -> [T] { return [t] }

func foo(x: inout Int) {
  let arr = foo({ (a: Int, b: () -> Int) in }, (0, {10}))
  print(arr[0].1())
}

@slavapestov
Copy link
Member

#24079

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
@AnthonyLatsis AnthonyLatsis added the crash Bug: A crash, i.e., an abnormal termination of software label Dec 12, 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 crash Bug: A crash, i.e., an abnormal termination of software
Projects
None yet
Development

No branches or pull requests

5 participants