Skip to content

Commit 53423c0

Browse files
authored
Merge pull request #40490 from etcwilde/ewilde/concurrency/unavailablefromasync-messages
2 parents 3e2404d + 2eb6e3b commit 53423c0

File tree

13 files changed

+151
-10
lines changed

13 files changed

+151
-10
lines changed

include/swift/AST/Attr.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -699,7 +699,7 @@ CONTEXTUAL_SIMPLE_DECL_ATTR(_const, CompileTimeConst,
699699
ABIStableToAdd | ABIStableToRemove | APIBreakingToAdd | APIStableToRemove,
700700
126)
701701

702-
SIMPLE_DECL_ATTR(_unavailableFromAsync, UnavailableFromAsync,
702+
DECL_ATTR(_unavailableFromAsync, UnavailableFromAsync,
703703
OnFunc | OnConstructor | UserInaccessible |
704704
ABIStableToAdd | ABIStableToRemove |
705705
APIBreakingToAdd | APIStableToRemove,

include/swift/AST/Attr.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2085,6 +2085,26 @@ class TypeSequenceAttr : public DeclAttribute {
20852085
}
20862086
};
20872087

2088+
/// The @_unavailableFromAsync attribute, used to make function declarations
2089+
/// unavailable from async contexts.
2090+
class UnavailableFromAsyncAttr : public DeclAttribute {
2091+
public:
2092+
UnavailableFromAsyncAttr(StringRef Message, SourceLoc AtLoc,
2093+
SourceRange Range, bool Implicit)
2094+
: DeclAttribute(DAK_UnavailableFromAsync, AtLoc, Range, Implicit),
2095+
Message(Message) {}
2096+
UnavailableFromAsyncAttr(StringRef Message, bool Implicit)
2097+
: UnavailableFromAsyncAttr(Message, SourceLoc(), SourceRange(),
2098+
Implicit) {}
2099+
const StringRef Message;
2100+
2101+
bool hasMessage() const { return !Message.empty(); }
2102+
2103+
static bool classof(const DeclAttribute *DA) {
2104+
return DA->getKind() == DAK_UnavailableFromAsync;
2105+
}
2106+
};
2107+
20882108
/// Attributes that may be applied to declarations.
20892109
class DeclAttributes {
20902110
/// Linked list of declaration attributes.

include/swift/AST/DiagnosticsParse.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1435,6 +1435,8 @@ ERROR(attr_missing_label,PointsToFirstBadToken,
14351435
"missing label '%0:' in '@%1' attribute", (StringRef, StringRef))
14361436
ERROR(attr_expected_label,none,
14371437
"expected label '%0:' in '@%1' attribute", (StringRef, StringRef))
1438+
ERROR(attr_expected_colon_after_label,none,
1439+
"expected ':' after label '%0'", (StringRef))
14381440

14391441
ERROR(alignment_must_be_positive_integer,none,
14401442
"alignment value must be a positive integer literal", ())

include/swift/AST/DiagnosticsSema.def

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4719,7 +4719,8 @@ ERROR(async_named_decl_must_be_available_from_async,none,
47194719
"asynchronous %0 %1 must be available from asynchronous contexts",
47204720
(DescriptiveDeclKind, DeclName))
47214721
ERROR(async_unavailable_decl,none,
4722-
"%0 %1 is unavailable from asynchronous contexts", (DescriptiveDeclKind, DeclBaseName))
4722+
"%0 %1 is unavailable from asynchronous contexts%select{|; %3}2",
4723+
(DescriptiveDeclKind, DeclBaseName, bool, StringRef))
47234724

47244725
//------------------------------------------------------------------------------
47254726
// MARK: Type Check Types

lib/AST/Attr.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1164,6 +1164,17 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
11641164
break;
11651165
}
11661166

1167+
case DAK_UnavailableFromAsync: {
1168+
Printer.printAttrName("@_unavailableFromAsync");
1169+
const UnavailableFromAsyncAttr *attr = cast<UnavailableFromAsyncAttr>(this);
1170+
if (attr->hasMessage()) {
1171+
Printer << "(message: \"";
1172+
Printer << attr->Message;
1173+
Printer << "\")";
1174+
}
1175+
break;
1176+
}
1177+
11671178
case DAK_Count:
11681179
llvm_unreachable("exceed declaration attribute kinds");
11691180

@@ -1317,6 +1328,8 @@ StringRef DeclAttribute::getAttrName() const {
13171328
return "transpose";
13181329
case DAK_TypeSequence:
13191330
return "_typeSequence";
1331+
case DAK_UnavailableFromAsync:
1332+
return "_unavailableFromAsync";
13201333
}
13211334
llvm_unreachable("bad DeclAttrKind");
13221335
}

lib/Parse/ParseDecl.cpp

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2749,6 +2749,53 @@ bool Parser::parseNewDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc,
27492749
Attributes.add(TypeSequenceAttr::create(Context, AtLoc, range));
27502750
break;
27512751
}
2752+
2753+
case DAK_UnavailableFromAsync: {
2754+
StringRef message;
2755+
if (consumeIf(tok::l_paren)) {
2756+
if (!Tok.is(tok::identifier)) {
2757+
llvm_unreachable("Flag must start with an indentifier");
2758+
}
2759+
2760+
StringRef flag = Tok.getText();
2761+
2762+
if (flag != "message") {
2763+
diagnose(Tok.getLoc(), diag::attr_unknown_option, flag, AttrName);
2764+
return true;
2765+
}
2766+
consumeToken();
2767+
if (!consumeIf(tok::colon)) {
2768+
if (!Tok.is(tok::equal)) {
2769+
diagnose(Tok.getLoc(), diag::attr_expected_colon_after_label, flag);
2770+
return false;
2771+
}
2772+
diagnose(Tok.getLoc(), diag::replace_equal_with_colon_for_value)
2773+
.fixItReplace(Tok.getLoc(), ": ");
2774+
consumeToken();
2775+
}
2776+
if (!Tok.is(tok::string_literal)) {
2777+
diagnose(Tok.getLoc(), diag::attr_expected_string_literal, AttrName);
2778+
return false;
2779+
}
2780+
2781+
Optional<StringRef> value = getStringLiteralIfNotInterpolated(
2782+
Tok.getLoc(), flag);
2783+
if (!value)
2784+
return false;
2785+
Token stringTok = Tok;
2786+
consumeToken();
2787+
message = *value;
2788+
2789+
if (!consumeIf(tok::r_paren))
2790+
diagnose(stringTok.getRange().getEnd(), diag::attr_expected_rparen,
2791+
AttrName, /*isModifiler*/false)
2792+
.fixItInsertAfter(stringTok.getLoc(), ")");
2793+
}
2794+
2795+
Attributes.add(new (Context) UnavailableFromAsyncAttr(
2796+
message, AtLoc, SourceRange(Loc, Tok.getLoc()), false));
2797+
break;
2798+
}
27522799
}
27532800

27542801
if (DuplicateAttribute) {

lib/Sema/TypeCheckAvailability.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3149,10 +3149,12 @@ diagnoseDeclUnavailableFromAsync(const ValueDecl *D, SourceRange R,
31493149
return false;
31503150

31513151
ASTContext &ctx = Where.getDeclContext()->getASTContext();
3152+
const UnavailableFromAsyncAttr *attr =
3153+
D->getAttrs().getAttribute<UnavailableFromAsyncAttr>();
31523154
SourceLoc diagLoc = call ? call->getLoc() : R.Start;
31533155
ctx.Diags
31543156
.diagnose(diagLoc, diag::async_unavailable_decl, D->getDescriptiveKind(),
3155-
D->getBaseName())
3157+
D->getBaseName(), attr->hasMessage(), attr->Message)
31563158
.warnUntilSwiftVersion(6);
31573159
D->diagnose(diag::decl_declared_here, D->getName());
31583160
return true;

lib/Serialization/Deserialization.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4747,6 +4747,14 @@ llvm::Error DeclDeserializer::deserializeDeclCommon() {
47474747
break;
47484748
}
47494749

4750+
case decls_block::UnavailableFromAsync_DECL_ATTR: {
4751+
bool isImplicit;
4752+
serialization::decls_block::UnavailableFromAsyncDeclAttrLayout::
4753+
readRecord(scratch, isImplicit);
4754+
Attr = new (ctx) UnavailableFromAsyncAttr(blobData, isImplicit);
4755+
break;
4756+
}
4757+
47504758
#define SIMPLE_DECL_ATTR(NAME, CLASS, ...) \
47514759
case decls_block::CLASS##_DECL_ATTR: { \
47524760
bool isImplicit; \

lib/Serialization/ModuleFormat.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
5656
/// describe what change you made. The content of this comment isn't important;
5757
/// it just ensures a conflict if two people change the module format.
5858
/// Don't worry about adhering to the 80-column limit for this line.
59-
const uint16_t SWIFTMODULE_VERSION_MINOR = 648; // mark_unresolved_move_addr
59+
const uint16_t SWIFTMODULE_VERSION_MINOR = 649; // _unavailableFromAsync message
6060

6161
/// A standard hash seed used for all string hashes in a serialized module.
6262
///
@@ -2022,6 +2022,12 @@ namespace decls_block {
20222022
TypeIDField, // type referenced by this custom attribute
20232023
BCFixed<1> // is the argument (unsafe)
20242024
>;
2025+
2026+
using UnavailableFromAsyncDeclAttrLayout = BCRecordLayout<
2027+
UnavailableFromAsync_DECL_ATTR,
2028+
BCFixed<1>, // Implicit flag
2029+
BCBlob // Message
2030+
>;
20252031
}
20262032

20272033
/// Returns the encoding kind for the given decl.

lib/Serialization/Serialization.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2754,6 +2754,16 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
27542754
TypeSequenceDeclAttrLayout::emitRecord(S.Out, S.ScratchRecord, abbrCode);
27552755
return;
27562756
}
2757+
2758+
case DAK_UnavailableFromAsync: {
2759+
auto abbrCode =
2760+
S.DeclTypeAbbrCodes[UnavailableFromAsyncDeclAttrLayout::Code];
2761+
auto *theAttr = cast<UnavailableFromAsyncAttr>(DA);
2762+
UnavailableFromAsyncDeclAttrLayout::emitRecord(
2763+
S.Out, S.ScratchRecord, abbrCode, theAttr->isImplicit(),
2764+
theAttr->Message);
2765+
return;
2766+
}
27572767
}
27582768
}
27592769

0 commit comments

Comments
 (0)