Skip to content

Commit ff5b821

Browse files
authored
Merge pull request swiftlang#81419 from DougGregor/lookupexpr-effects-cleanup
[Effects] Simplify handling of LookupExpr in effects checking
2 parents 49aea31 + 61ac302 commit ff5b821

File tree

1 file changed

+50
-40
lines changed

1 file changed

+50
-40
lines changed

lib/Sema/TypeCheckEffects.cpp

Lines changed: 50 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1398,7 +1398,8 @@ class ApplyClassifier {
13981398
if (isa<SubscriptDecl>(cdr.getDecl()))
13991399
return PotentialEffectReason::forSubscriptAccess();
14001400

1401-
assert(isa<VarDecl>(cdr.getDecl()));
1401+
// Note that declarations other than properties end up with
1402+
// "property access" effect reasons for historical... reasons.
14021403
return PotentialEffectReason::forPropertyAccess();
14031404
}
14041405

@@ -1537,18 +1538,18 @@ class ApplyClassifier {
15371538
if (!member)
15381539
return Classification::forInvalidCode();
15391540

1540-
PotentialEffectReason reason =
1541-
PotentialEffectReason::forPropertyAccess();
1542-
Classification classification;
1541+
ConcreteDeclRef declToClassify;
15431542
if (auto getter = getEffectfulGetOnlyAccessor(member)) {
1544-
reason = getKindOfEffectfulProp(member);
1545-
classification = Classification::forDeclRef(
1546-
getter, ConditionalEffectKind::Always, reason, E->getLoc(),
1547-
assumedSafeArguments && assumedSafeArguments->contains(E));
1548-
} else if (isa<SubscriptExpr>(E) || isa<DynamicSubscriptExpr>(E)) {
1549-
reason = PotentialEffectReason::forSubscriptAccess();
1543+
declToClassify = getter;
1544+
} else {
1545+
declToClassify = member;
15501546
}
15511547

1548+
PotentialEffectReason reason = getKindOfEffectfulProp(member);
1549+
Classification classification = Classification::forDeclRef(
1550+
declToClassify, ConditionalEffectKind::Always, reason, E->getLoc(),
1551+
assumedSafeArguments && assumedSafeArguments->contains(E));
1552+
15521553
classification.setDowngradeToWarning(
15531554
downgradeAsyncAccessToWarning(member.getDecl()));
15541555

@@ -1557,14 +1558,6 @@ class ApplyClassifier {
15571558
E->isImplicitlyAsync().has_value(), E->isImplicitlyThrows(),
15581559
reason);
15591560

1560-
if (!classification.hasUnsafe()) {
1561-
classification.merge(
1562-
Classification::forDeclRef(
1563-
member, ConditionalEffectKind::Always, reason, E->getLoc(),
1564-
assumedSafeArguments && assumedSafeArguments->contains(E),
1565-
EffectKind::Unsafe));
1566-
}
1567-
15681561
if (assumedSafeArguments) {
15691562
// If the declaration we're referencing is explicitly @safe, mark arguments
15701563
// as potentially being safe.
@@ -1646,9 +1639,10 @@ class ApplyClassifier {
16461639
PotentialEffectReason::forApply());
16471640
}
16481641

1649-
/// Check to see if the given function application throws or is async.
1642+
/// Check to see if the given function application throws, is async, or
1643+
/// involves unsafe behavior.
16501644
Classification classifyApply(
1651-
ApplyExpr *E,
1645+
ApplyExpr *E,
16521646
llvm::DenseSet<const Expr *> *assumedSafeArguments
16531647
) {
16541648
// An apply expression is a potential throw site if the function throws.
@@ -1664,9 +1658,28 @@ class ApplyClassifier {
16641658
if (!type) return Classification::forInvalidCode();
16651659
auto fnType = type->getAs<AnyFunctionType>();
16661660
if (!fnType) return Classification::forInvalidCode();
1667-
16681661
Expr *calleeFn = nullptr;
16691662
auto fnRef = AbstractFunction::getAppliedFn(E, &calleeFn);
1663+
1664+
auto *args = E->getArgs();
1665+
return classifyApply(
1666+
E, fnRef, calleeFn, fnType, args,
1667+
E->isImplicitlyAsync().has_value(), E->implicitlyThrows(),
1668+
assumedSafeArguments);
1669+
}
1670+
1671+
/// Check to see if the given function application throws, is async, or
1672+
/// involves unsafe behavior.
1673+
Classification classifyApply(
1674+
Expr *call,
1675+
const AbstractFunction &fnRef,
1676+
Expr *calleeFn,
1677+
const AnyFunctionType *fnType,
1678+
ArgumentList *args,
1679+
bool implicitlyAsync,
1680+
bool implicitlyThrows,
1681+
llvm::DenseSet<const Expr *> *assumedSafeArguments
1682+
) {
16701683
auto substitutions = fnRef.getSubstitutions();
16711684
const bool hasAnyConformances =
16721685
llvm::any_of(substitutions.getConformances(),
@@ -1692,26 +1705,23 @@ class ApplyClassifier {
16921705
// If this is calling a @safe function, treat local variables as being
16931706
// safe.
16941707
if (fnRef.getExplicitSafety() == ExplicitSafety::Safe) {
1695-
markArgumentsSafe(E->getArgs(), *assumedSafeArguments);
1708+
markArgumentsSafe(args, *assumedSafeArguments);
16961709
}
16971710
}
16981711

1699-
ASTContext &ctx = type->getASTContext();
1712+
ASTContext &ctx = fnType->getASTContext();
17001713

17011714
// If the function doesn't have any effects or conformances, we're done
17021715
// here.
17031716
if (!fnType->isThrowing() &&
1704-
!E->implicitlyThrows() &&
1717+
!implicitlyThrows &&
17051718
!fnType->isAsync() &&
1706-
!E->isImplicitlyAsync() &&
1719+
!implicitlyAsync &&
17071720
!hasAnyConformances &&
17081721
fnRef.getExplicitSafety() == ExplicitSafety::Safe) {
17091722
return Classification();
17101723
}
17111724

1712-
// Decompose the application.
1713-
auto *args = E->getArgs();
1714-
17151725
// If any of the arguments didn't type check, fail.
17161726
for (auto arg : *args) {
17171727
auto *argExpr = arg.getExpr();
@@ -1721,7 +1731,7 @@ class ApplyClassifier {
17211731

17221732
Classification result;
17231733
result.mergeImplicitEffects(
1724-
ctx, E->isImplicitlyAsync().has_value(), E->implicitlyThrows(),
1734+
ctx, implicitlyAsync, implicitlyThrows,
17251735
PotentialEffectReason::forApply());
17261736

17271737
// Downgrade missing 'await' errors for preconcurrency references.
@@ -1732,8 +1742,8 @@ class ApplyClassifier {
17321742
auto classifyApplyEffect = [&](EffectKind kind) {
17331743
if (kind != EffectKind::Unsafe &&
17341744
!fnType->hasEffect(kind) &&
1735-
!(kind == EffectKind::Async && E->isImplicitlyAsync()) &&
1736-
!(kind == EffectKind::Throws && E->implicitlyThrows())) {
1745+
!(kind == EffectKind::Async && implicitlyAsync) &&
1746+
!(kind == EffectKind::Throws && implicitlyThrows)) {
17371747
return;
17381748
}
17391749

@@ -1767,7 +1777,7 @@ class ApplyClassifier {
17671777
} else if (kind == EffectKind::Unsafe) {
17681778
// For explicitly @unsafe functions, the entire call is considered
17691779
// unsafe.
1770-
AbstractFunctionDecl *calleeFn =
1780+
AbstractFunctionDecl *calleeDecl =
17711781
fnRef.getKind() == AbstractFunction::Function
17721782
? fnRef.getFunction()
17731783
: nullptr;
@@ -1776,7 +1786,7 @@ class ApplyClassifier {
17761786
Classification::forUnsafe(
17771787
{
17781788
UnsafeUse::forReferenceToUnsafe(
1779-
calleeFn, true, fnRef.getType(), E->getLoc())
1789+
calleeDecl, true, fnRef.getType(), call->getLoc())
17801790
}
17811791
));
17821792
return;
@@ -1807,7 +1817,7 @@ class ApplyClassifier {
18071817
// to fix their code.
18081818
if (kind == EffectKind::Async &&
18091819
fnRef.getKind() == AbstractFunction::Function) {
1810-
if (auto *ctor = dyn_cast<ConstructorRefCallExpr>(E->getFn())) {
1820+
if (auto *ctor = dyn_cast<ConstructorRefCallExpr>(calleeFn)) {
18111821
if (ctor->getFn()->isImplicit() && args->isUnlabeledUnary())
18121822
result.setDowngradeToWarning(true);
18131823
}
@@ -1848,15 +1858,15 @@ class ApplyClassifier {
18481858
return;
18491859
}
18501860

1851-
AbstractFunctionDecl *calleeFn =
1861+
AbstractFunctionDecl *calleeDecl =
18521862
fnRef.getKind() == AbstractFunction::Function
18531863
? fnRef.getFunction()
18541864
: nullptr;
18551865

18561866
for (unsigned i = 0, e = args->size(); i < e; ++i) {
18571867
Type origParamType = fnRef.getOrigParamInterfaceType(i);
18581868
auto argClassification = classifyArgument(
1859-
E, calleeFn, args->getLabel(i), i,
1869+
call, calleeDecl, args->getLabel(i), i,
18601870
args->getExpr(i), origParamType, fnRef.getSubstitutions(),
18611871
kind);
18621872

@@ -1874,7 +1884,7 @@ class ApplyClassifier {
18741884
if (auto appliedSelf = fnRef.getAppliedSelf()) {
18751885
Type origParamType = fnRef.getOrigParamSelfType();
18761886
auto selfClassification = classifyArgument(
1877-
E, calleeFn, ctx.Id_self, 0, appliedSelf->getBase(),
1887+
call, calleeDecl, ctx.Id_self, 0, appliedSelf->getBase(),
18781888
origParamType, fnRef.getSubstitutions(), kind);
18791889
result.merge(selfClassification);
18801890
}
@@ -1924,7 +1934,7 @@ class ApplyClassifier {
19241934
// If the safety of the callee is unspecified, check the safety of the
19251935
// arguments specifically.
19261936
if (hasUnspecifiedSafety &&
1927-
!(assumedSafeArguments && assumedSafeArguments->contains(E))) {
1937+
!(assumedSafeArguments && assumedSafeArguments->contains(call))) {
19281938
classifyApplyEffect(EffectKind::Unsafe);
19291939
}
19301940

@@ -2611,7 +2621,7 @@ class ApplyClassifier {
26112621

26122622
/// Classify an argument being passed to a rethrows/reasync function.
26132623
Classification classifyArgument(
2614-
ApplyExpr *call, const Decl* calleeDecl, Identifier argName,
2624+
Expr *call, const Decl* calleeDecl, Identifier argName,
26152625
unsigned argIndex, Expr *arg, Type paramType, SubstitutionMap subs,
26162626
EffectKind kind) {
26172627
// Check for an unsafe argument.
@@ -2718,7 +2728,7 @@ class ApplyClassifier {
27182728
}
27192729

27202730
/// Classify an argument to a rethrows/reasync function that's a tuple literal.
2721-
Classification classifyTupleArgument(ApplyExpr *call,
2731+
Classification classifyTupleArgument(Expr *call,
27222732
const Decl* calleeDecl,
27232733
Identifier argName,
27242734
unsigned argIndex,

0 commit comments

Comments
 (0)