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"
@@ -918,63 +919,104 @@ bool ProtocolConformance::isVisibleFrom(const DeclContext *dc) const {
918
919
return true ;
919
920
}
920
921
921
- ProtocolConformance *
922
+ ProtocolConformanceRef
922
923
ProtocolConformance::subst (SubstitutionMap subMap,
923
924
SubstOptions options) const {
924
925
InFlightSubstitutionViaSubMap IFS (subMap, options);
925
926
return subst (IFS);
926
927
}
927
928
928
- ProtocolConformance *
929
+ ProtocolConformanceRef
929
930
ProtocolConformance::subst (TypeSubstitutionFn subs,
930
931
LookupConformanceFn conformances,
931
932
SubstOptions options) const {
932
933
InFlightSubstitution IFS (subs, conformances, options);
933
934
return subst (IFS);
934
935
}
935
936
936
- ProtocolConformance *
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
+
969
+ ProtocolConformanceRef
937
970
ProtocolConformance::subst (InFlightSubstitution &IFS) const {
971
+ auto *mutableThis = const_cast <ProtocolConformance *>(this );
972
+
938
973
switch (getKind ()) {
939
974
case ProtocolConformanceKind::Normal: {
940
975
auto origType = getType ();
941
976
if (!origType->hasTypeParameter () &&
942
977
!origType->hasArchetype ())
943
- return const_cast <ProtocolConformance *>( this );
978
+ return ProtocolConformanceRef (mutableThis );
944
979
945
980
auto substType = origType.subst (IFS);
946
981
if (substType->isEqual (origType))
947
- return const_cast <ProtocolConformance *>( this );
982
+ return ProtocolConformanceRef (mutableThis );
948
983
984
+ auto *generic = cast<NormalProtocolConformance>(mutableThis);
949
985
auto subMap = SubstitutionMap::get (getGenericSignature (), IFS);
950
986
951
- auto *mutableThis = const_cast <ProtocolConformance *>(this );
952
- return substType->getASTContext ()
953
- .getSpecializedConformance (substType,
954
- cast<NormalProtocolConformance>(mutableThis),
955
- subMap);
987
+ if (isVanishingTupleConformance (generic, subMap))
988
+ return unwrapVanishingTupleConformance (subMap);
989
+
990
+ auto &ctx = substType->getASTContext ();
991
+ auto *concrete = ctx.getSpecializedConformance (substType, generic, subMap);
992
+
993
+ return ProtocolConformanceRef (concrete);
956
994
}
995
+
957
996
case ProtocolConformanceKind::Builtin: {
958
997
auto origType = getType ();
959
998
if (!origType->hasTypeParameter () &&
960
999
!origType->hasArchetype ())
961
- return const_cast <ProtocolConformance *>( this );
1000
+ return ProtocolConformanceRef (mutableThis );
962
1001
963
1002
auto substType = origType.subst (IFS);
964
1003
965
1004
// We do an exact pointer equality check because subst() can
966
1005
// change sugar.
967
1006
if (substType.getPointer () == origType.getPointer ())
968
- return const_cast <ProtocolConformance *>( this );
1007
+ return ProtocolConformanceRef (mutableThis );
969
1008
970
1009
auto kind = cast<BuiltinProtocolConformance>(this )
971
1010
->getBuiltinConformanceKind ();
972
1011
973
- return substType->getASTContext ()
1012
+ auto *concrete = substType->getASTContext ()
974
1013
.getBuiltinConformance (substType, getProtocol (), kind);
1014
+ return ProtocolConformanceRef (concrete);
975
1015
}
1016
+
976
1017
case ProtocolConformanceKind::Self:
977
- return const_cast <ProtocolConformance*>(this );
1018
+ return ProtocolConformanceRef (mutableThis);
1019
+
978
1020
case ProtocolConformanceKind::Inherited: {
979
1021
// Substitute the base.
980
1022
auto inheritedConformance
@@ -983,31 +1025,42 @@ ProtocolConformance::subst(InFlightSubstitution &IFS) const {
983
1025
auto origType = getType ();
984
1026
if (!origType->hasTypeParameter () &&
985
1027
!origType->hasArchetype ()) {
986
- return const_cast <ProtocolConformance *>( this );
1028
+ return ProtocolConformanceRef (mutableThis );
987
1029
}
988
1030
989
1031
auto origBaseType = inheritedConformance->getType ();
990
1032
if (origBaseType->hasTypeParameter () ||
991
1033
origBaseType->hasArchetype ()) {
992
1034
// Substitute into the superclass.
993
- inheritedConformance = inheritedConformance->subst (IFS);
1035
+ auto substConformance = inheritedConformance->subst (IFS);
1036
+ if (!substConformance.isConcrete ())
1037
+ return substConformance;
1038
+
1039
+ inheritedConformance = substConformance.getConcrete ();
994
1040
}
995
1041
996
1042
auto substType = origType.subst (IFS);
997
- return substType->getASTContext ()
1043
+ auto *concrete = substType->getASTContext ()
998
1044
.getInheritedConformance (substType, inheritedConformance);
1045
+ return ProtocolConformanceRef (concrete);
999
1046
}
1047
+
1000
1048
case ProtocolConformanceKind::Specialized: {
1001
1049
// Substitute the substitutions in the specialized conformance.
1002
1050
auto spec = cast<SpecializedProtocolConformance>(this );
1003
- auto genericConformance = spec->getGenericConformance ();
1004
- auto subMap = spec->getSubstitutionMap ();
1005
1051
1006
- auto origType = getType ();
1007
- auto substType = origType.subst (IFS);
1008
- return substType->getASTContext ()
1009
- .getSpecializedConformance (substType, genericConformance,
1010
- subMap.subst (IFS));
1052
+ auto *generic = spec->getGenericConformance ();
1053
+ auto subMap = spec->getSubstitutionMap ().subst (IFS);
1054
+
1055
+ if (isVanishingTupleConformance (generic, subMap))
1056
+ return unwrapVanishingTupleConformance (subMap);
1057
+
1058
+ auto substType = spec->getType ().subst (IFS);
1059
+
1060
+ auto &ctx = substType->getASTContext ();
1061
+ auto *concrete = ctx.getSpecializedConformance (substType, generic, subMap);
1062
+
1063
+ return ProtocolConformanceRef (concrete);
1011
1064
}
1012
1065
}
1013
1066
llvm_unreachable (" bad ProtocolConformanceKind" );
0 commit comments