25
25
#include " swift/AST/InFlightSubstitution.h"
26
26
#include " swift/AST/LazyResolver.h"
27
27
#include " swift/AST/Module.h"
28
+ #include " swift/AST/PackConformance.h"
28
29
#include " swift/AST/TypeCheckRequests.h"
29
30
#include " swift/AST/Types.h"
30
31
#include " swift/Basic/Statistic.h"
@@ -933,6 +934,38 @@ ProtocolConformance::subst(TypeSubstitutionFn subs,
933
934
return subst (IFS);
934
935
}
935
936
937
+ // / Check if the replacement is a one-element pack with a scalar type.
938
+ static bool isVanishingTupleConformance (
939
+ RootProtocolConformance *generic,
940
+ SubstitutionMap substitutions) {
941
+ if (!isa<BuiltinTupleDecl>(generic->getDeclContext ()->getSelfNominalTypeDecl ()))
942
+ return false ;
943
+
944
+ auto replacementTypes = substitutions.getReplacementTypes ();
945
+ assert (replacementTypes.size () == 1 );
946
+ auto packType = replacementTypes[0 ]->castTo <PackType>();
947
+
948
+ return (packType->getNumElements () == 1 &&
949
+ !packType->getElementTypes ()[0 ]->is <PackExpansionType>());
950
+ }
951
+
952
+ // / Don't form a tuple conformance if the substituted type is unwrapped
953
+ // / from a one-element tuple.
954
+ // /
955
+ // / That is, [(repeat each T): P] ⊗ {each T := Pack{U};
956
+ // / [each T: P]: Pack{ [U: P] }}
957
+ // / => [U: P]
958
+ static ProtocolConformanceRef unwrapVanishingTupleConformance (
959
+ SubstitutionMap substitutions) {
960
+ auto conformances = substitutions.getConformances ();
961
+ assert (conformances.size () == 1 );
962
+ assert (conformances[0 ].isPack ());
963
+ auto packConformance = conformances[0 ].getPack ();
964
+
965
+ assert (packConformance->getPatternConformances ().size () == 1 );
966
+ return packConformance->getPatternConformances ()[0 ];
967
+ }
968
+
936
969
ProtocolConformanceRef
937
970
ProtocolConformance::subst (InFlightSubstitution &IFS) const {
938
971
auto *mutableThis = const_cast <ProtocolConformance *>(this );
@@ -951,6 +984,9 @@ ProtocolConformance::subst(InFlightSubstitution &IFS) const {
951
984
auto *generic = cast<NormalProtocolConformance>(mutableThis);
952
985
auto subMap = SubstitutionMap::get (getGenericSignature (), IFS);
953
986
987
+ if (isVanishingTupleConformance (generic, subMap))
988
+ return unwrapVanishingTupleConformance (subMap);
989
+
954
990
auto &ctx = substType->getASTContext ();
955
991
auto *concrete = ctx.getSpecializedConformance (substType, generic, subMap);
956
992
@@ -1016,6 +1052,9 @@ ProtocolConformance::subst(InFlightSubstitution &IFS) const {
1016
1052
auto *generic = spec->getGenericConformance ();
1017
1053
auto subMap = spec->getSubstitutionMap ().subst (IFS);
1018
1054
1055
+ if (isVanishingTupleConformance (generic, subMap))
1056
+ return unwrapVanishingTupleConformance (subMap);
1057
+
1019
1058
auto substType = spec->getType ().subst (IFS);
1020
1059
1021
1060
auto &ctx = substType->getASTContext ();
0 commit comments