swiftlang / swift

The Swift Programming Language
https://swift.org
Apache License 2.0
67.59k stars 10.36k forks source link

Accessing computed property sometimes causes unexpected consume of borrowed value #73292

Closed ORBAT closed 5 months ago

ORBAT commented 6 months ago

Description

I've found two cases of values getting consumed when reading computed properties, and they seem like they're not correct behavior based on my reading of SE-0377 and SE-0390.

Reproduction

Case 1: borrowed parameter with opaque type

struct Example {
  protocol Proto {
    // doesn't work with { borrowing get } either
    var count: Int { get }
  }

  func takeProto(_ p: borrowing some Proto) -> Int {
    p.count
  }
}

Result is

error: 'p' is borrowed and cannot be consumed
  func takeProto(_ p: borrowing some Proto) -> Int {
                   ^

note: consumed here
    p.count
      ^

Interestingly using p: borrowing any Proto leads to a different error. Should I make another issue for this as the error suggests?

error: usage of no-implicit-copy value that the compiler can't verify. 
This is a compiler bug. Please file a bug with a small example of the bug

Case 2: borrowing method in a generic struct with stored property of generic type

struct Broken<Base> {
  let base: Base
  var compd: Int { 666 }
  borrowing func doSomething() -> Int { compd }
}
error: 'self' is borrowed and cannot be consumed
  borrowing func doSomething() -> Int { compd }
                 ^
note: consumed here
  borrowing func doSomething() -> Int { compd }
                                        ^

Expected behavior

Case 1

Expected no error

Case 2

Expected no error, like in the following cases that compile fine:

class Class<Base> {
  let base: Base
  var computed: Int { 666 } 

  borrowing func doSomething() -> Int { computed }

  init(base: Base) {
    self.base = base
  }
}

struct NoProp<Base> {
  var computed: Int { 666 }
  borrowing func doSomething() -> Int { computed }
}

struct NotGeneric {
  var computed: Int { 666 }
  borrowing func doSomething() -> Int { computed }
}

Environment

swift-driver version: 1.90.11.1 Apple Swift version 5.10 (swiftlang-5.10.0.13 clang-1500.3.9.4)
Target: arm64-apple-macosx14.0

Additional information

Forum post

tbkka commented 6 months ago

CC: @atrick @jckarter

ORBAT commented 6 months ago

I noticed that the first example's takeProto compiles fine on 5.10 if I (ab)use a closure and do { p.count }() instead of p.count:

struct Example {
  protocol Proto {
    var count: Int { get }
  }

  func takeProto(_ p: borrowing some Proto) -> Int {
    { p.count }()
  }
}

However, when I tried the same trick with the latest 6.0-dev (swift-6.0-DEVELOPMENT-SNAPSHOT-2024-04-30-a / org.swift.600202404301a), the compiler crashes with an assertion failure Assertion failed: (fnConv.getSILType(Params[i + firstCapture], typeExpansionContext) == captures[i].getType() && "capture doesn't match param type"), function claimCaptureParams, file SILGenApply.cpp, line 4803. The same happens with the second example if I use { compd }(). Using -swift-version 6 makes no difference.

Full swiftc output

Apple Swift version 6.0-dev (LLVM 7b8e6346027d2b1, Swift 763421cee31dc8f)
Target: arm64-apple-macosx14.0
/Library/Developer/Toolchains/swift-6.0-DEVELOPMENT-SNAPSHOT-2024-04-30-a.xctoolchain/usr/bin/swift-frontend -frontend -c -primary-file Struct+Main.swift -target arm64-apple-macosx14.0 -Xllvm -aarch64-use-tbi -enable-objc-interop -sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.4.sdk -color-diagnostics -empty-abi-descriptor -resource-dir /Library/Developer/Toolchains/swift-6.0-DEVELOPMENT-SNAPSHOT-2024-04-30-a.xctoolchain/usr/lib/swift -Xcc -v -module-name main -target-sdk-version 14.4 -target-sdk-name macosx14.4 -external-plugin-path '/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/usr/lib/swift/host/plugins#/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/usr/bin/swift-plugin-server' -external-plugin-path '/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/usr/local/lib/swift/host/plugins#/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/usr/bin/swift-plugin-server' -plugin-path /Library/Developer/Toolchains/swift-6.0-DEVELOPMENT-SNAPSHOT-2024-04-30-a.xctoolchain/usr/lib/swift/host/plugins -plugin-path /Library/Developer/Toolchains/swift-6.0-DEVELOPMENT-SNAPSHOT-2024-04-30-a.xctoolchain/usr/local/lib/swift/host/plugins -o /var/folders/b1/zckxsnfj1gg94dr8z6qm3d9w0000gp/T/TemporaryDirectory.v72Ypd/Struct+Main-1.o
error: compile command failed due to signal 6 (use -v to see invocation)
Apple clang version 17.0.0 (https://github.com/apple/llvm-project.git 7b8e6346027d2b1b50905bbac557e4c35f84bec0)
Target: arm64-apple-macosx14.0
Thread model: posix
InstalledDir: /Library/Developer/Toolchains/swift-6.0-DEVELOPMENT-SNAPSHOT-2024-04-30-a.xctoolchain/usr/bin
ignoring nonexistent directory "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.4.sdk/usr/local/include"
ignoring nonexistent directory "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.4.sdk/Library/Frameworks"
#include "..." search starts here:
#include <...> search starts here:
 /usr/local/include
 /Library/Developer/Toolchains/swift-6.0-DEVELOPMENT-SNAPSHOT-2024-04-30-a.xctoolchain/usr/lib/swift
 /Library/Developer/Toolchains/swift-6.0-DEVELOPMENT-SNAPSHOT-2024-04-30-a.xctoolchain/usr/lib/swift/clang/include
 /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.4.sdk/usr/include
 /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.4.sdk/System/Library/Frameworks (framework directory)
End of search list.
Assertion failed: (fnConv.getSILType(Params[i + firstCapture], typeExpansionContext) == captures[i].getType() && "capture doesn't match param type"), function claimCaptureParams, file SILGenApply.cpp, line 4803.
Please submit a bug report (https://swift.org/contributing/#reporting-bugs) and include the crash backtrace.
Stack dump:
0.  Program arguments: /Library/Developer/Toolchains/swift-6.0-DEVELOPMENT-SNAPSHOT-2024-04-30-a.xctoolchain/usr/bin/swift-frontend -frontend -c -primary-file Struct+Main.swift -target arm64-apple-macosx14.0 -Xllvm -aarch64-use-tbi -enable-objc-interop -sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.4.sdk -color-diagnostics -empty-abi-descriptor -resource-dir /Library/Developer/Toolchains/swift-6.0-DEVELOPMENT-SNAPSHOT-2024-04-30-a.xctoolchain/usr/lib/swift -Xcc -v -module-name main -target-sdk-version 14.4 -target-sdk-name macosx14.4 -external-plugin-path /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/usr/lib/swift/host/plugins#/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/usr/bin/swift-plugin-server -external-plugin-path /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/usr/local/lib/swift/host/plugins#/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/usr/bin/swift-plugin-server -plugin-path /Library/Developer/Toolchains/swift-6.0-DEVELOPMENT-SNAPSHOT-2024-04-30-a.xctoolchain/usr/lib/swift/host/plugins -plugin-path /Library/Developer/Toolchains/swift-6.0-DEVELOPMENT-SNAPSHOT-2024-04-30-a.xctoolchain/usr/local/lib/swift/host/plugins -o /var/folders/b1/zckxsnfj1gg94dr8z6qm3d9w0000gp/T/TemporaryDirectory.v72Ypd/Struct+Main-1.o
1.  Apple Swift version 6.0-dev (LLVM 7b8e6346027d2b1, Swift 763421cee31dc8f)
2.  Compiling with effective version 5.10
3.  While evaluating request ASTLoweringRequest(Lowering AST to SIL for file "Struct+Main.swift")
4.  While silgen emitFunction SIL function "@$s4main7ExampleV9takeProtoySixAC0D0RzlF".
 for 'takeProto(_:)' (at Struct+Main.swift:7:3)
Stack dump without symbol names (ensure you have llvm-symbolizer in your PATH or set the environment var `LLVM_SYMBOLIZER_PATH` to point to it):
0  swift-frontend           0x00000001084693b4 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) + 56
1  swift-frontend           0x0000000108467b80 llvm::sys::RunSignalHandlers() + 112
2  swift-frontend           0x00000001084699fc SignalHandler(int) + 304
3  libsystem_platform.dylib 0x0000000180bcf584 _sigtramp + 56
4  libsystem_pthread.dylib  0x0000000180b9ec20 pthread_kill + 288
5  libsystem_c.dylib        0x0000000180aaba20 abort + 180
6  libsystem_c.dylib        0x0000000180aaad10 err + 0
7  swift-frontend           0x000000010856b218 (anonymous namespace)::CallEmission::emitArgumentsForNormalApply(swift::Lowering::AbstractionPattern, swift::CanTypeWrapper<swift::SILFunctionType>, swift::ForeignInfo const&, llvm::SmallVectorImpl<swift::Lowering::ManagedValue>&, std::__1::optional<swift::SILLocation>&) (.cold.14) + 0
8  swift-frontend           0x0000000103631c64 (anonymous namespace)::CallEmission::emitArgumentsForNormalApply(swift::Lowering::AbstractionPattern, swift::CanTypeWrapper<swift::SILFunctionType>, swift::ForeignInfo const&, llvm::SmallVectorImpl<swift::Lowering::ManagedValue>&, std::__1::optional<swift::SILLocation>&) + 1568
9  swift-frontend           0x000000010361d4b4 (anonymous namespace)::CallEmission::apply(swift::Lowering::SGFContext) + 1800
10 swift-frontend           0x000000010361bb48 swift::Lowering::SILGenFunction::emitApplyExpr(swift::ApplyExpr*, swift::Lowering::SGFContext) + 2028
11 swift-frontend           0x0000000103672ca0 swift::Lowering::SILGenFunction::emitRValue(swift::Expr*, swift::Lowering::SGFContext) + 40
12 swift-frontend           0x00000001036f9e20 swift::Lowering::SILGenFunction::emitReturnExpr(swift::SILLocation, swift::Expr*) + 496
13 swift-frontend           0x00000001036f8110 swift::ASTVisitor<(anonymous namespace)::StmtEmitter, void, void, void, void, void, void>::visit(swift::Stmt*) + 6568
14 swift-frontend           0x00000001036f78d0 swift::ASTVisitor<(anonymous namespace)::StmtEmitter, void, void, void, void, void, void>::visit(swift::Stmt*) + 4456
15 swift-frontend           0x00000001036f675c swift::Lowering::SILGenFunction::emitStmt(swift::Stmt*) + 24
16 swift-frontend           0x0000000103697750 swift::Lowering::SILGenFunction::emitFunction(swift::FuncDecl*) + 432
17 swift-frontend           0x0000000103609ed0 swift::Lowering::SILGenModule::emitFunctionDefinition(swift::SILDeclRef, swift::SILFunction*) + 6324
18 swift-frontend           0x000000010360ad14 swift::Lowering::SILGenModule::emitOrDelayFunction(swift::SILDeclRef) + 252
19 swift-frontend           0x00000001036085e4 swift::Lowering::SILGenModule::emitFunction(swift::FuncDecl*) + 196
20 swift-frontend           0x000000010370b468 (anonymous namespace)::SILGenType::visitFuncDecl(swift::FuncDecl*) + 28
21 swift-frontend           0x00000001037083b4 (anonymous namespace)::SILGenType::emitType() + 276
22 swift-frontend           0x0000000103708294 swift::Lowering::SILGenModule::visitNominalTypeDecl(swift::NominalTypeDecl*) + 24
23 swift-frontend           0x000000010360d654 swift::ASTLoweringRequest::evaluate(swift::Evaluator&, swift::ASTLoweringDescriptor) const + 880
24 swift-frontend           0x00000001036f61b4 swift::SimpleRequest<swift::ASTLoweringRequest, std::__1::unique_ptr<swift::SILModule, std::__1::default_delete<swift::SILModule>> (swift::ASTLoweringDescriptor), (swift::RequestFlags)9>::evaluateRequest(swift::ASTLoweringRequest const&, swift::Evaluator&) + 148
25 swift-frontend           0x0000000103612f48 swift::ASTLoweringRequest::OutputType swift::Evaluator::getResultUncached<swift::ASTLoweringRequest, swift::ASTLoweringRequest::OutputType swift::evaluateOrFatal<swift::ASTLoweringRequest>(swift::Evaluator&, swift::ASTLoweringRequest)::'lambda'()>(swift::ASTLoweringRequest const&, swift::ASTLoweringRequest::OutputType swift::evaluateOrFatal<swift::ASTLoweringRequest>(swift::Evaluator&, swift::ASTLoweringRequest)::'lambda'()) + 340
26 swift-frontend           0x000000010360df58 swift::performASTLowering(swift::FileUnit&, swift::Lowering::TypeConverter&, swift::SILOptions const&, swift::IRGenOptions const*) + 96
27 swift-frontend           0x0000000102ffbb8c swift::performCompileStepsPostSema(swift::CompilerInstance&, int&, swift::FrontendObserver*) + 568
28 swift-frontend           0x000000010300cdfc withSemanticAnalysis(swift::CompilerInstance&, swift::FrontendObserver*, llvm::function_ref<bool (swift::CompilerInstance&)>, bool) + 160
29 swift-frontend           0x0000000102ffe1c8 performCompile(swift::CompilerInstance&, int&, swift::FrontendObserver*) + 708
30 swift-frontend           0x0000000102ffd134 swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 2368
31 swift-frontend           0x0000000102e1792c swift::mainEntry(int, char const**) + 3096
32 dyld                     0x00000001808160e0 start + 2360
nate-chandler commented 5 months ago

Fixed by https://github.com/apple/swift/pull/74235 .