@@ -827,6 +827,9 @@ void GenericSignature::verify(ArrayRef<Requirement> reqts) const {
827
827
// We collect conformance requirements to check that they're minimal.
828
828
llvm::SmallDenseMap<CanType, SmallVector<ProtocolDecl *, 2 >, 2 > conformances;
829
829
830
+ // We collect same-type requirements to check that they're minimal.
831
+ llvm::SmallDenseMap<CanType, SmallVector<Type, 2 >, 2 > sameTypeComponents;
832
+
830
833
// Check that the requirements satisfy certain invariants.
831
834
for (unsigned idx : indices (reqts)) {
832
835
const auto &reqt = reqts[idx].getCanonical ();
@@ -873,6 +876,10 @@ void GenericSignature::verify(ArrayRef<Requirement> reqts) const {
873
876
874
877
auto firstType = reqt.getFirstType ();
875
878
auto secondType = reqt.getSecondType ();
879
+
880
+ auto canType = canSig->getCanonicalTypeInContext (firstType);
881
+ auto &component = sameTypeComponents[canType];
882
+
876
883
if (!hasCanonicalOrConcreteParent (firstType)) {
877
884
llvm::errs () << " Left hand side does not have a canonical parent: " ;
878
885
reqt.dump (llvm::errs ());
@@ -893,13 +900,34 @@ void GenericSignature::verify(ArrayRef<Requirement> reqts) const {
893
900
llvm::errs () << " \n " ;
894
901
abort ();
895
902
}
903
+
904
+ if (component.empty ()) {
905
+ component.push_back (firstType);
906
+ } else if (!component.back ()->isEqual (firstType)) {
907
+ llvm::errs () << " Same-type requirement within an equiv. class "
908
+ << " is out-of-order: " ;
909
+ reqt.dump (llvm::errs ());
910
+ llvm::errs () << " \n " ;
911
+ abort ();
912
+ }
913
+
914
+ component.push_back (secondType);
896
915
} else {
897
916
if (!canSig->isCanonicalTypeInContext (secondType)) {
898
917
llvm::errs () << " Right hand side is not canonical: " ;
899
918
reqt.dump (llvm::errs ());
900
919
llvm::errs () << " \n " ;
901
920
abort ();
902
921
}
922
+
923
+ if (component.empty ()) {
924
+ component.push_back (secondType);
925
+ } else if (!component.back ()->isEqual (secondType)) {
926
+ llvm::errs () << " Inconsistent concrete requirement in equiv. class: " ;
927
+ reqt.dump (llvm::errs ());
928
+ llvm::errs () << " \n " ;
929
+ abort ();
930
+ }
903
931
}
904
932
break ;
905
933
}
@@ -925,33 +953,6 @@ void GenericSignature::verify(ArrayRef<Requirement> reqts) const {
925
953
abort ();
926
954
}
927
955
928
- // If we have two same-type requirements where the left-hand sides differ
929
- // but fall into the same equivalence class, we can check the form.
930
- if (compareLHS < 0 && reqt.getKind () == RequirementKind::SameType &&
931
- prevReqt.getKind () == RequirementKind::SameType &&
932
- canSig->areSameTypeParameterInContext (prevReqt.getFirstType (),
933
- reqt.getFirstType ())) {
934
- // If it's a it's a type parameter, make sure the equivalence class is
935
- // wired together sanely.
936
- if (prevReqt.getSecondType ()->isTypeParameter ()) {
937
- if (!prevReqt.getSecondType ()->isEqual (reqt.getFirstType ())) {
938
- llvm::errs () << " Same-type requirement within an equiv. class "
939
- << " is out-of-order: " ;
940
- reqt.dump (llvm::errs ());
941
- llvm::errs () << " \n " ;
942
- abort ();
943
- }
944
- } else {
945
- // Otherwise, the concrete types must match up.
946
- if (!prevReqt.getSecondType ()->isEqual (reqt.getSecondType ())) {
947
- llvm::errs () << " Inconsistent concrete requirement in equiv. class: " ;
948
- reqt.dump (llvm::errs ());
949
- llvm::errs () << " \n " ;
950
- abort ();
951
- }
952
- }
953
- }
954
-
955
956
// If we have a concrete same-type requirement, we shouldn't have any
956
957
// other requirements on the same type.
957
958
if (reqt.getKind () == RequirementKind::SameType &&
@@ -974,7 +975,7 @@ void GenericSignature::verify(ArrayRef<Requirement> reqts) const {
974
975
}
975
976
976
977
// Make sure we don't have redundant protocol conformance requirements.
977
- for (auto pair : conformances) {
978
+ for (const auto & pair : conformances) {
978
979
const auto &protos = pair.second ;
979
980
auto canonicalProtos = protos;
980
981
@@ -992,6 +993,18 @@ void GenericSignature::verify(ArrayRef<Requirement> reqts) const {
992
993
abort ();
993
994
}
994
995
}
996
+
997
+ // Check same-type components for consistency.
998
+ for (const auto &pair : sameTypeComponents) {
999
+ if (pair.second .front ()->isTypeParameter () &&
1000
+ !canSig->isCanonicalTypeInContext (pair.second .front ())) {
1001
+ llvm::errs () << " Abstract same-type requirement involving concrete types\n " ;
1002
+ llvm::errs () << " Canonical type: " << pair.first << " \n " ;
1003
+ llvm::errs () << " Left hand side of first requirement: "
1004
+ << pair.second .front () << " \n " ;
1005
+ abort ();
1006
+ }
1007
+ }
995
1008
}
996
1009
997
1010
static Type stripBoundDependentMemberTypes (Type t) {
0 commit comments