@@ -1037,6 +1037,7 @@ ParameterListInfo::ParameterListInfo(
1037
1037
propertyWrappers.resize (params.size ());
1038
1038
implicitSelfCapture.resize (params.size ());
1039
1039
inheritActorContext.resize (params.size ());
1040
+ variadicGenerics.resize (params.size ());
1040
1041
1041
1042
// No parameter owner means no parameter list means no default arguments
1042
1043
// - hand back the zeroed bitvector.
@@ -1096,6 +1097,11 @@ ParameterListInfo::ParameterListInfo(
1096
1097
if (param->getAttrs ().hasAttribute <InheritActorContextAttr>()) {
1097
1098
inheritActorContext.set (i);
1098
1099
}
1100
+
1101
+ if (param->isVariadic () &&
1102
+ param->getVarargBaseTy ()->hasTypeSequence ()) {
1103
+ variadicGenerics.set (i);
1104
+ }
1099
1105
}
1100
1106
}
1101
1107
@@ -1130,6 +1136,13 @@ bool ParameterListInfo::anyContextualInfo() const {
1130
1136
return implicitSelfCapture.any () || inheritActorContext.any ();
1131
1137
}
1132
1138
1139
+ bool ParameterListInfo::isVariadicGenericParameter (unsigned paramIdx) const {
1140
+ return paramIdx < variadicGenerics.size ()
1141
+ ? variadicGenerics[paramIdx]
1142
+ : false ;
1143
+ }
1144
+
1145
+
1133
1146
// / Turn a param list into a symbolic and printable representation that does not
1134
1147
// / include the types, something like (_:, b:, c:)
1135
1148
std::string swift::getParamListAsString (ArrayRef<AnyFunctionType::Param> params) {
@@ -1360,6 +1373,13 @@ CanType TypeBase::computeCanonicalType() {
1360
1373
break ;
1361
1374
}
1362
1375
1376
+ case TypeKind::PackExpansion: {
1377
+ auto *expansion = cast<PackExpansionType>(this );
1378
+ auto pattern = expansion->getPatternType ()->getCanonicalType ();
1379
+ Result = PackExpansionType::get (pattern);
1380
+ break ;
1381
+ }
1382
+
1363
1383
case TypeKind::Tuple: {
1364
1384
TupleType *TT = cast<TupleType>(this );
1365
1385
assert (TT->getNumElements () != 0 && " Empty tuples are always canonical" );
@@ -5061,18 +5081,152 @@ case TypeKind::Id:
5061
5081
return ParenType::get (Ptr->getASTContext (), underlying->getInOutObjectType (), otherFlags);
5062
5082
}
5063
5083
5084
+ case TypeKind::Pack: {
5085
+ auto pack = cast<PackType>(base);
5086
+ bool anyChanged = false ;
5087
+ SmallVector<Type, 4 > elements;
5088
+ unsigned Index = 0 ;
5089
+ for (Type eltTy : pack->getElementTypes ()) {
5090
+ Type transformedEltTy = eltTy.transformRec (fn);
5091
+ if (!transformedEltTy)
5092
+ return Type ();
5093
+
5094
+ // If nothing has changed, just keep going.
5095
+ if (!anyChanged &&
5096
+ transformedEltTy.getPointer () == eltTy.getPointer ()) {
5097
+ ++Index;
5098
+ continue ;
5099
+ }
5100
+
5101
+ // If this is the first change we've seen, copy all of the previous
5102
+ // elements.
5103
+ if (!anyChanged) {
5104
+ // Copy all of the previous elements.
5105
+ elements.append (pack->getElementTypes ().begin (),
5106
+ pack->getElementTypes ().begin () + Index);
5107
+ anyChanged = true ;
5108
+ }
5109
+
5110
+ elements.push_back (transformedEltTy);
5111
+ ++Index;
5112
+ }
5113
+
5114
+ if (!anyChanged)
5115
+ return *this ;
5116
+
5117
+ return PackType::get (Ptr->getASTContext (), elements);
5118
+ }
5119
+
5120
+ case TypeKind::PackExpansion: {
5121
+ auto expand = cast<PackExpansionType>(base);
5122
+ struct ExpansionGatherer {
5123
+ llvm::function_ref<Optional<Type>(TypeBase *)> baselineFn;
5124
+ llvm::DenseMap<TypeBase *, PackType *> cache;
5125
+ unsigned maxArity;
5126
+
5127
+ public:
5128
+ ExpansionGatherer (
5129
+ llvm::function_ref<Optional<Type>(TypeBase *)> baselineFn)
5130
+ : baselineFn(baselineFn), maxArity(0 ) {}
5131
+
5132
+ Optional<Type> operator ()(TypeBase *input) {
5133
+ auto remap = baselineFn (input);
5134
+ if (!remap) {
5135
+ return remap;
5136
+ }
5137
+
5138
+ if (input->is <TypeVariableType>()) {
5139
+ if (auto *PT = (*remap)->getAs <PackType>()) {
5140
+ maxArity = std::max (maxArity, PT->getNumElements ());
5141
+ cache.insert ({input, PT});
5142
+ }
5143
+ } else if (input->isTypeSequenceParameter ()) {
5144
+ if (auto *PT = (*remap)->getAs <PackType>()) {
5145
+ maxArity = std::max (maxArity, PT->getNumElements ());
5146
+ cache.insert ({input, PT});
5147
+ }
5148
+ }
5149
+ return remap;
5150
+ }
5151
+
5152
+ std::pair<llvm::DenseMap<TypeBase *, PackType *>, unsigned >
5153
+ intoExpansions () && {
5154
+ return std::make_pair (cache, maxArity);
5155
+ }
5156
+ };
5157
+
5158
+ // First, substitute down the pattern type to gather the mapping from
5159
+ // contained substitutable types to packs.
5160
+ auto gather = ExpansionGatherer{fn};
5161
+ Type transformedPat = expand->getPatternType ().transformRec (gather);
5162
+ if (!transformedPat)
5163
+ return Type ();
5164
+
5165
+ if (transformedPat.getPointer () == expand->getPatternType ().getPointer ())
5166
+ return *this ;
5167
+
5168
+ llvm::DenseMap<TypeBase *, PackType *> expansions;
5169
+ unsigned arity;
5170
+ std::tie (expansions, arity) = std::move (gather).intoExpansions ();
5171
+ if (expansions.empty ()) {
5172
+ // If we didn't find any expansions, either the caller wasn't interested
5173
+ // in expanding this pack, or something has gone wrong. Leave off the
5174
+ // expansion and return the transformed type.
5175
+ return PackExpansionType::get (transformedPat);
5176
+ }
5177
+
5178
+ SmallVector<Type, 8 > elts;
5179
+ elts.reserve (arity);
5180
+ // Perform the expansion element-wise according to the maximum arity we
5181
+ // picked up during the gather step above.
5182
+ //
5183
+ // For a pack expansion (F<... T..., U..., ...>) and mapping
5184
+ //
5185
+ // T... -> <X, Y, Z>
5186
+ // U... -> <A, B, C>
5187
+ //
5188
+ // The expected expansion is
5189
+ //
5190
+ // <F<... X, A, ...>, F<... Y, B, ...>, F<... Z, C, ...> ...>
5191
+ for (unsigned i = 0 ; i < arity; ++i) {
5192
+ struct ElementExpander {
5193
+ const llvm::DenseMap<TypeBase *, PackType *> &expansions;
5194
+ llvm::function_ref<Optional<Type>(TypeBase *)> outerFn;
5195
+ unsigned index;
5196
+
5197
+ public:
5198
+ Optional<Type> operator ()(TypeBase *input) {
5199
+ // FIXME: Does this need to do bounds checking?
5200
+ if (PackType *element = expansions.lookup (input))
5201
+ return element->getElementType (index);
5202
+ return outerFn (input);
5203
+ }
5204
+ };
5205
+
5206
+ auto expandedElt = expand->getPatternType ().transformRec (
5207
+ ElementExpander{expansions, fn, i});
5208
+ if (!expandedElt)
5209
+ return Type ();
5210
+
5211
+ elts.push_back (expandedElt);
5212
+ }
5213
+ return PackType::get (base->getASTContext (), elts);
5214
+ }
5215
+
5064
5216
case TypeKind::Tuple: {
5065
5217
auto tuple = cast<TupleType>(base);
5066
5218
bool anyChanged = false ;
5067
5219
SmallVector<TupleTypeElt, 4 > elements;
5068
5220
unsigned Index = 0 ;
5069
5221
for (const auto &elt : tuple->getElements ()) {
5070
- Type eltTy = elt.getType ().transformRec (fn);
5071
- if (!eltTy)
5222
+ Type eltTy = elt.getType ();
5223
+ Type transformedEltTy = eltTy.transformRec (fn);
5224
+ if (!transformedEltTy)
5072
5225
return Type ();
5073
5226
5074
5227
// If nothing has changed, just keep going.
5075
- if (!anyChanged && eltTy.getPointer () == elt.getType ().getPointer ()) {
5228
+ if (!anyChanged &&
5229
+ transformedEltTy.getPointer () == elt.getType ().getPointer ()) {
5076
5230
++Index;
5077
5231
continue ;
5078
5232
}
@@ -5086,9 +5240,18 @@ case TypeKind::Id:
5086
5240
anyChanged = true ;
5087
5241
}
5088
5242
5089
- // Add the new tuple element, with the new type, no initializer,
5090
- elements.push_back (elt.getWithType (eltTy));
5091
- ++Index;
5243
+ if (eltTy->isTypeSequenceParameter () &&
5244
+ transformedEltTy->is <PackType>()) {
5245
+ assert (anyChanged);
5246
+ // Splat the tuple in by copying in all of the transformed elements.
5247
+ auto tuple = dyn_cast<PackType>(transformedEltTy.getPointer ());
5248
+ elements.append (tuple->getElementTypes ().begin (),
5249
+ tuple->getElementTypes ().end ());
5250
+ } else {
5251
+ // Add the new tuple element, with the transformed type.
5252
+ elements.push_back (elt.getWithType (transformedEltTy));
5253
+ ++Index;
5254
+ }
5092
5255
}
5093
5256
5094
5257
if (!anyChanged)
@@ -5505,6 +5668,8 @@ ReferenceCounting TypeBase::getReferenceCounting() {
5505
5668
case TypeKind::SILToken:
5506
5669
case TypeKind::GenericTypeParam:
5507
5670
case TypeKind::DependentMember:
5671
+ case TypeKind::Pack:
5672
+ case TypeKind::PackExpansion:
5508
5673
#define REF_STORAGE (Name, ...) \
5509
5674
case TypeKind::Name##Storage:
5510
5675
#include " swift/AST/ReferenceStorage.def"
0 commit comments