Skip to content

Commit c68fdc8

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: swiftlang#61024 (cherry picked from commit 61d3a9f)
1 parent c9adb5b commit c68fdc8

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
@@ -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/expr/closure/multi_statement.swift

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -554,3 +554,44 @@ do {
554554
}
555555
}
556556
}
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)