Skip to content

Commit 128d6e1

Browse files
authored
Merge pull request swiftlang#42072 from xedin/type-checker-part-of-multi-opaque
[TypeChecker] Allow opaque to have multiple underlying types based on availability
2 parents 8bbee9c + c143c55 commit 128d6e1

File tree

10 files changed

+422
-84
lines changed

10 files changed

+422
-84
lines changed

include/swift/AST/Decl.h

Lines changed: 68 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
#include "swift/AST/AccessScope.h"
2121
#include "swift/AST/Attr.h"
22+
#include "swift/AST/Availability.h"
2223
#include "swift/AST/CaptureInfo.h"
2324
#include "swift/AST/ClangNode.h"
2425
#include "swift/AST/ConcreteDeclRef.h"
@@ -2786,6 +2787,12 @@ class OpaqueTypeDecl final :
27862787
private llvm::TrailingObjects<OpaqueTypeDecl, OpaqueReturnTypeRepr *> {
27872788
friend TrailingObjects;
27882789

2790+
public:
2791+
/// A set of substitutions that represents a possible underlying type iff
2792+
/// associated set of availability conditions is met.
2793+
class ConditionallyAvailableSubstitutions;
2794+
2795+
private:
27892796
/// The original declaration that "names" the opaque type. Although a specific
27902797
/// opaque type cannot be explicitly named, oapque types can propagate
27912798
/// arbitrarily through expressions, so we need to know *which* opaque type is
@@ -2805,8 +2812,17 @@ class OpaqueTypeDecl final :
28052812
/// expressed as a SubstitutionMap for the opaque interface generic signature.
28062813
/// This maps types in the interface generic signature to the outer generic
28072814
/// signature of the original declaration.
2808-
Optional<SubstitutionMap> UnderlyingTypeSubstitutions;
2809-
2815+
Optional<SubstitutionMap> UniqueUnderlyingType;
2816+
2817+
/// A set of substitutions which are used based on the availability
2818+
/// checks performed at runtime. This set of only populated if there
2819+
/// is no single unique underlying type for this opaque type declaration.
2820+
///
2821+
/// It always contains one or more conditionally available substitutions
2822+
/// followed by a universally available type used as a fallback.
2823+
Optional<MutableArrayRef<ConditionallyAvailableSubstitutions *>>
2824+
ConditionallyAvailableTypes = None;
2825+
28102826
mutable Identifier OpaqueReturnTypeIdentifier;
28112827

28122828
OpaqueTypeDecl(ValueDecl *NamingDecl, GenericParamList *GenericParams,
@@ -2882,16 +2898,25 @@ class OpaqueTypeDecl final :
28822898
}
28832899

28842900
/// The substitutions that map the generic parameters of the opaque type to
2885-
/// their underlying types, when that information is known.
2886-
Optional<SubstitutionMap> getUnderlyingTypeSubstitutions() const {
2887-
return UnderlyingTypeSubstitutions;
2901+
/// the unique underlying types, when that information is known.
2902+
Optional<SubstitutionMap> getUniqueUnderlyingTypeSubstitutions() const {
2903+
return UniqueUnderlyingType;
28882904
}
28892905

2890-
void setUnderlyingTypeSubstitutions(SubstitutionMap subs) {
2891-
assert(!UnderlyingTypeSubstitutions.hasValue() && "resetting underlying type?!");
2892-
UnderlyingTypeSubstitutions = subs;
2906+
void setUniqueUnderlyingTypeSubstitutions(SubstitutionMap subs) {
2907+
assert(!UniqueUnderlyingType.hasValue() && "resetting underlying type?!");
2908+
UniqueUnderlyingType = subs;
28932909
}
2894-
2910+
2911+
ArrayRef<ConditionallyAvailableSubstitutions *>
2912+
getConditionallyAvailableSubstitutions() const {
2913+
assert(ConditionallyAvailableTypes);
2914+
return ConditionallyAvailableTypes.getValue();
2915+
}
2916+
2917+
void setConditionallyAvailableSubstitutions(
2918+
ArrayRef<ConditionallyAvailableSubstitutions *> substitutions);
2919+
28952920
// Opaque type decls are currently always implicit
28962921
SourceRange getSourceRange() const { return SourceRange(); }
28972922

@@ -2910,6 +2935,40 @@ class OpaqueTypeDecl final :
29102935
return classof(D);
29112936
return false;
29122937
}
2938+
2939+
class ConditionallyAvailableSubstitutions final
2940+
: private llvm::TrailingObjects<ConditionallyAvailableSubstitutions,
2941+
VersionRange> {
2942+
friend TrailingObjects;
2943+
2944+
unsigned NumAvailabilityConditions;
2945+
2946+
SubstitutionMap Substitutions;
2947+
2948+
/// A type with limited availability described by the provided set
2949+
/// of availability conditions (with `and` relationship).
2950+
ConditionallyAvailableSubstitutions(
2951+
ArrayRef<VersionRange> availabilityContext,
2952+
SubstitutionMap substitutions)
2953+
: NumAvailabilityConditions(availabilityContext.size()),
2954+
Substitutions(substitutions) {
2955+
assert(!availabilityContext.empty());
2956+
std::uninitialized_copy(availabilityContext.begin(),
2957+
availabilityContext.end(),
2958+
getTrailingObjects<VersionRange>());
2959+
}
2960+
2961+
public:
2962+
ArrayRef<VersionRange> getAvailability() const {
2963+
return {getTrailingObjects<VersionRange>(), NumAvailabilityConditions};
2964+
}
2965+
2966+
SubstitutionMap getSubstitutions() const { return Substitutions; }
2967+
2968+
static ConditionallyAvailableSubstitutions *
2969+
get(ASTContext &ctx, ArrayRef<VersionRange> availabilityContext,
2970+
SubstitutionMap substitutions);
2971+
};
29132972
};
29142973

29152974
/// TypeAliasDecl - This is a declaration of a typealias, for example:

lib/AST/ASTDumper.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -572,7 +572,7 @@ namespace {
572572
<< OTD->getDeclaredInterfaceType().getString();
573573
OS << " in "
574574
<< OTD->getOpaqueInterfaceGenericSignature()->getAsString();
575-
if (auto underlyingSubs = OTD->getUnderlyingTypeSubstitutions()) {
575+
if (auto underlyingSubs = OTD->getUniqueUnderlyingTypeSubstitutions()) {
576576
OS << " underlying:\n";
577577
SmallPtrSet<const ProtocolConformance *, 4> Dumped;
578578
dumpSubstitutionMapRec(*underlyingSubs, OS,

lib/AST/Decl.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8173,6 +8173,23 @@ Identifier OpaqueTypeDecl::getOpaqueReturnTypeIdentifier() const {
81738173
return OpaqueReturnTypeIdentifier;
81748174
}
81758175

8176+
void OpaqueTypeDecl::setConditionallyAvailableSubstitutions(
8177+
ArrayRef<ConditionallyAvailableSubstitutions *> substitutions) {
8178+
assert(!ConditionallyAvailableTypes &&
8179+
"resetting conditionally available substitutions?!");
8180+
ConditionallyAvailableTypes = getASTContext().AllocateCopy(substitutions);
8181+
}
8182+
8183+
OpaqueTypeDecl::ConditionallyAvailableSubstitutions *
8184+
OpaqueTypeDecl::ConditionallyAvailableSubstitutions::get(
8185+
ASTContext &ctx, ArrayRef<VersionRange> availabilityContext,
8186+
SubstitutionMap substitutions) {
8187+
auto size = totalSizeToAlloc<VersionRange>(availabilityContext.size());
8188+
auto mem = ctx.Allocate(size, alignof(ConditionallyAvailableSubstitutions));
8189+
return new (mem)
8190+
ConditionallyAvailableSubstitutions(availabilityContext, substitutions);
8191+
}
8192+
81768193
bool AbstractFunctionDecl::hasInlinableBodyText() const {
81778194
switch (getBodyKind()) {
81788195
case BodyKind::Deserialized:

lib/AST/Type.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3638,7 +3638,7 @@ operator()(SubstitutableType *maybeOpaqueType) const {
36383638
return maybeOpaqueType;
36393639
}
36403640

3641-
auto subs = opaqueRoot->getDecl()->getUnderlyingTypeSubstitutions();
3641+
auto subs = opaqueRoot->getDecl()->getUniqueUnderlyingTypeSubstitutions();
36423642
// If the body of the opaque decl providing decl has not been type checked we
36433643
// don't have a underlying subsitution.
36443644
if (!subs.hasValue())
@@ -3749,7 +3749,7 @@ operator()(CanType maybeOpaqueType, Type replacementType,
37493749
return abstractRef;
37503750
}
37513751

3752-
auto subs = opaqueRoot->getDecl()->getUnderlyingTypeSubstitutions();
3752+
auto subs = opaqueRoot->getDecl()->getUniqueUnderlyingTypeSubstitutions();
37533753
// If the body of the opaque decl providing decl has not been type checked we
37543754
// don't have a underlying subsitution.
37553755
if (!subs.hasValue())

lib/IRGen/GenMeta.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2040,7 +2040,7 @@ namespace {
20402040
void addUnderlyingTypeAndConformances() {
20412041
auto sig = O->getOpaqueInterfaceGenericSignature();
20422042
auto contextSig = O->getGenericSignature().getCanonicalSignature();
2043-
auto subs = *O->getUnderlyingTypeSubstitutions();
2043+
auto subs = *O->getUniqueUnderlyingTypeSubstitutions();
20442044

20452045
// Add the underlying types for each generic parameter.
20462046
for (auto genericParam : O->getOpaqueGenericParams()) {

lib/Sema/CSApply.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8442,7 +8442,7 @@ static Optional<SolutionApplicationTarget> applySolutionToInitialization(
84428442
return expr;
84438443
});
84448444

8445-
opaque->setUnderlyingTypeSubstitutions(substitutions);
8445+
opaque->setUniqueUnderlyingTypeSubstitutions(substitutions);
84468446
}
84478447
}
84488448

0 commit comments

Comments
 (0)