Skip to content

Commit d103bf7

Browse files
authored
Merge pull request #63883 from rjmccall/silgen-variadic-generics
Progress towards SILGen for variadic generic argument lowering
2 parents 38d3864 + fb95781 commit d103bf7

17 files changed

+1352
-226
lines changed

include/swift/AST/GenericEnvironment.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,10 @@ class OpaqueTypeDecl;
3838
class ElementArchetypeType;
3939
class OpenedArchetypeType;
4040
class PackArchetypeType;
41+
class PackExpansionType;
4142
class SILModule;
4243
class SILType;
44+
template <class> class CanTypeWrapper;
4345

4446
/// Query function suitable for use as a \c TypeSubstitutionFn that queries
4547
/// the mapping of interface types to archetypes.
@@ -310,6 +312,23 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final
310312

311313
SWIFT_DEBUG_DUMP;
312314
};
315+
316+
/// A pair of an opened-element generic signature and an opened-element
317+
/// generic environment.
318+
struct OpenedElementContext {
319+
/// The opened-element environment for this expansion.
320+
GenericEnvironment *environment;
321+
322+
/// The opened-element signature for this expansion.
323+
CanGenericSignature signature;
324+
325+
/// Create a fresh opened element context from a contextual pack
326+
/// expansion type. This is useful when writing code that needs to
327+
/// break down the components of a pack expansion.
328+
static OpenedElementContext
329+
createForContextualExpansion(ASTContext &ctx,
330+
CanTypeWrapper<PackExpansionType> expansionType);
331+
};
313332

314333
} // end namespace swift
315334

include/swift/AST/Types.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6740,6 +6740,8 @@ class PackType final : public TypeBase, public llvm::FoldingSetNode,
67406740
}
67416741
};
67426742
BEGIN_CAN_TYPE_WRAPPER(PackType, Type)
6743+
static CanPackType get(const ASTContext &ctx, ArrayRef<CanType> elements);
6744+
67436745
CanType getElementType(unsigned elementNo) const {
67446746
return CanType(getPointer()->getElementType(elementNo));
67456747
}

include/swift/SIL/AbstractionPattern.h

Lines changed: 110 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,7 @@ class AbstractionPattern {
425425
const void *RawTypePtr;
426426
};
427427
CanGenericSignature GenericSig;
428+
SubstitutionMap GenericSubs;
428429

429430
Kind getKind() const { return Kind(TheKind); }
430431

@@ -507,45 +508,53 @@ class AbstractionPattern {
507508
}
508509
}
509510

510-
void initSwiftType(CanGenericSignature signature, CanType origType,
511+
void initSwiftType(SubstitutionMap subs,
512+
CanGenericSignature signature,
513+
CanType origType,
511514
Kind kind = Kind::Type) {
512515
assert(signature || !origType->hasTypeParameter());
513516
TheKind = unsigned(kind);
514517
OrigType = origType;
515518
GenericSig = CanGenericSignature();
519+
GenericSubs = subs;
516520
if (OrigType->hasTypeParameter()) {
517521
assert(OrigType == signature.getReducedType(origType));
518522
GenericSig = signature;
519523
}
524+
assert(!subs || !OrigType->hasTypeParameter() ||
525+
subs.getGenericSignature()->isEqual(
526+
getGenericSignatureForFunctionComponent()));
520527
}
521528

522-
void initClangType(CanGenericSignature signature,
529+
void initClangType(SubstitutionMap subs, CanGenericSignature signature,
523530
CanType origType, const clang::Type *clangType,
524531
Kind kind = Kind::ClangType) {
525-
initSwiftType(signature, origType, kind);
532+
initSwiftType(subs, signature, origType, kind);
526533
ClangType = clangType;
527534
}
528535

529-
void initObjCMethod(CanGenericSignature signature,
536+
void initObjCMethod(SubstitutionMap subs, CanGenericSignature signature,
530537
CanType origType, const clang::ObjCMethodDecl *method,
531538
Kind kind, EncodedForeignInfo errorInfo) {
532-
initSwiftType(signature, origType, kind);
539+
initSwiftType(subs, signature, origType, kind);
533540
ObjCMethod = method;
534541
OtherData = errorInfo.getOpaqueValue();
535542
}
536543

537-
void initCFunctionAsMethod(CanGenericSignature signature,
544+
void initCFunctionAsMethod(SubstitutionMap subs,
545+
CanGenericSignature signature,
538546
CanType origType, const clang::Type *clangType,
539547
Kind kind,
540548
ImportAsMemberStatus memberStatus) {
541-
initClangType(signature, origType, clangType, kind);
549+
initClangType(subs, signature, origType, clangType, kind);
542550
OtherData = memberStatus.getRawValue();
543551
}
544552

545-
void initCXXMethod(CanGenericSignature signature, CanType origType,
553+
void initCXXMethod(SubstitutionMap subs,
554+
CanGenericSignature signature, CanType origType,
546555
const clang::CXXMethodDecl *method, Kind kind,
547556
ImportAsMemberStatus memberStatus) {
548-
initSwiftType(signature, origType, kind);
557+
initSwiftType(subs, signature, origType, kind);
549558
CXXMethod = method;
550559
OtherData = memberStatus.getRawValue();
551560
}
@@ -559,13 +568,27 @@ class AbstractionPattern {
559568
explicit AbstractionPattern(CanType origType)
560569
: AbstractionPattern(nullptr, origType) {}
561570
explicit AbstractionPattern(CanGenericSignature signature, CanType origType) {
562-
initSwiftType(signature, origType);
571+
initSwiftType(SubstitutionMap(), signature, origType);
572+
}
573+
explicit AbstractionPattern(SubstitutionMap subs, CanType origType) {
574+
initSwiftType(subs, subs.getGenericSignature().getCanonicalSignature(),
575+
origType);
576+
}
577+
explicit AbstractionPattern(SubstitutionMap subs, CanGenericSignature sig,
578+
CanType origType) {
579+
initSwiftType(subs, sig, origType);
563580
}
564581
explicit AbstractionPattern(CanType origType, const clang::Type *clangType)
565582
: AbstractionPattern(nullptr, origType, clangType) {}
566583
explicit AbstractionPattern(CanGenericSignature signature, CanType origType,
567584
const clang::Type *clangType) {
568-
initClangType(signature, origType, clangType);
585+
initClangType(SubstitutionMap(), signature, origType, clangType);
586+
}
587+
explicit AbstractionPattern(SubstitutionMap subs,
588+
CanGenericSignature signature,
589+
CanType origType,
590+
const clang::Type *clangType) {
591+
initClangType(subs, signature, origType, clangType);
569592
}
570593

571594
static AbstractionPattern getOpaque() {
@@ -610,6 +633,10 @@ class AbstractionPattern {
610633
llvm_unreachable("Unhandled AbstractionPatternKind in switch");
611634
}
612635

636+
SubstitutionMap getGenericSubstitutions() const {
637+
return GenericSubs;
638+
}
639+
613640
CanGenericSignature getGenericSignature() const {
614641
assert(hasGenericSignature());
615642
return CanGenericSignature(GenericSig);
@@ -635,12 +662,13 @@ class AbstractionPattern {
635662
/// corresponding to the parameters of a completion handler
636663
/// block of an API that was imported as async.
637664
static AbstractionPattern
638-
getObjCCompletionHandlerArgumentsType(CanGenericSignature sig,
665+
getObjCCompletionHandlerArgumentsType(SubstitutionMap subs,
666+
CanGenericSignature sig,
639667
CanType origTupleType,
640668
const clang::Type *clangBlockType,
641669
EncodedForeignInfo foreignInfo) {
642670
AbstractionPattern pattern(Kind::ObjCCompletionHandlerArgumentsType);
643-
pattern.initClangType(sig, origTupleType, clangBlockType,
671+
pattern.initClangType(subs, sig, origTupleType, clangBlockType,
644672
Kind::ObjCCompletionHandlerArgumentsType);
645673
pattern.OtherData = foreignInfo.getOpaqueValue();
646674

@@ -670,7 +698,8 @@ class AbstractionPattern {
670698
ImportAsMemberStatus memberStatus) {
671699
assert(isa<AnyFunctionType>(origType));
672700
AbstractionPattern pattern;
673-
pattern.initCFunctionAsMethod(nullptr, origType, clangType,
701+
pattern.initCFunctionAsMethod(SubstitutionMap(), nullptr,
702+
origType, clangType,
674703
Kind::CFunctionAsMethodType,
675704
memberStatus);
676705
return pattern;
@@ -705,7 +734,7 @@ class AbstractionPattern {
705734
ImportAsMemberStatus memberStatus) {
706735
assert(isa<AnyFunctionType>(origType));
707736
AbstractionPattern pattern;
708-
pattern.initCXXMethod(nullptr, origType, method,
737+
pattern.initCXXMethod(SubstitutionMap(), nullptr, origType, method,
709738
Kind::CXXMethodType, memberStatus);
710739
return pattern;
711740
}
@@ -722,7 +751,7 @@ class AbstractionPattern {
722751
ImportAsMemberStatus memberStatus) {
723752
assert(isa<AnyFunctionType>(origType));
724753
AbstractionPattern pattern;
725-
pattern.initCXXMethod(nullptr, origType, method,
754+
pattern.initCXXMethod(SubstitutionMap(), nullptr, origType, method,
726755
Kind::CurriedCXXMethodType, memberStatus);
727756
return pattern;
728757
}
@@ -738,10 +767,11 @@ class AbstractionPattern {
738767

739768
/// Return an abstraction pattern for a value that is discarded after being
740769
/// evaluated.
741-
static AbstractionPattern
742-
getDiscard(CanGenericSignature signature, CanType origType) {
770+
static AbstractionPattern getDiscard(SubstitutionMap subs,
771+
CanGenericSignature signature,
772+
CanType origType) {
743773
AbstractionPattern pattern;
744-
pattern.initSwiftType(signature, origType, Kind::Discard);
774+
pattern.initSwiftType(subs, signature, origType, Kind::Discard);
745775
return pattern;
746776
}
747777

@@ -761,7 +791,7 @@ class AbstractionPattern {
761791
EncodedForeignInfo errorInfo) {
762792
assert(isa<AnyFunctionType>(origType));
763793
AbstractionPattern pattern;
764-
pattern.initObjCMethod(nullptr, origType, method,
794+
pattern.initObjCMethod(SubstitutionMap(), nullptr, origType, method,
765795
Kind::CurriedObjCMethodType, errorInfo);
766796
return pattern;
767797
}
@@ -772,7 +802,8 @@ class AbstractionPattern {
772802
ImportAsMemberStatus memberStatus) {
773803
assert(isa<AnyFunctionType>(origType));
774804
AbstractionPattern pattern;
775-
pattern.initCFunctionAsMethod(nullptr, origType, clangType,
805+
pattern.initCFunctionAsMethod(SubstitutionMap(), nullptr,
806+
origType, clangType,
776807
Kind::CurriedCFunctionAsMethodType,
777808
memberStatus);
778809
return pattern;
@@ -781,13 +812,14 @@ class AbstractionPattern {
781812
/// Return an abstraction pattern for the partially-applied curried
782813
/// type of an Objective-C method.
783814
static AbstractionPattern
784-
getPartialCurriedObjCMethod(CanGenericSignature signature,
815+
getPartialCurriedObjCMethod(SubstitutionMap subs,
816+
CanGenericSignature signature,
785817
CanType origType,
786818
const clang::ObjCMethodDecl *method,
787819
EncodedForeignInfo errorInfo) {
788820
assert(isa<AnyFunctionType>(origType));
789821
AbstractionPattern pattern;
790-
pattern.initObjCMethod(signature, origType, method,
822+
pattern.initObjCMethod(subs, signature, origType, method,
791823
Kind::PartialCurriedObjCMethodType, errorInfo);
792824
return pattern;
793825
}
@@ -802,13 +834,14 @@ class AbstractionPattern {
802834
/// and the partially-applied curried type is:
803835
/// (CCTemperature) -> ()
804836
static AbstractionPattern
805-
getPartialCurriedCFunctionAsMethod(CanGenericSignature signature,
837+
getPartialCurriedCFunctionAsMethod(SubstitutionMap subs,
838+
CanGenericSignature signature,
806839
CanType origType,
807840
const clang::Type *clangType,
808841
ImportAsMemberStatus memberStatus) {
809842
assert(isa<AnyFunctionType>(origType));
810843
AbstractionPattern pattern;
811-
pattern.initCFunctionAsMethod(signature, origType, clangType,
844+
pattern.initCFunctionAsMethod(subs, signature, origType, clangType,
812845
Kind::PartialCurriedCFunctionAsMethodType,
813846
memberStatus);
814847
return pattern;
@@ -823,12 +856,13 @@ class AbstractionPattern {
823856
/// then the partially-applied curried type is:
824857
/// (Compartment, Temperature) -> ()
825858
static AbstractionPattern
826-
getPartialCurriedCXXMethod(CanGenericSignature signature, CanType origType,
859+
getPartialCurriedCXXMethod(SubstitutionMap subs,
860+
CanGenericSignature signature, CanType origType,
827861
const clang::CXXMethodDecl *method,
828862
ImportAsMemberStatus memberStatus) {
829863
assert(isa<AnyFunctionType>(origType));
830864
AbstractionPattern pattern;
831-
pattern.initCXXMethod(signature, origType, method,
865+
pattern.initCXXMethod(subs, signature, origType, method,
832866
Kind::PartialCurriedCXXMethodType, memberStatus);
833867
return pattern;
834868
}
@@ -848,7 +882,8 @@ class AbstractionPattern {
848882
EncodedForeignInfo errorInfo) {
849883
assert(isa<AnyFunctionType>(origType));
850884
AbstractionPattern pattern;
851-
pattern.initObjCMethod(nullptr, origType, method, Kind::ObjCMethodType,
885+
pattern.initObjCMethod(SubstitutionMap(), nullptr,
886+
origType, method, Kind::ObjCMethodType,
852887
errorInfo);
853888
return pattern;
854889
}
@@ -947,7 +982,17 @@ class AbstractionPattern {
947982
return false;
948983
}
949984
}
950-
985+
986+
bool isPackExpansion() const {
987+
switch (getKind()) {
988+
case Kind::Type:
989+
case Kind::Discard:
990+
return isa<PackExpansionType>(getType());
991+
default:
992+
return false;
993+
}
994+
}
995+
951996
/// Is this an interface type that is subject to a concrete
952997
/// same-type constraint?
953998
bool isConcreteType() const;
@@ -1032,6 +1077,24 @@ class AbstractionPattern {
10321077
llvm_unreachable("bad kind");
10331078
}
10341079

1080+
/// Add substitutions to this pattern.
1081+
AbstractionPattern withSubstitutions(SubstitutionMap subs) const {
1082+
AbstractionPattern result = *this;
1083+
if (subs) {
1084+
#ifndef NDEBUG
1085+
// If we have a generic signature, it should match the substitutions.
1086+
// But there are situations in which it's okay that we don't store
1087+
// a signature.
1088+
auto sig = getGenericSignatureForFunctionComponent();
1089+
assert((sig && sig->isEqual(subs.getGenericSignature())) ||
1090+
!OrigType ||
1091+
!OrigType->hasTypeParameter());
1092+
#endif
1093+
result.GenericSubs = subs;
1094+
}
1095+
return result;
1096+
}
1097+
10351098
/// Return whether this abstraction pattern contains foreign type
10361099
/// information.
10371100
///
@@ -1359,8 +1422,14 @@ class AbstractionPattern {
13591422
/// the abstraction pattern for one of its parameter types.
13601423
AbstractionPattern getFunctionParamType(unsigned index) const;
13611424

1362-
/// Given that the value being abstracted is a function type, return
1363-
/// the number of parameters.
1425+
/// Given that the value being abstracted is a function type, and that
1426+
/// this is not an opaque abstraction pattern, return the parameter flags
1427+
/// for one of its parameters.
1428+
ParameterTypeFlags getFunctionParamFlags(unsigned index) const;
1429+
1430+
/// Given that the value being abstracted is a function type, and that
1431+
/// this is not an opaque abstraction pattern, return the number of
1432+
/// parameters in the pattern.
13641433
unsigned getNumFunctionParams() const;
13651434

13661435
/// Given that the value being abstracted is optional, return the
@@ -1394,13 +1463,22 @@ class AbstractionPattern {
13941463
AbstractionPattern getObjCMethodAsyncCompletionHandlerType(
13951464
CanType swiftCompletionHandlerType) const;
13961465

1466+
/// Given that this is a pack expansion, invoke the given callback for
1467+
/// each component of the substituted expansion of this pattern. The
1468+
/// pattern will be for a pack expansion type over a contextual type if
1469+
/// the substituted component is still a pack expansion. If there aren't
1470+
/// substitutions available, this will just invoke the callback with the
1471+
/// component.
1472+
void forEachPackExpandedComponent(
1473+
llvm::function_ref<void(AbstractionPattern pattern)> fn) const;
1474+
13971475
/// If this pattern refers to a foreign ObjC method that was imported as
13981476
/// async, return the bridged-back-to-ObjC completion handler type.
13991477
CanType getObjCMethodAsyncCompletionHandlerForeignType(
14001478
ForeignAsyncConvention convention,
14011479
Lowering::TypeConverter &TC
14021480
) const;
1403-
1481+
14041482
/// How values are passed or returned according to this abstraction pattern.
14051483
enum CallingConventionKind {
14061484
// Value is passed or returned directly as a unit.

lib/AST/ASTContext.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3302,6 +3302,11 @@ PackType *PackType::getEmpty(const ASTContext &C) {
33023302
return cast<PackType>(CanType(C.TheEmptyPackType));
33033303
}
33043304

3305+
CanPackType CanPackType::get(const ASTContext &C, ArrayRef<CanType> elements) {
3306+
SmallVector<Type, 8> ncElements(elements.begin(), elements.end());
3307+
return CanPackType(PackType::get(C, ncElements));
3308+
}
3309+
33053310
PackType *PackType::get(const ASTContext &C, ArrayRef<Type> elements) {
33063311
RecursiveTypeProperties properties;
33073312
bool isCanonical = true;

0 commit comments

Comments
 (0)