Skip to content

Commit 61ac302

Browse files
committed
Factor out effects checking of ApplyExpr to not be specific to ApplyExpr
1 parent ff830dd commit 61ac302

File tree

1 file changed

+39
-22
lines changed

1 file changed

+39
-22
lines changed

lib/Sema/TypeCheckEffects.cpp

Lines changed: 39 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1639,9 +1639,10 @@ class ApplyClassifier {
16391639
PotentialEffectReason::forApply());
16401640
}
16411641

1642-
/// 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.
16431644
Classification classifyApply(
1644-
ApplyExpr *E,
1645+
ApplyExpr *E,
16451646
llvm::DenseSet<const Expr *> *assumedSafeArguments
16461647
) {
16471648
// An apply expression is a potential throw site if the function throws.
@@ -1657,9 +1658,28 @@ class ApplyClassifier {
16571658
if (!type) return Classification::forInvalidCode();
16581659
auto fnType = type->getAs<AnyFunctionType>();
16591660
if (!fnType) return Classification::forInvalidCode();
1660-
16611661
Expr *calleeFn = nullptr;
16621662
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+
) {
16631683
auto substitutions = fnRef.getSubstitutions();
16641684
const bool hasAnyConformances =
16651685
llvm::any_of(substitutions.getConformances(),
@@ -1685,26 +1705,23 @@ class ApplyClassifier {
16851705
// If this is calling a @safe function, treat local variables as being
16861706
// safe.
16871707
if (fnRef.getExplicitSafety() == ExplicitSafety::Safe) {
1688-
markArgumentsSafe(E->getArgs(), *assumedSafeArguments);
1708+
markArgumentsSafe(args, *assumedSafeArguments);
16891709
}
16901710
}
16911711

1692-
ASTContext &ctx = type->getASTContext();
1712+
ASTContext &ctx = fnType->getASTContext();
16931713

16941714
// If the function doesn't have any effects or conformances, we're done
16951715
// here.
16961716
if (!fnType->isThrowing() &&
1697-
!E->implicitlyThrows() &&
1717+
!implicitlyThrows &&
16981718
!fnType->isAsync() &&
1699-
!E->isImplicitlyAsync() &&
1719+
!implicitlyAsync &&
17001720
!hasAnyConformances &&
17011721
fnRef.getExplicitSafety() == ExplicitSafety::Safe) {
17021722
return Classification();
17031723
}
17041724

1705-
// Decompose the application.
1706-
auto *args = E->getArgs();
1707-
17081725
// If any of the arguments didn't type check, fail.
17091726
for (auto arg : *args) {
17101727
auto *argExpr = arg.getExpr();
@@ -1714,7 +1731,7 @@ class ApplyClassifier {
17141731

17151732
Classification result;
17161733
result.mergeImplicitEffects(
1717-
ctx, E->isImplicitlyAsync().has_value(), E->implicitlyThrows(),
1734+
ctx, implicitlyAsync, implicitlyThrows,
17181735
PotentialEffectReason::forApply());
17191736

17201737
// Downgrade missing 'await' errors for preconcurrency references.
@@ -1725,8 +1742,8 @@ class ApplyClassifier {
17251742
auto classifyApplyEffect = [&](EffectKind kind) {
17261743
if (kind != EffectKind::Unsafe &&
17271744
!fnType->hasEffect(kind) &&
1728-
!(kind == EffectKind::Async && E->isImplicitlyAsync()) &&
1729-
!(kind == EffectKind::Throws && E->implicitlyThrows())) {
1745+
!(kind == EffectKind::Async && implicitlyAsync) &&
1746+
!(kind == EffectKind::Throws && implicitlyThrows)) {
17301747
return;
17311748
}
17321749

@@ -1760,7 +1777,7 @@ class ApplyClassifier {
17601777
} else if (kind == EffectKind::Unsafe) {
17611778
// For explicitly @unsafe functions, the entire call is considered
17621779
// unsafe.
1763-
AbstractFunctionDecl *calleeFn =
1780+
AbstractFunctionDecl *calleeDecl =
17641781
fnRef.getKind() == AbstractFunction::Function
17651782
? fnRef.getFunction()
17661783
: nullptr;
@@ -1769,7 +1786,7 @@ class ApplyClassifier {
17691786
Classification::forUnsafe(
17701787
{
17711788
UnsafeUse::forReferenceToUnsafe(
1772-
calleeFn, true, fnRef.getType(), E->getLoc())
1789+
calleeDecl, true, fnRef.getType(), call->getLoc())
17731790
}
17741791
));
17751792
return;
@@ -1800,7 +1817,7 @@ class ApplyClassifier {
18001817
// to fix their code.
18011818
if (kind == EffectKind::Async &&
18021819
fnRef.getKind() == AbstractFunction::Function) {
1803-
if (auto *ctor = dyn_cast<ConstructorRefCallExpr>(E->getFn())) {
1820+
if (auto *ctor = dyn_cast<ConstructorRefCallExpr>(calleeFn)) {
18041821
if (ctor->getFn()->isImplicit() && args->isUnlabeledUnary())
18051822
result.setDowngradeToWarning(true);
18061823
}
@@ -1841,15 +1858,15 @@ class ApplyClassifier {
18411858
return;
18421859
}
18431860

1844-
AbstractFunctionDecl *calleeFn =
1861+
AbstractFunctionDecl *calleeDecl =
18451862
fnRef.getKind() == AbstractFunction::Function
18461863
? fnRef.getFunction()
18471864
: nullptr;
18481865

18491866
for (unsigned i = 0, e = args->size(); i < e; ++i) {
18501867
Type origParamType = fnRef.getOrigParamInterfaceType(i);
18511868
auto argClassification = classifyArgument(
1852-
E, calleeFn, args->getLabel(i), i,
1869+
call, calleeDecl, args->getLabel(i), i,
18531870
args->getExpr(i), origParamType, fnRef.getSubstitutions(),
18541871
kind);
18551872

@@ -1867,7 +1884,7 @@ class ApplyClassifier {
18671884
if (auto appliedSelf = fnRef.getAppliedSelf()) {
18681885
Type origParamType = fnRef.getOrigParamSelfType();
18691886
auto selfClassification = classifyArgument(
1870-
E, calleeFn, ctx.Id_self, 0, appliedSelf->getBase(),
1887+
call, calleeDecl, ctx.Id_self, 0, appliedSelf->getBase(),
18711888
origParamType, fnRef.getSubstitutions(), kind);
18721889
result.merge(selfClassification);
18731890
}
@@ -1917,7 +1934,7 @@ class ApplyClassifier {
19171934
// If the safety of the callee is unspecified, check the safety of the
19181935
// arguments specifically.
19191936
if (hasUnspecifiedSafety &&
1920-
!(assumedSafeArguments && assumedSafeArguments->contains(E))) {
1937+
!(assumedSafeArguments && assumedSafeArguments->contains(call))) {
19211938
classifyApplyEffect(EffectKind::Unsafe);
19221939
}
19231940

@@ -2604,7 +2621,7 @@ class ApplyClassifier {
26042621

26052622
/// Classify an argument being passed to a rethrows/reasync function.
26062623
Classification classifyArgument(
2607-
ApplyExpr *call, const Decl* calleeDecl, Identifier argName,
2624+
Expr *call, const Decl* calleeDecl, Identifier argName,
26082625
unsigned argIndex, Expr *arg, Type paramType, SubstitutionMap subs,
26092626
EffectKind kind) {
26102627
// Check for an unsafe argument.
@@ -2711,7 +2728,7 @@ class ApplyClassifier {
27112728
}
27122729

27132730
/// Classify an argument to a rethrows/reasync function that's a tuple literal.
2714-
Classification classifyTupleArgument(ApplyExpr *call,
2731+
Classification classifyTupleArgument(Expr *call,
27152732
const Decl* calleeDecl,
27162733
Identifier argName,
27172734
unsigned argIndex,

0 commit comments

Comments
 (0)