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.
This commit is contained in:
Doug Gregor
2021-12-24 22:06:48 -08:00
parent 3892268cc6
commit 99a9c021e2
8 changed files with 101 additions and 41 deletions

View File

@@ -7780,16 +7780,41 @@ void AbstractFunctionDecl::setParameters(ParameterList *BodyParams) {
OpaqueTypeDecl::OpaqueTypeDecl(ValueDecl *NamingDecl,
GenericParamList *GenericParams, DeclContext *DC,
GenericSignature OpaqueInterfaceGenericSignature,
OpaqueReturnTypeRepr *UnderlyingInterfaceRepr,
ArrayRef<OpaqueReturnTypeRepr *>
OpaqueReturnTypeReprs,
GenericTypeParamType *UnderlyingInterfaceType)
: GenericTypeDecl(DeclKind::OpaqueType, DC, Identifier(), SourceLoc(), {},
GenericParams),
NamingDecl(NamingDecl),
NamingDeclAndHasOpaqueReturnTypeRepr(
NamingDecl, !OpaqueReturnTypeReprs.empty()),
OpaqueInterfaceGenericSignature(OpaqueInterfaceGenericSignature),
UnderlyingInterfaceRepr(UnderlyingInterfaceRepr),
UnderlyingInterfaceType(UnderlyingInterfaceType) {
// Always implicit.
setImplicit();
/// We either have no opaque return type representations ('some P'), or we
/// have one for each opaque generic parameter.
assert(OpaqueReturnTypeReprs.empty() ||
OpaqueReturnTypeReprs.size() ==
OpaqueInterfaceGenericSignature.getInnermostGenericParams().size());
std::uninitialized_copy(
OpaqueReturnTypeReprs.begin(), OpaqueReturnTypeReprs.end(),
getTrailingObjects<OpaqueReturnTypeRepr *>());
}
OpaqueTypeDecl *OpaqueTypeDecl::get(
ValueDecl *NamingDecl, GenericParamList *GenericParams,
DeclContext *DC,
GenericSignature OpaqueInterfaceGenericSignature,
ArrayRef<OpaqueReturnTypeRepr *> OpaqueReturnTypeReprs,
GenericTypeParamType *UnderlyingInterfaceType) {
ASTContext &ctx = DC->getASTContext();
auto size = totalSizeToAlloc<OpaqueReturnTypeRepr *>(
OpaqueReturnTypeReprs.size());
auto mem = ctx.Allocate(size, alignof(OpaqueTypeDecl));
return new (mem) OpaqueTypeDecl(
NamingDecl, GenericParams, DC, OpaqueInterfaceGenericSignature,
OpaqueReturnTypeReprs, UnderlyingInterfaceType);
}
bool OpaqueTypeDecl::isOpaqueReturnTypeOfFunction(
@@ -7809,11 +7834,13 @@ bool OpaqueTypeDecl::isOpaqueReturnTypeOfFunction(
unsigned OpaqueTypeDecl::getAnonymousOpaqueParamOrdinal(
OpaqueReturnTypeRepr *repr) const {
// TODO [OPAQUE SUPPORT]: we will need to generalize here when we allow
// multiple "some" types.
assert(UnderlyingInterfaceRepr &&
assert(NamingDeclAndHasOpaqueReturnTypeRepr.getInt() &&
"can't do opaque param lookup without underlying interface repr");
return repr == UnderlyingInterfaceRepr ? 0 : -1;
auto opaqueReprs = getOpaqueReturnTypeReprs();
auto found = std::find(opaqueReprs.begin(), opaqueReprs.end(), repr);
if (found != opaqueReprs.end())
return found - opaqueReprs.begin();
return -1;
}
Identifier OpaqueTypeDecl::getOpaqueReturnTypeIdentifier() const {