Skip to content

Commit ce20a30

Browse files
authored
Merge pull request #26352 from jckarter/property-wrapper-optional-nil-default-master
Check default init before synthesizing wrapper backing properties.
2 parents e6e6307 + 0c13a4b commit ce20a30

File tree

6 files changed

+56
-10
lines changed

6 files changed

+56
-10
lines changed

lib/AST/Decl.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5821,7 +5821,8 @@ Expr *swift::findOriginalPropertyWrapperInitialValue(VarDecl *var,
58215821
return nullptr;
58225822

58235823
// If there is no '=' on the pattern, there was no initial value.
5824-
if (PBD->getPatternList()[0].getEqualLoc().isInvalid())
5824+
if (PBD->getPatternList()[0].getEqualLoc().isInvalid()
5825+
&& !PBD->isDefaultInitializable())
58255826
return nullptr;
58265827

58275828
ASTContext &ctx = var->getASTContext();

lib/Sema/CodeSynthesis.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1912,6 +1912,18 @@ PropertyWrapperBackingPropertyInfoRequest::evaluate(Evaluator &evaluator,
19121912
// Take the initializer from the original property.
19131913
auto parentPBD = var->getParentPatternBinding();
19141914
unsigned patternNumber = parentPBD->getPatternEntryIndexForVarDecl(var);
1915+
1916+
// Force the default initializer to come into existence, if there is one,
1917+
// and the wrapper doesn't provide its own.
1918+
if (!parentPBD->isInitialized(patternNumber)
1919+
&& parentPBD->isDefaultInitializable(patternNumber)
1920+
&& !wrapperInfo.defaultInit) {
1921+
auto &tc = *static_cast<TypeChecker *>(ctx.getLazyResolver());
1922+
auto ty = parentPBD->getPattern(patternNumber)->getType();
1923+
if (auto defaultInit = tc.buildDefaultInitializer(ty))
1924+
parentPBD->setInit(patternNumber, defaultInit);
1925+
}
1926+
19151927
if (parentPBD->isInitialized(patternNumber) &&
19161928
!parentPBD->isInitializerChecked(patternNumber)) {
19171929
auto &tc = *static_cast<TypeChecker *>(ctx.getLazyResolver());
@@ -2558,7 +2570,12 @@ static void maybeAddMemberwiseDefaultArg(ParamDecl *arg, VarDecl *var,
25582570
return;
25592571

25602572
// Whether we have explicit initialization.
2561-
bool isExplicitlyInitialized = var->isParentInitialized();
2573+
bool isExplicitlyInitialized = false;
2574+
if (auto pbd = var->getParentPatternBinding()) {
2575+
auto &entry = pbd->getPatternEntryForVarDecl(var);
2576+
isExplicitlyInitialized =
2577+
entry.isInitialized() && entry.getEqualLoc().isValid();
2578+
}
25622579

25632580
// Whether we can default-initialize this property.
25642581
auto binding = var->getParentPatternBinding();

lib/Sema/TypeCheckDecl.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -642,10 +642,10 @@ TypeChecker::handleSILGenericParams(GenericParamList *genericParams,
642642
}
643643

644644
/// Build a default initializer for the given type.
645-
static Expr *buildDefaultInitializer(TypeChecker &tc, Type type) {
645+
Expr *TypeChecker::buildDefaultInitializer(Type type) {
646646
// Default-initialize optional types and weak values to 'nil'.
647647
if (type->getReferenceStorageReferent()->getOptionalObjectType())
648-
return new (tc.Context) NilLiteralExpr(SourceLoc(), /*Implicit=*/true);
648+
return new (Context) NilLiteralExpr(SourceLoc(), /*Implicit=*/true);
649649

650650
// Build tuple literals for tuple types.
651651
if (auto tupleType = type->getAs<TupleType>()) {
@@ -654,14 +654,14 @@ static Expr *buildDefaultInitializer(TypeChecker &tc, Type type) {
654654
if (elt.isVararg())
655655
return nullptr;
656656

657-
auto eltInit = buildDefaultInitializer(tc, elt.getType());
657+
auto eltInit = buildDefaultInitializer(elt.getType());
658658
if (!eltInit)
659659
return nullptr;
660660

661661
inits.push_back(eltInit);
662662
}
663663

664-
return TupleExpr::createImplicit(tc.Context, inits, { });
664+
return TupleExpr::createImplicit(Context, inits, { });
665665
}
666666

667667
// We don't default-initialize anything else.
@@ -2629,7 +2629,7 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
26292629
PBD->getPattern(i)->hasStorage() &&
26302630
!PBD->getPattern(i)->getType()->hasError()) {
26312631
auto type = PBD->getPattern(i)->getType();
2632-
if (auto defaultInit = buildDefaultInitializer(TC, type)) {
2632+
if (auto defaultInit = TC.buildDefaultInitializer(type)) {
26332633
// If we got a default initializer, install it and re-type-check it
26342634
// to make sure it is properly coerced to the pattern type.
26352635
PBD->setInit(i, defaultInit);

lib/Sema/TypeCheckPropertyWrapper.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -666,10 +666,14 @@ Expr *swift::buildPropertyWrapperInitialValueCall(
666666
= var->getAttachedPropertyWrapperTypeInfo(i).wrappedValueInit) {
667667
argName = init->getFullName().getArgumentNames()[0];
668668
}
669+
670+
auto endLoc = initializer->getEndLoc();
671+
if (endLoc.isInvalid() && startLoc.isValid())
672+
endLoc = wrapperAttrs[i]->getTypeLoc().getSourceRange().End;
669673

670674
initializer = CallExpr::create(
671675
ctx, typeExpr, startLoc, {initializer}, {argName},
672-
{initializer->getStartLoc()}, initializer->getEndLoc(),
676+
{initializer->getStartLoc()}, endLoc,
673677
nullptr, /*implicit=*/true);
674678
continue;
675679
}
@@ -694,10 +698,14 @@ Expr *swift::buildPropertyWrapperInitialValueCall(
694698
elementNames.push_back(Identifier());
695699
elementLocs.push_back(SourceLoc());
696700
}
701+
702+
auto endLoc = attr->getArg()->getEndLoc();
703+
if (endLoc.isInvalid() && startLoc.isValid())
704+
endLoc = wrapperAttrs[i]->getTypeLoc().getSourceRange().End;
697705

698706
initializer = CallExpr::create(
699707
ctx, typeExpr, startLoc, elements, elementNames, elementLocs,
700-
attr->getArg()->getEndLoc(), nullptr, /*implicit=*/true);
708+
endLoc, nullptr, /*implicit=*/true);
701709
}
702710

703711
return initializer;

lib/Sema/TypeChecker.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1799,6 +1799,8 @@ class TypeChecker final : public LazyResolver {
17991799
FragileFunctionKind Kind,
18001800
bool TreatUsableFromInlineAsPublic);
18011801

1802+
Expr *buildDefaultInitializer(Type type);
1803+
18021804
private:
18031805
bool diagnoseInlinableDeclRefAccess(SourceLoc loc, const ValueDecl *D,
18041806
const DeclContext *DC,

test/SILOptimizer/di_property_wrappers.swift

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,24 @@ func testOptIntStruct() {
360360
print("\n## OptIntStruct")
361361

362362
let use = OptIntStruct()
363-
// CHECK-NEXT: .. init Optional(42)
363+
// CHECK-NEXT: .. init nil
364+
// CHECK-NEXT: .. set Optional(42)
365+
}
366+
367+
// rdar://problem/53504653
368+
369+
struct DefaultNilOptIntStruct {
370+
@Wrapper var wrapped: Int?
371+
372+
init() {
373+
}
374+
}
375+
func testDefaultNilOptIntStruct() {
376+
// CHECK: ## DefaultNilOptIntStruct
377+
print("\n## DefaultNilOptIntStruct")
378+
379+
let use = DefaultNilOptIntStruct()
380+
// CHECK-NEXT: .. init nil
364381
}
365382

366383
testIntStruct()
@@ -369,3 +386,4 @@ testRefStruct()
369386
testGenericClass()
370387
testDefaultInit()
371388
testOptIntStruct()
389+
testDefaultNilOptIntStruct()

0 commit comments

Comments
 (0)