Skip to content

Commit 5ffe847

Browse files
authored
Merge pull request #61052 from xedin/closure-property-wrapper-fixes
[CSClosure] Fix property wrapper handling
2 parents 3f5dec5 + 61d3a9f commit 5ffe847

File tree

3 files changed

+79
-16
lines changed

3 files changed

+79
-16
lines changed

lib/Sema/CSClosure.cpp

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

119119
return Action::Continue(expr);
@@ -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: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -566,3 +566,63 @@ struct Test {
566566
}
567567
}
568568
}
569+
570+
https://github.com/apple/swift/issues/61017
571+
do {
572+
@propertyWrapper
573+
struct Wrapper {
574+
var wrappedValue: Int
575+
576+
init(wrappedValue: Int) {
577+
self.wrappedValue = wrappedValue
578+
}
579+
}
580+
581+
class Test {
582+
let bar: () -> Void = {
583+
@Wrapper var wrapped = 1
584+
let wrapper: Wrapper = _wrapped // Ok
585+
}
586+
}
587+
}
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+
}

validation-test/Sema/type_checker_crashers_fixed/issue59294.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ class Test {
7474
if $value.returnValue() > 0 {
7575
test {
7676
return $value.returnValue() == $0 &&
77-
_value == $0
77+
_value.wrappedValue == $0
7878
}
7979
}
8080
return false
@@ -84,7 +84,7 @@ class Test {
8484
@WrapperValue var value = $0
8585

8686
test {
87-
if _value != $0 { // Ok
87+
if _value.wrappedValue != $0 { // Ok
8888
$value.printValue()
8989
}
9090
}
@@ -99,7 +99,8 @@ class Test {
9999
if true {
100100
@OuterWrapper @WrapperValue var value = $0
101101
if true {
102-
let _: Bool = _value == $0
102+
let _: OuterWrapper<WrapperValue<Bool>> = _value
103+
let _ = _value.wrappedValue.wrappedValue == $0
103104
let _: OuterWrapper<WrapperValue<Bool>> = $value
104105
let _: Bool = value
105106
}

0 commit comments

Comments
 (0)