Skip to content

Commit 61d3a9f

Browse files
committed
[CSClosure] Always pre-check init targets of wrapped vars
If a variable with attached property wrapper has an initializer expression it could be modified by implicit wrapper application, if there is no initializer - one would be synthesized by the compiler (without arguments). In both cases target has to be pre-checked before constraints are generated for it. Resolves: #61024
1 parent 3e791dd commit 61d3a9f

File tree

2 files changed

+55
-12
lines changed

2 files changed

+55
-12
lines changed

lib/Sema/CSClosure.cpp

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -530,18 +530,13 @@ class SyntacticElementConstraintGenerator
530530
init = TypeChecker::buildDefaultInitializer(patternType);
531531
}
532532

533-
if (init) {
534-
return SolutionApplicationTarget::forInitialization(
535-
init, patternBinding->getDeclContext(), patternType, patternBinding,
536-
index,
537-
/*bindPatternVarsOneWay=*/false);
538-
}
539-
540-
// If there was no initializer, there could be one from a property
541-
// wrapper which has to be pre-checked before use. This is not a
542-
// problem in top-level code because pattern bindings go through
543-
// `typeCheckExpression` which does pre-check automatically and
544-
// result builders do not allow declaring local wrapped variables.
533+
// A property wrapper initializer (either user-defined
534+
// or a synthesized one) has to be pre-checked before use.
535+
//
536+
// This is not a problem in top-level code because pattern
537+
// bindings go through `typeCheckExpression` which does
538+
// pre-check automatically and result builders do not allow
539+
// declaring local wrapped variables (yet).
545540
if (hasPropertyWrapper(pattern)) {
546541
auto target = SolutionApplicationTarget::forInitialization(
547542
init, patternBinding->getDeclContext(), patternType, patternBinding,
@@ -556,6 +551,13 @@ class SyntacticElementConstraintGenerator
556551
return target;
557552
}
558553

554+
if (init) {
555+
return SolutionApplicationTarget::forInitialization(
556+
init, patternBinding->getDeclContext(), patternType, patternBinding,
557+
index,
558+
/*bindPatternVarsOneWay=*/false);
559+
}
560+
559561
return SolutionApplicationTarget::forUninitializedVar(patternBinding, index,
560562
patternType);
561563
}

test/expr/closure/multi_statement.swift

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -585,3 +585,44 @@ do {
585585
}
586586
}
587587
}
588+
589+
https://github.com/apple/swift/issues/61024
590+
do {
591+
enum Baz: String {
592+
case someCase
593+
}
594+
595+
@propertyWrapper
596+
struct Wrapper {
597+
var wrappedValue: Int
598+
let argument: String
599+
600+
init(wrappedValue: Int, argument: String) { // expected-note 2 {{'init(wrappedValue:argument:)' declared here}}
601+
self.wrappedValue = wrappedValue
602+
self.argument = argument
603+
}
604+
}
605+
606+
class Foo {
607+
let ok: () -> Void = {
608+
@Wrapper(argument: Baz.someCase.rawValue) var wrapped1 = 1 // Ok
609+
@Wrapper(wrappedValue: 42, argument: Baz.someCase.rawValue) var wrapped2 // Ok
610+
@Wrapper(wrappedValue: 42, argument: Baz.someCase.rawValue) var wrapped3: Int // Ok
611+
}
612+
613+
let bad0: () -> Void = {
614+
@Wrapper var wrapped: Int
615+
// expected-error@-1 {{missing arguments for parameters 'wrappedValue', 'argument' in call}}
616+
}
617+
618+
let bad1: () -> Void = {
619+
@Wrapper var wrapped = 0
620+
// expected-error@-1 {{missing argument for parameter 'argument' in property wrapper initializer; add 'wrappedValue' and 'argument' arguments in '@Wrapper(...)'}}
621+
}
622+
623+
let bad2: () -> Void = {
624+
@Wrapper(wrappedValue: 42, argument: Baz.someCase.rawValue) var wrapped = 0
625+
// expected-error@-1 {{extra argument 'wrappedValue' in call}}
626+
}
627+
}
628+
}

0 commit comments

Comments
 (0)