@@ -520,14 +520,8 @@ ActorIsolationRestriction ActorIsolationRestriction::forDeclaration(
520
520
case DeclKind::Constructor:
521
521
case DeclKind::Func:
522
522
case DeclKind::Subscript: {
523
- // Local captures can only be referenced in their local context or a
524
- // context that is guaranteed not to run concurrently with it.
523
+ // Local captures are checked separately.
525
524
if (cast<ValueDecl>(decl)->isLocalCapture ()) {
526
- // Local functions are safe to capture; their bodies are checked based on
527
- // where that capture is used.
528
- if (isa<FuncDecl>(decl))
529
- return forUnrestricted ();
530
-
531
525
return forLocalCapture (decl->getDeclContext ());
532
526
}
533
527
@@ -911,7 +905,9 @@ bool swift::diagnoseNonConcurrentTypesInReference(
911
905
}
912
906
913
907
if (auto var = dyn_cast<VarDecl>(declRef.getDecl ())) {
914
- Type propertyType = var->getValueInterfaceType ().subst (subs);
908
+ Type propertyType = var->isLocalCapture ()
909
+ ? var->getType ()
910
+ : var->getValueInterfaceType ().subst (subs);
915
911
if (!isConcurrentValueType (dc, propertyType)) {
916
912
return diagnoseNonConcurrentProperty (loc, refKind, var, propertyType);
917
913
}
@@ -938,69 +934,14 @@ bool swift::diagnoseNonConcurrentTypesInReference(
938
934
return false ;
939
935
}
940
936
941
- bool swift::diagnoseNonConcurrentTypesInFunctionType (
942
- const AnyFunctionType *fnType, const DeclContext *dc, SourceLoc loc,
943
- bool isClosure) {
944
- ASTContext &ctx = dc->getASTContext ();
945
- // Bail out immediately if we aren't supposed to do this checking.
946
- if (!dc->getASTContext ().LangOpts .EnableExperimentalConcurrentValueChecking )
947
- return false ;
948
-
949
- // Check parameter types.
950
- for (const auto ¶m : fnType->getParams ()) {
951
- Type paramType = param.getParameterType ();
952
- if (!isConcurrentValueType (dc, paramType)) {
953
- ctx.Diags .diagnose (
954
- loc, diag::non_concurrent_function_type, isClosure, false , paramType);
955
- return true ;
956
- }
957
- }
958
-
959
- // Check result type.
960
- if (!isConcurrentValueType (dc, fnType->getResult ())) {
961
- ctx.Diags .diagnose (
962
- loc, diag::non_concurrent_function_type, isClosure, true ,
963
- fnType->getResult ());
964
- return true ;
965
- }
966
-
967
- return false ;
968
- }
969
-
970
937
namespace {
971
- // / Check whether a particular context may execute concurrently within
972
- // / another context.
973
- class ConcurrentExecutionChecker {
974
- // / Keeps track of the first location at which a given local function is
975
- // / referenced from a context that may execute concurrently with the
976
- // / context in which it was introduced.
977
- llvm::SmallDenseMap<const FuncDecl *, SourceLoc, 4 > concurrentRefs;
978
-
979
- public:
980
- // / Determine whether (and where) a given local function is referenced
981
- // / from a context that may execute concurrently with the context in
982
- // / which it is declared.
983
- // /
984
- // / \returns the source location of the first reference to the local
985
- // / function that may be concurrent. If the result is an invalid
986
- // / source location, there are no such references.
987
- SourceLoc getConcurrentReferenceLoc (const FuncDecl *localFunc);
988
-
989
- // / Determine whether code in the given use context might execute
990
- // / concurrently with code in the definition context.
991
- bool mayExecuteConcurrentlyWith (
992
- const DeclContext *useContext, const DeclContext *defContext);
993
- };
994
-
995
938
// / Check for adherence to the actor isolation rules, emitting errors
996
939
// / when actor-isolated declarations are used in an unsafe manner.
997
940
class ActorIsolationChecker : public ASTWalker {
998
941
ASTContext &ctx;
999
942
SmallVector<const DeclContext *, 4 > contextStack;
1000
943
SmallVector<ApplyExpr*, 4 > applyStack;
1001
944
1002
- ConcurrentExecutionChecker concurrentExecutionChecker;
1003
-
1004
945
using MutableVarSource = llvm::PointerUnion<DeclRefExpr *, InOutExpr *>;
1005
946
using MutableVarParent = llvm::PointerUnion<InOutExpr *, LoadExpr *>;
1006
947
@@ -1016,10 +957,7 @@ namespace {
1016
957
// / Determine whether code in the given use context might execute
1017
958
// / concurrently with code in the definition context.
1018
959
bool mayExecuteConcurrentlyWith (
1019
- const DeclContext *useContext, const DeclContext *defContext) {
1020
- return concurrentExecutionChecker.mayExecuteConcurrentlyWith (
1021
- useContext, defContext);
1022
- }
960
+ const DeclContext *useContext, const DeclContext *defContext);
1023
961
1024
962
// / If the subexpression is a reference to a mutable local variable from a
1025
963
// / different context, record its parent. We'll query this as part of
@@ -1148,18 +1086,6 @@ namespace {
1148
1086
if (auto *closure = dyn_cast<AbstractClosureExpr>(expr)) {
1149
1087
closure->setActorIsolation (determineClosureIsolation (closure));
1150
1088
contextStack.push_back (closure);
1151
-
1152
-
1153
- // Concurrent closures must be composed of concurrent-safe parameter
1154
- // and result types.
1155
- if (isConcurrentClosure (closure)) {
1156
- if (auto fnType = closure->getType ()->getAs <FunctionType>()) {
1157
- (void )diagnoseNonConcurrentTypesInFunctionType (
1158
- fnType, getDeclContext (), closure->getLoc (),
1159
- /* isClosure=*/ true );
1160
- }
1161
- }
1162
-
1163
1089
return { true , expr };
1164
1090
}
1165
1091
@@ -1689,6 +1615,22 @@ namespace {
1689
1615
return true ;
1690
1616
}
1691
1617
1618
+ if (auto func = dyn_cast<FuncDecl>(value)) {
1619
+ if (func->isConcurrent ())
1620
+ return false ;
1621
+
1622
+ func->diagnose (
1623
+ diag::local_function_executed_concurrently,
1624
+ func->getDescriptiveKind (), func->getName ())
1625
+ .fixItInsert (func->getAttributeInsertionLoc (false ), " @concurrent " );
1626
+
1627
+ // Add the @concurrent attribute implicitly, so we don't diagnose
1628
+ // again.
1629
+ const_cast <FuncDecl *>(func)->getAttrs ().add (
1630
+ new (ctx) ConcurrentAttr (true ));
1631
+ return true ;
1632
+ }
1633
+
1692
1634
// Concurrent access to some other local.
1693
1635
ctx.Diags .diagnose (
1694
1636
loc, diag::concurrent_access_local,
@@ -1910,111 +1852,7 @@ namespace {
1910
1852
};
1911
1853
}
1912
1854
1913
- SourceLoc ConcurrentExecutionChecker::getConcurrentReferenceLoc (
1914
- const FuncDecl *localFunc) {
1915
-
1916
- // If we've already computed a result, we're done.
1917
- auto known = concurrentRefs.find (localFunc);
1918
- if (known != concurrentRefs.end ())
1919
- return known->second ;
1920
-
1921
- // Record that there are no concurrent references to this local function. This
1922
- // prevents infinite recursion if two local functions call each other.
1923
- concurrentRefs[localFunc] = SourceLoc ();
1924
-
1925
- class ConcurrentLocalRefWalker : public ASTWalker {
1926
- ConcurrentExecutionChecker &checker;
1927
- const FuncDecl *targetFunc;
1928
- SmallVector<const DeclContext *, 4 > contextStack;
1929
-
1930
- const DeclContext *getDeclContext () const {
1931
- return contextStack.back ();
1932
- }
1933
-
1934
- public:
1935
- ConcurrentLocalRefWalker (
1936
- ConcurrentExecutionChecker &checker, const FuncDecl *targetFunc
1937
- ) : checker(checker), targetFunc(targetFunc) {
1938
- contextStack.push_back (targetFunc->getDeclContext ());
1939
- }
1940
-
1941
- std::pair<bool , Expr *> walkToExprPre (Expr *expr) override {
1942
- if (auto *closure = dyn_cast<AbstractClosureExpr>(expr)) {
1943
- contextStack.push_back (closure);
1944
- return { true , expr };
1945
- }
1946
-
1947
- if (auto *declRef = dyn_cast<DeclRefExpr>(expr)) {
1948
- // If this is a reference to the target function from a context
1949
- // that may execute concurrently with the context where the target
1950
- // function was declared, record the location.
1951
- if (declRef->getDecl () == targetFunc &&
1952
- checker.mayExecuteConcurrentlyWith (
1953
- getDeclContext (), contextStack.front ())) {
1954
- SourceLoc &loc = checker.concurrentRefs [targetFunc];
1955
- if (loc.isInvalid ())
1956
- loc = declRef->getLoc ();
1957
-
1958
- return { false , expr };
1959
- }
1960
-
1961
- return { true , expr };
1962
- }
1963
-
1964
- return { true , expr };
1965
- }
1966
-
1967
- Expr *walkToExprPost (Expr *expr) override {
1968
- if (auto *closure = dyn_cast<AbstractClosureExpr>(expr)) {
1969
- assert (contextStack.back () == closure);
1970
- contextStack.pop_back ();
1971
- }
1972
-
1973
- return expr;
1974
- }
1975
-
1976
- bool walkToDeclPre (Decl *decl) override {
1977
- if (isa<NominalTypeDecl>(decl) || isa<ExtensionDecl>(decl))
1978
- return false ;
1979
-
1980
- if (auto func = dyn_cast<AbstractFunctionDecl>(decl)) {
1981
- contextStack.push_back (func);
1982
- }
1983
-
1984
- return true ;
1985
- }
1986
-
1987
- bool walkToDeclPost (Decl *decl) override {
1988
- if (auto func = dyn_cast<AbstractFunctionDecl>(decl)) {
1989
- assert (contextStack.back () == func);
1990
- contextStack.pop_back ();
1991
- }
1992
-
1993
- return true ;
1994
- }
1995
- };
1996
-
1997
- // Walk the body of the enclosing function, where all references to the
1998
- // given local function would occur.
1999
- Stmt *enclosingBody = nullptr ;
2000
- DeclContext *enclosingDC = localFunc->getDeclContext ();
2001
- if (auto enclosingFunc = dyn_cast<AbstractFunctionDecl>(enclosingDC))
2002
- enclosingBody = enclosingFunc->getBody ();
2003
- else if (auto enclosingClosure = dyn_cast<ClosureExpr>(enclosingDC))
2004
- enclosingBody = enclosingClosure->getBody ();
2005
- else if (auto enclosingTopLevelCode = dyn_cast<TopLevelCodeDecl>(enclosingDC))
2006
- enclosingBody = enclosingTopLevelCode->getBody ();
2007
- else
2008
- return SourceLoc ();
2009
-
2010
- assert (enclosingBody && " Cannot have a local function here" );
2011
- ConcurrentLocalRefWalker walker (*this , localFunc);
2012
- enclosingBody->walk (walker);
2013
-
2014
- return concurrentRefs[localFunc];
2015
- }
2016
-
2017
- bool ConcurrentExecutionChecker::mayExecuteConcurrentlyWith (
1855
+ bool ActorIsolationChecker::mayExecuteConcurrentlyWith (
2018
1856
const DeclContext *useContext, const DeclContext *defContext) {
2019
1857
// Walk the context chain from the use to the definition.
2020
1858
while (useContext != defContext) {
@@ -2029,25 +1867,6 @@ bool ConcurrentExecutionChecker::mayExecuteConcurrentlyWith(
2029
1867
// If the function is @concurrent... it can be run concurrently.
2030
1868
if (func->isConcurrent ())
2031
1869
return true ;
2032
-
2033
- // If we find a local function that was referenced in code that can be
2034
- // executed concurrently with where the local function was declared, the
2035
- // local function can be run concurrently.
2036
- SourceLoc concurrentLoc = getConcurrentReferenceLoc (func);
2037
- if (concurrentLoc.isValid ()) {
2038
- ASTContext &ctx = func->getASTContext ();
2039
- func->diagnose (
2040
- diag::local_function_executed_concurrently,
2041
- func->getDescriptiveKind (), func->getName ())
2042
- .fixItInsert (func->getAttributeInsertionLoc (false ), " @concurrent " );
2043
- ctx.Diags .diagnose (concurrentLoc, diag::concurrent_access_here);
2044
-
2045
- // Add the @concurrent attribute implicitly, so we don't diagnose
2046
- // again.
2047
- const_cast <FuncDecl *>(func)->getAttrs ().add (
2048
- new (ctx) ConcurrentAttr (true ));
2049
- return true ;
2050
- }
2051
1870
}
2052
1871
}
2053
1872
0 commit comments