Skip to content

Commit 41502a8

Browse files
Merge pull request #4604 from swiftwasm/main
[pull] swiftwasm from main
2 parents afc8954 + 43ddb88 commit 41502a8

28 files changed

+154
-68
lines changed

include/swift/AST/Module.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -631,11 +631,18 @@ class ModuleDecl
631631
/// might include "missing" conformances, which are synthesized for some
632632
/// protocols as an error recovery mechanism.
633633
///
634+
/// \param allowUnavailable When \c true, the resulting conformance reference
635+
/// might include "unavailable" conformances, meaning that the conformance
636+
/// cannot actually be used and will be diagnosed if used later. Pass
637+
/// \c false here for queries that want to determine whether the conformance
638+
/// is likely to be usable.
639+
///
634640
/// \returns The result of the conformance search, which will be
635641
/// None if the type does not conform to the protocol or contain a
636642
/// ProtocolConformanceRef if it does conform.
637643
ProtocolConformanceRef lookupConformance(Type type, ProtocolDecl *protocol,
638-
bool allowMissing = false);
644+
bool allowMissing = false,
645+
bool allowUnavailable = true);
639646

640647
/// Look for the conformance of the given existential type to the given
641648
/// protocol.

include/swift/AST/ProtocolConformanceRef.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,10 @@ class ProtocolConformanceRef {
106106
return Union.get<ProtocolDecl*>();
107107
}
108108

109+
/// Determine whether this conformance (or a conformance it depends on)
110+
/// involves an always-unavailable conformance.
111+
bool hasUnavailableConformance() const;
112+
109113
/// Determine whether this conformance (or a conformance it depends on)
110114
/// involves a "missing" conformance anywhere. Such conformances
111115
/// cannot be depended on to always exist.

lib/AST/ConformanceLookupTable.cpp

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ DeclContext *ConformanceLookupTable::ConformanceSource::getDeclContext() const {
4141
return getImpliedSource()->Source.getDeclContext();
4242

4343
case ConformanceEntryKind::Synthesized:
44-
return getSynthesizedDecl();
44+
return getSynthesizedDeclContext();
4545
}
4646

4747
llvm_unreachable("Unhandled ConformanceEntryKind in switch.");
@@ -241,6 +241,14 @@ void ConformanceLookupTable::inheritConformances(ClassDecl *classDecl,
241241
auto addInheritedConformance = [&](ConformanceEntry *entry) {
242242
auto protocol = entry->getProtocol();
243243

244+
// Don't add unavailable conformances.
245+
if (auto dc = entry->Source.getDeclContext()) {
246+
if (auto ext = dyn_cast<ExtensionDecl>(dc)) {
247+
if (AvailableAttr::isUnavailable(ext))
248+
return;
249+
}
250+
}
251+
244252
// Don't add redundant conformances here. This is merely an
245253
// optimization; resolveConformances() would zap the duplicates
246254
// anyway.
@@ -812,7 +820,8 @@ DeclContext *ConformanceLookupTable::getConformingContext(
812820
if (superclassTy->is<ErrorType>())
813821
return nullptr;
814822
auto inheritedConformance = module->lookupConformance(
815-
superclassTy, protocol);
823+
superclassTy, protocol, /*allowMissing=*/false,
824+
/*allowUnavailable=*/false);
816825
if (inheritedConformance)
817826
return superclassDecl;
818827
} while ((superclassDecl = superclassDecl->getSuperclassDecl()));
@@ -927,10 +936,11 @@ ConformanceLookupTable::getConformance(NominalTypeDecl *nominal,
927936
return entry->Conformance.get<ProtocolConformance *>();
928937
}
929938

930-
void ConformanceLookupTable::addSynthesizedConformance(NominalTypeDecl *nominal,
931-
ProtocolDecl *protocol) {
939+
void ConformanceLookupTable::addSynthesizedConformance(
940+
NominalTypeDecl *nominal, ProtocolDecl *protocol,
941+
DeclContext *conformanceDC) {
932942
addProtocol(protocol, nominal->getLoc(),
933-
ConformanceSource::forSynthesized(nominal));
943+
ConformanceSource::forSynthesized(conformanceDC));
934944
}
935945

936946
void ConformanceLookupTable::registerProtocolConformance(
@@ -956,7 +966,7 @@ void ConformanceLookupTable::registerProtocolConformance(
956966
auto inherited = dyn_cast<InheritedProtocolConformance>(conformance);
957967
ConformanceSource source
958968
= inherited ? ConformanceSource::forInherited(cast<ClassDecl>(nominal)) :
959-
synthesized ? ConformanceSource::forSynthesized(nominal) :
969+
synthesized ? ConformanceSource::forSynthesized(dc) :
960970
ConformanceSource::forExplicit(dc);
961971

962972
ASTContext &ctx = nominal->getASTContext();

lib/AST/ConformanceLookupTable.h

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -120,10 +120,10 @@ class ConformanceLookupTable : public ASTAllocated<ConformanceLookupTable> {
120120

121121
/// Create a synthesized conformance.
122122
///
123-
/// The given nominal type declaration will get a synthesized
123+
/// The given declaration context (for a type) will get a synthesized
124124
/// conformance to the requested protocol.
125-
static ConformanceSource forSynthesized(NominalTypeDecl *typeDecl) {
126-
return ConformanceSource(typeDecl, ConformanceEntryKind::Synthesized);
125+
static ConformanceSource forSynthesized(DeclContext *dc) {
126+
return ConformanceSource(dc, ConformanceEntryKind::Synthesized);
127127
}
128128

129129
/// Return a new conformance source with the given location of "@unchecked".
@@ -188,9 +188,9 @@ class ConformanceLookupTable : public ASTAllocated<ConformanceLookupTable> {
188188

189189
/// For a synthesized conformance, retrieve the nominal type decl
190190
/// that will receive the conformance.
191-
NominalTypeDecl *getSynthesizedDecl() const {
191+
DeclContext *getSynthesizedDeclContext() const {
192192
assert(getKind() == ConformanceEntryKind::Synthesized);
193-
return static_cast<NominalTypeDecl *>(Storage.getPointer());
193+
return static_cast<DeclContext *>(Storage.getPointer());
194194
}
195195

196196
/// Get the declaration context that this conformance will be
@@ -428,7 +428,8 @@ class ConformanceLookupTable : public ASTAllocated<ConformanceLookupTable> {
428428

429429
/// Add a synthesized conformance to the lookup table.
430430
void addSynthesizedConformance(NominalTypeDecl *nominal,
431-
ProtocolDecl *protocol);
431+
ProtocolDecl *protocol,
432+
DeclContext *conformanceDC);
432433

433434
/// Register an externally-supplied protocol conformance.
434435
void registerProtocolConformance(ProtocolConformance *conformance,

lib/AST/Module.cpp

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1015,7 +1015,9 @@ ModuleDecl::lookupExistentialConformance(Type type, ProtocolDecl *protocol) {
10151015
// If the existential is class-constrained, the class might conform
10161016
// concretely.
10171017
if (auto superclass = layout.explicitSuperclass) {
1018-
if (auto result = lookupConformance(superclass, protocol))
1018+
if (auto result = lookupConformance(
1019+
superclass, protocol, /*allowMissing=*/false,
1020+
/*allowUnavailable=*/false))
10191021
return result;
10201022
}
10211023

@@ -1071,7 +1073,8 @@ ProtocolConformanceRef ProtocolConformanceRef::forMissingOrInvalid(
10711073

10721074
ProtocolConformanceRef ModuleDecl::lookupConformance(Type type,
10731075
ProtocolDecl *protocol,
1074-
bool allowMissing) {
1076+
bool allowMissing,
1077+
bool allowUnavailable) {
10751078
// If we are recursively checking for implicit conformance of a nominal
10761079
// type to Sendable, fail without evaluating this request. This
10771080
// squashes cycles.
@@ -1088,13 +1091,18 @@ ProtocolConformanceRef ModuleDecl::lookupConformance(Type type,
10881091
auto result = evaluateOrDefault(
10891092
getASTContext().evaluator, request, ProtocolConformanceRef::forInvalid());
10901093

1091-
// If we aren't supposed to allow missing conformances through for this
1092-
// protocol, replace the result with an "invalid" result.
1094+
// If we aren't supposed to allow missing conformances but we have one,
1095+
// replace the result with an "invalid" result.
10931096
if (!allowMissing &&
10941097
shouldCreateMissingConformances(type, protocol) &&
10951098
result.hasMissingConformance(this))
10961099
return ProtocolConformanceRef::forInvalid();
10971100

1101+
// If we aren't supposed to allow unavailable conformances but we have one,
1102+
// replace the result with an "invalid" result.
1103+
if (!allowUnavailable && result.hasUnavailableConformance())
1104+
return ProtocolConformanceRef::forInvalid();
1105+
10981106
return result;
10991107
}
11001108

@@ -1248,7 +1256,9 @@ LookupConformanceInModuleRequest::evaluate(
12481256
// able to be resolved by a substitution that makes the archetype
12491257
// concrete.
12501258
if (auto super = archetype->getSuperclass()) {
1251-
if (auto inheritedConformance = mod->lookupConformance(super, protocol)) {
1259+
if (auto inheritedConformance = mod->lookupConformance(
1260+
super, protocol, /*allowMissing=*/false,
1261+
/*allowUnavailable=*/false)) {
12521262
return ProtocolConformanceRef(ctx.getInheritedConformance(
12531263
type, inheritedConformance.getConcrete()));
12541264
}

lib/AST/ProtocolConformance.cpp

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1270,7 +1270,8 @@ void NominalTypeDecl::prepareConformanceTable() const {
12701270
auto addSynthesized = [&](KnownProtocolKind kind) {
12711271
if (auto *proto = getASTContext().getProtocol(kind)) {
12721272
if (protocols.count(proto) == 0) {
1273-
ConformanceTable->addSynthesizedConformance(mutableThis, proto);
1273+
ConformanceTable->addSynthesizedConformance(
1274+
mutableThis, proto, mutableThis);
12741275
protocols.insert(proto);
12751276
}
12761277
}
@@ -1743,6 +1744,28 @@ SourceLoc swift::extractNearestSourceLoc(const ProtocolConformanceRef conformanc
17431744
return SourceLoc();
17441745
}
17451746

1747+
bool ProtocolConformanceRef::hasUnavailableConformance() const {
1748+
// Abstract conformances are never unavailable.
1749+
if (!isConcrete())
1750+
return false;
1751+
1752+
// Check whether this conformance is on an unavailable extension.
1753+
auto concrete = getConcrete();
1754+
auto ext = dyn_cast<ExtensionDecl>(concrete->getDeclContext());
1755+
if (ext && AvailableAttr::isUnavailable(ext))
1756+
return true;
1757+
1758+
// Check the conformances in the substitution map.
1759+
auto module = concrete->getDeclContext()->getParentModule();
1760+
auto subMap = concrete->getSubstitutions(module);
1761+
for (auto subConformance : subMap.getConformances()) {
1762+
if (subConformance.hasUnavailableConformance())
1763+
return true;
1764+
}
1765+
1766+
return false;
1767+
}
1768+
17461769
bool ProtocolConformanceRef::hasMissingConformance(ModuleDecl *module) const {
17471770
return forEachMissingConformance(module,
17481771
[](BuiltinProtocolConformance *builtin) {

lib/AST/RequirementMachine/ConcreteContraction.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -275,8 +275,10 @@ Optional<Type> ConcreteContraction::substTypeParameterRec(
275275
// 'allowMissing' value here is actually irrelevant.
276276
auto conformance = ((*substBaseType)->isTypeParameter()
277277
? ProtocolConformanceRef(proto)
278-
: module->lookupConformance(*substBaseType, proto,
279-
/*allowMissing=*/false));
278+
: module->lookupConformance(
279+
*substBaseType, proto,
280+
/*allowMissing=*/false,
281+
/*allowUnavailable=*/false));
280282

281283
// The base type doesn't conform, in which case the requirement remains
282284
// unsubstituted.
@@ -391,7 +393,7 @@ ConcreteContraction::substRequirement(const Requirement &req) const {
391393

392394
if (!substFirstType->isTypeParameter() &&
393395
!module->lookupConformance(substFirstType, proto,
394-
allowMissing)) {
396+
allowMissing, /*allowUnavailable=*/false)) {
395397
// Handle the case of <T where T : P, T : C> where C is a class and
396398
// C does not conform to P by leaving the conformance requirement
397399
// unsubstituted.

lib/AST/RequirementMachine/ConcreteTypeWitness.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ void PropertyMap::concretizeNestedTypesFromConcreteParent(
156156
auto conformance = module->lookupConformance(concreteType,
157157
const_cast<ProtocolDecl *>(proto),
158158
allowMissing);
159-
if (conformance.isInvalid()) {
159+
if (conformance.isInvalid() || conformance.hasUnavailableConformance()) {
160160
// For superclass rules, it is totally fine to have a signature like:
161161
//
162162
// protocol P {}

lib/PrintAsClang/DeclAndTypePrinter.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -290,8 +290,8 @@ class DeclAndTypePrinter::Implementation
290290
printDocumentationComment(CD);
291291

292292
// This is just for testing, so we check explicitly for the attribute instead
293-
// of asking if the class is weak imported. If the class has availablility,
294-
// we'll print a SWIFT_AVAIALBLE() which implies __attribute__((weak_imported))
293+
// of asking if the class is weak imported. If the class has availability,
294+
// we'll print a SWIFT_AVAILABLE() which implies __attribute__((weak_imported))
295295
// already.
296296
if (CD->getAttrs().hasAttribute<WeakLinkedAttr>())
297297
os << "SWIFT_WEAK_IMPORT\n";

lib/SILOptimizer/Mandatory/PerformanceDiagnostics.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ static bool isEffectFreeArraySemanticCall(SILInstruction *inst) {
9090
bool PerformanceDiagnostics::visitFunction(SILFunction *function,
9191
PerformanceConstraints perfConstr,
9292
LocWithParent *parentLoc) {
93+
if (!function->isDefinition())
94+
return false;
95+
9396
ReachingReturnBlocks rrBlocks(function);
9497
NonErrorHandlingBlocks neBlocks(function);
9598

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 4 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -593,29 +593,6 @@ static void addSendableFixIt(const GenericTypeParamDecl *genericArgument,
593593
}
594594
}
595595

596-
/// Determine whether there is an unavailable conformance here.
597-
static bool hasUnavailableConformance(ProtocolConformanceRef conformance) {
598-
// Abstract conformances are never unavailable.
599-
if (!conformance.isConcrete())
600-
return false;
601-
602-
// Check whether this conformance is on an unavailable extension.
603-
auto concrete = conformance.getConcrete();
604-
auto ext = dyn_cast<ExtensionDecl>(concrete->getDeclContext());
605-
if (ext && AvailableAttr::isUnavailable(ext))
606-
return true;
607-
608-
// Check the conformances in the substitution map.
609-
auto module = concrete->getDeclContext()->getParentModule();
610-
auto subMap = concrete->getSubstitutions(module);
611-
for (auto subConformance : subMap.getConformances()) {
612-
if (hasUnavailableConformance(subConformance))
613-
return true;
614-
}
615-
616-
return false;
617-
}
618-
619596
static bool shouldDiagnoseExistingDataRaces(const DeclContext *dc) {
620597
return contextRequiresStrictConcurrencyChecking(dc, [](const AbstractClosureExpr *) {
621598
return Type();
@@ -913,7 +890,7 @@ bool swift::diagnoseNonSendableTypes(
913890

914891
// FIXME: More detail for unavailable conformances.
915892
auto conformance = TypeChecker::conformsToProtocol(type, proto, module);
916-
if (conformance.isInvalid() || hasUnavailableConformance(conformance)) {
893+
if (conformance.isInvalid() || conformance.hasUnavailableConformance()) {
917894
return diagnoseSingleNonSendableType(type, fromContext, loc, diagnose);
918895
}
919896

@@ -1062,7 +1039,7 @@ namespace {
10621039
return true;
10631040

10641041
// If there is an unavailable conformance here, fail.
1065-
if (hasUnavailableConformance(conformance))
1042+
if (conformance.hasUnavailableConformance())
10661043
return true;
10671044

10681045
// Look for missing Sendable conformances.
@@ -4433,7 +4410,8 @@ ProtocolConformance *GetImplicitSendableRequest::evaluate(
44334410
auto classModule = classDecl->getParentModule();
44344411
if (auto inheritedConformance = TypeChecker::conformsToProtocol(
44354412
classDecl->mapTypeIntoContext(superclass),
4436-
proto, classModule, /*allowMissing=*/false)) {
4413+
proto, classModule, /*allowMissing=*/false,
4414+
/*allowUnavailable=*/false)) {
44374415
inheritedConformance = inheritedConformance
44384416
.mapConformanceOutOfContext();
44394417
if (inheritedConformance.isConcrete()) {

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3389,7 +3389,8 @@ void ConformanceChecker::recordTypeWitness(AssociatedTypeDecl *assocType,
33893389
auto overriddenConformance =
33903390
DC->getParentModule()->lookupConformance(Adoptee,
33913391
overridden->getProtocol(),
3392-
/*allowMissing=*/true);
3392+
/*allowMissing=*/true,
3393+
/*allowUnavailable=*/false);
33933394
if (overriddenConformance.isInvalid() ||
33943395
!overriddenConformance.isConcrete())
33953396
continue;
@@ -5614,9 +5615,10 @@ TypeChecker::containsProtocol(Type T, ProtocolDecl *Proto, ModuleDecl *M,
56145615

56155616
ProtocolConformanceRef
56165617
TypeChecker::conformsToProtocol(Type T, ProtocolDecl *Proto, ModuleDecl *M,
5617-
bool allowMissing) {
5618+
bool allowMissing, bool allowUnavailable) {
56185619
// Look up conformance in the module.
5619-
auto lookupResult = M->lookupConformance(T, Proto, allowMissing);
5620+
auto lookupResult = M->lookupConformance(
5621+
T, Proto, allowMissing, allowUnavailable);
56205622
if (lookupResult.isInvalid()) {
56215623
return ProtocolConformanceRef::forInvalid();
56225624
}

lib/Sema/TypeChecker.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -800,7 +800,8 @@ ProtocolConformanceRef containsProtocol(Type T, ProtocolDecl *Proto,
800800
/// protocol \c Proto, or \c None.
801801
ProtocolConformanceRef conformsToProtocol(Type T, ProtocolDecl *Proto,
802802
ModuleDecl *M,
803-
bool allowMissing = true);
803+
bool allowMissing = true,
804+
bool allowUnavailable = true);
804805

805806
/// Check whether the type conforms to a given known protocol.
806807
bool conformsToKnownProtocol(Type type, KnownProtocolKind protocol,

lib/TBDGen/TBDGen.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ getLinkerPlatformName(OriginallyDefinedInAttr::ActiveVersion Ver) {
269269
return getLinkerPlatformName((uint8_t)getLinkerPlatformId(Ver));
270270
}
271271

272-
/// Find the most relevant introducing version of the decl stack we have visted
272+
/// Find the most relevant introducing version of the decl stack we have visited
273273
/// so far.
274274
static Optional<llvm::VersionTuple>
275275
getInnermostIntroVersion(ArrayRef<Decl*> DeclStack, PlatformKind Platform) {

test/ClangImporter/objc_async.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,3 +374,10 @@ func testSender(
374374
sender.sendPtr(ptr)
375375
sender.sendStringArray(stringArray)
376376
}
377+
378+
// Sendable checking
379+
public struct SomeWrapper<T: AuditedNonSendable> {
380+
public let unit: T
381+
}
382+
383+
extension SomeWrapper: Sendable where T: Sendable {}

0 commit comments

Comments
 (0)