Skip to content

Commit 3a989b6

Browse files
Merge pull request #69833 from sophiapoirier/nonisolated-unsafe-globals
🍒 parse nonisolated(unsafe) as decl contextual keyword in top-level global scope rather than as function invocation
2 parents cb1bf57 + 3d1ad49 commit 3a989b6

File tree

3 files changed

+40
-7
lines changed

3 files changed

+40
-7
lines changed

lib/ASTGen/Sources/ASTGen/SourceFile.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ extension Parser.ExperimentalFeatures {
3636
}
3737
}
3838
mapFeature(.ThenStatements, to: .thenStatements)
39+
mapFeature(.GlobalConcurrency, to: .globalConcurrency)
3940
}
4041
}
4142

lib/Parse/ParseDecl.cpp

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#include "llvm/Support/Path.h"
4444
#include "llvm/Support/SaveAndRestore.h"
4545
#include <algorithm>
46+
#include <initializer_list>
4647

4748
using namespace swift;
4849

@@ -5143,18 +5144,34 @@ bool swift::isKeywordPossibleDeclStart(const LangOptions &options,
51435144
}
51445145
}
51455146

5146-
/// Given a current token of 'unowned', check to see if it is followed by a
5147-
/// "(safe)" or "(unsafe)" specifier.
5148-
static bool isParenthesizedUnowned(Parser &P) {
5149-
assert(P.Tok.getText() == "unowned" && P.peekToken().is(tok::l_paren) &&
5147+
static bool
5148+
isParenthesizedModifier(Parser &P, StringRef name,
5149+
std::initializer_list<StringRef> allowedArguments) {
5150+
assert((P.Tok.getText() == name) && P.peekToken().is(tok::l_paren) &&
51505151
"Invariant violated");
5151-
5152+
51525153
// Look ahead to parse the parenthesized expression.
51535154
Parser::BacktrackingScope Backtrack(P);
51545155
P.consumeToken(tok::identifier);
51555156
P.consumeToken(tok::l_paren);
5156-
return P.Tok.is(tok::identifier) && P.peekToken().is(tok::r_paren) &&
5157-
(P.Tok.getText() == "safe" || P.Tok.getText() == "unsafe");
5157+
5158+
const bool argumentIsAllowed =
5159+
std::find(allowedArguments.begin(), allowedArguments.end(),
5160+
P.Tok.getText()) != allowedArguments.end();
5161+
return argumentIsAllowed && P.Tok.is(tok::identifier) &&
5162+
P.peekToken().is(tok::r_paren);
5163+
}
5164+
5165+
/// Given a current token of 'unowned', check to see if it is followed by a
5166+
/// "(safe)" or "(unsafe)" specifier.
5167+
static bool isParenthesizedUnowned(Parser &P) {
5168+
return isParenthesizedModifier(P, "unowned", {"safe", "unsafe"});
5169+
}
5170+
5171+
/// Given a current token of 'nonisolated', check to see if it is followed by an
5172+
/// "(unsafe)" specifier.
5173+
static bool isParenthesizedNonisolated(Parser &P) {
5174+
return isParenthesizedModifier(P, "nonisolated", {"unsafe"});
51585175
}
51595176

51605177
static void skipAttribute(Parser &P) {
@@ -5326,6 +5343,19 @@ bool Parser::isStartOfSwiftDecl(bool allowPoundIfAttributes,
53265343
/*hadAttrsOrModifiers=*/true);
53275344
}
53285345

5346+
// If this is 'nonisolated', check to see if it is valid.
5347+
if (Context.LangOpts.hasFeature(Feature::GlobalConcurrency) &&
5348+
Tok.isContextualKeyword("nonisolated") && Tok2.is(tok::l_paren) &&
5349+
isParenthesizedNonisolated(*this)) {
5350+
BacktrackingScope backtrack(*this);
5351+
consumeToken(tok::identifier);
5352+
consumeToken(tok::l_paren);
5353+
consumeToken(tok::identifier);
5354+
consumeToken(tok::r_paren);
5355+
return isStartOfSwiftDecl(/*allowPoundIfAttributes=*/false,
5356+
/*hadAttrsOrModifiers=*/true);
5357+
}
5358+
53295359
if (Tok.isContextualKeyword("actor")) {
53305360
if (Tok2.is(tok::identifier)) // actor Foo {}
53315361
return true;

test/Concurrency/experimental_feature_strictconcurrency.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ final class TestNonsendable {
4545
init() {}
4646
}
4747

48+
nonisolated(unsafe) let immutableNonisolatedUnsafeTopLevelGlobal = TestNonsendable()
49+
4850
@propertyWrapper
4951
public struct TestWrapper {
5052
public init() {}

0 commit comments

Comments
 (0)