Skip to content

Commit c172608

Browse files
authored
Merge pull request #42231 from xedin/rdar-91225620-5.7
[5.7][CSClosure] Handle wrapped variables without explicit initializers
2 parents b7b4fa4 + 7e09b48 commit c172608

File tree

2 files changed

+75
-17
lines changed

2 files changed

+75
-17
lines changed

lib/Sema/CSClosure.cpp

Lines changed: 51 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,53 @@ class ClosureConstraintGenerator
510510
}
511511
}
512512

513+
Optional<SolutionApplicationTarget>
514+
getTargetForPattern(PatternBindingDecl *patternBinding, unsigned index,
515+
Type patternType) {
516+
auto hasPropertyWrapper = [&](Pattern *pattern) -> bool {
517+
if (auto *singleVar = pattern->getSingleVar())
518+
return singleVar->hasAttachedPropertyWrapper();
519+
return false;
520+
};
521+
522+
auto *pattern = patternBinding->getPattern(index);
523+
auto *init = patternBinding->getInit(index);
524+
525+
if (!init && patternBinding->isDefaultInitializable(index) &&
526+
pattern->hasStorage()) {
527+
init = TypeChecker::buildDefaultInitializer(patternType);
528+
}
529+
530+
if (init) {
531+
return SolutionApplicationTarget::forInitialization(
532+
init, patternBinding->getDeclContext(), patternType, patternBinding,
533+
index,
534+
/*bindPatternVarsOneWay=*/false);
535+
}
536+
537+
// If there was no initializer, there could be one from a property
538+
// wrapper which has to be pre-checked before use. This is not a
539+
// problem in top-level code because pattern bindings go through
540+
// `typeCheckExpression` which does pre-check automatically and
541+
// result builders do not allow declaring local wrapped variables.
542+
if (hasPropertyWrapper(pattern)) {
543+
auto target = SolutionApplicationTarget::forInitialization(
544+
init, patternBinding->getDeclContext(), patternType, patternBinding,
545+
index,
546+
/*bindPatternVarsOneWay=*/false);
547+
548+
if (ConstraintSystem::preCheckTarget(
549+
target, /*replaceInvalidRefsWithErrors=*/true,
550+
/*LeaveCLosureBodyUnchecked=*/false))
551+
return None;
552+
553+
return target;
554+
}
555+
556+
return SolutionApplicationTarget::forUninitializedVar(patternBinding, index,
557+
patternType);
558+
}
559+
513560
void visitPatternBindingElement(PatternBindingDecl *patternBinding) {
514561
assert(locator->isLastElement<LocatorPathElt::PatternBindingElement>());
515562

@@ -527,28 +574,15 @@ class ClosureConstraintGenerator
527574
return;
528575
}
529576

530-
auto *pattern = patternBinding->getPattern(index);
531-
auto *init = patternBinding->getInit(index);
532-
533-
if (!init && patternBinding->isDefaultInitializable(index) &&
534-
pattern->hasStorage()) {
535-
init = TypeChecker::buildDefaultInitializer(patternType);
536-
}
537-
538-
auto target = init ? SolutionApplicationTarget::forInitialization(
539-
init, patternBinding->getDeclContext(),
540-
patternType, patternBinding, index,
541-
/*bindPatternVarsOneWay=*/false)
542-
: SolutionApplicationTarget::forUninitializedVar(
543-
patternBinding, index, patternType);
544-
545-
if (cs.generateConstraints(target, FreeTypeVariableBinding::Disallow)) {
577+
auto target = getTargetForPattern(patternBinding, index, patternType);
578+
if (!target ||
579+
cs.generateConstraints(*target, FreeTypeVariableBinding::Disallow)) {
546580
hadError = true;
547581
return;
548582
}
549583

550584
// Keep track of this binding entry.
551-
cs.setSolutionApplicationTarget({patternBinding, index}, target);
585+
cs.setSolutionApplicationTarget({patternBinding, index}, *target);
552586
}
553587

554588
void visitDecl(Decl *decl) {

test/expr/closure/multi_statement.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,3 +292,27 @@ func test_pattern_matches_only_cases() {
292292
}
293293
}
294294
}
295+
296+
// rdar://91225620 - type of expression is ambiguous without more context in closure
297+
func test_wrapped_var_without_initializer() {
298+
@propertyWrapper
299+
struct Wrapper {
300+
private let name: String
301+
302+
var wrappedValue: Bool {
303+
didSet {}
304+
}
305+
306+
init(name: String) {
307+
self.wrappedValue = false
308+
self.name = name
309+
}
310+
}
311+
312+
func fn(_: () -> Void) {}
313+
314+
fn {
315+
@Wrapper(name: "foo")
316+
var v;
317+
}
318+
}

0 commit comments

Comments
 (0)