Allow AbstractionPattern to optionally carry substitutions

This allows the AP to answer questions like how many
elements/parameters in the substituted type correspond to
this pack expansion.

I've threaded this through a lot of cases for foreign patterns
that probably won't ever need it.
This commit is contained in:
John McCall
2023-02-24 14:49:53 -05:00
parent b06a9dced5
commit bd53f5d5df
2 changed files with 253 additions and 73 deletions

View File

@@ -425,6 +425,7 @@ class AbstractionPattern {
const void *RawTypePtr;
};
CanGenericSignature GenericSig;
SubstitutionMap GenericSubs;
Kind getKind() const { return Kind(TheKind); }
@@ -507,45 +508,53 @@ class AbstractionPattern {
}
}
void initSwiftType(CanGenericSignature signature, CanType origType,
void initSwiftType(SubstitutionMap subs,
CanGenericSignature signature,
CanType origType,
Kind kind = Kind::Type) {
assert(signature || !origType->hasTypeParameter());
TheKind = unsigned(kind);
OrigType = origType;
GenericSig = CanGenericSignature();
GenericSubs = subs;
if (OrigType->hasTypeParameter()) {
assert(OrigType == signature.getReducedType(origType));
GenericSig = signature;
}
assert(!subs || !OrigType->hasTypeParameter() ||
subs.getGenericSignature()->isEqual(
getGenericSignatureForFunctionComponent()));
}
void initClangType(CanGenericSignature signature,
void initClangType(SubstitutionMap subs, CanGenericSignature signature,
CanType origType, const clang::Type *clangType,
Kind kind = Kind::ClangType) {
initSwiftType(signature, origType, kind);
initSwiftType(subs, signature, origType, kind);
ClangType = clangType;
}
void initObjCMethod(CanGenericSignature signature,
void initObjCMethod(SubstitutionMap subs, CanGenericSignature signature,
CanType origType, const clang::ObjCMethodDecl *method,
Kind kind, EncodedForeignInfo errorInfo) {
initSwiftType(signature, origType, kind);
initSwiftType(subs, signature, origType, kind);
ObjCMethod = method;
OtherData = errorInfo.getOpaqueValue();
}
void initCFunctionAsMethod(CanGenericSignature signature,
void initCFunctionAsMethod(SubstitutionMap subs,
CanGenericSignature signature,
CanType origType, const clang::Type *clangType,
Kind kind,
ImportAsMemberStatus memberStatus) {
initClangType(signature, origType, clangType, kind);
initClangType(subs, signature, origType, clangType, kind);
OtherData = memberStatus.getRawValue();
}
void initCXXMethod(CanGenericSignature signature, CanType origType,
void initCXXMethod(SubstitutionMap subs,
CanGenericSignature signature, CanType origType,
const clang::CXXMethodDecl *method, Kind kind,
ImportAsMemberStatus memberStatus) {
initSwiftType(signature, origType, kind);
initSwiftType(subs, signature, origType, kind);
CXXMethod = method;
OtherData = memberStatus.getRawValue();
}
@@ -559,13 +568,27 @@ public:
explicit AbstractionPattern(CanType origType)
: AbstractionPattern(nullptr, origType) {}
explicit AbstractionPattern(CanGenericSignature signature, CanType origType) {
initSwiftType(signature, origType);
initSwiftType(SubstitutionMap(), signature, origType);
}
explicit AbstractionPattern(SubstitutionMap subs, CanType origType) {
initSwiftType(subs, subs.getGenericSignature().getCanonicalSignature(),
origType);
}
explicit AbstractionPattern(SubstitutionMap subs, CanGenericSignature sig,
CanType origType) {
initSwiftType(subs, sig, origType);
}
explicit AbstractionPattern(CanType origType, const clang::Type *clangType)
: AbstractionPattern(nullptr, origType, clangType) {}
explicit AbstractionPattern(CanGenericSignature signature, CanType origType,
const clang::Type *clangType) {
initClangType(signature, origType, clangType);
initClangType(SubstitutionMap(), signature, origType, clangType);
}
explicit AbstractionPattern(SubstitutionMap subs,
CanGenericSignature signature,
CanType origType,
const clang::Type *clangType) {
initClangType(subs, signature, origType, clangType);
}
static AbstractionPattern getOpaque() {
@@ -610,6 +633,10 @@ public:
llvm_unreachable("Unhandled AbstractionPatternKind in switch");
}
SubstitutionMap getGenericSubstitutions() const {
return GenericSubs;
}
CanGenericSignature getGenericSignature() const {
assert(hasGenericSignature());
return CanGenericSignature(GenericSig);
@@ -635,12 +662,13 @@ public:
/// corresponding to the parameters of a completion handler
/// block of an API that was imported as async.
static AbstractionPattern
getObjCCompletionHandlerArgumentsType(CanGenericSignature sig,
getObjCCompletionHandlerArgumentsType(SubstitutionMap subs,
CanGenericSignature sig,
CanType origTupleType,
const clang::Type *clangBlockType,
EncodedForeignInfo foreignInfo) {
AbstractionPattern pattern(Kind::ObjCCompletionHandlerArgumentsType);
pattern.initClangType(sig, origTupleType, clangBlockType,
pattern.initClangType(subs, sig, origTupleType, clangBlockType,
Kind::ObjCCompletionHandlerArgumentsType);
pattern.OtherData = foreignInfo.getOpaqueValue();
@@ -670,7 +698,8 @@ public:
ImportAsMemberStatus memberStatus) {
assert(isa<AnyFunctionType>(origType));
AbstractionPattern pattern;
pattern.initCFunctionAsMethod(nullptr, origType, clangType,
pattern.initCFunctionAsMethod(SubstitutionMap(), nullptr,
origType, clangType,
Kind::CFunctionAsMethodType,
memberStatus);
return pattern;
@@ -705,7 +734,7 @@ public:
ImportAsMemberStatus memberStatus) {
assert(isa<AnyFunctionType>(origType));
AbstractionPattern pattern;
pattern.initCXXMethod(nullptr, origType, method,
pattern.initCXXMethod(SubstitutionMap(), nullptr, origType, method,
Kind::CXXMethodType, memberStatus);
return pattern;
}
@@ -722,7 +751,7 @@ public:
ImportAsMemberStatus memberStatus) {
assert(isa<AnyFunctionType>(origType));
AbstractionPattern pattern;
pattern.initCXXMethod(nullptr, origType, method,
pattern.initCXXMethod(SubstitutionMap(), nullptr, origType, method,
Kind::CurriedCXXMethodType, memberStatus);
return pattern;
}
@@ -738,10 +767,11 @@ public:
/// Return an abstraction pattern for a value that is discarded after being
/// evaluated.
static AbstractionPattern
getDiscard(CanGenericSignature signature, CanType origType) {
static AbstractionPattern getDiscard(SubstitutionMap subs,
CanGenericSignature signature,
CanType origType) {
AbstractionPattern pattern;
pattern.initSwiftType(signature, origType, Kind::Discard);
pattern.initSwiftType(subs, signature, origType, Kind::Discard);
return pattern;
}
@@ -761,7 +791,7 @@ private:
EncodedForeignInfo errorInfo) {
assert(isa<AnyFunctionType>(origType));
AbstractionPattern pattern;
pattern.initObjCMethod(nullptr, origType, method,
pattern.initObjCMethod(SubstitutionMap(), nullptr, origType, method,
Kind::CurriedObjCMethodType, errorInfo);
return pattern;
}
@@ -772,7 +802,8 @@ private:
ImportAsMemberStatus memberStatus) {
assert(isa<AnyFunctionType>(origType));
AbstractionPattern pattern;
pattern.initCFunctionAsMethod(nullptr, origType, clangType,
pattern.initCFunctionAsMethod(SubstitutionMap(), nullptr,
origType, clangType,
Kind::CurriedCFunctionAsMethodType,
memberStatus);
return pattern;
@@ -781,13 +812,14 @@ private:
/// Return an abstraction pattern for the partially-applied curried
/// type of an Objective-C method.
static AbstractionPattern
getPartialCurriedObjCMethod(CanGenericSignature signature,
getPartialCurriedObjCMethod(SubstitutionMap subs,
CanGenericSignature signature,
CanType origType,
const clang::ObjCMethodDecl *method,
EncodedForeignInfo errorInfo) {
assert(isa<AnyFunctionType>(origType));
AbstractionPattern pattern;
pattern.initObjCMethod(signature, origType, method,
pattern.initObjCMethod(subs, signature, origType, method,
Kind::PartialCurriedObjCMethodType, errorInfo);
return pattern;
}
@@ -802,13 +834,14 @@ private:
/// and the partially-applied curried type is:
/// (CCTemperature) -> ()
static AbstractionPattern
getPartialCurriedCFunctionAsMethod(CanGenericSignature signature,
getPartialCurriedCFunctionAsMethod(SubstitutionMap subs,
CanGenericSignature signature,
CanType origType,
const clang::Type *clangType,
ImportAsMemberStatus memberStatus) {
assert(isa<AnyFunctionType>(origType));
AbstractionPattern pattern;
pattern.initCFunctionAsMethod(signature, origType, clangType,
pattern.initCFunctionAsMethod(subs, signature, origType, clangType,
Kind::PartialCurriedCFunctionAsMethodType,
memberStatus);
return pattern;
@@ -823,12 +856,13 @@ private:
/// then the partially-applied curried type is:
/// (Compartment, Temperature) -> ()
static AbstractionPattern
getPartialCurriedCXXMethod(CanGenericSignature signature, CanType origType,
getPartialCurriedCXXMethod(SubstitutionMap subs,
CanGenericSignature signature, CanType origType,
const clang::CXXMethodDecl *method,
ImportAsMemberStatus memberStatus) {
assert(isa<AnyFunctionType>(origType));
AbstractionPattern pattern;
pattern.initCXXMethod(signature, origType, method,
pattern.initCXXMethod(subs, signature, origType, method,
Kind::PartialCurriedCXXMethodType, memberStatus);
return pattern;
}
@@ -848,7 +882,8 @@ private:
EncodedForeignInfo errorInfo) {
assert(isa<AnyFunctionType>(origType));
AbstractionPattern pattern;
pattern.initObjCMethod(nullptr, origType, method, Kind::ObjCMethodType,
pattern.initObjCMethod(SubstitutionMap(), nullptr,
origType, method, Kind::ObjCMethodType,
errorInfo);
return pattern;
}
@@ -947,7 +982,17 @@ public:
return false;
}
}
bool isPackExpansion() const {
switch (getKind()) {
case Kind::Type:
case Kind::Discard:
return isa<PackExpansionType>(getType());
default:
return false;
}
}
/// Is this an interface type that is subject to a concrete
/// same-type constraint?
bool isConcreteType() const;
@@ -1032,6 +1077,24 @@ public:
llvm_unreachable("bad kind");
}
/// Add substitutions to this pattern.
AbstractionPattern withSubstitutions(SubstitutionMap subs) const {
AbstractionPattern result = *this;
if (subs) {
#ifndef NDEBUG
// If we have a generic signature, it should match the substitutions.
// But there are situations in which it's okay that we don't store
// a signature.
auto sig = getGenericSignatureForFunctionComponent();
assert((sig && sig->isEqual(subs.getGenericSignature())) ||
!OrigType ||
!OrigType->hasTypeParameter());
#endif
result.GenericSubs = subs;
}
return result;
}
/// Return whether this abstraction pattern contains foreign type
/// information.
///
@@ -1359,8 +1422,14 @@ public:
/// the abstraction pattern for one of its parameter types.
AbstractionPattern getFunctionParamType(unsigned index) const;
/// Given that the value being abstracted is a function type, return
/// the number of parameters.
/// Given that the value being abstracted is a function type, and that
/// this is not an opaque abstraction pattern, return the parameter flags
/// for one of its parameters.
ParameterTypeFlags getFunctionParamFlags(unsigned index) const;
/// Given that the value being abstracted is a function type, and that
/// this is not an opaque abstraction pattern, return the number of
/// parameters in the pattern.
unsigned getNumFunctionParams() const;
/// Given that the value being abstracted is optional, return the
@@ -1394,13 +1463,22 @@ public:
AbstractionPattern getObjCMethodAsyncCompletionHandlerType(
CanType swiftCompletionHandlerType) const;
/// Given that this is a pack expansion, invoke the given callback for
/// each component of the substituted expansion of this pattern. The
/// pattern will be for a pack expansion type over a contextual type if
/// the substituted component is still a pack expansion. If there aren't
/// substitutions available, this will just invoke the callback with the
/// component.
void forEachPackExpandedComponent(
llvm::function_ref<void(AbstractionPattern pattern)> fn) const;
/// If this pattern refers to a foreign ObjC method that was imported as
/// async, return the bridged-back-to-ObjC completion handler type.
CanType getObjCMethodAsyncCompletionHandlerForeignType(
ForeignAsyncConvention convention,
Lowering::TypeConverter &TC
) const;
/// How values are passed or returned according to this abstraction pattern.
enum CallingConventionKind {
// Value is passed or returned directly as a unit.