Skip to content

Commit cf886a5

Browse files
Merge pull request #4894 from swiftwasm/release/5.7
[pull] swiftwasm-release/5.7 from release/5.7
2 parents cdbe9cb + 4058fbf commit cf886a5

File tree

8 files changed

+277
-35
lines changed

8 files changed

+277
-35
lines changed

lib/SILGen/LValue.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,6 @@ class PathComponent {
105105
CoroutineAccessorKind, // coroutine accessor
106106
ValueKind, // random base pointer as an lvalue
107107
PhysicalKeyPathApplicationKind, // applying a key path
108-
ABISafeConversionKind, // unchecked_addr_cast
109108

110109
// Logical LValue kinds
111110
GetterSetterKind, // property or subscript getter/setter
@@ -118,6 +117,7 @@ class PathComponent {
118117
// Translation LValue kinds (a subtype of logical)
119118
OrigToSubstKind, // generic type substitution
120119
SubstToOrigKind, // generic type substitution
120+
UncheckedConversionKind, // unchecked_X_cast
121121

122122
FirstLogicalKind = GetterSetterKind,
123123
FirstTranslationKind = OrigToSubstKind,

lib/SILGen/SILGenBuilder.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -620,7 +620,8 @@ ManagedValue SILGenBuilder::createUncheckedBitCast(SILLocation loc,
620620
// updated.
621621
assert((isa<UncheckedTrivialBitCastInst>(cast) ||
622622
isa<UncheckedRefCastInst>(cast) ||
623-
isa<UncheckedBitwiseCastInst>(cast)) &&
623+
isa<UncheckedBitwiseCastInst>(cast) ||
624+
isa<ConvertFunctionInst>(cast)) &&
624625
"SILGenBuilder is out of sync with SILBuilder.");
625626

626627
// If we have a trivial inst, just return early.

lib/SILGen/SILGenLValue.cpp

Lines changed: 72 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2204,26 +2204,82 @@ namespace {
22042204
}
22052205
};
22062206

2207-
/// A physical component which performs an unchecked_addr_cast
2208-
class ABISafeConversionComponent final : public PhysicalPathComponent {
2207+
/// A translation component that performs \c unchecked_*_cast 's as-needed.
2208+
class UncheckedConversionComponent final : public TranslationPathComponent {
2209+
private:
2210+
Type OrigType;
2211+
2212+
/// \returns the type this component is trying to convert \b to
2213+
CanType getTranslatedType() const {
2214+
return getTypeData().SubstFormalType->getCanonicalType();
2215+
}
2216+
2217+
/// \returns the type this component is trying to convert \b from
2218+
CanType getUntranslatedType() const {
2219+
return OrigType->getRValueType()->getCanonicalType();
2220+
}
2221+
2222+
/// perform a conversion of ManagedValue -> ManagedValue
2223+
ManagedValue doUncheckedConversion(SILGenFunction &SGF, SILLocation loc,
2224+
ManagedValue val, CanType toType) {
2225+
auto toTy = SGF.getLoweredType(toType);
2226+
auto fromTy = val.getType();
2227+
2228+
if (fromTy == toTy)
2229+
return val; // nothing to do.
2230+
2231+
// otherwise emit the right kind of cast based on whether it's an address.
2232+
assert(fromTy.isAddress() == toTy.isAddress());
2233+
2234+
if (toTy.isAddress())
2235+
return SGF.B.createUncheckedAddrCast(loc, val, toTy);
2236+
2237+
return SGF.B.createUncheckedBitCast(loc, val, toTy);
2238+
}
2239+
2240+
/// perform a conversion of RValue -> RValue
2241+
RValue doUncheckedConversion(SILGenFunction &SGF, SILLocation loc,
2242+
RValue &&rv, CanType toType) {
2243+
auto val = std::move(rv).getAsSingleValue(SGF, loc);
2244+
val = doUncheckedConversion(SGF, loc, val, toType);
2245+
return RValue(SGF, loc, toType, val);
2246+
}
2247+
22092248
public:
2210-
ABISafeConversionComponent(LValueTypeData typeData)
2211-
: PhysicalPathComponent(typeData, ABISafeConversionKind,
2212-
/*actorIsolation=*/None) {}
2249+
/// \param OrigType is the type we are converting \b from
2250+
/// \param typeData will contain the type we are converting \b to
2251+
UncheckedConversionComponent(LValueTypeData typeData, Type OrigType)
2252+
: TranslationPathComponent(typeData, UncheckedConversionKind),
2253+
OrigType(OrigType) {}
22132254

2214-
ManagedValue project(SILGenFunction &SGF, SILLocation loc,
2215-
ManagedValue base) && override {
2216-
auto toType = SGF.getLoweredType(getTypeData().SubstFormalType)
2217-
.getAddressType();
2255+
bool isLoadingPure() const override { return true; }
22182256

2219-
if (base.getType() == toType)
2220-
return base; // nothing to do
2257+
/// Used during write operations to convert the value prior to writing to
2258+
/// the base.
2259+
RValue untranslate(SILGenFunction &SGF, SILLocation loc,
2260+
RValue &&rv, SGFContext c) && override {
2261+
return doUncheckedConversion(SGF, loc, std::move(rv),
2262+
getUntranslatedType());
2263+
}
22212264

2222-
return SGF.B.createUncheckedAddrCast(loc, base, toType);
2265+
/// Used during read operations to convert the value after reading the base.
2266+
RValue translate(SILGenFunction &SGF, SILLocation loc,
2267+
RValue &&rv, SGFContext c) && override {
2268+
return doUncheckedConversion(SGF, loc, std::move(rv),
2269+
getTranslatedType());
2270+
}
2271+
2272+
std::unique_ptr<LogicalPathComponent>
2273+
clone(SILGenFunction &SGF, SILLocation loc) const override {
2274+
return std::make_unique<UncheckedConversionComponent>(getTypeData(),
2275+
OrigType);
22232276
}
22242277

22252278
void dump(raw_ostream &OS, unsigned indent) const override {
2226-
OS.indent(indent) << "ABISafeConversionComponent\n";
2279+
OS.indent(indent) << "UncheckedConversionComponent"
2280+
<< "\n\tfromType: " << getUntranslatedType()
2281+
<< "\n\ttoType: " << getTranslatedType()
2282+
<< "\n";
22272283
}
22282284
};
22292285
} // end anonymous namespace
@@ -3741,7 +3797,9 @@ LValue SILGenLValue::visitABISafeConversionExpr(ABISafeConversionExpr *e,
37413797
LValue lval = visitRec(e->getSubExpr(), accessKind, options);
37423798
auto typeData = getValueTypeData(SGF, accessKind, e);
37433799

3744-
lval.add<ABISafeConversionComponent>(typeData);
3800+
auto OrigType = e->getSubExpr()->getType();
3801+
3802+
lval.add<UncheckedConversionComponent>(typeData, OrigType);
37453803

37463804
return lval;
37473805
}

lib/Sema/CSClosure.cpp

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ class TypeVariableRefFinder : public ASTWalker {
109109
CS.setType(var, computeProjectedValueType(wrappedVar, wrapperType));
110110
} else {
111111
// _<name> is the wrapper var
112-
CS.setType(var, computeWrappedValueType(wrappedVar, wrapperType));
112+
CS.setType(var, wrapperType);
113113
}
114114

115115
return {true, expr};
@@ -498,18 +498,13 @@ class SyntacticElementConstraintGenerator
498498
init = TypeChecker::buildDefaultInitializer(patternType);
499499
}
500500

501-
if (init) {
502-
return SolutionApplicationTarget::forInitialization(
503-
init, patternBinding->getDeclContext(), patternType, patternBinding,
504-
index,
505-
/*bindPatternVarsOneWay=*/false);
506-
}
507-
508-
// If there was no initializer, there could be one from a property
509-
// wrapper which has to be pre-checked before use. This is not a
510-
// problem in top-level code because pattern bindings go through
511-
// `typeCheckExpression` which does pre-check automatically and
512-
// result builders do not allow declaring local wrapped variables.
501+
// A property wrapper initializer (either user-defined
502+
// or a synthesized one) has to be pre-checked before use.
503+
//
504+
// This is not a problem in top-level code because pattern
505+
// bindings go through `typeCheckExpression` which does
506+
// pre-check automatically and result builders do not allow
507+
// declaring local wrapped variables (yet).
513508
if (hasPropertyWrapper(pattern)) {
514509
auto target = SolutionApplicationTarget::forInitialization(
515510
init, patternBinding->getDeclContext(), patternType, patternBinding,
@@ -524,6 +519,13 @@ class SyntacticElementConstraintGenerator
524519
return target;
525520
}
526521

522+
if (init) {
523+
return SolutionApplicationTarget::forInitialization(
524+
init, patternBinding->getDeclContext(), patternType, patternBinding,
525+
index,
526+
/*bindPatternVarsOneWay=*/false);
527+
}
528+
527529
return SolutionApplicationTarget::forUninitializedVar(patternBinding, index,
528530
patternType);
529531
}

test/SILGen/objc_preconcurrency.swift

Lines changed: 118 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@
77
@preconcurrency var sendyHandler: @Sendable () -> Void { get set }
88
}
99

10+
@preconcurrency class OldWorld {
11+
@preconcurrency var handler: (@Sendable () -> Void)?
12+
@preconcurrency var mainHandler: (@MainActor () -> Void)?
13+
@preconcurrency var nonOptionalHandler: @Sendable () -> Void = {}
14+
@preconcurrency var nonOptionalMainHandler: @MainActor () -> Void = {}
15+
}
16+
1017
// CHECK-LABEL: sil hidden [ossa] @$s19objc_preconcurrency19testDynamicDispatch1p17completionHandleryAA1P_p_yyctF
1118
// CHECK: dynamic_method_br
1219
// CHECK: bb{{[0-9]+}}(%{{[0-9]+}} : $@convention(objc_method) (@convention(block) @Sendable () -> (), @opened
@@ -19,26 +26,134 @@ func testDynamicDispatch(p: P, completionHandler: @escaping () -> Void) {
1926
}
2027

2128
// CHECK-LABEL: sil hidden [ossa] @$s19objc_preconcurrency21testOptionalVarAccessyySo12NSTouchGrassCF
22-
// CHECK: unchecked_addr_cast {{.*}} : $*Optional<@Sendable @callee_guaranteed () -> ()> to $*Optional<@callee_guaranteed () -> ()>
29+
// CHECK: unchecked_bitwise_cast {{.*}} : $Optional<@Sendable @callee_guaranteed () -> ()> to $Optional<@callee_guaranteed () -> ()>
2330
// CHECK: } // end sil function '$s19objc_preconcurrency21testOptionalVarAccessyySo12NSTouchGrassCF'
2431
func testOptionalVarAccess(_ grass: NSTouchGrass) {
2532
grass.cancellationHandler?()
2633
}
2734

35+
// CHECK-LABEL: sil hidden [ossa] @$s19objc_preconcurrency33testOptionalVarAccessPartialApplyyyycSgSo12NSTouchGrassCF
36+
// CHECK: unchecked_bitwise_cast {{.*}} : $Optional<@Sendable @callee_guaranteed () -> ()> to $Optional<@callee_guaranteed () -> ()>
37+
// CHECK: } // end sil function '$s19objc_preconcurrency33testOptionalVarAccessPartialApplyyyycSgSo12NSTouchGrassCF'
38+
func testOptionalVarAccessPartialApply(_ grass: NSTouchGrass) -> (() -> Void)? {
39+
let handler = grass.cancellationHandler
40+
if let unwrapped = handler {
41+
unwrapped()
42+
}
43+
return handler
44+
}
45+
46+
// CHECK-LABEL: sil hidden [ossa] @$s19objc_preconcurrency16testObjCVarWriteyySo12NSTouchGrassCF
47+
// CHECK: unchecked_bitwise_cast {{.*}} : $Optional<@callee_guaranteed () -> ()> to $Optional<@Sendable @callee_guaranteed () -> ()>
48+
// CHECK: objc_method {{.*}} : $NSTouchGrass, #NSTouchGrass.cancellationHandler!setter.foreign : (NSTouchGrass) -> ((@Sendable () -> ())?) -> (), $@convention(objc_method) (Optional<@convention(block) @Sendable () -> ()>, NSTouchGrass) -> ()
49+
// CHECK: } // end sil function '$s19objc_preconcurrency16testObjCVarWriteyySo12NSTouchGrassCF'
50+
func testObjCVarWrite(_ grass: NSTouchGrass) {
51+
grass.cancellationHandler = {}
52+
}
53+
54+
// the below looks kinda long and wonky, but is expected. for a summary, the steps are:
55+
// 1. objc to native
56+
// 2. Sendable to non-Sendable (major part of this test)
57+
// 3. non-optional to optional
58+
// 4. from non-Sendable to Sendable (major part of this test)
59+
// 5. from native to objc (which involves unwrapping and rewrapping that optional; kinda silly but optimization will clean it up)
60+
//
61+
// CHECK-LABEL: sil hidden [ossa] @$s19objc_preconcurrency22testObjCVarWriteAcrossyySo12NSTouchGrassCF
62+
// CHECK: [[GET_EXCEPTION:%[0-9]+]] = objc_method {{.*}} : $NSTouchGrass, #NSTouchGrass.exceptionHandler!getter.foreign
63+
// CHECK: [[SENDABLE_BLOCK:%[0-9]+]] = apply [[GET_EXCEPTION]]({{.*}}) : $@convention(objc_method) (NSTouchGrass) -> @autoreleased @convention(block) @Sendable () -> ()
64+
// << step 1 >>
65+
// CHECK: [[NATIVE_THUNK:%[0-9]+]] = function_ref @$sIeyBh_Iegh_TR : $@convention(thin) @Sendable (@guaranteed @convention(block) @Sendable () -> ()) -> ()
66+
// CHECK: [[NATIVE_SENDABLE_EXCEPTION:%[0-9]+]] = partial_apply [callee_guaranteed] [[NATIVE_THUNK]]([[SENDABLE_BLOCK]])
67+
// << step 2 >>
68+
// CHECK: [[NATIVE_EXCEPTION:%[0-9]+]] = convert_function [[NATIVE_SENDABLE_EXCEPTION]] : $@Sendable @callee_guaranteed () -> () to $@callee_guaranteed () -> ()
69+
// << step 3 >>
70+
// CHECK: [[OPTIONAL_NATIVE_EXCEPTION:%[0-9]+]] = enum $Optional<@callee_guaranteed () -> ()>, #Optional.some!enumelt, [[NATIVE_EXCEPTION]] : $@callee_guaranteed () -> ()
71+
// << step 4 >>
72+
// CHECK: = unchecked_bitwise_cast [[OPTIONAL_NATIVE_EXCEPTION]] : $Optional<@callee_guaranteed () -> ()> to $Optional<@Sendable @callee_guaranteed () -> ()>
73+
// << step 5 >>
74+
// CHECK: switch_enum {{.*}} : $Optional<@Sendable @callee_guaranteed () -> ()>
75+
//
76+
// CHECK: bb1({{.*}} : @owned $@Sendable @callee_guaranteed () -> ()):
77+
// CHECK: init_block_storage_header {{.*}} : $*@block_storage @Sendable @callee_guaranteed () -> ()
78+
// CHECK: } // end sil function '$s19objc_preconcurrency22testObjCVarWriteAcrossyySo12NSTouchGrassCF'
79+
func testObjCVarWriteAcross(_ grass: NSTouchGrass) {
80+
grass.cancellationHandler = grass.exceptionHandler // *slaps roof of assignment* this bad boy can fit so much conversion in it!
81+
}
82+
83+
// CHECK-LABEL: sil hidden [ossa] @$s19objc_preconcurrency25testOptionalAssignSetter1yyAA8OldWorldCF
84+
// CHECK: unchecked_bitwise_cast {{.*}} : $Optional<@callee_guaranteed () -> ()> to $Optional<@Sendable @callee_guaranteed () -> ()>
85+
// CHECK: #OldWorld.handler!setter : (OldWorld) -> ((@Sendable () -> ())?) -> ()
86+
// CHECK: } // end sil function '$s19objc_preconcurrency25testOptionalAssignSetter1yyAA8OldWorldCF'
87+
func testOptionalAssignSetter1(_ oldWorld: OldWorld) {
88+
oldWorld.handler = {}
89+
}
90+
91+
// CHECK-LABEL: sil hidden [ossa] @$s19objc_preconcurrency25testOptionalAssignSetter2yyAA8OldWorldCF
92+
// CHECK: convert_function {{.*}} : $@callee_guaranteed () -> () to $@Sendable @callee_guaranteed () -> ()
93+
// CHECK: $OldWorld, #OldWorld.nonOptionalHandler!setter : (OldWorld) -> (@escaping @Sendable () -> ()) -> ()
94+
// CHECK: } // end sil function '$s19objc_preconcurrency25testOptionalAssignSetter2yyAA8OldWorldCF'
95+
func testOptionalAssignSetter2(_ oldWorld: OldWorld) {
96+
oldWorld.nonOptionalHandler = {}
97+
}
98+
99+
// CHECK-LABEL: sil hidden [ossa] @$s19objc_preconcurrency21testMainHandlerWritesyyAA8OldWorldCF
100+
// CHECK: = unchecked_bitwise_cast {{.*}} : $Optional<@callee_guaranteed () -> ()> to $Optional<@Sendable @callee_guaranteed () -> ()>
101+
// CHECK: = unchecked_bitwise_cast {{.*}} : $Optional<@Sendable @callee_guaranteed () -> ()> to $Optional<@callee_guaranteed () -> ()>
102+
// CHECK: } // end sil function '$s19objc_preconcurrency21testMainHandlerWritesyyAA8OldWorldCF'
103+
func testMainHandlerWrites(_ oldWorld: OldWorld) {
104+
oldWorld.handler = oldWorld.mainHandler
105+
oldWorld.mainHandler = oldWorld.handler
106+
}
107+
108+
// CHECK-LABEL: sil hidden [ossa] @$s19objc_preconcurrency32testMainHandlerNonOptionalWritesyyAA8OldWorldCF
109+
// CHECK: = convert_function {{.*}} : $@callee_guaranteed () -> () to $@Sendable @callee_guaranteed () -> ()
110+
// CHECK: = convert_function {{.*}} : $@Sendable @callee_guaranteed () -> () to $@callee_guaranteed () -> ()
111+
// CHECK: } // end sil function '$s19objc_preconcurrency32testMainHandlerNonOptionalWritesyyAA8OldWorldCF'
112+
func testMainHandlerNonOptionalWrites(_ oldWorld: OldWorld) {
113+
oldWorld.nonOptionalHandler = oldWorld.nonOptionalMainHandler
114+
oldWorld.nonOptionalMainHandler = oldWorld.nonOptionalHandler
115+
}
116+
117+
// CHECK-LABEL: sil hidden [ossa] @$s19objc_preconcurrency15testMixedWritesyyAA8OldWorldCF
118+
//
119+
// << sendable conversions should be here >>
120+
// CHECK: = unchecked_bitwise_cast {{.*}} : $Optional<@Sendable @callee_guaranteed () -> ()> to $Optional<@callee_guaranteed () -> ()>
121+
// CHECK: = convert_function {{.*}} : $@callee_guaranteed () -> () to $@Sendable @callee_guaranteed () -> ()
122+
//
123+
// << but main actor type mismatches are accepted by SIL >>
124+
// CHECK: [[NO_MAIN_ACTOR:%[0-9]+]] = partial_apply {{.*}} : $@convention(thin) (@guaranteed @callee_guaranteed () -> @out ()) -> ()
125+
// CHECK: [[SETTER:%[0-9]+]] = class_method {{.*}} : $OldWorld, #OldWorld.nonOptionalMainHandler!setter : (OldWorld) -> (@escaping @MainActor () -> ()) -> (), $@convention(method) (@owned @callee_guaranteed () -> (), @guaranteed OldWorld) -> ()
126+
// CHECK: apply [[SETTER]]([[NO_MAIN_ACTOR]]
127+
// CHECK: } // end sil function '$s19objc_preconcurrency15testMixedWritesyyAA8OldWorldCF'
128+
func testMixedWrites(_ oldWorld: OldWorld) {
129+
oldWorld.nonOptionalHandler = oldWorld.handler ?? {}
130+
oldWorld.nonOptionalMainHandler = oldWorld.mainHandler ?? {}
131+
}
132+
28133
func modify(_ v: inout () -> Void) {
29134
v = {}
30135
}
31136

32137
// CHECK-LABEL: sil hidden [ossa] @$s19objc_preconcurrency15testInoutAccessyySo12NSTouchGrassCF
33-
// CHECK: unchecked_addr_cast {{.*}} : $*@Sendable @callee_guaranteed () -> () to $*@callee_guaranteed () -> ()
138+
// CHECK: [[BEFORE_MODIFY:%[0-9]+]] = convert_function {{.*}} : $@Sendable @callee_guaranteed () -> () to $@callee_guaranteed () -> ()
139+
// CHECK: store [[BEFORE_MODIFY]] to [init] [[INOUT_ALLOC:%[0-9]+]] : $*@callee_guaranteed () -> ()
140+
// CHECK: [[MODIFY_FN:%[0-9]+]] = function_ref @$s19objc_preconcurrency6modifyyyyyczF : $@convention(thin) (@inout @callee_guaranteed () -> ()) -> ()
141+
// CHECK: = apply [[MODIFY_FN]]([[INOUT_ALLOC]])
142+
// CHECK: [[AFTER_MODIFY:%[0-9]+]] = load [take] [[INOUT_ALLOC]] : $*@callee_guaranteed () -> ()
143+
// CHECK: convert_function [[AFTER_MODIFY]] : $@callee_guaranteed () -> () to $@Sendable @callee_guaranteed () -> ()
34144
// CHECK: } // end sil function '$s19objc_preconcurrency15testInoutAccessyySo12NSTouchGrassCF'
35145
func testInoutAccess(_ grass: NSTouchGrass) {
36146
modify(&grass.exceptionHandler)
37147
}
38148

39149

40150
// CHECK-LABEL: sil hidden [ossa] @$s19objc_preconcurrency21testProtocolVarAccess1pyAA1P_p_tF
41-
// CHECK: unchecked_addr_cast {{.*}} : $*@Sendable @callee_guaranteed () -> () to $*@callee_guaranteed () -> ()
151+
// CHECK: [[BEFORE_MODIFY:%[0-9]+]] = convert_function {{.*}} : $@Sendable @callee_guaranteed () -> () to $@callee_guaranteed () -> ()
152+
// CHECK: store [[BEFORE_MODIFY]] to [init] [[INOUT_ALLOC:%[0-9]+]] : $*@callee_guaranteed () -> ()
153+
// CHECK: [[MODIFY_FN:%[0-9]+]] = function_ref @$s19objc_preconcurrency6modifyyyyyczF : $@convention(thin) (@inout @callee_guaranteed () -> ()) -> ()
154+
// CHECK: = apply [[MODIFY_FN]]([[INOUT_ALLOC]])
155+
// CHECK: [[AFTER_MODIFY:%[0-9]+]] = load [take] [[INOUT_ALLOC]] : $*@callee_guaranteed () -> ()
156+
// CHECK: convert_function [[AFTER_MODIFY]] : $@callee_guaranteed () -> () to $@Sendable @callee_guaranteed () -> ()
42157
// CHECK: } // end sil function '$s19objc_preconcurrency21testProtocolVarAccess1pyAA1P_p_tF'
43158
func testProtocolVarAccess(p: P) {
44159
modify(&p.sendyHandler)

test/expr/closure/multi_statement.swift

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,3 +535,63 @@ struct Test {
535535
}
536536
}
537537
}
538+
539+
https://github.com/apple/swift/issues/61017
540+
do {
541+
@propertyWrapper
542+
struct Wrapper {
543+
var wrappedValue: Int
544+
545+
init(wrappedValue: Int) {
546+
self.wrappedValue = wrappedValue
547+
}
548+
}
549+
550+
class Test {
551+
let bar: () -> Void = {
552+
@Wrapper var wrapped = 1
553+
let wrapper: Wrapper = _wrapped // Ok
554+
}
555+
}
556+
}
557+
558+
https://github.com/apple/swift/issues/61024
559+
do {
560+
enum Baz: String {
561+
case someCase
562+
}
563+
564+
@propertyWrapper
565+
struct Wrapper {
566+
var wrappedValue: Int
567+
let argument: String
568+
569+
init(wrappedValue: Int, argument: String) { // expected-note 2 {{'init(wrappedValue:argument:)' declared here}}
570+
self.wrappedValue = wrappedValue
571+
self.argument = argument
572+
}
573+
}
574+
575+
class Foo {
576+
let ok: () -> Void = {
577+
@Wrapper(argument: Baz.someCase.rawValue) var wrapped1 = 1 // Ok
578+
@Wrapper(wrappedValue: 42, argument: Baz.someCase.rawValue) var wrapped2 // Ok
579+
@Wrapper(wrappedValue: 42, argument: Baz.someCase.rawValue) var wrapped3: Int // Ok
580+
}
581+
582+
let bad0: () -> Void = {
583+
@Wrapper var wrapped: Int
584+
// expected-error@-1 {{missing arguments for parameters 'wrappedValue', 'argument' in call}}
585+
}
586+
587+
let bad1: () -> Void = {
588+
@Wrapper var wrapped = 0
589+
// expected-error@-1 {{missing argument for parameter 'argument' in property wrapper initializer; add 'wrappedValue' and 'argument' arguments in '@Wrapper(...)'}}
590+
}
591+
592+
let bad2: () -> Void = {
593+
@Wrapper(wrappedValue: 42, argument: Baz.someCase.rawValue) var wrapped = 0
594+
// expected-error@-1 {{extra argument 'wrappedValue' in call}}
595+
}
596+
}
597+
}

0 commit comments

Comments
 (0)