@@ -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+
17721790bool 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
0 commit comments