@@ -1639,9 +1639,10 @@ class ApplyClassifier {
1639
1639
PotentialEffectReason::forApply ());
1640
1640
}
1641
1641
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.
1643
1644
Classification classifyApply (
1644
- ApplyExpr *E,
1645
+ ApplyExpr *E,
1645
1646
llvm::DenseSet<const Expr *> *assumedSafeArguments
1646
1647
) {
1647
1648
// An apply expression is a potential throw site if the function throws.
@@ -1657,9 +1658,28 @@ class ApplyClassifier {
1657
1658
if (!type) return Classification::forInvalidCode ();
1658
1659
auto fnType = type->getAs <AnyFunctionType>();
1659
1660
if (!fnType) return Classification::forInvalidCode ();
1660
-
1661
1661
Expr *calleeFn = nullptr ;
1662
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
+ ) {
1663
1683
auto substitutions = fnRef.getSubstitutions ();
1664
1684
const bool hasAnyConformances =
1665
1685
llvm::any_of (substitutions.getConformances (),
@@ -1685,26 +1705,23 @@ class ApplyClassifier {
1685
1705
// If this is calling a @safe function, treat local variables as being
1686
1706
// safe.
1687
1707
if (fnRef.getExplicitSafety () == ExplicitSafety::Safe) {
1688
- markArgumentsSafe (E-> getArgs () , *assumedSafeArguments);
1708
+ markArgumentsSafe (args , *assumedSafeArguments);
1689
1709
}
1690
1710
}
1691
1711
1692
- ASTContext &ctx = type ->getASTContext ();
1712
+ ASTContext &ctx = fnType ->getASTContext ();
1693
1713
1694
1714
// If the function doesn't have any effects or conformances, we're done
1695
1715
// here.
1696
1716
if (!fnType->isThrowing () &&
1697
- !E-> implicitlyThrows () &&
1717
+ !implicitlyThrows &&
1698
1718
!fnType->isAsync () &&
1699
- !E-> isImplicitlyAsync () &&
1719
+ !implicitlyAsync &&
1700
1720
!hasAnyConformances &&
1701
1721
fnRef.getExplicitSafety () == ExplicitSafety::Safe) {
1702
1722
return Classification ();
1703
1723
}
1704
1724
1705
- // Decompose the application.
1706
- auto *args = E->getArgs ();
1707
-
1708
1725
// If any of the arguments didn't type check, fail.
1709
1726
for (auto arg : *args) {
1710
1727
auto *argExpr = arg.getExpr ();
@@ -1714,7 +1731,7 @@ class ApplyClassifier {
1714
1731
1715
1732
Classification result;
1716
1733
result.mergeImplicitEffects (
1717
- ctx, E-> isImplicitlyAsync (). has_value (), E-> implicitlyThrows () ,
1734
+ ctx, implicitlyAsync, implicitlyThrows,
1718
1735
PotentialEffectReason::forApply ());
1719
1736
1720
1737
// Downgrade missing 'await' errors for preconcurrency references.
@@ -1725,8 +1742,8 @@ class ApplyClassifier {
1725
1742
auto classifyApplyEffect = [&](EffectKind kind) {
1726
1743
if (kind != EffectKind::Unsafe &&
1727
1744
!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)) {
1730
1747
return ;
1731
1748
}
1732
1749
@@ -1760,7 +1777,7 @@ class ApplyClassifier {
1760
1777
} else if (kind == EffectKind::Unsafe) {
1761
1778
// For explicitly @unsafe functions, the entire call is considered
1762
1779
// unsafe.
1763
- AbstractFunctionDecl *calleeFn =
1780
+ AbstractFunctionDecl *calleeDecl =
1764
1781
fnRef.getKind () == AbstractFunction::Function
1765
1782
? fnRef.getFunction ()
1766
1783
: nullptr ;
@@ -1769,7 +1786,7 @@ class ApplyClassifier {
1769
1786
Classification::forUnsafe (
1770
1787
{
1771
1788
UnsafeUse::forReferenceToUnsafe (
1772
- calleeFn , true , fnRef.getType (), E ->getLoc ())
1789
+ calleeDecl , true , fnRef.getType (), call ->getLoc ())
1773
1790
}
1774
1791
));
1775
1792
return ;
@@ -1800,7 +1817,7 @@ class ApplyClassifier {
1800
1817
// to fix their code.
1801
1818
if (kind == EffectKind::Async &&
1802
1819
fnRef.getKind () == AbstractFunction::Function) {
1803
- if (auto *ctor = dyn_cast<ConstructorRefCallExpr>(E-> getFn () )) {
1820
+ if (auto *ctor = dyn_cast<ConstructorRefCallExpr>(calleeFn )) {
1804
1821
if (ctor->getFn ()->isImplicit () && args->isUnlabeledUnary ())
1805
1822
result.setDowngradeToWarning (true );
1806
1823
}
@@ -1841,15 +1858,15 @@ class ApplyClassifier {
1841
1858
return ;
1842
1859
}
1843
1860
1844
- AbstractFunctionDecl *calleeFn =
1861
+ AbstractFunctionDecl *calleeDecl =
1845
1862
fnRef.getKind () == AbstractFunction::Function
1846
1863
? fnRef.getFunction ()
1847
1864
: nullptr ;
1848
1865
1849
1866
for (unsigned i = 0 , e = args->size (); i < e; ++i) {
1850
1867
Type origParamType = fnRef.getOrigParamInterfaceType (i);
1851
1868
auto argClassification = classifyArgument (
1852
- E, calleeFn , args->getLabel (i), i,
1869
+ call, calleeDecl , args->getLabel (i), i,
1853
1870
args->getExpr (i), origParamType, fnRef.getSubstitutions (),
1854
1871
kind);
1855
1872
@@ -1867,7 +1884,7 @@ class ApplyClassifier {
1867
1884
if (auto appliedSelf = fnRef.getAppliedSelf ()) {
1868
1885
Type origParamType = fnRef.getOrigParamSelfType ();
1869
1886
auto selfClassification = classifyArgument (
1870
- E, calleeFn , ctx.Id_self , 0 , appliedSelf->getBase (),
1887
+ call, calleeDecl , ctx.Id_self , 0 , appliedSelf->getBase (),
1871
1888
origParamType, fnRef.getSubstitutions (), kind);
1872
1889
result.merge (selfClassification);
1873
1890
}
@@ -1917,7 +1934,7 @@ class ApplyClassifier {
1917
1934
// If the safety of the callee is unspecified, check the safety of the
1918
1935
// arguments specifically.
1919
1936
if (hasUnspecifiedSafety &&
1920
- !(assumedSafeArguments && assumedSafeArguments->contains (E ))) {
1937
+ !(assumedSafeArguments && assumedSafeArguments->contains (call ))) {
1921
1938
classifyApplyEffect (EffectKind::Unsafe);
1922
1939
}
1923
1940
@@ -2604,7 +2621,7 @@ class ApplyClassifier {
2604
2621
2605
2622
// / Classify an argument being passed to a rethrows/reasync function.
2606
2623
Classification classifyArgument (
2607
- ApplyExpr *call, const Decl* calleeDecl, Identifier argName,
2624
+ Expr *call, const Decl* calleeDecl, Identifier argName,
2608
2625
unsigned argIndex, Expr *arg, Type paramType, SubstitutionMap subs,
2609
2626
EffectKind kind) {
2610
2627
// Check for an unsafe argument.
@@ -2711,7 +2728,7 @@ class ApplyClassifier {
2711
2728
}
2712
2729
2713
2730
// / Classify an argument to a rethrows/reasync function that's a tuple literal.
2714
- Classification classifyTupleArgument (ApplyExpr *call,
2731
+ Classification classifyTupleArgument (Expr *call,
2715
2732
const Decl* calleeDecl,
2716
2733
Identifier argName,
2717
2734
unsigned argIndex,
0 commit comments