Skip to content

Commit 5a1e042

Browse files
authored
Merge pull request #40267 from beccadax/send-me-an-object-recommit
[Re-merge] Support __available__((swift_attr("@sendable")))
2 parents 07a78fd + 1880118 commit 5a1e042

39 files changed

+626
-238
lines changed

include/swift/AST/Attr.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -605,7 +605,7 @@ CONTEXTUAL_SIMPLE_DECL_ATTR(async, Async,
605605
106)
606606

607607
SIMPLE_DECL_ATTR(Sendable, Sendable,
608-
OnFunc | OnConstructor | OnAccessor |
608+
OnFunc | OnConstructor | OnAccessor | OnAnyClangDecl |
609609
ABIBreakingToAdd | ABIBreakingToRemove |
610610
APIBreakingToAdd | APIBreakingToRemove,
611611
107)

include/swift/AST/Attr.h

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,8 +168,9 @@ class DeclAttribute : public AttributeBase {
168168
);
169169

170170
SWIFT_INLINE_BITFIELD(SynthesizedProtocolAttr, DeclAttribute,
171-
NumKnownProtocolKindBits,
172-
kind : NumKnownProtocolKindBits
171+
NumKnownProtocolKindBits+1,
172+
kind : NumKnownProtocolKindBits,
173+
isUnchecked : 1
173174
);
174175
} Bits;
175176

@@ -288,6 +289,9 @@ class DeclAttribute : public AttributeBase {
288289

289290
/// Whether this attribute is only valid when distributed is enabled.
290291
DistributedOnly = 1ull << (unsigned(DeclKindIndex::Last_Decl) + 17),
292+
293+
/// Whether this attribute is valid on additional decls in ClangImporter.
294+
OnAnyClangDecl = 1ull << (unsigned(DeclKindIndex::Last_Decl) + 18),
291295
};
292296

293297
LLVM_READNONE
@@ -1276,11 +1280,13 @@ class SynthesizedProtocolAttr : public DeclAttribute {
12761280

12771281
public:
12781282
SynthesizedProtocolAttr(KnownProtocolKind protocolKind,
1279-
LazyConformanceLoader *Loader)
1283+
LazyConformanceLoader *Loader,
1284+
bool isUnchecked)
12801285
: DeclAttribute(DAK_SynthesizedProtocol, SourceLoc(), SourceRange(),
12811286
/*Implicit=*/true), Loader(Loader)
12821287
{
12831288
Bits.SynthesizedProtocolAttr.kind = unsigned(protocolKind);
1289+
Bits.SynthesizedProtocolAttr.isUnchecked = unsigned(isUnchecked);
12841290
}
12851291

12861292
/// Retrieve the known protocol kind naming the protocol to be
@@ -1289,6 +1295,10 @@ class SynthesizedProtocolAttr : public DeclAttribute {
12891295
return KnownProtocolKind(Bits.SynthesizedProtocolAttr.kind);
12901296
}
12911297

1298+
bool isUnchecked() const {
1299+
return bool(Bits.SynthesizedProtocolAttr.isUnchecked);
1300+
}
1301+
12921302
/// Retrieve the lazy loader that will be used to populate the
12931303
/// synthesized conformance.
12941304
LazyConformanceLoader *getLazyLoader() const { return Loader; }
@@ -2217,6 +2227,15 @@ class DeclAttributes {
22172227
return nullptr;
22182228
}
22192229

2230+
/// Returns the "winning" \c NonSendableAttr or \c SendableAttr in this
2231+
/// attribute list, or \c nullptr if there are none.
2232+
const DeclAttribute *getEffectiveSendableAttr() const;
2233+
2234+
DeclAttribute *getEffectiveSendableAttr() {
2235+
return const_cast<DeclAttribute *>(
2236+
const_cast<const DeclAttributes *>(this)->getEffectiveSendableAttr());
2237+
}
2238+
22202239
private:
22212240
/// Predicate used to filter MatchingAttributeRange.
22222241
template <typename ATTR, bool AllowInvalid> struct ToAttributeKind {

include/swift/AST/DiagnosticsClangImporter.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,10 @@ NOTE(unresolvable_clang_decl_is_a_framework_bug,none,
8585
WARNING(clang_swift_attr_unhandled,none,
8686
"Ignoring unknown Swift attribute or modifier '%0'", (StringRef))
8787

88+
WARNING(clang_error_code_must_be_sendable,none,
89+
"cannot make error code type '%0' non-sendable because Swift errors "
90+
"are always sendable", (StringRef))
91+
8892
WARNING(implicit_bridging_header_imported_from_module,none,
8993
"implicit import of bridging header '%0' via module %1 "
9094
"is deprecated and will be removed in a later version of Swift",

include/swift/AST/FileUnit.h

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,11 @@
1717
#include "swift/AST/RawComment.h"
1818
#include "swift/Basic/BasicSourceInfo.h"
1919

20+
#include "llvm/ADT/PointerIntPair.h"
21+
2022
namespace swift {
23+
class SynthesizedFileUnit;
24+
2125
/// A container for module-scope declarations that itself provides a scope; the
2226
/// smallest unit of code organization.
2327
///
@@ -33,19 +37,25 @@ class FileUnit : public DeclContext, public ASTAllocated<FileUnit> {
3337
friend class DirectOperatorLookupRequest;
3438
friend class DirectPrecedenceGroupLookupRequest;
3539

36-
// FIXME: Stick this in a PointerIntPair.
37-
const FileUnitKind Kind;
40+
// The pointer is FileUnit insted of SynthesizedFileUnit to break circularity.
41+
llvm::PointerIntPair<FileUnit *, 3, FileUnitKind> SynthesizedFileAndKind;
3842

3943
protected:
4044
FileUnit(FileUnitKind kind, ModuleDecl &M)
41-
: DeclContext(DeclContextKind::FileUnit, &M), Kind(kind) {
45+
: DeclContext(DeclContextKind::FileUnit, &M),
46+
SynthesizedFileAndKind(nullptr, kind) {
4247
}
4348

4449
public:
4550
FileUnitKind getKind() const {
46-
return Kind;
51+
return SynthesizedFileAndKind.getInt();
4752
}
4853

54+
/// Returns the synthesized file for this source file, if it exists.
55+
SynthesizedFileUnit *getSynthesizedFile() const;
56+
57+
SynthesizedFileUnit &getOrCreateSynthesizedFile();
58+
4959
/// Look up a (possibly overloaded) value set at top-level scope
5060
/// (but with the specified access path, which may come from an import decl)
5161
/// within this file.

include/swift/AST/Module.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -758,7 +758,9 @@ class ModuleDecl
758758
/// The order of the results is not guaranteed to be meaningful.
759759
///
760760
/// This can differ from \c getTopLevelDecls, e.g. it returns decls from a
761-
/// shadowed clang module.
761+
/// shadowed clang module. It does not force synthesized top-level decls that
762+
/// should be printed to be added; use \c swift::getTopLevelDeclsForDisplay()
763+
/// for that.
762764
void getDisplayDecls(SmallVectorImpl<Decl*> &results) const;
763765

764766
using LinkLibraryCallback = llvm::function_ref<void(LinkLibrary)>;

include/swift/AST/PrintOptions.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,10 @@ struct PrintOptions {
235235
/// Whether to print unavailable parts of the AST.
236236
bool SkipUnavailable = false;
237237

238+
/// Whether to print synthesized extensions created by '@_nonSendable', even
239+
/// if SkipImplicit or SkipUnavailable is set.
240+
bool AlwaysPrintNonSendableExtensions = true;
241+
238242
bool SkipSwiftPrivateClangDecls = false;
239243

240244
/// Whether to skip internal stdlib declarations.
@@ -667,6 +671,7 @@ struct PrintOptions {
667671
PO.ShouldQualifyNestedDeclarations = QualifyNestedDeclarations::TypesOnly;
668672
PO.PrintParameterSpecifiers = true;
669673
PO.SkipImplicit = true;
674+
PO.AlwaysPrintNonSendableExtensions = false;
670675
PO.AlwaysTryPrintParameterLabels = true;
671676
return PO;
672677
}

include/swift/AST/ProtocolConformance.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,13 @@ class NormalProtocolConformance : public RootProtocolConformance,
514514
return ContextAndBits.getInt() & UncheckedFlag;
515515
}
516516

517+
/// Mark the conformance as unchecked (equivalent to the @unchecked
518+
/// conformance attribute).
519+
void setUnchecked() {
520+
// OK to mutate because the flags are not part of the folding set node ID.
521+
ContextAndBits.setInt(ContextAndBits.getInt() | UncheckedFlag);
522+
}
523+
517524
/// Get the kind of source from which this conformance comes.
518525
ConformanceEntryKind getSourceKind() const {
519526
return SourceKindAndImplyingConformance.getInt();

include/swift/AST/SourceFile.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,6 @@ class SourceFile final : public FileUnit {
8989
/// same module.
9090
mutable Identifier PrivateDiscriminator;
9191

92-
/// A synthesized file corresponding to this file, created on-demand.
93-
SynthesizedFileUnit *SynthesizedFile = nullptr;
94-
9592
/// The root TypeRefinementContext for this SourceFile.
9693
///
9794
/// This is set during type checking.
@@ -409,11 +406,6 @@ class SourceFile final : public FileUnit {
409406
Optional<ExternalSourceLocs::RawLocs>
410407
getExternalRawLocsForDecl(const Decl *D) const override;
411408

412-
/// Returns the synthesized file for this source file, if it exists.
413-
SynthesizedFileUnit *getSynthesizedFile() const { return SynthesizedFile; };
414-
415-
SynthesizedFileUnit &getOrCreateSynthesizedFile();
416-
417409
virtual bool walk(ASTWalker &walker) override;
418410

419411
/// The buffer ID for the file that was imported, or None if there

include/swift/AST/SynthesizedFileUnit.h

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,12 @@
1818

1919
namespace swift {
2020

21-
class SourceFile;
22-
2321
/// A container for synthesized declarations, attached to a `SourceFile`.
2422
///
2523
/// Currently, only module-level synthesized declarations are supported.
2624
class SynthesizedFileUnit final : public FileUnit {
2725
/// The parent source file.
28-
SourceFile &SF;
26+
FileUnit &FU;
2927

3028
/// Synthesized top level declarations.
3129
TinyPtrVector<Decl *> TopLevelDecls;
@@ -36,11 +34,11 @@ class SynthesizedFileUnit final : public FileUnit {
3634
mutable Identifier PrivateDiscriminator;
3735

3836
public:
39-
SynthesizedFileUnit(SourceFile &SF);
37+
SynthesizedFileUnit(FileUnit &FU);
4038
~SynthesizedFileUnit() = default;
4139

4240
/// Returns the parent source file.
43-
SourceFile &getSourceFile() const { return SF; }
41+
FileUnit &getFileUnit() const { return FU; }
4442

4543
/// Add a synthesized top-level declaration.
4644
void addTopLevelDecl(Decl *D) { TopLevelDecls.push_back(D); }

include/swift/Sema/IDETypeChecking.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,13 @@ namespace swift {
140140
LookupResult
141141
lookupSemanticMember(DeclContext *DC, Type ty, DeclName name);
142142

143+
/// Get all of the top-level declarations that should be printed as part of
144+
/// this module. This may force synthesis of top-level declarations that
145+
/// \c ModuleDecl::getDisplayDecls() would only return if previous
146+
/// work happened to have synthesized them.
147+
void
148+
getTopLevelDeclsForDisplay(ModuleDecl *M, SmallVectorImpl<Decl*> &Results);
149+
143150
struct ExtensionInfo {
144151
// The extension with the declarations to apply.
145152
ExtensionDecl *Ext;

lib/APIDigester/ModuleAnalyzerNodes.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
#include "llvm/ADT/STLExtras.h"
2+
#include "swift/AST/ASTMangler.h"
23
#include "swift/Basic/Defer.h"
4+
#include "swift/Sema/IDETypeChecking.h"
35
#include "swift/SIL/SILDeclRef.h"
4-
#include "swift/AST/ASTMangler.h"
56
#include <swift/APIDigester/ModuleAnalyzerNodes.h>
67
#include <algorithm>
78

@@ -1872,7 +1873,7 @@ void SwiftDeclCollector::printTopLevelNames() {
18721873
void SwiftDeclCollector::lookupVisibleDecls(ArrayRef<ModuleDecl *> Modules) {
18731874
for (auto M: Modules) {
18741875
llvm::SmallVector<Decl*, 512> Decls;
1875-
M->getDisplayDecls(Decls);
1876+
swift::getTopLevelDeclsForDisplay(M, Decls);
18761877
for (auto D : Decls) {
18771878
if (Ctx.shouldIgnore(D))
18781879
continue;

lib/AST/ASTPrinter.cpp

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1769,6 +1769,24 @@ bool ShouldPrintChecker::shouldPrint(const Pattern *P,
17691769
return ShouldPrint;
17701770
}
17711771

1772+
bool isNonSendableExtension(const Decl *D) {
1773+
ASTContext &ctx = D->getASTContext();
1774+
1775+
const ExtensionDecl *ED = dyn_cast<ExtensionDecl>(D);
1776+
if (!ED || !ED->getAttrs().isUnavailable(ctx))
1777+
return false;
1778+
1779+
auto nonSendable =
1780+
ED->getExtendedNominal()->getAttrs().getEffectiveSendableAttr();
1781+
if (!isa_and_nonnull<NonSendableAttr>(nonSendable))
1782+
return false;
1783+
1784+
// GetImplicitSendableRequest::evaluate() creates its extension with the
1785+
// attribute's AtLoc, so this is a good way to quickly check if the extension
1786+
// was synthesized for an '@_nonSendable' attribute.
1787+
return ED->getLocFromSource() == nonSendable->AtLoc;
1788+
}
1789+
17721790
bool ShouldPrintChecker::shouldPrint(const Decl *D,
17731791
const PrintOptions &Options) {
17741792
#if SWIFT_BUILD_ONLY_SYNTAXPARSERLIB
@@ -1791,15 +1809,18 @@ bool ShouldPrintChecker::shouldPrint(const Decl *D,
17911809
return false;
17921810
}
17931811

1794-
if (Options.SkipImplicit && D->isImplicit()) {
1795-
const auto &IgnoreList = Options.TreatAsExplicitDeclList;
1796-
if (std::find(IgnoreList.begin(), IgnoreList.end(), D) == IgnoreList.end())
1812+
// Optionally skip these checks for extensions synthesized for '@_nonSendable'
1813+
if (!Options.AlwaysPrintNonSendableExtensions || !isNonSendableExtension(D)) {
1814+
if (Options.SkipImplicit && D->isImplicit()) {
1815+
const auto &IgnoreList = Options.TreatAsExplicitDeclList;
1816+
if (!llvm::is_contained(IgnoreList, D))
17971817
return false;
1798-
}
1818+
}
17991819

1800-
if (Options.SkipUnavailable &&
1801-
D->getAttrs().isUnavailable(D->getASTContext()))
1802-
return false;
1820+
if (Options.SkipUnavailable &&
1821+
D->getAttrs().isUnavailable(D->getASTContext()))
1822+
return false;
1823+
}
18031824

18041825
if (Options.ExplodeEnumCaseDecls) {
18051826
if (isa<EnumElementDecl>(D))
@@ -5906,6 +5927,7 @@ swift::getInheritedForPrinting(
59065927
// Collect synthesized conformances.
59075928
auto &ctx = decl->getASTContext();
59085929
llvm::SetVector<ProtocolDecl *> protocols;
5930+
llvm::TinyPtrVector<ProtocolDecl *> uncheckedProtocols;
59095931
for (auto attr : decl->getAttrs().getAttributes<SynthesizedProtocolAttr>()) {
59105932
if (auto *proto = ctx.getProtocol(attr->getProtocolKind())) {
59115933
// The SerialExecutor conformance is only synthesized on the root
@@ -5918,11 +5940,14 @@ swift::getInheritedForPrinting(
59185940
cast<EnumDecl>(decl)->hasRawType())
59195941
continue;
59205942
protocols.insert(proto);
5943+
if (attr->isUnchecked())
5944+
uncheckedProtocols.push_back(proto);
59215945
}
59225946
}
59235947

59245948
for (size_t i = 0; i < protocols.size(); i++) {
59255949
auto proto = protocols[i];
5950+
bool isUnchecked = llvm::is_contained(uncheckedProtocols, proto);
59265951

59275952
if (!options.shouldPrint(proto)) {
59285953
// If private stdlib protocols are skipped and this is a private stdlib
@@ -5933,12 +5958,14 @@ swift::getInheritedForPrinting(
59335958
proto->isPrivateStdlibDecl(!options.SkipUnderscoredStdlibProtocols)) {
59345959
auto inheritedProtocols = proto->getInheritedProtocols();
59355960
protocols.insert(inheritedProtocols.begin(), inheritedProtocols.end());
5961+
if (isUnchecked)
5962+
copy(inheritedProtocols, std::back_inserter(uncheckedProtocols));
59365963
}
59375964
continue;
59385965
}
59395966

59405967
Results.push_back({TypeLoc::withoutLoc(proto->getDeclaredInterfaceType()),
5941-
/*isUnchecked=*/false});
5968+
isUnchecked});
59425969
}
59435970
}
59445971

lib/AST/Attr.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,8 @@ DeclAttrKind DeclAttribute::getAttrKindFromString(StringRef Str) {
131131

132132
/// Returns true if this attribute can appear on the specified decl.
133133
bool DeclAttribute::canAttributeAppearOnDecl(DeclAttrKind DK, const Decl *D) {
134+
if ((getOptions(DK) & OnAnyClangDecl) && D->hasClangNode())
135+
return true;
134136
return canAttributeAppearOnDeclKind(DK, D->getKind());
135137
}
136138

@@ -699,6 +701,13 @@ void DeclAttributes::print(ASTPrinter &Printer, const PrintOptions &Options,
699701
if (Options.excludeAttrKind(DA->getKind()))
700702
continue;
701703

704+
// If this attribute is only allowed because this is a Clang decl, don't
705+
// print it.
706+
if (D && D->hasClangNode()
707+
&& !DeclAttribute::canAttributeAppearOnDeclKind(
708+
DA->getKind(), D->getKind()))
709+
continue;
710+
702711
// Be careful not to coalesce `@available(swift 5)` with other short
703712
// `available' attributes.
704713
if (auto *availableAttr = dyn_cast<AvailableAttr>(DA)) {
@@ -2102,6 +2111,23 @@ TypeSequenceAttr *TypeSequenceAttr::create(ASTContext &Ctx, SourceLoc atLoc,
21022111
return new (mem) TypeSequenceAttr(atLoc, range);
21032112
}
21042113

2114+
const DeclAttribute *
2115+
DeclAttributes::getEffectiveSendableAttr() const {
2116+
const NonSendableAttr *assumedAttr = nullptr;
2117+
2118+
for (auto attr : getAttributes<NonSendableAttr>()) {
2119+
if (attr->Specificity == NonSendableKind::Specific)
2120+
return attr;
2121+
if (!assumedAttr)
2122+
assumedAttr = attr;
2123+
}
2124+
2125+
if (auto sendableAttr = getAttribute<SendableAttr>())
2126+
return sendableAttr;
2127+
2128+
return assumedAttr;
2129+
}
2130+
21052131
void swift::simple_display(llvm::raw_ostream &out, const DeclAttribute *attr) {
21062132
if (attr)
21072133
attr->print(out);

0 commit comments

Comments
 (0)