Skip to content

Commit 67311e5

Browse files
committed
[AST] Augment OpaqueTypeDecl to store conditionally available alternatives
In preparation to support cases like this: ``` func test() -> some P { if #available(...) { return X() } return Y() } ``` where both `X` and `Y` conform to `P` but are different types.
1 parent d00ea98 commit 67311e5

File tree

2 files changed

+104
-2
lines changed

2 files changed

+104
-2
lines changed

include/swift/AST/Decl.h

Lines changed: 84 additions & 2 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,40 @@ 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:
2796+
/// A container to keep a set of conditional available underlying type
2797+
/// substitutions with their availability conditions.
2798+
class ConditionalAlternatives final
2799+
: private llvm::TrailingObjects<ConditionalAlternatives,
2800+
ConditionallyAvailableSubstitutions *> {
2801+
friend TrailingObjects;
2802+
2803+
unsigned NumAlternatives;
2804+
2805+
ConditionalAlternatives(
2806+
ArrayRef<ConditionallyAvailableSubstitutions *> underlyingTypes)
2807+
: NumAlternatives(underlyingTypes.size()) {
2808+
std::uninitialized_copy(
2809+
underlyingTypes.begin(), underlyingTypes.end(),
2810+
getTrailingObjects<ConditionallyAvailableSubstitutions *>());
2811+
}
2812+
2813+
public:
2814+
ArrayRef<ConditionallyAvailableSubstitutions *> getAlternatives() const {
2815+
return {getTrailingObjects<ConditionallyAvailableSubstitutions *>(),
2816+
NumAlternatives};
2817+
}
2818+
2819+
static ConditionalAlternatives *
2820+
get(ASTContext &ctx,
2821+
ArrayRef<ConditionallyAvailableSubstitutions *> underlyingTypes);
2822+
};
2823+
27892824
/// The original declaration that "names" the opaque type. Although a specific
27902825
/// opaque type cannot be explicitly named, oapque types can propagate
27912826
/// arbitrarily through expressions, so we need to know *which* opaque type is
@@ -2806,7 +2841,12 @@ class OpaqueTypeDecl final :
28062841
/// This maps types in the interface generic signature to the outer generic
28072842
/// signature of the original declaration.
28082843
Optional<SubstitutionMap> UnderlyingTypeSubstitutions;
2809-
2844+
2845+
/// A set of substitutions which are used based on the availability
2846+
/// checks performed at runtime. This set of only populated if there
2847+
/// is no single unique underlying type for this opaque type declaration.
2848+
ConditionalAlternatives *ConditionallyAvailableTypes = nullptr;
2849+
28102850
mutable Identifier OpaqueReturnTypeIdentifier;
28112851

28122852
OpaqueTypeDecl(ValueDecl *NamingDecl, GenericParamList *GenericParams,
@@ -2891,7 +2931,15 @@ class OpaqueTypeDecl final :
28912931
assert(!UnderlyingTypeSubstitutions.hasValue() && "resetting underlying type?!");
28922932
UnderlyingTypeSubstitutions = subs;
28932933
}
2894-
2934+
t
2935+
void setConditionallyAvailableSubstitutions(
2936+
ArrayRef<ConditionallyAvailableSubstitutions *> substitutions) {
2937+
assert(!ConditionallyAvailableTypes &&
2938+
"resetting conditional substitutions?!");
2939+
ConditionallyAvailableTypes =
2940+
ConditionalAlternatives::get(getASTContext(), substitutions);
2941+
}
2942+
28952943
// Opaque type decls are currently always implicit
28962944
SourceRange getSourceRange() const { return SourceRange(); }
28972945

@@ -2910,6 +2958,40 @@ class OpaqueTypeDecl final :
29102958
return classof(D);
29112959
return false;
29122960
}
2961+
2962+
class ConditionallyAvailableSubstitutions final
2963+
: private llvm::TrailingObjects<ConditionallyAvailableSubstitutions,
2964+
VersionRange> {
2965+
friend TrailingObjects;
2966+
2967+
unsigned NumAvailabilityConditions;
2968+
2969+
SubstitutionMap Substitutions;
2970+
2971+
/// A type with limited availability described by the provided set
2972+
/// of availability conditions (with `and` relationship).
2973+
ConditionallyAvailableSubstitutions(
2974+
ArrayRef<VersionRange> availabilityContext,
2975+
SubstitutionMap substitutions)
2976+
: NumAvailabilityConditions(availabilityContext.size()),
2977+
Substitutions(substitutions) {
2978+
assert(!availabilityContext.empty());
2979+
std::uninitialized_copy(availabilityContext.begin(),
2980+
availabilityContext.end(),
2981+
getTrailingObjects<VersionRange>());
2982+
}
2983+
2984+
public:
2985+
ArrayRef<VersionRange> getAvailability() const {
2986+
return {getTrailingObjects<VersionRange>(), NumAvailabilityConditions};
2987+
}
2988+
2989+
SubstitutionMap getSubstitutions() const { return Substitutions; }
2990+
2991+
static ConditionallyAvailableSubstitutions *
2992+
get(ASTContext &ctx, ArrayRef<VersionRange> availabilityContext,
2993+
SubstitutionMap substitutions);
2994+
};
29132995
};
29142996

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

lib/AST/Decl.cpp

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

8176+
OpaqueTypeDecl::ConditionalAlternatives *
8177+
OpaqueTypeDecl::ConditionalAlternatives::get(
8178+
ASTContext &ctx,
8179+
ArrayRef<ConditionallyAvailableSubstitutions *> underlyingTypes) {
8180+
auto size = totalSizeToAlloc<ConditionallyAvailableSubstitutions *>(
8181+
underlyingTypes.size());
8182+
auto mem = ctx.Allocate(size, alignof(ConditionalAlternatives));
8183+
return new (mem) ConditionalAlternatives(underlyingTypes);
8184+
}
8185+
8186+
OpaqueTypeDecl::ConditionallyAvailableSubstitutions *
8187+
OpaqueTypeDecl::ConditionallyAvailableSubstitutions::get(
8188+
ASTContext &ctx, ArrayRef<VersionRange> availabilityContext,
8189+
SubstitutionMap substitutions) {
8190+
auto size = totalSizeToAlloc<VersionRange>(availabilityContext.size());
8191+
auto mem = ctx.Allocate(size, alignof(ConditionallyAvailableSubstitutions));
8192+
return new (mem)
8193+
ConditionallyAvailableSubstitutions(availabilityContext, substitutions);
8194+
}
8195+
81768196
bool AbstractFunctionDecl::hasInlinableBodyText() const {
81778197
switch (getBodyKind()) {
81788198
case BodyKind::Deserialized:

0 commit comments

Comments
 (0)