Skip to content

Commit 99a9c02

Browse files
committed
Carry through the ordinal for opaque type declarations.
Generalize the implementation of opaque type declarations to maintain the "ordinal", which represents a particular "some" utterance in a structural opaque type, throughout more of the compiler. The ordinal value for a given "some" matches with the index of the corresponding generic parameter in the opaque type declaration's generic signature. To properly be able to determine the ordinal for a given "some" type representation, retain all of the "some" type representations in the `OpaqueTypeDecl` (using trailing storage), so we can map them to the proper generic parameter and ordinal later on.
1 parent 3892268 commit 99a9c02

File tree

8 files changed

+101
-41
lines changed

8 files changed

+101
-41
lines changed

include/swift/AST/Decl.h

Lines changed: 55 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2699,22 +2699,26 @@ class GenericTypeDecl : public GenericContext, public TypeDecl {
26992699
/// The declared type uses a special kind of archetype type to represent
27002700
/// abstracted types, e.g. `(some P, some Q)` becomes `((opaque archetype 0),
27012701
/// (opaque archetype 1))`.
2702-
class OpaqueTypeDecl : public GenericTypeDecl {
2702+
class OpaqueTypeDecl final :
2703+
public GenericTypeDecl,
2704+
private llvm::TrailingObjects<OpaqueTypeDecl, OpaqueReturnTypeRepr *> {
2705+
friend TrailingObjects;
2706+
27032707
/// The original declaration that "names" the opaque type. Although a specific
27042708
/// opaque type cannot be explicitly named, oapque types can propagate
27052709
/// arbitrarily through expressions, so we need to know *which* opaque type is
27062710
/// propagated.
2707-
ValueDecl *NamingDecl;
2711+
///
2712+
/// The bit indicates whether there are any trailing
2713+
/// OpaqueReturnTypeReprs.
2714+
llvm::PointerIntPair<ValueDecl *, 1>
2715+
NamingDeclAndHasOpaqueReturnTypeRepr;
27082716

27092717
/// The generic signature of the opaque interface to the type. This is the
27102718
/// outer generic signature with added generic parameters representing the
27112719
/// abstracted underlying types.
27122720
GenericSignature OpaqueInterfaceGenericSignature;
27132721

2714-
/// The type repr of the underlying type. Might be null if no source location
2715-
/// is availble, e.g. if this decl was loaded from a serialized module.
2716-
OpaqueReturnTypeRepr *UnderlyingInterfaceRepr;
2717-
27182722
/// The generic parameter that represents the underlying type.
27192723
GenericTypeParamType *UnderlyingInterfaceType;
27202724

@@ -2725,19 +2729,47 @@ class OpaqueTypeDecl : public GenericTypeDecl {
27252729
Optional<SubstitutionMap> UnderlyingTypeSubstitutions;
27262730

27272731
mutable Identifier OpaqueReturnTypeIdentifier;
2728-
2729-
public:
2732+
27302733
OpaqueTypeDecl(ValueDecl *NamingDecl, GenericParamList *GenericParams,
27312734
DeclContext *DC,
27322735
GenericSignature OpaqueInterfaceGenericSignature,
2733-
OpaqueReturnTypeRepr *UnderlyingInterfaceRepr,
2736+
ArrayRef<OpaqueReturnTypeRepr *> OpaqueReturnTypeReprs,
27342737
GenericTypeParamType *UnderlyingInterfaceType);
27352738

2736-
ValueDecl *getNamingDecl() const { return NamingDecl; }
2739+
unsigned getNumOpaqueReturnTypeReprs() const {
2740+
return NamingDeclAndHasOpaqueReturnTypeRepr.getInt()
2741+
? getOpaqueGenericParams().size()
2742+
: 0;
2743+
}
2744+
2745+
size_t numTrailingObjects(OverloadToken<OpaqueReturnTypeRepr *>) const {
2746+
return getNumOpaqueReturnTypeReprs();
2747+
}
2748+
2749+
/// Retrieve the buffer containing the opaque return type
2750+
/// representations that correspond to the opaque generic parameters.
2751+
ArrayRef<OpaqueReturnTypeRepr *> getOpaqueReturnTypeReprs() const {
2752+
return {
2753+
getTrailingObjects<OpaqueReturnTypeRepr *>(),
2754+
getNumOpaqueReturnTypeReprs()
2755+
};
2756+
}
2757+
2758+
public:
2759+
static OpaqueTypeDecl *get(
2760+
ValueDecl *NamingDecl, GenericParamList *GenericParams,
2761+
DeclContext *DC,
2762+
GenericSignature OpaqueInterfaceGenericSignature,
2763+
ArrayRef<OpaqueReturnTypeRepr *> OpaqueReturnTypeReprs,
2764+
GenericTypeParamType *UnderlyingInterfaceType);
2765+
2766+
ValueDecl *getNamingDecl() const {
2767+
return NamingDeclAndHasOpaqueReturnTypeRepr.getPointer();
2768+
}
27372769

27382770
void setNamingDecl(ValueDecl *D) {
2739-
assert(!NamingDecl && "already have naming decl");
2740-
NamingDecl = D;
2771+
assert(!getNamingDecl() && "already have naming decl");
2772+
NamingDeclAndHasOpaqueReturnTypeRepr.setPointer(D);
27412773
}
27422774

27432775
/// Is this opaque type the opaque return type of the given function?
@@ -2754,7 +2786,17 @@ class OpaqueTypeDecl : public GenericTypeDecl {
27542786
GenericSignature getOpaqueInterfaceGenericSignature() const {
27552787
return OpaqueInterfaceGenericSignature;
27562788
}
2757-
2789+
2790+
/// Retrieve the generic parameters that represent the opaque types described by this opaque
2791+
/// type declaration.
2792+
TypeArrayView<GenericTypeParamType> getOpaqueGenericParams() const {
2793+
return OpaqueInterfaceGenericSignature.getInnermostGenericParams();
2794+
}
2795+
2796+
/// The underlying interface type describing the whole opaque type.
2797+
///
2798+
/// FIXME: Structured opaque types will generalize this to an
2799+
/// arbitrary type.
27582800
GenericTypeParamType *getUnderlyingInterfaceType() const {
27592801
return UnderlyingInterfaceType;
27602802
}

include/swift/AST/Types.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5601,10 +5601,7 @@ class OpaqueTypeArchetypeType final : public ArchetypeType,
56015601
/// func foo() -> (some P, some Q)
56025602
///
56035603
/// then the underlying type of `some P` would be ordinal 0, and `some Q` would be ordinal 1.
5604-
unsigned getOrdinal() const {
5605-
// TODO [OPAQUE SUPPORT]: multiple opaque types
5606-
return 0;
5607-
}
5604+
unsigned getOrdinal() const;
56085605

56095606
static void Profile(llvm::FoldingSetNodeID &ID,
56105607
OpaqueTypeDecl *OpaqueDecl,

lib/AST/ASTContext.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4275,9 +4275,7 @@ DependentMemberType *DependentMemberType::get(Type base,
42754275
OpaqueTypeArchetypeType *
42764276
OpaqueTypeArchetypeType::get(OpaqueTypeDecl *Decl, unsigned ordinal,
42774277
SubstitutionMap Substitutions) {
4278-
// TODO [OPAQUE SUPPORT]: multiple opaque types
4279-
assert(ordinal == 0 && "we only support one 'some' type per composite type");
4280-
auto opaqueParamType = Decl->getUnderlyingInterfaceType();
4278+
auto opaqueParamType = Decl->getOpaqueGenericParams()[ordinal];
42814279

42824280
// TODO: We could attempt to preserve type sugar in the substitution map.
42834281
// Currently archetypes are assumed to be always canonical in many places,

lib/AST/ASTDemangler.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -265,11 +265,6 @@ Type ASTBuilder::resolveOpaqueType(NodePointer opaqueDescriptor,
265265
auto opaqueDecl = parentModule->lookupOpaqueResultType(mangledName);
266266
if (!opaqueDecl)
267267
return Type();
268-
// TODO [OPAQUE SUPPORT]: multiple opaque types
269-
assert(ordinal == 0 && "not implemented");
270-
if (ordinal != 0)
271-
return Type();
272-
273268
SmallVector<Type, 8> allArgs;
274269
for (auto argSet : args) {
275270
allArgs.append(argSet.begin(), argSet.end());

lib/AST/Decl.cpp

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7780,16 +7780,41 @@ void AbstractFunctionDecl::setParameters(ParameterList *BodyParams) {
77807780
OpaqueTypeDecl::OpaqueTypeDecl(ValueDecl *NamingDecl,
77817781
GenericParamList *GenericParams, DeclContext *DC,
77827782
GenericSignature OpaqueInterfaceGenericSignature,
7783-
OpaqueReturnTypeRepr *UnderlyingInterfaceRepr,
7783+
ArrayRef<OpaqueReturnTypeRepr *>
7784+
OpaqueReturnTypeReprs,
77847785
GenericTypeParamType *UnderlyingInterfaceType)
77857786
: GenericTypeDecl(DeclKind::OpaqueType, DC, Identifier(), SourceLoc(), {},
77867787
GenericParams),
7787-
NamingDecl(NamingDecl),
7788+
NamingDeclAndHasOpaqueReturnTypeRepr(
7789+
NamingDecl, !OpaqueReturnTypeReprs.empty()),
77887790
OpaqueInterfaceGenericSignature(OpaqueInterfaceGenericSignature),
7789-
UnderlyingInterfaceRepr(UnderlyingInterfaceRepr),
77907791
UnderlyingInterfaceType(UnderlyingInterfaceType) {
77917792
// Always implicit.
77927793
setImplicit();
7794+
7795+
/// We either have no opaque return type representations ('some P'), or we
7796+
/// have one for each opaque generic parameter.
7797+
assert(OpaqueReturnTypeReprs.empty() ||
7798+
OpaqueReturnTypeReprs.size() ==
7799+
OpaqueInterfaceGenericSignature.getInnermostGenericParams().size());
7800+
std::uninitialized_copy(
7801+
OpaqueReturnTypeReprs.begin(), OpaqueReturnTypeReprs.end(),
7802+
getTrailingObjects<OpaqueReturnTypeRepr *>());
7803+
}
7804+
7805+
OpaqueTypeDecl *OpaqueTypeDecl::get(
7806+
ValueDecl *NamingDecl, GenericParamList *GenericParams,
7807+
DeclContext *DC,
7808+
GenericSignature OpaqueInterfaceGenericSignature,
7809+
ArrayRef<OpaqueReturnTypeRepr *> OpaqueReturnTypeReprs,
7810+
GenericTypeParamType *UnderlyingInterfaceType) {
7811+
ASTContext &ctx = DC->getASTContext();
7812+
auto size = totalSizeToAlloc<OpaqueReturnTypeRepr *>(
7813+
OpaqueReturnTypeReprs.size());
7814+
auto mem = ctx.Allocate(size, alignof(OpaqueTypeDecl));
7815+
return new (mem) OpaqueTypeDecl(
7816+
NamingDecl, GenericParams, DC, OpaqueInterfaceGenericSignature,
7817+
OpaqueReturnTypeReprs, UnderlyingInterfaceType);
77937818
}
77947819

77957820
bool OpaqueTypeDecl::isOpaqueReturnTypeOfFunction(
@@ -7809,11 +7834,13 @@ bool OpaqueTypeDecl::isOpaqueReturnTypeOfFunction(
78097834

78107835
unsigned OpaqueTypeDecl::getAnonymousOpaqueParamOrdinal(
78117836
OpaqueReturnTypeRepr *repr) const {
7812-
// TODO [OPAQUE SUPPORT]: we will need to generalize here when we allow
7813-
// multiple "some" types.
7814-
assert(UnderlyingInterfaceRepr &&
7837+
assert(NamingDeclAndHasOpaqueReturnTypeRepr.getInt() &&
78157838
"can't do opaque param lookup without underlying interface repr");
7816-
return repr == UnderlyingInterfaceRepr ? 0 : -1;
7839+
auto opaqueReprs = getOpaqueReturnTypeReprs();
7840+
auto found = std::find(opaqueReprs.begin(), opaqueReprs.end(), repr);
7841+
if (found != opaqueReprs.end())
7842+
return found - opaqueReprs.begin();
7843+
return -1;
78177844
}
78187845

78197846
Identifier OpaqueTypeDecl::getOpaqueReturnTypeIdentifier() const {

lib/AST/Type.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3289,6 +3289,10 @@ OpaqueTypeArchetypeType::OpaqueTypeArchetypeType(OpaqueTypeDecl *OpaqueDecl,
32893289
{
32903290
}
32913291

3292+
unsigned OpaqueTypeArchetypeType::getOrdinal() const {
3293+
return getInterfaceType()->castTo<GenericTypeParamType>()->getIndex();
3294+
}
3295+
32923296
SequenceArchetypeType::SequenceArchetypeType(
32933297
const ASTContext &Ctx, GenericEnvironment *GenericEnv, Type InterfaceType,
32943298
ArrayRef<ProtocolDecl *> ConformsTo, Type Superclass,

lib/Sema/TypeCheckGeneric.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -296,11 +296,9 @@ OpaqueResultTypeRequest::evaluate(Evaluator &evaluator,
296296
}
297297

298298
// Create the OpaqueTypeDecl for the result type.
299-
auto opaqueDecl = new (ctx)
300-
OpaqueTypeDecl(originatingDecl, genericParams, parentDC,
301-
interfaceSignature,
302-
opaqueReprs.empty() ? 0 : opaqueReprs[0],
303-
underlyingGenericParamType);
299+
auto opaqueDecl = OpaqueTypeDecl::get(
300+
originatingDecl, genericParams, parentDC, interfaceSignature, opaqueReprs,
301+
underlyingGenericParamType);
304302
opaqueDecl->copyFormalAccessFrom(originatingDecl);
305303
if (auto originatingSig = originatingDC->getGenericSignatureOfContext()) {
306304
opaqueDecl->setGenericSignature(originatingSig);

lib/Serialization/Deserialization.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3464,10 +3464,9 @@ class DeclDeserializer {
34643464
return cast<OpaqueTypeDecl>(declOrOffset.get());
34653465

34663466
// Create the decl.
3467-
auto opaqueDecl = new (ctx)
3468-
OpaqueTypeDecl(/*NamingDecl*/ nullptr,
3469-
/*GenericParams*/ nullptr, declContext, interfaceSig,
3470-
/*UnderlyingInterfaceTypeRepr*/ nullptr, interfaceType);
3467+
auto opaqueDecl = OpaqueTypeDecl::get(
3468+
/*NamingDecl*/ nullptr, /*GenericParams*/ nullptr, declContext,
3469+
interfaceSig, /*OpaqueReturnTypeReprs*/ { }, interfaceType);
34713470
declOrOffset = opaqueDecl;
34723471

34733472
auto namingDecl = cast<ValueDecl>(MF.getDecl(namingDeclID));

0 commit comments

Comments
 (0)