Empty propertyWrapper initializer changes memberwise initializer type

I've encountered some strange (to me) behavior in dealing with a struct that contains a wrapped property with a default initializer. A contrived main.swift example is below:

protocol DefaultConstructible {
	init()
}

extension String: DefaultConstructible {}


@propertyWrapper
struct Wrapper<Value: DefaultConstructible> {
	private var value: Value

	public var wrappedValue: Value {
		return value
	}

	public init(wrappedValue: Value) {
		self.value = wrappedValue
	}

	//public init() { value = Value() }
}


struct SomeData {
	@Wrapper
	var data: String

	func print() {
		Swift.print(data)
	}
}


let data = SomeData(data: "data")
data.print()

As pasted above, this compiles and runs just fine, but if I uncomment the //public init() { value = Value() } line above, I get:

main.swift:34:27: error: cannot convert value of type 'String' to expected argument type 'Wrapper<String>'
let data = SomeData(data: "data")
                          ^

The memberwise initialization section of the property wrapper proposal doesn't mention an empty initializer for the the wrapper changing the memberwise initializer back to the wrapper type, but I may be misinterpreting the difference between "initial value" and having an empty initializer.

Can anyone provide any more information or workarounds so I can have both the memberwise initializer on the struct and an empty initializer on the property wrapper?

1 Like

It seems to work fine with me with and without the init (iOS playground Swift 5.1).

Hmm, here's the output of my swift --version:

Apple Swift version 5.2.4 (swiftlang-1103.0.32.9 clang-1103.0.32.53)
Target: x86_64-apple-darwin19.4.0

I'm using the stock Xcode from the App Store, compiling and running from the command line.

It does have the same problem with Swift 5.2 on Linux.

Anyhow, the arguments in synthesized initializer needs to be prioritized given that we’re not synthesizing all wrapper/wrapped combinations thereof. What surprises me is that choice changes between minor version. That alone does sound like a bug.

This is interesting, if I compile the code on 5.2 (using swiftenv, if it matters), I get the same behavior as originally reported on 5.2.4, but on 5.1.5 I get a compiler error and stack dump when trying to compile with the init() uncommented (commented out it works just fine):

$ swift build
SIL verification failed: return value type does not match return type of function: functionResultType == instResultType
Verifying instruction:
     %1 = apply %0() : $@convention(thin) () -> @owned Wrapper<String> // user: %2
->   return %1 : $Wrapper<String>                 // id: %2
In function:
// default argument 0 of SomeData.init(data:)
sil [ossa] @$s21StructPropertyWrapper8SomeDataV4dataACSS_tcfcfA_ : $@convention(thin) () -> @owned String {
bb0:
  // function_ref variable initialization expression of SomeData._data
  %0 = function_ref @$s21StructPropertyWrapper8SomeDataV5_data33_4741C1CC30866EF9503AFFCFBFF2CBB6LLAA0C0VySSGvpfi : $@convention(thin) () -> @owned Wrapper<String> // user: %1
  %1 = apply %0() : $@convention(thin) () -> @owned Wrapper<String> // user: %2
  return %1 : $Wrapper<String>                    // id: %2
} // end sil function '$s21StructPropertyWrapper8SomeDataV4dataACSS_tcfcfA_'

Stack dump:
0.	Program arguments: /Library/Developer/Toolchains/swift-5.1.5-RELEASE.xctoolchain/usr/bin/swift -frontend -c -primary-file /Users/mplewis/Projects/StructPropertyWrapper/Sources/StructPropertyWrapper/main.swift -emit-module-path /Users/mplewis/Projects/StructPropertyWrapper/.build/x86_64-apple-macosx/debug/StructPropertyWrapper.build/main~partial.swiftmodule -emit-module-doc-path /Users/mplewis/Projects/StructPropertyWrapper/.build/x86_64-apple-macosx/debug/StructPropertyWrapper.build/main~partial.swiftdoc -emit-dependencies-path /Users/mplewis/Projects/StructPropertyWrapper/.build/x86_64-apple-macosx/debug/StructPropertyWrapper.build/main.d -emit-reference-dependencies-path /Users/mplewis/Projects/StructPropertyWrapper/.build/x86_64-apple-macosx/debug/StructPropertyWrapper.build/main.swiftdeps -target x86_64-apple-macosx10.10 -enable-objc-interop -sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk -I /Users/mplewis/Projects/StructPropertyWrapper/.build/x86_64-apple-macosx/debug -F /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks -enable-testing -g -module-cache-path /Users/mplewis/Projects/StructPropertyWrapper/.build/x86_64-apple-macosx/debug/ModuleCache -swift-version 5 -Onone -D SWIFT_PACKAGE -D DEBUG -color-diagnostics -enable-anonymous-context-mangled-names -module-name StructPropertyWrapper -o /Users/mplewis/Projects/StructPropertyWrapper/.build/x86_64-apple-macosx/debug/StructPropertyWrapper.build/main.swift.o -index-store-path /Users/mplewis/Projects/StructPropertyWrapper/.build/x86_64-apple-macosx/debug/index/store -index-system-modules 
1.	While silgen emitDefaultArgGenerator  SIL function "@$s21StructPropertyWrapper8SomeDataV4dataACSS_tcfcfA_".
 for '_data' (at /Users/mplewis/Projects/StructPropertyWrapper/Sources/StructPropertyWrapper/main.swift:26:6)
2.	While verifying SIL function "@$s21StructPropertyWrapper8SomeDataV4dataACSS_tcfcfA_".
 for '_data' (at /Users/mplewis/Projects/StructPropertyWrapper/Sources/StructPropertyWrapper/main.swift:26:6)
0  swift                    0x000000010c27cff5 llvm::sys::PrintStackTrace(llvm::raw_ostream&) + 37
1  swift                    0x000000010c27c2e5 llvm::sys::RunSignalHandlers() + 85
2  swift                    0x000000010c27d5d8 SignalHandler(int) + 264
3  libsystem_platform.dylib 0x00007fff6aecb5fd _sigtramp + 29
4  swift                    0x000000010e0c5000 (anonymous namespace)::DarwinX86AsmBackend::getCompactUnwindRegNum(unsigned int) const::CU64BitRegs + 219730
5  libsystem_c.dylib        0x00007fff6ada1808 abort + 120
6  swift                    0x000000010924eab8 (anonymous namespace)::SILVerifier::_require(bool, llvm::Twine const&, std::__1::function<void ()> const&) + 616
7  swift                    0x0000000109261f00 swift::SILInstructionVisitor<(anonymous namespace)::SILVerifier, void>::visit(swift::SILInstruction*) + 67248
8  swift                    0x00000001092505dc (anonymous namespace)::SILVerifier::visitSILBasicBlock(swift::SILBasicBlock*) + 1484
9  swift                    0x000000010924b287 swift::SILFunction::verify(bool) const + 7303
10 swift                    0x0000000108cff26d swift::Lowering::SILGenModule::postEmitFunction(swift::SILDeclRef, swift::SILFunction*) + 205
11 swift                    0x0000000108d07849 swift::Lowering::SILGenModule::emitDefaultArgGenerator(swift::SILDeclRef, swift::ParamDecl*)::$_5::operator()(swift::SILFunction*) const + 217
12 swift                    0x0000000108d013d7 swift::Lowering::SILGenModule::emitDefaultArgGenerator(swift::SILDeclRef, swift::ParamDecl*) + 407
13 swift                    0x0000000108cff58a swift::Lowering::SILGenModule::emitAbstractFuncDecl(swift::AbstractFunctionDecl*) + 122
14 swift                    0x0000000108cff77f swift::Lowering::SILGenModule::emitConstructor(swift::ConstructorDecl*) + 31
15 swift                    0x0000000108dd1307 (anonymous namespace)::SILGenType::emitType() + 535
16 swift                    0x0000000108dd10e9 swift::Lowering::SILGenModule::visitNominalTypeDecl(swift::NominalTypeDecl*) + 25
17 swift                    0x0000000108d03cc6 swift::Lowering::SILGenModule::emitSourceFile(swift::SourceFile*) + 822
18 swift                    0x0000000108d04b25 swift::SILModule::constructSIL(swift::ModuleDecl*, swift::SILOptions&, swift::FileUnit*) + 293
19 swift                    0x0000000108d05046 swift::performSILGeneration(swift::FileUnit&, swift::SILOptions&) + 38
20 swift                    0x0000000108a291f3 performCompile(swift::CompilerInstance&, swift::CompilerInvocation&, llvm::ArrayRef<char const*>, int&, swift::FrontendObserver*, swift::UnifiedStatsReporter*) + 8291
21 swift                    0x0000000108a2626a swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 3002
22 swift                    0x00000001089ced18 main + 696
23 libdyld.dylib            0x00007fff6acd2cc9 start + 1
24 libdyld.dylib            0x000000000000002a start + 2503136098

The iOS version might handle things differently, I guess.