@@ -350,6 +350,12 @@ bool CanType::isObjCExistentialTypeImpl(CanType type) {
350
350
return type.getExistentialLayout().isObjC();
351
351
}
352
352
353
+ bool CanType::isTypeErasedGenericClassTypeImpl(CanType type) {
354
+ if (auto nom = type->getAnyNominal())
355
+ return nom->isTypeErasedGenericClass();
356
+ return false;
357
+ }
358
+
353
359
bool TypeBase::isSpecialized() {
354
360
Type t = getCanonicalType();
355
361
@@ -822,6 +828,32 @@ Type TypeBase::replaceCovariantResultType(Type newResultType,
822
828
return FunctionType::get(inputType, resultType, fnType->getExtInfo());
823
829
}
824
830
831
+ /// Whether this parameter accepts an unlabeled trailing closure argument
832
+ /// using the more-restrictive forward-scan rule.
833
+ static bool allowsUnlabeledTrailingClosureParameter(const ParamDecl *param) {
834
+ // inout parameters never allow an unlabeled trailing closure.
835
+ if (param->isInOut())
836
+ return false;
837
+
838
+ Type paramType = param->isVariadic() ? param->getVarargBaseTy()
839
+ : param->getInterfaceType();
840
+ paramType = paramType->getRValueType()->lookThroughAllOptionalTypes();
841
+
842
+ // For autoclosure parameters, look through the autoclosure result type
843
+ // to get the actual argument type.
844
+ if (param->isAutoClosure()) {
845
+ auto fnType = paramType->getAs<AnyFunctionType>();
846
+ if (!fnType)
847
+ return false;
848
+
849
+ paramType = fnType->getResult()->lookThroughAllOptionalTypes();
850
+ }
851
+
852
+ // After lookup through all optional types, this parameter allows an
853
+ // unlabeled trailing closure if it is (structurally) a function type.
854
+ return paramType->is<AnyFunctionType>();
855
+ }
856
+
825
857
ParameterListInfo::ParameterListInfo(
826
858
ArrayRef<AnyFunctionType::Param> params,
827
859
const ValueDecl *paramOwner,
@@ -831,7 +863,7 @@ ParameterListInfo::ParameterListInfo(
831
863
// No parameter owner means no parameter list means no default arguments
832
864
// - hand back the zeroed bitvector.
833
865
//
834
- // FIXME: We ought to not request default argument info in this case.
866
+ // FIXME: We ought to not request paramer list info in this case.
835
867
if (!paramOwner)
836
868
return;
837
869
@@ -865,12 +897,21 @@ ParameterListInfo::ParameterListInfo(
865
897
if (params.size() != paramList->size())
866
898
return;
867
899
868
- // Note which parameters have default arguments and/or function builders.
900
+ // Now we have enough information to determine which parameters accept
901
+ // unlabled trailing closures.
902
+ acceptsUnlabeledTrailingClosures.resize(params.size());
903
+
904
+ // Note which parameters have default arguments and/or accept unlabeled
905
+ // trailing closure arguments with the forward-scan rule.
869
906
for (auto i : range(0, params.size())) {
870
907
auto param = paramList->get(i);
871
908
if (param->isDefaultArgument()) {
872
909
defaultArguments.set(i);
873
910
}
911
+
912
+ if (allowsUnlabeledTrailingClosureParameter(param)) {
913
+ acceptsUnlabeledTrailingClosures.set(i);
914
+ }
874
915
}
875
916
}
876
917
@@ -879,6 +920,12 @@ bool ParameterListInfo::hasDefaultArgument(unsigned paramIdx) const {
879
920
: false;
880
921
}
881
922
923
+ bool ParameterListInfo::acceptsUnlabeledTrailingClosureArgument(
924
+ unsigned paramIdx) const {
925
+ return paramIdx >= acceptsUnlabeledTrailingClosures.size() ||
926
+ acceptsUnlabeledTrailingClosures[paramIdx];
927
+ }
928
+
882
929
/// Turn a param list into a symbolic and printable representation that does not
883
930
/// include the types, something like (_:, b:, c:)
884
931
std::string swift::getParamListAsString(ArrayRef<AnyFunctionType::Param> params) {
@@ -4261,17 +4308,27 @@ case TypeKind::Id:
4261
4308
case TypeKind::SILFunction: {
4262
4309
auto fnTy = cast<SILFunctionType>(base);
4263
4310
bool changed = false;
4264
-
4311
+ auto hasTypeErasedGenericClassType = [](Type ty) -> bool {
4312
+ return ty.findIf([](Type subType) -> bool {
4313
+ if (subType->getCanonicalType().isTypeErasedGenericClassType())
4314
+ return true;
4315
+ else
4316
+ return false;
4317
+ });
4318
+ };
4265
4319
auto updateSubs = [&](SubstitutionMap &subs) -> bool {
4266
4320
// This interface isn't suitable for updating the substitution map in a
4267
4321
// substituted SILFunctionType.
4268
4322
// TODO(SILFunctionType): Is it suitable for any SILFunctionType??
4269
4323
SmallVector<Type, 4> newReplacements;
4270
4324
for (Type type : subs.getReplacementTypes()) {
4271
4325
auto transformed = type.transformRec(fn);
4272
- assert((type->isEqual(transformed)
4273
- || (type->hasTypeParameter() && transformed->hasTypeParameter()))
4274
- && "Substituted SILFunctionType can't be transformed into a concrete type");
4326
+ assert((type->isEqual(transformed) ||
4327
+ (type->hasTypeParameter() && transformed->hasTypeParameter()) ||
4328
+ (hasTypeErasedGenericClassType(type) &&
4329
+ hasTypeErasedGenericClassType(transformed))) &&
4330
+ "Substituted SILFunctionType can't be transformed into a "
4331
+ "concrete type");
4275
4332
newReplacements.push_back(transformed->getCanonicalType());
4276
4333
if (!type->isEqual(transformed))
4277
4334
changed = true;
0 commit comments