@@ -587,7 +587,9 @@ getEnclosingSelfPropertyWrapperAccess(VarDecl *property, bool forProjected) {
587
587
return result;
588
588
}
589
589
590
- // / Build an l-value for the storage of a declaration.
590
+ // / Build an l-value for the storage of a declaration. Returns nullptr if there
591
+ // / was an error. This should only occur if an invalid declaration was type
592
+ // / checked; another diagnostic should have been emitted already.
591
593
static Expr *buildStorageReference (AccessorDecl *accessor,
592
594
AbstractStorageDecl *storage,
593
595
TargetImpl target,
@@ -674,12 +676,8 @@ static Expr *buildStorageReference(AccessorDecl *accessor,
674
676
auto *backing = var->getPropertyWrapperBackingProperty ();
675
677
676
678
// Error recovery.
677
- if (!backing) {
678
- auto type = storage->getValueInterfaceType ();
679
- if (isLValue)
680
- type = LValueType::get (type);
681
- return new (ctx) ErrorExpr (SourceRange (), type);
682
- }
679
+ if (!backing)
680
+ return nullptr ;
683
681
684
682
storage = backing;
685
683
@@ -721,12 +719,8 @@ static Expr *buildStorageReference(AccessorDecl *accessor,
721
719
auto *backing = var->getPropertyWrapperBackingProperty ();
722
720
723
721
// Error recovery.
724
- if (!backing) {
725
- auto type = storage->getValueInterfaceType ();
726
- if (isLValue)
727
- type = LValueType::get (type);
728
- return new (ctx) ErrorExpr (SourceRange (), type);
729
- }
722
+ if (!backing)
723
+ return nullptr ;
730
724
731
725
storage = backing;
732
726
@@ -836,7 +830,12 @@ static Expr *buildStorageReference(AccessorDecl *accessor,
836
830
ctx, wrapperMetatype, SourceLoc (), args,
837
831
subscriptDecl->getFullName ().getArgumentNames (), { }, SourceLoc (),
838
832
nullptr , subscriptDecl, /* Implicit=*/ true );
839
- TypeChecker::typeCheckExpression (lookupExpr, accessor);
833
+
834
+ // FIXME: Since we're not resolving overloads or anything, we should be
835
+ // building fully type-checked AST above; we already have all the
836
+ // information that we need.
837
+ if (!TypeChecker::typeCheckExpression (lookupExpr, accessor))
838
+ return nullptr ;
840
839
841
840
// Make sure we produce an lvalue only when desired.
842
841
if (isMemberLValue != lookupExpr->getType ()->is <LValueType>()) {
@@ -1034,6 +1033,10 @@ void createPropertyStoreOrCallSuperclassSetter(AccessorDecl *accessor,
1034
1033
Expr *dest = buildStorageReference (accessor, storage, target,
1035
1034
/* isLValue=*/ true , ctx);
1036
1035
1036
+ // Error recovery.
1037
+ if (dest == nullptr )
1038
+ return ;
1039
+
1037
1040
// A lazy property setter will store a value of type T into underlying storage
1038
1041
// of type T?.
1039
1042
auto destType = dest->getType ()->getWithoutSpecifierType ();
@@ -1043,6 +1046,7 @@ void createPropertyStoreOrCallSuperclassSetter(AccessorDecl *accessor,
1043
1046
return ;
1044
1047
1045
1048
if (!destType->isEqual (value->getType ())) {
1049
+ assert (destType->getOptionalObjectType ());
1046
1050
assert (destType->getOptionalObjectType ()->isEqual (value->getType ()));
1047
1051
value = new (ctx) InjectIntoOptionalExpr (value, destType);
1048
1052
}
@@ -1078,10 +1082,15 @@ synthesizeTrivialGetterBody(AccessorDecl *getter, TargetImpl target,
1078
1082
1079
1083
Expr *result =
1080
1084
createPropertyLoadOrCallSuperclassGetter (getter, storage, target, ctx);
1081
- ASTNode returnStmt = new (ctx) ReturnStmt (SourceLoc (), result,
1082
- /* IsImplicit=*/ true );
1083
1085
1084
- return { BraceStmt::create (ctx, loc, returnStmt, loc, true ),
1086
+ SmallVector<ASTNode, 2 > body;
1087
+ if (result != nullptr ) {
1088
+ ASTNode returnStmt = new (ctx) ReturnStmt (SourceLoc (), result,
1089
+ /* IsImplicit=*/ true );
1090
+ body.push_back (returnStmt);
1091
+ }
1092
+
1093
+ return { BraceStmt::create (ctx, loc, body, loc, true ),
1085
1094
/* isTypeChecked=*/ true };
1086
1095
}
1087
1096
@@ -1473,7 +1482,13 @@ synthesizeObservedSetterBody(AccessorDecl *Set, TargetImpl target,
1473
1482
if (VD->getParsedAccessor (AccessorKind::DidSet)) {
1474
1483
Expr *OldValueExpr
1475
1484
= buildStorageReference (Set, VD, target, /* isLValue=*/ true , Ctx);
1476
- OldValueExpr = new (Ctx) LoadExpr (OldValueExpr, VD->getType ());
1485
+
1486
+ // Error recovery.
1487
+ if (OldValueExpr == nullptr ) {
1488
+ OldValueExpr = new (Ctx) ErrorExpr (SourceRange (), VD->getType ());
1489
+ } else {
1490
+ OldValueExpr = new (Ctx) LoadExpr (OldValueExpr, VD->getType ());
1491
+ }
1477
1492
1478
1493
OldValue = new (Ctx) VarDecl (/* IsStatic*/ false , VarDecl::Introducer::Let,
1479
1494
/* IsCaptureList*/ false , SourceLoc (),
@@ -1601,13 +1616,14 @@ synthesizeCoroutineAccessorBody(AccessorDecl *accessor, ASTContext &ctx) {
1601
1616
1602
1617
// Build a reference to the storage.
1603
1618
Expr *ref = buildStorageReference (accessor, storage, target, isLValue, ctx);
1619
+ if (ref != nullptr ) {
1620
+ // Wrap it with an `&` marker if this is a modify.
1621
+ ref = maybeWrapInOutExpr (ref, ctx);
1604
1622
1605
- // Wrap it with an `&` marker if this is a modify.
1606
- ref = maybeWrapInOutExpr (ref, ctx);
1607
-
1608
- // Yield it.
1609
- YieldStmt *yield = YieldStmt::create (ctx, loc, loc, ref, loc, true );
1610
- body.push_back (yield);
1623
+ // Yield it.
1624
+ YieldStmt *yield = YieldStmt::create (ctx, loc, loc, ref, loc, true );
1625
+ body.push_back (yield);
1626
+ }
1611
1627
1612
1628
return { BraceStmt::create (ctx, loc, body, loc, true ),
1613
1629
/* isTypeChecked=*/ true };
0 commit comments