@@ -1398,7 +1398,8 @@ class ApplyClassifier {
1398
1398
if (isa<SubscriptDecl>(cdr.getDecl ()))
1399
1399
return PotentialEffectReason::forSubscriptAccess ();
1400
1400
1401
- assert (isa<VarDecl>(cdr.getDecl ()));
1401
+ // Note that declarations other than properties end up with
1402
+ // "property access" effect reasons for historical... reasons.
1402
1403
return PotentialEffectReason::forPropertyAccess ();
1403
1404
}
1404
1405
@@ -1537,18 +1538,18 @@ class ApplyClassifier {
1537
1538
if (!member)
1538
1539
return Classification::forInvalidCode ();
1539
1540
1540
- PotentialEffectReason reason =
1541
- PotentialEffectReason::forPropertyAccess ();
1542
- Classification classification;
1541
+ ConcreteDeclRef declToClassify;
1543
1542
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;
1550
1546
}
1551
1547
1548
+ PotentialEffectReason reason = getKindOfEffectfulProp (member);
1549
+ Classification classification = Classification::forDeclRef (
1550
+ declToClassify, ConditionalEffectKind::Always, reason, E->getLoc (),
1551
+ assumedSafeArguments && assumedSafeArguments->contains (E));
1552
+
1552
1553
classification.setDowngradeToWarning (
1553
1554
downgradeAsyncAccessToWarning (member.getDecl ()));
1554
1555
@@ -1557,14 +1558,6 @@ class ApplyClassifier {
1557
1558
E->isImplicitlyAsync ().has_value (), E->isImplicitlyThrows (),
1558
1559
reason);
1559
1560
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
-
1568
1561
if (assumedSafeArguments) {
1569
1562
// If the declaration we're referencing is explicitly @safe, mark arguments
1570
1563
// as potentially being safe.
@@ -1646,9 +1639,10 @@ class ApplyClassifier {
1646
1639
PotentialEffectReason::forApply ());
1647
1640
}
1648
1641
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.
1650
1644
Classification classifyApply (
1651
- ApplyExpr *E,
1645
+ ApplyExpr *E,
1652
1646
llvm::DenseSet<const Expr *> *assumedSafeArguments
1653
1647
) {
1654
1648
// An apply expression is a potential throw site if the function throws.
@@ -1664,9 +1658,28 @@ class ApplyClassifier {
1664
1658
if (!type) return Classification::forInvalidCode ();
1665
1659
auto fnType = type->getAs <AnyFunctionType>();
1666
1660
if (!fnType) return Classification::forInvalidCode ();
1667
-
1668
1661
Expr *calleeFn = nullptr ;
1669
1662
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
+ ) {
1670
1683
auto substitutions = fnRef.getSubstitutions ();
1671
1684
const bool hasAnyConformances =
1672
1685
llvm::any_of (substitutions.getConformances (),
@@ -1692,26 +1705,23 @@ class ApplyClassifier {
1692
1705
// If this is calling a @safe function, treat local variables as being
1693
1706
// safe.
1694
1707
if (fnRef.getExplicitSafety () == ExplicitSafety::Safe) {
1695
- markArgumentsSafe (E-> getArgs () , *assumedSafeArguments);
1708
+ markArgumentsSafe (args , *assumedSafeArguments);
1696
1709
}
1697
1710
}
1698
1711
1699
- ASTContext &ctx = type ->getASTContext ();
1712
+ ASTContext &ctx = fnType ->getASTContext ();
1700
1713
1701
1714
// If the function doesn't have any effects or conformances, we're done
1702
1715
// here.
1703
1716
if (!fnType->isThrowing () &&
1704
- !E-> implicitlyThrows () &&
1717
+ !implicitlyThrows &&
1705
1718
!fnType->isAsync () &&
1706
- !E-> isImplicitlyAsync () &&
1719
+ !implicitlyAsync &&
1707
1720
!hasAnyConformances &&
1708
1721
fnRef.getExplicitSafety () == ExplicitSafety::Safe) {
1709
1722
return Classification ();
1710
1723
}
1711
1724
1712
- // Decompose the application.
1713
- auto *args = E->getArgs ();
1714
-
1715
1725
// If any of the arguments didn't type check, fail.
1716
1726
for (auto arg : *args) {
1717
1727
auto *argExpr = arg.getExpr ();
@@ -1721,7 +1731,7 @@ class ApplyClassifier {
1721
1731
1722
1732
Classification result;
1723
1733
result.mergeImplicitEffects (
1724
- ctx, E-> isImplicitlyAsync (). has_value (), E-> implicitlyThrows () ,
1734
+ ctx, implicitlyAsync, implicitlyThrows,
1725
1735
PotentialEffectReason::forApply ());
1726
1736
1727
1737
// Downgrade missing 'await' errors for preconcurrency references.
@@ -1732,8 +1742,8 @@ class ApplyClassifier {
1732
1742
auto classifyApplyEffect = [&](EffectKind kind) {
1733
1743
if (kind != EffectKind::Unsafe &&
1734
1744
!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)) {
1737
1747
return ;
1738
1748
}
1739
1749
@@ -1767,7 +1777,7 @@ class ApplyClassifier {
1767
1777
} else if (kind == EffectKind::Unsafe) {
1768
1778
// For explicitly @unsafe functions, the entire call is considered
1769
1779
// unsafe.
1770
- AbstractFunctionDecl *calleeFn =
1780
+ AbstractFunctionDecl *calleeDecl =
1771
1781
fnRef.getKind () == AbstractFunction::Function
1772
1782
? fnRef.getFunction ()
1773
1783
: nullptr ;
@@ -1776,7 +1786,7 @@ class ApplyClassifier {
1776
1786
Classification::forUnsafe (
1777
1787
{
1778
1788
UnsafeUse::forReferenceToUnsafe (
1779
- calleeFn , true , fnRef.getType (), E ->getLoc ())
1789
+ calleeDecl , true , fnRef.getType (), call ->getLoc ())
1780
1790
}
1781
1791
));
1782
1792
return ;
@@ -1807,7 +1817,7 @@ class ApplyClassifier {
1807
1817
// to fix their code.
1808
1818
if (kind == EffectKind::Async &&
1809
1819
fnRef.getKind () == AbstractFunction::Function) {
1810
- if (auto *ctor = dyn_cast<ConstructorRefCallExpr>(E-> getFn () )) {
1820
+ if (auto *ctor = dyn_cast<ConstructorRefCallExpr>(calleeFn )) {
1811
1821
if (ctor->getFn ()->isImplicit () && args->isUnlabeledUnary ())
1812
1822
result.setDowngradeToWarning (true );
1813
1823
}
@@ -1848,15 +1858,15 @@ class ApplyClassifier {
1848
1858
return ;
1849
1859
}
1850
1860
1851
- AbstractFunctionDecl *calleeFn =
1861
+ AbstractFunctionDecl *calleeDecl =
1852
1862
fnRef.getKind () == AbstractFunction::Function
1853
1863
? fnRef.getFunction ()
1854
1864
: nullptr ;
1855
1865
1856
1866
for (unsigned i = 0 , e = args->size (); i < e; ++i) {
1857
1867
Type origParamType = fnRef.getOrigParamInterfaceType (i);
1858
1868
auto argClassification = classifyArgument (
1859
- E, calleeFn , args->getLabel (i), i,
1869
+ call, calleeDecl , args->getLabel (i), i,
1860
1870
args->getExpr (i), origParamType, fnRef.getSubstitutions (),
1861
1871
kind);
1862
1872
@@ -1874,7 +1884,7 @@ class ApplyClassifier {
1874
1884
if (auto appliedSelf = fnRef.getAppliedSelf ()) {
1875
1885
Type origParamType = fnRef.getOrigParamSelfType ();
1876
1886
auto selfClassification = classifyArgument (
1877
- E, calleeFn , ctx.Id_self , 0 , appliedSelf->getBase (),
1887
+ call, calleeDecl , ctx.Id_self , 0 , appliedSelf->getBase (),
1878
1888
origParamType, fnRef.getSubstitutions (), kind);
1879
1889
result.merge (selfClassification);
1880
1890
}
@@ -1924,7 +1934,7 @@ class ApplyClassifier {
1924
1934
// If the safety of the callee is unspecified, check the safety of the
1925
1935
// arguments specifically.
1926
1936
if (hasUnspecifiedSafety &&
1927
- !(assumedSafeArguments && assumedSafeArguments->contains (E ))) {
1937
+ !(assumedSafeArguments && assumedSafeArguments->contains (call ))) {
1928
1938
classifyApplyEffect (EffectKind::Unsafe);
1929
1939
}
1930
1940
@@ -2611,7 +2621,7 @@ class ApplyClassifier {
2611
2621
2612
2622
// / Classify an argument being passed to a rethrows/reasync function.
2613
2623
Classification classifyArgument (
2614
- ApplyExpr *call, const Decl* calleeDecl, Identifier argName,
2624
+ Expr *call, const Decl* calleeDecl, Identifier argName,
2615
2625
unsigned argIndex, Expr *arg, Type paramType, SubstitutionMap subs,
2616
2626
EffectKind kind) {
2617
2627
// Check for an unsafe argument.
@@ -2718,7 +2728,7 @@ class ApplyClassifier {
2718
2728
}
2719
2729
2720
2730
// / Classify an argument to a rethrows/reasync function that's a tuple literal.
2721
- Classification classifyTupleArgument (ApplyExpr *call,
2731
+ Classification classifyTupleArgument (Expr *call,
2722
2732
const Decl* calleeDecl,
2723
2733
Identifier argName,
2724
2734
unsigned argIndex,
0 commit comments