Skip to content

Property wrapper with writable projectedValue causes IRGen crash when used as a function parameter #81021

Open
@chenhaiteng

Description

@chenhaiteng

Description

When a property wrapper that defines a projectedValue with both a getter and setter is used as a function parameter (as allowed by SE-0293), it causes the Swift 6.1 compiler to crash during IR generation.

Reproduction

@propertyWrapper
struct Clamping {
    private var value: CGFloat
    private var range: ClosedRange<CGFloat>

    init(wrappedValue: CGFloat, _ range: ClosedRange<CGFloat>) {
        self.range = range
        self.value = range.clamp(wrappedValue)
    }

    var wrappedValue: CGFloat {
        get { value }
        set { value = range.clamp(newValue) }
    }

    var projectedValue: ClosedRange<CGFloat> {
        get { range }
        set { range = newValue }
    }
}

extension ClosedRange where Bound: Comparable {
    func clamp(_ value: Bound) -> Bound {
        return min(max(lowerBound, value), upperBound)
    }
}

// 🔥 Function using the property wrapper as parameter
func clampingArg(@Clamping(0...10) _ value: CGFloat) {
    print(value)
}

func testFunction() {
    clampingArg(5) // Crash when use clampingArg
}

Stack dump

0.	Program arguments: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift-frontend -frontend -c -primary-file /Users/chenhai/Documents/Workspace/MyProjects/SwiftClamping/Tests/SwiftClampingTests/ClampingTests.swift -emit-dependencies-path /Users/chenhai/Library/Developer/Xcode/DerivedData/SwiftClamping-dbdckjuhkkhysncaefckltnnqfmf/Build/Intermediates.noindex/SwiftClamping.build/Debug/SwifrtClampingTests.build/Objects-normal/arm64/ClampingTests.d -emit-const-values-path /Users/chenhai/Library/Developer/Xcode/DerivedData/SwiftClamping-dbdckjuhkkhysncaefckltnnqfmf/Build/Intermediates.noindex/SwiftClamping.build/Debug/SwifrtClampingTests.build/Objects-normal/arm64/ClampingTests.swiftconstvalues -emit-reference-dependencies-path /Users/chenhai/Library/Developer/Xcode/DerivedData/SwiftClamping-dbdckjuhkkhysncaefckltnnqfmf/Build/Intermediates.noindex/SwiftClamping.build/Debug/SwifrtClampingTests.build/Objects-normal/arm64/ClampingTests.swiftdeps -serialize-diagnostics-path /Users/chenhai/Library/Developer/Xcode/DerivedData/SwiftClamping-dbdckjuhkkhysncaefckltnnqfmf/Build/Intermediates.noindex/SwiftClamping.build/Debug/SwifrtClampingTests.build/Objects-normal/arm64/ClampingTests.dia -target arm64-apple-macos14.0 -Xllvm -aarch64-use-tbi -enable-objc-interop -stack-check -sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.4.sdk -I /Users/chenhai/Library/Developer/Xcode/DerivedData/SwiftClamping-dbdckjuhkkhysncaefckltnnqfmf/Build/Products/Debug -I /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/usr/lib -F /Users/chenhai/Library/Developer/Xcode/DerivedData/SwiftClamping-dbdckjuhkkhysncaefckltnnqfmf/Build/Products/Debug/PackageFrameworks -F /Users/chenhai/Library/Developer/Xcode/DerivedData/SwiftClamping-dbdckjuhkkhysncaefckltnnqfmf/Build/Products/Debug -F /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks -no-color-diagnostics -enable-testing -g -debug-info-format=dwarf -dwarf-version=4 -module-cache-path /Users/chenhai/Library/Developer/Xcode/DerivedData/ModuleCache.noindex -profile-generate -profile-coverage-mapping -swift-version 6 -enforce-exclusivity=checked -Onone -D SWIFT_PACKAGE -D DEBUG -D Xcode -serialize-debugging-options -const-gather-protocols-file /Users/chenhai/Library/Developer/Xcode/DerivedData/SwiftClamping-dbdckjuhkkhysncaefckltnnqfmf/Build/Intermediates.noindex/SwiftClamping.build/Debug/SwifrtClampingTests.build/Objects-normal/arm64/SwifrtClampingTests_const_extract_protocols.json -enable-experimental-feature DebugDescriptionMacro -empty-abi-descriptor -plugin-path /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/host/plugins/testing -validate-clang-modules-once -clang-build-session-file /Users/chenhai/Library/Developer/Xcode/DerivedData/ModuleCache.noindex/Session.modulevalidation -Xcc -working-directory -Xcc /Users/chenhai/Documents/Workspace/MyProjects/SwiftClamping/.swiftpm/xcode -resource-dir /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift -enable-anonymous-context-mangled-names -file-compilation-dir /Users/chenhai/Documents/Workspace/MyProjects/SwiftClamping/.swiftpm/xcode -Xcc -ivfsstatcache -Xcc /Users/chenhai/Library/Developer/Xcode/DerivedData/SDKStatCaches.noindex/macosx15.4-24E241-88b860576fb364319593bd8fb30666b0.sdkstatcache -Xcc -I/Users/chenhai/Library/Developer/Xcode/DerivedData/SwiftClamping-dbdckjuhkkhysncaefckltnnqfmf/Build/Products/Debug/include -Xcc -I/Users/chenhai/Library/Developer/Xcode/DerivedData/SwiftClamping-dbdckjuhkkhysncaefckltnnqfmf/Build/Intermediates.noindex/SwiftClamping.build/Debug/SwifrtClampingTests.build/DerivedSources-normal/arm64 -Xcc -I/Users/chenhai/Library/Developer/Xcode/DerivedData/SwiftClamping-dbdckjuhkkhysncaefckltnnqfmf/Build/Intermediates.noindex/SwiftClamping.build/Debug/SwifrtClampingTests.build/DerivedSources/arm64 -Xcc -I/Users/chenhai/Library/Developer/Xcode/DerivedData/SwiftClamping-dbdckjuhkkhysncaefckltnnqfmf/Build/Intermediates.noindex/SwiftClamping.build/Debug/SwifrtClampingTests.build/DerivedSources -Xcc -DSWIFT_PACKAGE -Xcc -DDEBUG=1 -module-name SwifrtClampingTests -package-name swiftclamping -frontend-parseable-output -disable-clang-spi -target-sdk-version 15.4 -target-sdk-name macosx15.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 -in-process-plugin-server-path /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/host/libSwiftInProcPluginServer.dylib -plugin-path /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/host/plugins -plugin-path /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/local/lib/swift/host/plugins -parse-as-library -o /Users/chenhai/Library/Developer/Xcode/DerivedData/SwiftClamping-dbdckjuhkkhysncaefckltnnqfmf/Build/Intermediates.noindex/SwiftClamping.build/Debug/SwifrtClampingTests.build/Objects-normal/arm64/ClampingTests.o -index-unit-output-path /SwiftClamping.build/Debug/SwifrtClampingTests.build/Objects-normal/arm64/ClampingTests.o -index-store-path /Users/chenhai/Library/Developer/Xcode/DerivedData/SwiftClamping-dbdckjuhkkhysncaefckltnnqfmf/Index.noindex/DataStore -index-system-modules
1.	Apple Swift version 6.1 (swiftlang-6.1.0.110.21 clang-1700.0.13.3)
2.	Compiling with the current language version
3.	While evaluating request IRGenRequest(IR Generation for file "/Users/chenhai/Documents/Workspace/MyProjects/SwiftClamping/Tests/SwiftClampingTests/ClampingTests.swift")
4.	While emitting IR SIL function "@$s19SwifrtClampingTests0bC0C10clampedArgyy12CoreGraphics7CGFloatVF6$valueL_SNyAGGvs".
 for setter for $value (at /Users/chenhai/Documents/Workspace/MyProjects/SwiftClamping/Tests/SwiftClampingTests/ClampingTests.swift:10:40)
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           0x000000010747ac28 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) + 56
1  swift-frontend           0x0000000107478a60 llvm::sys::RunSignalHandlers() + 112
2  swift-frontend           0x000000010747b264 SignalHandler(int) + 360
3  libsystem_platform.dylib 0x0000000189fc6de4 _sigtramp + 56
4  swift-frontend           0x00000001016fb8b0 swift::irgen::allocateForCoercion(swift::irgen::IRGenFunction&, llvm::Type*, llvm::Type*, llvm::Twine const&) + 412
5  swift-frontend           0x00000001016fb8b0 swift::irgen::allocateForCoercion(swift::irgen::IRGenFunction&, llvm::Type*, llvm::Type*, llvm::Twine const&) + 412
6  swift-frontend           0x00000001016ec320 swift::irgen::IRGenFunction::coerceValue(llvm::Value*, llvm::Type*, llvm::DataLayout const&) + 636
7  swift-frontend           0x00000001016ed484 swift::irgen::CallEmission::emitCallSite() + 168
8  swift-frontend           0x00000001016f0748 swift::irgen::CallEmission::emitToExplosion(swift::irgen::Explosion&, bool) + 3048
9  swift-frontend           0x0000000101967ea4 (anonymous namespace)::IRGenSILFunction::visitFullApplySite(swift::FullApplySite) + 4832
10 swift-frontend           0x00000001019384e4 (anonymous namespace)::IRGenSILFunction::visitSILBasicBlock(swift::SILBasicBlock*) + 2636
11 swift-frontend           0x000000010193638c (anonymous namespace)::IRGenSILFunction::emitSILFunction() + 15860
12 swift-frontend           0x00000001019320e0 swift::irgen::IRGenModule::emitSILFunction(swift::SILFunction*) + 2788
13 swift-frontend           0x0000000101755560 swift::irgen::IRGenerator::emitGlobalTopLevel(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>> const&) + 2044
14 swift-frontend           0x00000001018e39fc swift::IRGenRequest::evaluate(swift::Evaluator&, swift::IRGenDescriptor) const + 4296
15 swift-frontend           0x000000010193133c swift::SimpleRequest<swift::IRGenRequest, swift::GeneratedModule (swift::IRGenDescriptor), (swift::RequestFlags)17>::evaluateRequest(swift::IRGenRequest const&, swift::Evaluator&) + 180
16 swift-frontend           0x00000001018ecf28 swift::IRGenRequest::OutputType swift::Evaluator::getResultUncached<swift::IRGenRequest, swift::IRGenRequest::OutputType swift::evaluateOrFatal<swift::IRGenRequest>(swift::Evaluator&, swift::IRGenRequest)::'lambda'()>(swift::IRGenRequest const&, swift::IRGenRequest::OutputType swift::evaluateOrFatal<swift::IRGenRequest>(swift::Evaluator&, swift::IRGenRequest)::'lambda'()) + 812
17 swift-frontend           0x00000001018e6688 swift::performIRGeneration(swift::FileUnit*, swift::IRGenOptions const&, swift::TBDGenOptions const&, std::__1::unique_ptr<swift::SILModule, std::__1::default_delete<swift::SILModule>>, llvm::StringRef, swift::PrimarySpecificPaths const&, llvm::StringRef, llvm::GlobalVariable**) + 176
18 swift-frontend           0x00000001012d1af0 generateIR(swift::IRGenOptions const&, swift::TBDGenOptions const&, std::__1::unique_ptr<swift::SILModule, std::__1::default_delete<swift::SILModule>>, swift::PrimarySpecificPaths const&, llvm::StringRef, llvm::PointerUnion<swift::ModuleDecl*, swift::SourceFile*>, llvm::GlobalVariable*&, llvm::ArrayRef<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>) + 156
19 swift-frontend           0x00000001012cd07c performCompileStepsPostSILGen(swift::CompilerInstance&, std::__1::unique_ptr<swift::SILModule, std::__1::default_delete<swift::SILModule>>, llvm::PointerUnion<swift::ModuleDecl*, swift::SourceFile*>, swift::PrimarySpecificPaths const&, int&, swift::FrontendObserver*) + 2108
20 swift-frontend           0x00000001012cc0a8 swift::performCompileStepsPostSema(swift::CompilerInstance&, int&, swift::FrontendObserver*) + 1036
21 swift-frontend           0x00000001012cf654 performCompile(swift::CompilerInstance&, int&, swift::FrontendObserver*) + 1764
22 swift-frontend           0x00000001012cdfd8 swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 3716
23 swift-frontend           0x00000001012520bc swift::mainEntry(int, char const**) + 5428
24 dyld                     0x0000000189c10274 start + 2840
Failed frontend command:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift-frontend -frontend -c -primary-file /Users/chenhai/Documents/Workspace/MyProjects/SwiftClamping/Tests/SwiftClampingTests/ClampingTests.swift -emit-dependencies-path /Users/chenhai/Library/Developer/Xcode/DerivedData/SwiftClamping-dbdckjuhkkhysncaefckltnnqfmf/Build/Intermediates.noindex/SwiftClamping.build/Debug/SwifrtClampingTests.build/Objects-normal/arm64/ClampingTests.d -emit-const-values-path /Users/chenhai/Library/Developer/Xcode/DerivedData/SwiftClamping-dbdckjuhkkhysncaefckltnnqfmf/Build/Intermediates.noindex/SwiftClamping.build/Debug/SwifrtClampingTests.build/Objects-normal/arm64/ClampingTests.swiftconstvalues -emit-reference-dependencies-path /Users/chenhai/Library/Developer/Xcode/DerivedData/SwiftClamping-dbdckjuhkkhysncaefckltnnqfmf/Build/Intermediates.noindex/SwiftClamping.build/Debug/SwifrtClampingTests.build/Objects-normal/arm64/ClampingTests.swiftdeps -serialize-diagnostics-path /Users/chenhai/Library/Developer/Xcode/DerivedData/SwiftClamping-dbdckjuhkkhysncaefckltnnqfmf/Build/Intermediates.noindex/SwiftClamping.build/Debug/SwifrtClampingTests.build/Objects-normal/arm64/ClampingTests.dia -target arm64-apple-macos14.0 -Xllvm -aarch64-use-tbi -enable-objc-interop -stack-check -sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.4.sdk -I /Users/chenhai/Library/Developer/Xcode/DerivedData/SwiftClamping-dbdckjuhkkhysncaefckltnnqfmf/Build/Products/Debug -I /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/usr/lib -F /Users/chenhai/Library/Developer/Xcode/DerivedData/SwiftClamping-dbdckjuhkkhysncaefckltnnqfmf/Build/Products/Debug/PackageFrameworks -F /Users/chenhai/Library/Developer/Xcode/DerivedData/SwiftClamping-dbdckjuhkkhysncaefckltnnqfmf/Build/Products/Debug -F /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks -no-color-diagnostics -enable-testing -g -debug-info-format\=dwarf -dwarf-version\=4 -module-cache-path /Users/chenhai/Library/Developer/Xcode/DerivedData/ModuleCache.noindex -profile-generate -profile-coverage-mapping -swift-version 6 -enforce-exclusivity\=checked -Onone -D SWIFT_PACKAGE -D DEBUG -D Xcode -serialize-debugging-options -const-gather-protocols-file /Users/chenhai/Library/Developer/Xcode/DerivedData/SwiftClamping-dbdckjuhkkhysncaefckltnnqfmf/Build/Intermediates.noindex/SwiftClamping.build/Debug/SwifrtClampingTests.build/Objects-normal/arm64/SwifrtClampingTests_const_extract_protocols.json -enable-experimental-feature DebugDescriptionMacro -empty-abi-descriptor -plugin-path /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/host/plugins/testing -validate-clang-modules-once -clang-build-session-file /Users/chenhai/Library/Developer/Xcode/DerivedData/ModuleCache.noindex/Session.modulevalidation -Xcc -working-directory -Xcc /Users/chenhai/Documents/Workspace/MyProjects/SwiftClamping/.swiftpm/xcode -resource-dir /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift -enable-anonymous-context-mangled-names -file-compilation-dir /Users/chenhai/Documents/Workspace/MyProjects/SwiftClamping/.swiftpm/xcode -Xcc -ivfsstatcache -Xcc /Users/chenhai/Library/Developer/Xcode/DerivedData/SDKStatCaches.noindex/macosx15.4-24E241-88b860576fb364319593bd8fb30666b0.sdkstatcache -Xcc -I/Users/chenhai/Library/Developer/Xcode/DerivedData/SwiftClamping-dbdckjuhkkhysncaefckltnnqfmf/Build/Products/Debug/include -Xcc -I/Users/chenhai/Library/Developer/Xcode/DerivedData/SwiftClamping-dbdckjuhkkhysncaefckltnnqfmf/Build/Intermediates.noindex/SwiftClamping.build/Debug/SwifrtClampingTests.build/DerivedSources-normal/arm64 -Xcc -I/Users/chenhai/Library/Developer/Xcode/DerivedData/SwiftClamping-dbdckjuhkkhysncaefckltnnqfmf/Build/Intermediates.noindex/SwiftClamping.build/Debug/SwifrtClampingTests.build/DerivedSources/arm64 -Xcc -I/Users/chenhai/Library/Developer/Xcode/DerivedData/SwiftClamping-dbdckjuhkkhysncaefckltnnqfmf/Build/Intermediates.noindex/SwiftClamping.build/Debug/SwifrtClampingTests.build/DerivedSources -Xcc -DSWIFT_PACKAGE -Xcc -DDEBUG\=1 -module-name SwifrtClampingTests -package-name swiftclamping -frontend-parseable-output -disable-clang-spi -target-sdk-version 15.4 -target-sdk-name macosx15.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 -in-process-plugin-server-path /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/host/libSwiftInProcPluginServer.dylib -plugin-path /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/host/plugins -plugin-path /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/local/lib/swift/host/plugins -parse-as-library -o /Users/chenhai/Library/Developer/Xcode/DerivedData/SwiftClamping-dbdckjuhkkhysncaefckltnnqfmf/Build/Intermediates.noindex/SwiftClamping.build/Debug/SwifrtClampingTests.build/Objects-normal/arm64/ClampingTests.o -index-unit-output-path /SwiftClamping.build/Debug/SwifrtClampingTests.build/Objects-normal/arm64/ClampingTests.o -index-store-path /Users/chenhai/Library/Developer/Xcode/DerivedData/SwiftClamping-dbdckjuhkkhysncaefckltnnqfmf/Index.noindex/DataStore -index-system-modules

Expected behavior

Property Wrapper with writable projected value should works on function parameter without compile error.

Environment

Swift 6.1 (swiftlang-6.1.0.110.21)
Xcode Version 16.3 (16E140)

Additional information

There is a workaround to avoid this crash:

  • Declaring a class to wrap the projected value.
  • Make the projected value as nonmutating set
class RangeWrapper<Value: Comparable> {
    var range : ClosedRange<Value>
    init(_ range: ClosedRange<Value>) {
        self.range = range
    }
}

@propertyWrapper
struct Clamping {
    private var value: CGFloat
    private var range: RangeWrapper<CGFloat>

    init(wrappedValue: CGFloat, _ range: ClosedRange<CGFloat>) {
        self.range = RangeWrapper(range)
        self.value = range.clamp(wrappedValue)
    }

    var wrappedValue: CGFloat {
        get { value }
        set { value = range.range.clamp(newValue) }
    }

    var projectedValue: ClosedRange<CGFloat> {
        get { range }
        nonmutating set { range.range = newValue }
    }
}

extension ClosedRange where Bound: Comparable {
    func clamp(_ value: Bound) -> Bound {
        return min(max(lowerBound, value), upperBound)
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugA deviation from expected or documented behavior. Also: expected but undesirable behavior.crashBug: A crash, i.e., an abnormal termination of softwaretriage neededThis issue needs more specific labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions