Skip to content

Commit ff2ef7a

Browse files
committed
Ensure that the effects checker understands what declaration references are evaluated
1 parent a0ebd87 commit ff2ef7a

File tree

1 file changed

+33
-13
lines changed

1 file changed

+33
-13
lines changed

lib/Sema/TypeCheckEffects.cpp

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,7 @@ class EffectsHandlingWalker : public ASTWalker {
579579
recurse = asImpl().checkDeclRef(declRef,
580580
declRef->getDeclRef(),
581581
declRef->getLoc(),
582+
/*isEvaluated=*/true,
582583
declRef->isImplicitlyAsync().has_value(),
583584
declRef->isImplicitlyThrows());
584585
} else if (auto interpolated = dyn_cast<InterpolatedStringLiteralExpr>(E)) {
@@ -593,18 +594,22 @@ class EffectsHandlingWalker : public ASTWalker {
593594
recurse = asImpl().checkWithConformances(E, EE->getConformances());
594595
} else if (auto *OCD = dyn_cast<OtherConstructorDeclRefExpr>(E)) {
595596
recurse = asImpl().checkDeclRef(OCD, OCD->getDeclRef(), OCD->getLoc(),
597+
/*isEvaluated=*/true,
596598
/*isImplicitlyAsync=*/false,
597599
/*isImplicitlyThrows=*/false);
598600
} else if (auto *ME = dyn_cast<MacroExpansionExpr>(E)) {
599601
recurse = asImpl().checkDeclRef(ME, ME->getMacroRef(), ME->getLoc(),
602+
/*isEvaluated=*/false,
600603
/*isImplicitlyAsync=*/false,
601604
/*isImplicitlyThrows=*/false);
602605
} else if (auto *LE = dyn_cast<LiteralExpr>(E)) {
603606
recurse = asImpl().checkDeclRef(LE, LE->getInitializer(), LE->getLoc(),
607+
/*isEvaluated=*/false,
604608
/*isImplicitlyAsync=*/false,
605609
/*isImplicitlyThrows=*/false);
606610
} else if (auto *CE = dyn_cast<CollectionExpr>(E)) {
607611
recurse = asImpl().checkDeclRef(CE, CE->getInitializer(), CE->getLoc(),
612+
/*isEvaluated=*/false,
608613
/*isImplicitlyAsync=*/false,
609614
/*isImplicitlyThrows=*/false);
610615
} else if (auto ECE = dyn_cast<ExplicitCastExpr>(E)) {
@@ -620,6 +625,7 @@ class EffectsHandlingWalker : public ASTWalker {
620625
case KeyPathExpr::Component::Kind::Subscript: {
621626
(void)asImpl().checkDeclRef(KPE, component.getDeclRef(),
622627
component.getLoc(),
628+
/*isEvaluated=*/false,
623629
/*isImplicitlyAsync=*/false,
624630
/*isImplicitlyThrows=*/false);
625631
break;
@@ -1188,11 +1194,13 @@ class Classification {
11881194
/// "unsafe" uses.
11891195
static Classification forType(Type type, SourceLoc loc) {
11901196
Classification result;
1191-
diagnoseUnsafeType(type->getASTContext(), loc, type, [&](Type unsafeType) {
1192-
result.recordUnsafeUse(
1193-
UnsafeUse::forReferenceToUnsafe(
1194-
nullptr, /*isCall=*/false, unsafeType, loc));
1195-
});
1197+
if (type) {
1198+
diagnoseUnsafeType(type->getASTContext(), loc, type, [&](Type unsafeType) {
1199+
result.recordUnsafeUse(
1200+
UnsafeUse::forReferenceToUnsafe(
1201+
nullptr, /*isCall=*/false, unsafeType, loc));
1202+
});
1203+
}
11961204
return result;
11971205
}
11981206

@@ -1932,12 +1940,16 @@ class ApplyClassifier {
19321940
}
19331941
ShouldRecurse_t checkDeclRef(Expr *expr,
19341942
ConcreteDeclRef declRef, SourceLoc loc,
1943+
bool isEvaluated,
19351944
bool isImplicitlyAsync,
19361945
bool isImplicitlyThrows) {
1937-
classification.merge(
1938-
Self.classifyDeclRef(
1939-
declRef, loc, isImplicitlyAsync, isImplicitlyThrows
1940-
).onlyThrowing());
1946+
if (isEvaluated) {
1947+
classification.merge(
1948+
Self.classifyDeclRef(
1949+
declRef, loc, isImplicitlyAsync, isImplicitlyThrows
1950+
).onlyThrowing());
1951+
}
1952+
19411953
return ShouldRecurse;
19421954
}
19431955
ShouldRecurse_t checkAsyncLet(PatternBindingDecl *patternBinding) {
@@ -2060,13 +2072,16 @@ class ApplyClassifier {
20602072
}
20612073
ShouldRecurse_t checkDeclRef(Expr *expr,
20622074
ConcreteDeclRef declRef, SourceLoc loc,
2075+
bool isEvaluated,
20632076
bool isImplicitlyAsync,
20642077
bool isImplicitlyThrows) {
2065-
if (isImplicitlyAsync) {
2066-
AsyncKind = ConditionalEffectKind::Always;
2067-
} else if (auto getter = getEffectfulGetOnlyAccessor(declRef)) {
2068-
if (cast<AccessorDecl>(getter.getDecl())->hasAsync())
2078+
if (isEvaluated) {
2079+
if (isImplicitlyAsync) {
20692080
AsyncKind = ConditionalEffectKind::Always;
2081+
} else if (auto getter = getEffectfulGetOnlyAccessor(declRef)) {
2082+
if (cast<AccessorDecl>(getter.getDecl())->hasAsync())
2083+
AsyncKind = ConditionalEffectKind::Always;
2084+
}
20702085
}
20712086

20722087
return ShouldRecurse;
@@ -3684,10 +3699,15 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
36843699

36853700
ShouldRecurse_t checkDeclRef(Expr *expr,
36863701
ConcreteDeclRef declRef, SourceLoc loc,
3702+
bool isEvaluated,
36873703
bool isImplicitlyAsync,
36883704
bool isImplicitlyThrows) {
36893705
if (auto classification = getApplyClassifier().classifyDeclRef(
36903706
declRef, loc, isImplicitlyAsync, isImplicitlyThrows)) {
3707+
// If we aren't evaluating the reference, we only care about 'unsafe'.
3708+
if (!isEvaluated)
3709+
classification = classification.onlyUnsafe();
3710+
36913711
auto throwDest = checkEffectSite(
36923712
expr, classification.hasThrows(), classification);
36933713

0 commit comments

Comments
 (0)