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.
|
/// Whether to print unavailable parts of the AST.
|
||||||
bool SkipUnavailable = false;
|
bool SkipUnavailable = false;
|
||||||
|
|
||||||
|
/// Whether to print synthesized extensions created by '@_nonSendable', even
|
||||||
|
/// if SkipImplicit or SkipUnavailable is set.
|
||||||
|
bool AlwaysPrintNonSendableExtensions = true;
|
||||||
|
|
||||||
bool SkipSwiftPrivateClangDecls = false;
|
bool SkipSwiftPrivateClangDecls = false;
|
||||||
|
|
||||||
/// Whether to skip internal stdlib declarations.
|
/// Whether to skip internal stdlib declarations.
|
||||||
@@ -667,6 +671,7 @@ struct PrintOptions {
|
|||||||
PO.ShouldQualifyNestedDeclarations = QualifyNestedDeclarations::TypesOnly;
|
PO.ShouldQualifyNestedDeclarations = QualifyNestedDeclarations::TypesOnly;
|
||||||
PO.PrintParameterSpecifiers = true;
|
PO.PrintParameterSpecifiers = true;
|
||||||
PO.SkipImplicit = true;
|
PO.SkipImplicit = true;
|
||||||
|
PO.AlwaysPrintNonSendableExtensions = false;
|
||||||
PO.AlwaysTryPrintParameterLabels = true;
|
PO.AlwaysTryPrintParameterLabels = true;
|
||||||
return PO;
|
return PO;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1769,6 +1769,24 @@ bool ShouldPrintChecker::shouldPrint(const Pattern *P,
|
|||||||
return ShouldPrint;
|
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,
|
bool ShouldPrintChecker::shouldPrint(const Decl *D,
|
||||||
const PrintOptions &Options) {
|
const PrintOptions &Options) {
|
||||||
#if SWIFT_BUILD_ONLY_SYNTAXPARSERLIB
|
#if SWIFT_BUILD_ONLY_SYNTAXPARSERLIB
|
||||||
@@ -1791,15 +1809,18 @@ bool ShouldPrintChecker::shouldPrint(const Decl *D,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Options.SkipImplicit && D->isImplicit()) {
|
// Optionally skip these checks for extensions synthesized for '@_nonSendable'
|
||||||
const auto &IgnoreList = Options.TreatAsExplicitDeclList;
|
if (!Options.AlwaysPrintNonSendableExtensions || !isNonSendableExtension(D)) {
|
||||||
if (std::find(IgnoreList.begin(), IgnoreList.end(), D) == IgnoreList.end())
|
if (Options.SkipImplicit && D->isImplicit()) {
|
||||||
|
const auto &IgnoreList = Options.TreatAsExplicitDeclList;
|
||||||
|
if (!llvm::is_contained(IgnoreList, D))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Options.SkipUnavailable &&
|
if (Options.SkipUnavailable &&
|
||||||
D->getAttrs().isUnavailable(D->getASTContext()))
|
D->getAttrs().isUnavailable(D->getASTContext()))
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (Options.ExplodeEnumCaseDecls) {
|
if (Options.ExplodeEnumCaseDecls) {
|
||||||
if (isa<EnumElementDecl>(D))
|
if (isa<EnumElementDecl>(D))
|
||||||
|
|||||||
@@ -909,6 +909,28 @@ SourceFile::getExternalRawLocsForDecl(const Decl *D) const {
|
|||||||
void ModuleDecl::getDisplayDecls(SmallVectorImpl<Decl*> &Results) const {
|
void ModuleDecl::getDisplayDecls(SmallVectorImpl<Decl*> &Results) const {
|
||||||
// FIXME: Should this do extra access control filtering?
|
// FIXME: Should this do extra access control filtering?
|
||||||
FORWARD(getDisplayDecls, (Results));
|
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
|
ProtocolConformanceRef
|
||||||
|
|||||||
@@ -4004,6 +4004,8 @@ NormalProtocolConformance *GetImplicitSendableRequest::evaluate(
|
|||||||
auto inherits = ctx.AllocateCopy(makeArrayRef(
|
auto inherits = ctx.AllocateCopy(makeArrayRef(
|
||||||
InheritedEntry(TypeLoc::withoutLoc(proto->getDeclaredInterfaceType()),
|
InheritedEntry(TypeLoc::withoutLoc(proto->getDeclaredInterfaceType()),
|
||||||
/*isUnchecked*/true)));
|
/*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,
|
auto extension = ExtensionDecl::create(ctx, attrMakingUnavailable->AtLoc,
|
||||||
nullptr, inherits,
|
nullptr, inherits,
|
||||||
nominal->getModuleScopeContext(),
|
nominal->getModuleScopeContext(),
|
||||||
|
|||||||
@@ -23,10 +23,17 @@ import _Concurrency
|
|||||||
// CHECK-SAME: @unchecked Sendable
|
// CHECK-SAME: @unchecked Sendable
|
||||||
|
|
||||||
// CHECK-LABEL: class NonSendableClass
|
// CHECK-LABEL: class NonSendableClass
|
||||||
|
// CHECK: @available(*, unavailable)
|
||||||
|
// CHECK-NEXT: extension NonSendableClass : @unchecked Sendable {
|
||||||
|
|
||||||
// CHECK-LABEL: class AuditedSendable :
|
// CHECK-LABEL: class AuditedSendable :
|
||||||
// CHECK-SAME: @unchecked Sendable
|
// CHECK-SAME: @unchecked Sendable
|
||||||
|
|
||||||
// CHECK-LABEL: class AuditedNonSendable
|
// CHECK-LABEL: class AuditedNonSendable
|
||||||
|
// CHECK: @available(*, unavailable)
|
||||||
|
// CHECK-NEXT: extension AuditedNonSendable : @unchecked Sendable {
|
||||||
|
|
||||||
// CHECK-LABEL: class AuditedBoth
|
// 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
|
// 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.
|
// 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
|
// Protocols that use a missing protocol have to disappear (see the FileCheck
|
||||||
// lines).
|
// lines).
|
||||||
|
|||||||
Reference in New Issue
Block a user