Skip to content

Commit c941116

Browse files
committed
Add optional message to unavailablefromasync
Adding the ability to add an optional message to the unavailable from async attribute. This can be used to indicate other possible API to use, or help explain why it's unavailable.
1 parent 2668223 commit c941116

File tree

12 files changed

+110
-9
lines changed

12 files changed

+110
-9
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/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: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2749,6 +2749,45 @@ bool Parser::parseNewDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc,
27492749
Attributes.add(TypeSequenceAttr::create(Context, AtLoc, range));
27502750
break;
27512751
}
2752+
2753+
case DAK_UnavailableFromAsync: {
2754+
2755+
StringRef message;
2756+
if (consumeIf(tok::l_paren)) {
2757+
if (!Tok.is(tok::identifier)) {
2758+
llvm_unreachable("Flag must start with an indentifier");
2759+
}
2760+
2761+
StringRef flag = Tok.getText();
2762+
2763+
if (flag != "message") {
2764+
llvm_unreachable("Unknown unavailable argument");
2765+
}
2766+
consumeToken();
2767+
if (!consumeIf(tok::colon)) {
2768+
llvm_unreachable("Expected ':' following 'message'");
2769+
}
2770+
if (!Tok.is(tok::string_literal)) {
2771+
llvm_unreachable("Expected string literal");
2772+
}
2773+
2774+
Optional<StringRef> value = getStringLiteralIfNotInterpolated(
2775+
Loc, "' I don't know what goes here! '");
2776+
if (!value)
2777+
llvm_unreachable("Expected a message, homie");
2778+
2779+
consumeToken();
2780+
2781+
message = *value;
2782+
2783+
if (!consumeIf(tok::r_paren))
2784+
llvm_unreachable("Expected a closing r-paren");
2785+
}
2786+
2787+
Attributes.add(new (Context) UnavailableFromAsyncAttr(
2788+
message, AtLoc, SourceRange(Loc, Tok.getLoc()), false));
2789+
break;
2790+
}
27522791
}
27532792

27542793
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: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

test/ClangImporter/objc_async.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ func testSlowServer(slowServer: SlowServer) async throws {
4545
let _: Int = await slowServer.bestName("hello")
4646
let _: Int = await slowServer.customize("hello")
4747

48-
slowServer.unavailableMethod() // expected-warning{{'unavailableMethod' is unavailable from asynchronous contexts}}
48+
slowServer.unavailableMethod() // expected-warning{{instance method 'unavailableMethod' is unavailable from asynchronous contexts}}
49+
slowServer.unavailableMethodWithMessage() // expected-warning{{instance method 'unavailableMethodWithMessage' is unavailable from asynchronous contexts; Blarpy!}}
4950

5051
let _: String = await slowServer.dance("slide")
5152
let _: String = await slowServer.__leap(17)

0 commit comments

Comments
 (0)