mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Print Sendable conformances for clang types
This commit is contained in:
@@ -235,6 +235,10 @@ struct PrintOptions {
|
||||
/// Whether to print unavailable parts of the AST.
|
||||
bool SkipUnavailable = false;
|
||||
|
||||
/// Whether to print synthesized extensions created by '@_nonSendable', even
|
||||
/// if SkipImplicit or SkipUnavailable is set.
|
||||
bool AlwaysPrintNonSendableExtensions = true;
|
||||
|
||||
bool SkipSwiftPrivateClangDecls = false;
|
||||
|
||||
/// Whether to skip internal stdlib declarations.
|
||||
@@ -667,6 +671,7 @@ struct PrintOptions {
|
||||
PO.ShouldQualifyNestedDeclarations = QualifyNestedDeclarations::TypesOnly;
|
||||
PO.PrintParameterSpecifiers = true;
|
||||
PO.SkipImplicit = true;
|
||||
PO.AlwaysPrintNonSendableExtensions = false;
|
||||
PO.AlwaysTryPrintParameterLabels = true;
|
||||
return PO;
|
||||
}
|
||||
|
||||
@@ -1769,6 +1769,24 @@ bool ShouldPrintChecker::shouldPrint(const Pattern *P,
|
||||
return ShouldPrint;
|
||||
}
|
||||
|
||||
bool isNonSendableExtension(const Decl *D) {
|
||||
ASTContext &ctx = D->getASTContext();
|
||||
|
||||
const ExtensionDecl *ED = dyn_cast<ExtensionDecl>(D);
|
||||
if (!ED || !ED->getAttrs().isUnavailable(ctx))
|
||||
return false;
|
||||
|
||||
auto nonSendable =
|
||||
ED->getExtendedNominal()->getAttrs().getEffectiveSendableAttr();
|
||||
if (!isa_and_nonnull<NonSendableAttr>(nonSendable))
|
||||
return false;
|
||||
|
||||
// GetImplicitSendableRequest::evaluate() creates its extension with the
|
||||
// attribute's AtLoc, so this is a good way to quickly check if the extension
|
||||
// was synthesized for an '@_nonSendable' attribute.
|
||||
return ED->getLocFromSource() == nonSendable->AtLoc;
|
||||
}
|
||||
|
||||
bool ShouldPrintChecker::shouldPrint(const Decl *D,
|
||||
const PrintOptions &Options) {
|
||||
#if SWIFT_BUILD_ONLY_SYNTAXPARSERLIB
|
||||
@@ -1791,15 +1809,18 @@ bool ShouldPrintChecker::shouldPrint(const Decl *D,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Options.SkipImplicit && D->isImplicit()) {
|
||||
const auto &IgnoreList = Options.TreatAsExplicitDeclList;
|
||||
if (std::find(IgnoreList.begin(), IgnoreList.end(), D) == IgnoreList.end())
|
||||
// Optionally skip these checks for extensions synthesized for '@_nonSendable'
|
||||
if (!Options.AlwaysPrintNonSendableExtensions || !isNonSendableExtension(D)) {
|
||||
if (Options.SkipImplicit && D->isImplicit()) {
|
||||
const auto &IgnoreList = Options.TreatAsExplicitDeclList;
|
||||
if (!llvm::is_contained(IgnoreList, D))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (Options.SkipUnavailable &&
|
||||
D->getAttrs().isUnavailable(D->getASTContext()))
|
||||
return false;
|
||||
if (Options.SkipUnavailable &&
|
||||
D->getAttrs().isUnavailable(D->getASTContext()))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Options.ExplodeEnumCaseDecls) {
|
||||
if (isa<EnumElementDecl>(D))
|
||||
|
||||
@@ -909,6 +909,28 @@ SourceFile::getExternalRawLocsForDecl(const Decl *D) const {
|
||||
void ModuleDecl::getDisplayDecls(SmallVectorImpl<Decl*> &Results) const {
|
||||
// FIXME: Should this do extra access control filtering?
|
||||
FORWARD(getDisplayDecls, (Results));
|
||||
|
||||
// Force Sendable on all types, which might synthesize some extensions.
|
||||
// FIXME: We can remove this if @_nonSendable stops creating extensions.
|
||||
for (auto result : Results) {
|
||||
if (auto NTD = dyn_cast<NominalTypeDecl>(result))
|
||||
(void)swift::isSendableType(const_cast<ModuleDecl *>(this),
|
||||
NTD->getDeclaredInterfaceType());
|
||||
}
|
||||
|
||||
// Re-add anything from synthesized file units...
|
||||
auto oldCutoff = Results.size();
|
||||
for (auto file : getFiles())
|
||||
if (auto synthFile = dyn_cast<SynthesizedFileUnit>(file))
|
||||
synthFile->getDisplayDecls(Results);
|
||||
|
||||
// And then remove anything that was already in the results.
|
||||
auto oldResults = makeArrayRef(Results).take_front(oldCutoff);
|
||||
auto uniqueEnd = std::remove_if(Results.begin() + oldCutoff, Results.end(),
|
||||
[&](auto result) {
|
||||
return llvm::is_contained(oldResults, result);
|
||||
});
|
||||
Results.erase(uniqueEnd, Results.end());
|
||||
}
|
||||
|
||||
ProtocolConformanceRef
|
||||
|
||||
@@ -4004,6 +4004,8 @@ NormalProtocolConformance *GetImplicitSendableRequest::evaluate(
|
||||
auto inherits = ctx.AllocateCopy(makeArrayRef(
|
||||
InheritedEntry(TypeLoc::withoutLoc(proto->getDeclaredInterfaceType()),
|
||||
/*isUnchecked*/true)));
|
||||
// If you change the use of AtLoc in the ExtensionDecl, make sure you
|
||||
// update isNonSendableExtension() in ASTPrinter.
|
||||
auto extension = ExtensionDecl::create(ctx, attrMakingUnavailable->AtLoc,
|
||||
nullptr, inherits,
|
||||
nominal->getModuleScopeContext(),
|
||||
|
||||
@@ -23,10 +23,17 @@ import _Concurrency
|
||||
// CHECK-SAME: @unchecked Sendable
|
||||
|
||||
// CHECK-LABEL: class NonSendableClass
|
||||
// CHECK: @available(*, unavailable)
|
||||
// CHECK-NEXT: extension NonSendableClass : @unchecked Sendable {
|
||||
|
||||
// CHECK-LABEL: class AuditedSendable :
|
||||
// CHECK-SAME: @unchecked Sendable
|
||||
|
||||
// CHECK-LABEL: class AuditedNonSendable
|
||||
// CHECK: @available(*, unavailable)
|
||||
// CHECK-NEXT: extension AuditedNonSendable : @unchecked Sendable {
|
||||
|
||||
// CHECK-LABEL: class AuditedBoth
|
||||
// CHECK: @available(*, unavailable)
|
||||
// CHECK-NEXT: extension AuditedBoth : @unchecked Sendable {
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
// RUN: %target-swift-frontend -emit-module -DPROTOCOL_LIB -DAFTER %s -module-name protocol_lib -emit-module-path %t/protocol_lib.swiftmodule
|
||||
|
||||
// The conforming library's types should still deserialize.
|
||||
// RUN: %target-swift-ide-test -print-module -source-filename %s -module-to-print conforms_lib -I %t | %FileCheck %s
|
||||
// RUN: %target-swift-ide-test -print-module -source-filename %s -module-to-print conforms_lib -I %t -allow-compiler-errors | %FileCheck %s
|
||||
|
||||
// Protocols that use a missing protocol have to disappear (see the FileCheck
|
||||
// lines).
|
||||
|
||||
Reference in New Issue
Block a user