Skip to content

Commit 3f82b4c

Browse files
committed
[TypeChecker] Propagate HadError from elements in BraceStmts
Previously, if a `BraceStmt` had an element with an error, we still considered the entire `BraceStmt` as being type-checked successfully. This caused syntactic diagnostics to run for statements that weren’t valid. Propagate that information. Most places still ignore whether the brace statement contained an error because they ignore the return value of `typecheckFunctionBody()` but `typeCheckClosureBody` now returns the error, preventing syntactic diagnostics from running for closures in result builders. rdar://95629905
1 parent ff129c3 commit 3f82b4c

File tree

15 files changed

+139
-62
lines changed

15 files changed

+139
-62
lines changed

include/swift/AST/Decl.h

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -412,9 +412,9 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
412412
SWIFT_INLINE_BITFIELD(SubscriptDecl, VarDecl, 2,
413413
StaticSpelling : 2
414414
);
415-
SWIFT_INLINE_BITFIELD(AbstractFunctionDecl, ValueDecl, 3+2+8+1+1+1+1+1+1,
415+
SWIFT_INLINE_BITFIELD(AbstractFunctionDecl, ValueDecl, 4+2+8+1+1+1+1+1+1,
416416
/// \see AbstractFunctionDecl::BodyKind
417-
BodyKind : 3,
417+
BodyKind : 4,
418418

419419
/// \see AbstractFunctionDecl::SILSynthesizeKind
420420
SILSynthesizeKind : 2,
@@ -6236,13 +6236,17 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
62366236
/// Function body is present and type-checked.
62376237
TypeChecked,
62386238

6239+
/// The function body is present and was type-checked but at least one
6240+
/// statement within the body contained an error.
6241+
TypeCheckedWithError,
6242+
62396243
// Function body will be synthesized by SILGen.
62406244
SILSynthesize,
62416245

62426246
/// Function body text was deserialized from a .swiftmodule.
62436247
Deserialized
62446248

6245-
// This enum currently needs to fit in a 3-bit bitfield.
6249+
// This enum currently needs to fit in a 4-bit bitfield.
62466250
};
62476251

62486252
BodyKind getBodyKind() const {
@@ -6478,9 +6482,18 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
64786482
/// \sa hasBody()
64796483
BraceStmt *getBody(bool canSynthesize = true) const;
64806484

6485+
struct TypecheckedBodyResult {
6486+
/// The body of the function with as many statements type checked as
6487+
/// possible.
6488+
BraceStmt *TypecheckedBody;
6489+
/// If a single statement in the type checked body has an error, this is
6490+
/// \c true.
6491+
bool HadError;
6492+
};
6493+
64816494
/// Retrieve the type-checked body of the given function, or \c nullptr if
64826495
/// there's no body available.
6483-
BraceStmt *getTypecheckedBody() const;
6496+
TypecheckedBodyResult getTypecheckedBody() const;
64846497

64856498
/// Set a new body for the function.
64866499
void setBody(BraceStmt *S, BodyKind NewBodyKind);
@@ -6570,7 +6583,8 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
65706583
}
65716584

65726585
bool isBodyTypeChecked() const {
6573-
return getBodyKind() == BodyKind::TypeChecked;
6586+
return getBodyKind() == BodyKind::TypeChecked ||
6587+
getBodyKind() == BodyKind::TypeCheckedWithError;
65746588
}
65756589

65766590
bool isBodySILSynthesize() const {

include/swift/AST/TypeCheckRequests.h

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1480,25 +1480,32 @@ class LazyStoragePropertyRequest :
14801480
bool isCached() const { return true; }
14811481
};
14821482

1483+
struct TypeCheckFunctionBodyResult {
1484+
BraceStmt *TypeCheckedBody;
1485+
bool HadError;
1486+
};
1487+
14831488
/// Request to retrieve the type-checked body of the given function.
14841489
class TypeCheckFunctionBodyRequest
1485-
: public SimpleRequest<
1486-
TypeCheckFunctionBodyRequest, BraceStmt *(AbstractFunctionDecl *),
1487-
RequestFlags::SeparatelyCached | RequestFlags::DependencySource> {
1490+
: public SimpleRequest<TypeCheckFunctionBodyRequest,
1491+
TypeCheckFunctionBodyResult(AbstractFunctionDecl *),
1492+
RequestFlags::SeparatelyCached |
1493+
RequestFlags::DependencySource> {
14881494
public:
14891495
using SimpleRequest::SimpleRequest;
14901496

14911497
private:
14921498
friend SimpleRequest;
14931499

14941500
// Evaluation.
1495-
BraceStmt *evaluate(Evaluator &evaluator, AbstractFunctionDecl *func) const;
1501+
TypeCheckFunctionBodyResult evaluate(Evaluator &evaluator,
1502+
AbstractFunctionDecl *func) const;
14961503

14971504
public:
14981505
// Separate caching.
14991506
bool isCached() const { return true; }
1500-
Optional<BraceStmt *> getCachedResult() const;
1501-
void cacheResult(BraceStmt *body) const;
1507+
Optional<TypeCheckFunctionBodyResult> getCachedResult() const;
1508+
void cacheResult(TypeCheckFunctionBodyResult result) const;
15021509

15031510
public:
15041511
// Incremental dependencies.

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ SWIFT_REQUEST(TypeChecker, SynthesizeAccessorRequest,
309309
SWIFT_REQUEST(TypeChecker, TangentStoredPropertyRequest,
310310
llvm::Expected<VarDecl *>(VarDecl *, CanType), Cached, NoLocationInfo)
311311
SWIFT_REQUEST(TypeChecker, TypeCheckFunctionBodyRequest,
312-
BraceStmt *(AbstractFunctionDecl *), SeparatelyCached,
312+
TypeCheckFunctionBodyResult(AbstractFunctionDecl *), SeparatelyCached,
313313
NoLocationInfo)
314314
SWIFT_REQUEST(TypeChecker, TypeCheckASTNodeAtLocRequest,
315315
bool(TypeCheckASTNodeAtLocContext, SourceLoc),

lib/AST/ASTVerifier.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,7 @@ class Verifier : public ASTWalker {
474474
switch (afd->getBodyKind()) {
475475
case AbstractFunctionDecl::BodyKind::None:
476476
case AbstractFunctionDecl::BodyKind::TypeChecked:
477+
case AbstractFunctionDecl::BodyKind::TypeCheckedWithError:
477478
case AbstractFunctionDecl::BodyKind::Skipped:
478479
case AbstractFunctionDecl::BodyKind::SILSynthesize:
479480
case AbstractFunctionDecl::BodyKind::Deserialized:

lib/AST/Decl.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7819,11 +7819,14 @@ BraceStmt *AbstractFunctionDecl::getBody(bool canSynthesize) const {
78197819
.getBody();
78207820
}
78217821

7822-
BraceStmt *AbstractFunctionDecl::getTypecheckedBody() const {
7822+
AbstractFunctionDecl::TypecheckedBodyResult
7823+
AbstractFunctionDecl::getTypecheckedBody() const {
78237824
auto &ctx = getASTContext();
78247825
auto *mutableThis = const_cast<AbstractFunctionDecl *>(this);
7825-
return evaluateOrDefault(
7826-
ctx.evaluator, TypeCheckFunctionBodyRequest{mutableThis}, nullptr);
7826+
auto res = evaluateOrDefault(ctx.evaluator,
7827+
TypeCheckFunctionBodyRequest{mutableThis},
7828+
{nullptr, true});
7829+
return {res.TypeCheckedBody, res.HadError};
78277830
}
78287831

78297832
void AbstractFunctionDecl::setBody(BraceStmt *S, BodyKind NewBodyKind) {
@@ -7832,6 +7835,7 @@ void AbstractFunctionDecl::setBody(BraceStmt *S, BodyKind NewBodyKind) {
78327835

78337836
Optional<Fingerprint> fp = None;
78347837
if (getBodyKind() == BodyKind::TypeChecked ||
7838+
getBodyKind() == BodyKind::TypeCheckedWithError ||
78357839
getBodyKind() == BodyKind::Parsed) {
78367840
fp = BodyAndFP.getFingerprint();
78377841
}
@@ -7849,7 +7853,8 @@ void AbstractFunctionDecl::setBodyToBeReparsed(SourceRange bodyRange) {
78497853
assert(bodyRange.isValid());
78507854
assert(getBodyKind() == BodyKind::Unparsed ||
78517855
getBodyKind() == BodyKind::Parsed ||
7852-
getBodyKind() == BodyKind::TypeChecked);
7856+
getBodyKind() == BodyKind::TypeChecked ||
7857+
getBodyKind() == BodyKind::TypeCheckedWithError);
78537858

78547859
keepOriginalBodySourceRange();
78557860
BodyRange = bodyRange;
@@ -7874,6 +7879,7 @@ SourceRange AbstractFunctionDecl::getBodySourceRange() const {
78747879

78757880
case BodyKind::Parsed:
78767881
case BodyKind::TypeChecked:
7882+
case BodyKind::TypeCheckedWithError:
78777883
if (auto body = getBody(/*canSynthesize=*/false))
78787884
return body->getSourceRange();
78797885

@@ -8276,6 +8282,7 @@ bool AbstractFunctionDecl::hasInlinableBodyText() const {
82768282
case BodyKind::Unparsed:
82778283
case BodyKind::Parsed:
82788284
case BodyKind::TypeChecked:
8285+
case BodyKind::TypeCheckedWithError:
82798286
if (auto body = getBody())
82808287
return !body->isImplicit();
82818288
return false;
@@ -9401,6 +9408,7 @@ ParseAbstractFunctionBodyRequest::getCachedResult() const {
94019408
return BodyAndFingerprint{};
94029409

94039410
case BodyKind::TypeChecked:
9411+
case BodyKind::TypeCheckedWithError:
94049412
case BodyKind::Parsed:
94059413
return afd->BodyAndFP;
94069414

@@ -9426,6 +9434,7 @@ void ParseAbstractFunctionBodyRequest::cacheResult(
94269434

94279435
case BodyKind::Parsed:
94289436
case BodyKind::TypeChecked:
9437+
case BodyKind::TypeCheckedWithError:
94299438
afd->BodyAndFP = value;
94309439
return;
94319440

lib/AST/TypeCheckRequests.cpp

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1375,7 +1375,8 @@ void TypeCheckSourceFileRequest::cacheResult(evaluator::SideEffect) const {
13751375
// TypeCheckFunctionBodyRequest computation.
13761376
//----------------------------------------------------------------------------//
13771377

1378-
Optional<BraceStmt *> TypeCheckFunctionBodyRequest::getCachedResult() const {
1378+
Optional<TypeCheckFunctionBodyResult>
1379+
TypeCheckFunctionBodyRequest::getCachedResult() const {
13791380
using BodyKind = AbstractFunctionDecl::BodyKind;
13801381
auto *afd = std::get<0>(getStorage());
13811382
switch (afd->getBodyKind()) {
@@ -1384,10 +1385,12 @@ Optional<BraceStmt *> TypeCheckFunctionBodyRequest::getCachedResult() const {
13841385
case BodyKind::None:
13851386
case BodyKind::Skipped:
13861387
// These cases don't have any body available.
1387-
return nullptr;
1388+
return TypeCheckFunctionBodyResult{nullptr, false};
13881389

13891390
case BodyKind::TypeChecked:
1390-
return afd->BodyAndFP.getBody();
1391+
return TypeCheckFunctionBodyResult{afd->BodyAndFP.getBody(), false};
1392+
case BodyKind::TypeCheckedWithError:
1393+
return TypeCheckFunctionBodyResult{afd->BodyAndFP.getBody(), true};
13911394

13921395
case BodyKind::Synthesize:
13931396
case BodyKind::Parsed:
@@ -1397,9 +1400,13 @@ Optional<BraceStmt *> TypeCheckFunctionBodyRequest::getCachedResult() const {
13971400
llvm_unreachable("Unhandled BodyKind in switch");
13981401
}
13991402

1400-
void TypeCheckFunctionBodyRequest::cacheResult(BraceStmt *body) const {
1403+
void TypeCheckFunctionBodyRequest::cacheResult(
1404+
TypeCheckFunctionBodyResult result) const {
14011405
auto *afd = std::get<0>(getStorage());
1402-
afd->setBody(body, AbstractFunctionDecl::BodyKind::TypeChecked);
1406+
afd->setBody(result.TypeCheckedBody,
1407+
result.HadError
1408+
? AbstractFunctionDecl::BodyKind::TypeCheckedWithError
1409+
: AbstractFunctionDecl::BodyKind::TypeChecked);
14031410
}
14041411

14051412
evaluator::DependencySource

lib/Parse/ParseRequests.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ ParseAbstractFunctionBodyRequest::evaluate(Evaluator &evaluator,
100100
return {};
101101

102102
case BodyKind::TypeChecked:
103+
case BodyKind::TypeCheckedWithError:
103104
case BodyKind::Parsed:
104105
return afd->BodyAndFP;
105106

lib/SILGen/SILGenConstructor.cpp

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -461,11 +461,12 @@ void SILGenFunction::emitValueConstructor(ConstructorDecl *ctor) {
461461
emitMemberInitializers(ctor, selfDecl, nominal);
462462
}
463463

464-
emitProfilerIncrement(ctor->getTypecheckedBody());
464+
auto typecheckedBody = ctor->getTypecheckedBody();
465+
assert(!typecheckedBody.HadError);
466+
emitProfilerIncrement(typecheckedBody.TypecheckedBody);
465467
// Emit the constructor body.
466-
emitStmt(ctor->getTypecheckedBody());
468+
emitStmt(typecheckedBody.TypecheckedBody);
467469

468-
469470
// Build a custom epilog block, since the AST representation of the
470471
// constructor decl (which has no self in the return type) doesn't match the
471472
// SIL representation.
@@ -693,7 +694,9 @@ void SILGenFunction::emitClassConstructorAllocator(ConstructorDecl *ctor) {
693694
SILValue initedSelfValue = emitApplyWithRethrow(Loc, initVal.forward(*this),
694695
initTy, subMap, args);
695696

696-
emitProfilerIncrement(ctor->getTypecheckedBody());
697+
auto typecheckedBody = ctor->getTypecheckedBody();
698+
assert(!typecheckedBody.HadError);
699+
emitProfilerIncrement(typecheckedBody.TypecheckedBody);
697700

698701
// Return the initialized 'self'.
699702
B.createReturn(ImplicitReturnLocation(Loc), initedSelfValue);
@@ -732,7 +735,10 @@ void SILGenFunction::emitConstructorPrologActorHop(
732735
void SILGenFunction::emitClassConstructorInitializer(ConstructorDecl *ctor) {
733736
MagicFunctionName = SILGenModule::getMagicFunctionName(ctor);
734737

735-
assert(ctor->getTypecheckedBody() && "Class constructor without a body?");
738+
assert(!ctor->getTypecheckedBody().HadError &&
739+
"Class constructor with an error?");
740+
assert(ctor->getTypecheckedBody().TypecheckedBody &&
741+
"Class constructor without a body?");
736742

737743
// True if this constructor delegates to a peer constructor with self.init().
738744
bool isDelegating = false;
@@ -902,9 +908,11 @@ void SILGenFunction::emitClassConstructorInitializer(ConstructorDecl *ctor) {
902908
emitMemberInitializers(ctor, selfDecl, selfClassDecl);
903909
}
904910

905-
emitProfilerIncrement(ctor->getTypecheckedBody());
911+
auto typecheckedBody = ctor->getTypecheckedBody();
912+
assert(!typecheckedBody.HadError);
913+
emitProfilerIncrement(typecheckedBody.TypecheckedBody);
906914
// Emit the constructor body.
907-
emitStmt(ctor->getTypecheckedBody());
915+
emitStmt(typecheckedBody.TypecheckedBody);
908916

909917
// Emit the call to super.init() right before exiting from the initializer.
910918
if (NeedsBoxForSelf) {

lib/SILGen/SILGenDestructor.cpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,11 @@ void SILGenFunction::emitDestroyingDestructor(DestructorDecl *dd) {
3838
// We won't actually emit the block until we finish with the destructor body.
3939
prepareEpilog(None, false, CleanupLocation(Loc));
4040

41-
emitProfilerIncrement(dd->getTypecheckedBody());
41+
auto typecheckedBody = dd->getTypecheckedBody();
42+
assert(!typecheckedBody.HadError);
43+
emitProfilerIncrement(typecheckedBody.TypecheckedBody);
4244
// Emit the destructor body.
43-
emitStmt(dd->getTypecheckedBody());
45+
emitStmt(typecheckedBody.TypecheckedBody);
4446

4547
Optional<SILValue> maybeReturnValue;
4648
SILLocation returnLoc(Loc);
@@ -170,7 +172,9 @@ void SILGenFunction::emitDeallocatingDestructor(DestructorDecl *dd) {
170172
selfForDealloc = B.createUncheckedRefCast(loc, selfForDealloc, classTy);
171173
B.createDeallocRef(loc, selfForDealloc);
172174

173-
emitProfilerIncrement(dd->getTypecheckedBody());
175+
auto typecheckedBody = dd->getTypecheckedBody();
176+
assert(!typecheckedBody.HadError);
177+
emitProfilerIncrement(typecheckedBody.TypecheckedBody);
174178

175179
// Return.
176180
B.createReturn(loc, emitEmptyTuple(loc));
@@ -445,9 +449,11 @@ void SILGenFunction::emitObjCDestructor(SILDeclRef dtor) {
445449
// We won't actually emit the block until we finish with the destructor body.
446450
prepareEpilog(None, false, CleanupLocation(loc));
447451

448-
emitProfilerIncrement(dd->getTypecheckedBody());
452+
auto typecheckedBody = dd->getTypecheckedBody();
453+
assert(!typecheckedBody.HadError);
454+
emitProfilerIncrement(typecheckedBody.TypecheckedBody);
449455
// Emit the destructor body.
450-
emitStmt(dd->getTypecheckedBody());
456+
emitStmt(typecheckedBody.TypecheckedBody);
451457

452458
Optional<SILValue> maybeReturnValue;
453459
SILLocation returnLoc(loc);

lib/SILGen/SILGenFunction.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,9 @@ void SILGenFunction::emitFunction(FuncDecl *fd) {
525525
MagicFunctionName = SILGenModule::getMagicFunctionName(fd);
526526

527527
auto captureInfo = SGM.M.Types.getLoweredLocalCaptures(SILDeclRef(fd));
528-
emitProfilerIncrement(fd->getTypecheckedBody());
528+
auto typecheckedBody = fd->getTypecheckedBody();
529+
assert(!typecheckedBody.HadError);
530+
emitProfilerIncrement(typecheckedBody.TypecheckedBody);
529531
emitProlog(captureInfo, fd->getParameters(), fd->getImplicitSelfDecl(), fd,
530532
fd->getResultInterfaceType(), fd->hasThrows(), fd->getThrowsLoc());
531533

@@ -537,7 +539,7 @@ void SILGenFunction::emitFunction(FuncDecl *fd) {
537539
fd->hasThrows(), CleanupLocation(fd));
538540

539541
// Emit the actual function body as usual
540-
emitStmt(fd->getTypecheckedBody());
542+
emitStmt(typecheckedBody.TypecheckedBody);
541543

542544
emitEpilog(fd);
543545
}

lib/Sema/TypeCheckAvailability.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3229,7 +3229,7 @@ class ExprAvailabilityWalker : public ASTWalker {
32293229
maybeDiagParameterizedExistentialErasure(EE, Where);
32303230
}
32313231
if (auto *CC = dyn_cast<ExplicitCastExpr>(E)) {
3232-
if (!isa<CoerceExpr>(CC) &&
3232+
if (!isa<CoerceExpr>(CC) && CC->getCastType() &&
32333233
CC->getCastType()->hasParameterizedExistential()) {
32343234
SourceLoc loc = CC->getCastTypeRepr() ? CC->getCastTypeRepr()->getLoc()
32353235
: E->getLoc();

0 commit comments

Comments
 (0)