mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Module printing and serialization support for @unchecked Sendable
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
#include "swift/AST/Module.h"
|
||||
#include "swift/AST/ModuleNameLookup.h"
|
||||
#include "swift/AST/ProtocolConformance.h"
|
||||
#include "swift/AST/TypeRepr.h"
|
||||
#include "swift/Basic/STLExtras.h"
|
||||
#include "swift/Frontend/Frontend.h"
|
||||
#include "swift/Frontend/ModuleInterfaceSupport.h"
|
||||
@@ -301,7 +302,7 @@ class InheritedProtocolCollector {
|
||||
|
||||
using AvailableAttrList = TinyPtrVector<const AvailableAttr *>;
|
||||
using ProtocolAndAvailability =
|
||||
std::pair<ProtocolDecl *, AvailableAttrList>;
|
||||
std::tuple<ProtocolDecl *, AvailableAttrList, bool /*isUnchecked*/>;
|
||||
|
||||
/// Protocols that will be included by the ASTPrinter without any extra work.
|
||||
SmallVector<ProtocolDecl *, 8> IncludedProtocols;
|
||||
@@ -338,30 +339,23 @@ class InheritedProtocolCollector {
|
||||
}
|
||||
|
||||
static bool canPrintProtocolTypeNormally(Type type, const Decl *D) {
|
||||
if (!isPublicOrUsableFromInline(type))
|
||||
return false;
|
||||
|
||||
// Extensions and protocols can print marker protocols.
|
||||
if (isa<ExtensionDecl>(D) || isa<ProtocolDecl>(D))
|
||||
return true;
|
||||
|
||||
ExistentialLayout layout = type->getExistentialLayout();
|
||||
for (ProtocolType *protoTy : layout.getProtocols()) {
|
||||
if (protoTy->getDecl()->isMarkerProtocol())
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return isPublicOrUsableFromInline(type);
|
||||
}
|
||||
|
||||
|
||||
static bool isUncheckedConformance(ProtocolConformance *conformance) {
|
||||
if (auto normal = conformance->getRootNormalConformance())
|
||||
return normal->isUnchecked();
|
||||
return false;
|
||||
}
|
||||
|
||||
/// For each type in \p directlyInherited, classify the protocols it refers to
|
||||
/// as included for printing or not, and record them in the appropriate
|
||||
/// vectors.
|
||||
void recordProtocols(ArrayRef<TypeLoc> directlyInherited, const Decl *D,
|
||||
bool skipSynthesized = false) {
|
||||
void recordProtocols(ArrayRef<InheritedEntry> directlyInherited,
|
||||
const Decl *D, bool skipSynthesized = false) {
|
||||
Optional<AvailableAttrList> availableAttrs;
|
||||
|
||||
for (TypeLoc inherited : directlyInherited) {
|
||||
for (InheritedEntry inherited : directlyInherited) {
|
||||
Type inheritedTy = inherited.getType();
|
||||
if (!inheritedTy || !inheritedTy->isExistentialType())
|
||||
continue;
|
||||
@@ -373,7 +367,8 @@ class InheritedProtocolCollector {
|
||||
IncludedProtocols.push_back(protoTy->getDecl());
|
||||
else
|
||||
ExtraProtocols.push_back({protoTy->getDecl(),
|
||||
getAvailabilityAttrs(D, availableAttrs)});
|
||||
getAvailabilityAttrs(D, availableAttrs),
|
||||
inherited.isUnchecked});
|
||||
}
|
||||
// FIXME: This ignores layout constraints, but currently we don't support
|
||||
// any of those besides 'AnyObject'.
|
||||
@@ -391,7 +386,8 @@ class InheritedProtocolCollector {
|
||||
if (conf->getSourceKind() != ConformanceEntryKind::Synthesized)
|
||||
continue;
|
||||
ExtraProtocols.push_back({conf->getProtocol(),
|
||||
getAvailabilityAttrs(D, availableAttrs)});
|
||||
getAvailabilityAttrs(D, availableAttrs),
|
||||
isUncheckedConformance(conf)});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -423,7 +419,7 @@ public:
|
||||
///
|
||||
/// \sa recordProtocols
|
||||
static void collectProtocols(PerTypeMap &map, const Decl *D) {
|
||||
ArrayRef<TypeLoc> directlyInherited;
|
||||
ArrayRef<InheritedEntry> directlyInherited;
|
||||
const NominalTypeDecl *nominal;
|
||||
const IterableDeclContext *memberContext;
|
||||
|
||||
@@ -549,7 +545,10 @@ public:
|
||||
// of a protocol rather than the maximally available case.
|
||||
SmallVector<ProtocolAndAvailability, 16> protocolsToPrint;
|
||||
for (const auto &protoAndAvailability : ExtraProtocols) {
|
||||
protoAndAvailability.first->walkInheritedProtocols(
|
||||
auto proto = std::get<0>(protoAndAvailability);
|
||||
auto availability = std::get<1>(protoAndAvailability);
|
||||
auto isUnchecked = std::get<2>(protoAndAvailability);
|
||||
proto->walkInheritedProtocols(
|
||||
[&](ProtocolDecl *inherited) -> TypeWalker::Action {
|
||||
if (!handledProtocols.insert(inherited).second)
|
||||
return TypeWalker::Action::SkipChildren;
|
||||
@@ -569,7 +568,7 @@ public:
|
||||
if (isPublicOrUsableFromInline(inherited) &&
|
||||
conformanceDeclaredInModule(M, nominal, inherited) &&
|
||||
!M->isImportedImplementationOnly(inherited->getParentModule())) {
|
||||
protocolsToPrint.push_back({inherited, protoAndAvailability.second});
|
||||
protocolsToPrint.push_back({inherited, availability, isUnchecked});
|
||||
return TypeWalker::Action::SkipChildren;
|
||||
}
|
||||
|
||||
@@ -581,15 +580,16 @@ public:
|
||||
|
||||
for (const auto &protoAndAvailability : protocolsToPrint) {
|
||||
StreamPrinter printer(out);
|
||||
ProtocolDecl *proto = protoAndAvailability.first;
|
||||
auto proto = std::get<0>(protoAndAvailability);
|
||||
auto availability = std::get<1>(protoAndAvailability);
|
||||
auto isUnchecked = std::get<2>(protoAndAvailability);
|
||||
|
||||
bool haveFeatureChecks = printOptions.PrintCompatibilityFeatureChecks &&
|
||||
printCompatibilityFeatureChecksPre(printer, proto);
|
||||
|
||||
// FIXME: Shouldn't this be an implicit conversion?
|
||||
TinyPtrVector<const DeclAttribute *> attrs;
|
||||
attrs.insert(attrs.end(), protoAndAvailability.second.begin(),
|
||||
protoAndAvailability.second.end());
|
||||
attrs.insert(attrs.end(), availability.begin(), availability.end());
|
||||
auto spiAttributes = proto->getAttrs().getAttributes<SPIAccessControlAttr>();
|
||||
attrs.insert(attrs.end(), spiAttributes.begin(), spiAttributes.end());
|
||||
DeclAttributes::print(printer, printOptions, attrs);
|
||||
@@ -607,6 +607,9 @@ public:
|
||||
}
|
||||
printer << " : ";
|
||||
|
||||
if (isUnchecked)
|
||||
printer << "@unchecked ";
|
||||
|
||||
proto->getDeclaredInterfaceType()->print(printer, printOptions);
|
||||
|
||||
printer << " {}";
|
||||
|
||||
Reference in New Issue
Block a user