@@ -596,7 +596,9 @@ getEnclosingSelfPropertyWrapperAccess(VarDecl *property, bool forProjected) {
596
596
return result;
597
597
}
598
598
599
- // / Build an l-value for the storage of a declaration.
599
+ // / Build an l-value for the storage of a declaration. Returns nullptr if there
600
+ // / was an error. This should only occur if an invalid declaration was type
601
+ // / checked; another diagnostic should have been emitted already.
600
602
static Expr *buildStorageReference (AccessorDecl *accessor,
601
603
AbstractStorageDecl *storage,
602
604
TargetImpl target,
@@ -683,12 +685,8 @@ static Expr *buildStorageReference(AccessorDecl *accessor,
683
685
auto *backing = var->getPropertyWrapperBackingProperty ();
684
686
685
687
// Error recovery.
686
- if (!backing) {
687
- auto type = storage->getValueInterfaceType ();
688
- if (isLValue)
689
- type = LValueType::get (type);
690
- return new (ctx) ErrorExpr (SourceRange (), type);
691
- }
688
+ if (!backing)
689
+ return nullptr ;
692
690
693
691
storage = backing;
694
692
@@ -730,12 +728,8 @@ static Expr *buildStorageReference(AccessorDecl *accessor,
730
728
auto *backing = var->getPropertyWrapperBackingProperty ();
731
729
732
730
// Error recovery.
733
- if (!backing) {
734
- auto type = storage->getValueInterfaceType ();
735
- if (isLValue)
736
- type = LValueType::get (type);
737
- return new (ctx) ErrorExpr (SourceRange (), type);
738
- }
731
+ if (!backing)
732
+ return nullptr ;
739
733
740
734
storage = backing;
741
735
@@ -845,7 +839,12 @@ static Expr *buildStorageReference(AccessorDecl *accessor,
845
839
ctx, wrapperMetatype, SourceLoc (), args,
846
840
subscriptDecl->getFullName ().getArgumentNames (), { }, SourceLoc (),
847
841
nullptr , subscriptDecl, /* Implicit=*/ true );
848
- TypeChecker::typeCheckExpression (lookupExpr, accessor);
842
+
843
+ // FIXME: Since we're not resolving overloads or anything, we should be
844
+ // building fully type-checked AST above; we already have all the
845
+ // information that we need.
846
+ if (!TypeChecker::typeCheckExpression (lookupExpr, accessor))
847
+ return nullptr ;
849
848
850
849
// Make sure we produce an lvalue only when desired.
851
850
if (isMemberLValue != lookupExpr->getType ()->is <LValueType>()) {
@@ -1043,6 +1042,10 @@ void createPropertyStoreOrCallSuperclassSetter(AccessorDecl *accessor,
1043
1042
Expr *dest = buildStorageReference (accessor, storage, target,
1044
1043
/* isLValue=*/ true , ctx);
1045
1044
1045
+ // Error recovery.
1046
+ if (dest == nullptr )
1047
+ return ;
1048
+
1046
1049
// A lazy property setter will store a value of type T into underlying storage
1047
1050
// of type T?.
1048
1051
auto destType = dest->getType ()->getWithoutSpecifierType ();
@@ -1052,6 +1055,7 @@ void createPropertyStoreOrCallSuperclassSetter(AccessorDecl *accessor,
1052
1055
return ;
1053
1056
1054
1057
if (!destType->isEqual (value->getType ())) {
1058
+ assert (destType->getOptionalObjectType ());
1055
1059
assert (destType->getOptionalObjectType ()->isEqual (value->getType ()));
1056
1060
value = new (ctx) InjectIntoOptionalExpr (value, destType);
1057
1061
}
@@ -1087,10 +1091,15 @@ synthesizeTrivialGetterBody(AccessorDecl *getter, TargetImpl target,
1087
1091
1088
1092
Expr *result =
1089
1093
createPropertyLoadOrCallSuperclassGetter (getter, storage, target, ctx);
1090
- ASTNode returnStmt = new (ctx) ReturnStmt (SourceLoc (), result,
1091
- /* IsImplicit=*/ true );
1092
1094
1093
- return { BraceStmt::create (ctx, loc, returnStmt, loc, true ),
1095
+ SmallVector<ASTNode, 2 > body;
1096
+ if (result != nullptr ) {
1097
+ ASTNode returnStmt = new (ctx) ReturnStmt (SourceLoc (), result,
1098
+ /* IsImplicit=*/ true );
1099
+ body.push_back (returnStmt);
1100
+ }
1101
+
1102
+ return { BraceStmt::create (ctx, loc, body, loc, true ),
1094
1103
/* isTypeChecked=*/ true };
1095
1104
}
1096
1105
@@ -1482,7 +1491,13 @@ synthesizeObservedSetterBody(AccessorDecl *Set, TargetImpl target,
1482
1491
if (VD->getParsedAccessor (AccessorKind::DidSet)) {
1483
1492
Expr *OldValueExpr
1484
1493
= buildStorageReference (Set, VD, target, /* isLValue=*/ true , Ctx);
1485
- OldValueExpr = new (Ctx) LoadExpr (OldValueExpr, VD->getType ());
1494
+
1495
+ // Error recovery.
1496
+ if (OldValueExpr == nullptr ) {
1497
+ OldValueExpr = new (Ctx) ErrorExpr (SourceRange (), VD->getType ());
1498
+ } else {
1499
+ OldValueExpr = new (Ctx) LoadExpr (OldValueExpr, VD->getType ());
1500
+ }
1486
1501
1487
1502
OldValue = new (Ctx) VarDecl (/* IsStatic*/ false , VarDecl::Introducer::Let,
1488
1503
/* IsCaptureList*/ false , SourceLoc (),
@@ -1610,13 +1625,14 @@ synthesizeCoroutineAccessorBody(AccessorDecl *accessor, ASTContext &ctx) {
1610
1625
1611
1626
// Build a reference to the storage.
1612
1627
Expr *ref = buildStorageReference (accessor, storage, target, isLValue, ctx);
1628
+ if (ref != nullptr ) {
1629
+ // Wrap it with an `&` marker if this is a modify.
1630
+ ref = maybeWrapInOutExpr (ref, ctx);
1613
1631
1614
- // Wrap it with an `&` marker if this is a modify.
1615
- ref = maybeWrapInOutExpr (ref, ctx);
1616
-
1617
- // Yield it.
1618
- YieldStmt *yield = YieldStmt::create (ctx, loc, loc, ref, loc, true );
1619
- body.push_back (yield);
1632
+ // Yield it.
1633
+ YieldStmt *yield = YieldStmt::create (ctx, loc, loc, ref, loc, true );
1634
+ body.push_back (yield);
1635
+ }
1620
1636
1621
1637
return { BraceStmt::create (ctx, loc, body, loc, true ),
1622
1638
/* isTypeChecked=*/ true };
0 commit comments