@@ -647,6 +647,15 @@ template<> struct DenseMapInfo<swift::GenericSignatureBuilder::ExplicitRequireme
647
647
648
648
}
649
649
650
+ namespace {
651
+ struct ConflictingConcreteTypeRequirement {
652
+ ExplicitRequirement concreteTypeRequirement;
653
+ ExplicitRequirement otherRequirement;
654
+ Type resolvedConcreteType;
655
+ RequirementRHS otherRHS;
656
+ };
657
+ }
658
+
650
659
struct GenericSignatureBuilder ::Implementation {
651
660
// / Allocator.
652
661
llvm::BumpPtrAllocator Allocator;
@@ -716,6 +725,11 @@ struct GenericSignatureBuilder::Implementation {
716
725
// / the second one is recorded here. Built by computeRedundantRequirements().
717
726
llvm::DenseMap<ExplicitRequirement, RequirementRHS> ConflictingRequirements;
718
727
728
+ // / Pairs of conflicting concrete type vs. superclass/layout/conformance
729
+ // / requirements.
730
+ std::vector<ConflictingConcreteTypeRequirement>
731
+ ConflictingConcreteTypeRequirements;
732
+
719
733
#ifndef NDEBUG
720
734
// / Whether we've already computed redundant requiremnts.
721
735
bool computedRedundantRequirements = false ;
@@ -5775,10 +5789,25 @@ class RedundantRequirementGraph {
5775
5789
5776
5790
public:
5777
5791
template <typename T>
5778
- void addConstraintsFromEquivClass (
5792
+ void handleConstraintsImpliedByConcrete (
5793
+ RequirementKind kind,
5794
+ const SmallVectorImpl<Constraint<T>> &impliedByConcrete,
5795
+ const Optional<ExplicitRequirement> &concreteTypeRequirement) {
5796
+ for (auto constraint : impliedByConcrete) {
5797
+ if (constraint.source ->isDerivedNonRootRequirement ())
5798
+ continue ;
5799
+
5800
+ auto req = ExplicitRequirement::fromExplicitConstraint (kind, constraint);
5801
+ addEdge (*concreteTypeRequirement, req);
5802
+ }
5803
+ }
5804
+
5805
+ template <typename T>
5806
+ Optional<ExplicitRequirement>
5807
+ addConstraintsFromEquivClass (
5779
5808
RequirementKind kind,
5780
- SmallVectorImpl<Constraint<T>> &exact,
5781
- SmallVectorImpl<Constraint<T>> &lessSpecific) {
5809
+ const SmallVectorImpl<Constraint<T>> &exact,
5810
+ const SmallVectorImpl<Constraint<T>> &lessSpecific) {
5782
5811
// The set of 'redundant explicit requirements', which are known to be less
5783
5812
// specific than some other explicit requirements. An example is a type
5784
5813
// parameter with multiple superclass constraints:
@@ -5843,6 +5872,13 @@ class RedundantRequirementGraph {
5843
5872
redundantExplicitReqs.push_back (req);
5844
5873
}
5845
5874
5875
+ // Get the "best" explicit requirement that implies the rest.
5876
+ Optional<ExplicitRequirement> result;
5877
+ if (!rootReqs.empty ())
5878
+ result = rootReqs[0 ];
5879
+ else if (!explicitReqs.empty ())
5880
+ result = explicitReqs[0 ];
5881
+
5846
5882
// If all requirements are derived, there is nothing to do.
5847
5883
if (explicitReqs.empty ()) {
5848
5884
if (!redundantExplicitReqs.empty ()) {
@@ -5853,7 +5889,7 @@ class RedundantRequirementGraph {
5853
5889
}
5854
5890
}
5855
5891
}
5856
- return ;
5892
+ return result ;
5857
5893
}
5858
5894
5859
5895
// If there are multiple most specific explicit requirements, they will form a cycle.
@@ -5876,6 +5912,8 @@ class RedundantRequirementGraph {
5876
5912
for (auto rootReq : rootReqs) {
5877
5913
addEdge (rootReq, explicitReqs[0 ]);
5878
5914
}
5915
+
5916
+ return result;
5879
5917
}
5880
5918
5881
5919
private:
@@ -6241,8 +6279,11 @@ void GenericSignatureBuilder::computeRedundantRequirements() {
6241
6279
exact, lessSpecific);
6242
6280
}
6243
6281
6282
+ Type resolvedConcreteType;
6283
+ Optional<ExplicitRequirement> concreteTypeRequirement;
6284
+
6244
6285
if (equivClass.concreteType ) {
6245
- Type resolvedConcreteType =
6286
+ resolvedConcreteType =
6246
6287
getCanonicalTypeInContext (equivClass.concreteType , { });
6247
6288
6248
6289
SmallVector<Constraint<Type>, 2 > exact;
@@ -6285,17 +6326,22 @@ void GenericSignatureBuilder::computeRedundantRequirements() {
6285
6326
lessSpecific.push_back (constraint);
6286
6327
}
6287
6328
6288
- graph.addConstraintsFromEquivClass (RequirementKind::SameType,
6289
- exact, lessSpecific);
6329
+ concreteTypeRequirement =
6330
+ graph.addConstraintsFromEquivClass (RequirementKind::SameType,
6331
+ exact, lessSpecific);
6290
6332
}
6291
6333
6334
+ Type resolvedSuperclass;
6335
+ Optional<ExplicitRequirement> superclassRequirement;
6336
+
6292
6337
if (equivClass.superclass ) {
6293
6338
// Resolve any thus-far-unresolved dependent types.
6294
- Type resolvedSuperclass =
6295
- getCanonicalTypeInContext (equivClass.superclass , { } );
6339
+ resolvedSuperclass =
6340
+ getCanonicalTypeInContext (equivClass.superclass , getGenericParams () );
6296
6341
6297
6342
SmallVector<Constraint<Type>, 2 > exact;
6298
6343
SmallVector<Constraint<Type>, 2 > lessSpecific;
6344
+ SmallVector<Constraint<Type>, 2 > impliedByConcrete;
6299
6345
6300
6346
for (const auto &constraint : equivClass.superclassConstraints ) {
6301
6347
auto *source = constraint.source ;
@@ -6312,6 +6358,12 @@ void GenericSignatureBuilder::computeRedundantRequirements() {
6312
6358
if (derivedViaConcrete)
6313
6359
continue ;
6314
6360
6361
+ if (resolvedConcreteType) {
6362
+ Type resolvedType = getCanonicalTypeInContext (t, { });
6363
+ if (resolvedType->isExactSuperclassOf (resolvedConcreteType))
6364
+ impliedByConcrete.push_back (constraint);
6365
+ }
6366
+
6315
6367
if (t->isEqual (resolvedSuperclass)) {
6316
6368
exact.push_back (constraint);
6317
6369
continue ;
@@ -6333,12 +6385,16 @@ void GenericSignatureBuilder::computeRedundantRequirements() {
6333
6385
std::make_pair (req, resolvedSuperclass));
6334
6386
}
6335
6387
6336
- // FIXME: Check for a conflict via the concrete type.
6337
6388
lessSpecific.push_back (constraint);
6338
6389
}
6339
6390
6340
- graph.addConstraintsFromEquivClass (RequirementKind::Superclass,
6341
- exact, lessSpecific);
6391
+ superclassRequirement =
6392
+ graph.addConstraintsFromEquivClass (RequirementKind::Superclass,
6393
+ exact, lessSpecific);
6394
+
6395
+ graph.handleConstraintsImpliedByConcrete (RequirementKind::Superclass,
6396
+ impliedByConcrete,
6397
+ concreteTypeRequirement);
6342
6398
}
6343
6399
6344
6400
if (equivClass.layout ) {
@@ -6382,6 +6438,14 @@ void GenericSignatureBuilder::computeRedundantRequirements() {
6382
6438
graph.addConstraintsFromEquivClass (RequirementKind::Layout,
6383
6439
exact, lessSpecific);
6384
6440
}
6441
+
6442
+ if (resolvedConcreteType && resolvedSuperclass) {
6443
+ if (!resolvedSuperclass->isExactSuperclassOf (resolvedConcreteType)) {
6444
+ Impl->ConflictingConcreteTypeRequirements .push_back (
6445
+ {*concreteTypeRequirement, *superclassRequirement,
6446
+ resolvedConcreteType, resolvedSuperclass});
6447
+ }
6448
+ }
6385
6449
}
6386
6450
6387
6451
auto &SM = getASTContext ().SourceMgr ;
@@ -6403,6 +6467,7 @@ GenericSignatureBuilder::finalize(TypeArrayView<GenericTypeParamType> genericPar
6403
6467
6404
6468
computeRedundantRequirements ();
6405
6469
diagnoseRedundantRequirements ();
6470
+ diagnoseConflictingConcreteTypeRequirements ();
6406
6471
6407
6472
assert (!Impl->finalized && " Already finalized builder" );
6408
6473
#ifndef NDEBUG
@@ -7151,14 +7216,93 @@ void GenericSignatureBuilder::diagnoseRedundantRequirements() const {
7151
7216
break ;
7152
7217
}
7153
7218
7154
- case RequirementKind::Superclass:
7219
+ case RequirementKind::Superclass: {
7220
+ auto superclass = req.getRHS ().get <Type>();
7221
+
7222
+ auto conflict = Impl->ConflictingRequirements .find (req);
7223
+ if (conflict != Impl->ConflictingRequirements .end ()) {
7224
+ Impl->HadAnyError = true ;
7225
+
7226
+ auto otherSuperclass = conflict->second .get <Type>();
7227
+
7228
+ Context.Diags .diagnose (loc, diag::conflicting_superclass_constraints,
7229
+ subjectType, superclass, otherSuperclass);
7230
+
7231
+ for (auto otherReq : found->second ) {
7232
+ auto *otherSource = otherReq.getSource ();
7233
+ auto otherLoc = otherSource->getLoc ();
7234
+ if (otherLoc.isInvalid ())
7235
+ continue ;
7236
+
7237
+ Context.Diags .diagnose (otherLoc, diag::conflicting_superclass_constraint,
7238
+ subjectType, otherSuperclass);
7239
+ }
7240
+ } else {
7241
+ Context.Diags .diagnose (loc, diag::redundant_superclass_constraint,
7242
+ subjectType, superclass);
7243
+
7244
+ for (auto otherReq : found->second ) {
7245
+ auto *otherSource = otherReq.getSource ();
7246
+ auto otherLoc = otherSource->getLoc ();
7247
+ if (otherLoc.isInvalid ())
7248
+ continue ;
7249
+
7250
+ Context.Diags .diagnose (otherLoc, diag::superclass_redundancy_here,
7251
+ subjectType, superclass);
7252
+ }
7253
+ }
7254
+
7255
+ break ;
7256
+ }
7257
+
7155
7258
case RequirementKind::SameType:
7156
7259
// TODO
7157
7260
break ;
7158
7261
}
7159
7262
}
7160
7263
}
7161
7264
7265
+ void GenericSignatureBuilder::diagnoseConflictingConcreteTypeRequirements () const {
7266
+ for (auto pair : Impl->ConflictingConcreteTypeRequirements ) {
7267
+ SourceLoc loc = pair.concreteTypeRequirement .getSource ()->getLoc ();
7268
+ SourceLoc otherLoc = pair.otherRequirement .getSource ()->getLoc ();
7269
+
7270
+ Type otherRHS = pair.otherRHS .get <Type>();
7271
+
7272
+ if (loc.isInvalid () && otherLoc.isInvalid ())
7273
+ continue ;
7274
+
7275
+ auto subjectType = pair.concreteTypeRequirement .getSource ()->getStoredType ();
7276
+ SourceLoc subjectLoc = (loc.isInvalid () ? otherLoc : loc);
7277
+
7278
+ Impl->HadAnyError = true ;
7279
+
7280
+ switch (pair.otherRequirement .getKind ()) {
7281
+ case RequirementKind::Superclass: {
7282
+ Context.Diags .diagnose (subjectLoc, diag::type_does_not_inherit,
7283
+ subjectType, pair.resolvedConcreteType , otherRHS);
7284
+
7285
+ if (otherLoc.isValid ()) {
7286
+ Context.Diags .diagnose (otherLoc, diag::superclass_redundancy_here,
7287
+ subjectType, otherRHS);
7288
+ }
7289
+
7290
+ break ;
7291
+ }
7292
+
7293
+ case RequirementKind::Conformance:
7294
+ case RequirementKind::Layout:
7295
+ case RequirementKind::SameType:
7296
+ llvm_unreachable (" TODO" );
7297
+ }
7298
+
7299
+ if (loc.isValid ()) {
7300
+ Context.Diags .diagnose (loc, diag::same_type_redundancy_here,
7301
+ 1 , subjectType, pair.resolvedConcreteType );
7302
+ }
7303
+ }
7304
+ }
7305
+
7162
7306
namespace swift {
7163
7307
bool operator <(const DerivedSameTypeComponent &lhs,
7164
7308
const DerivedSameTypeComponent &rhs) {
@@ -7978,81 +8122,7 @@ void GenericSignatureBuilder::checkSuperclassConstraints(
7978
8122
EquivalenceClass *equivClass) {
7979
8123
assert (equivClass->superclass && " No superclass constraint?" );
7980
8124
7981
- // Resolve any thus-far-unresolved dependent types.
7982
- Type resolvedSuperclass =
7983
- getCanonicalTypeInContext (equivClass->superclass , genericParams);
7984
-
7985
- auto representativeConstraint =
7986
- checkConstraintList<Type>(
7987
- genericParams, equivClass->superclassConstraints , RequirementKind::Superclass,
7988
- [&](const ConcreteConstraint &constraint) {
7989
- if (constraint.value ->isEqual (resolvedSuperclass))
7990
- return true ;
7991
-
7992
- Type resolvedType =
7993
- getCanonicalTypeInContext (constraint.value , { });
7994
- return resolvedType->isEqual (resolvedSuperclass);
7995
- },
7996
- [&](const Constraint<Type> &constraint) {
7997
- Type superclass = constraint.value ;
7998
-
7999
- // If this class is a superclass of the "best"
8000
- if (superclass->isExactSuperclassOf (resolvedSuperclass))
8001
- return ConstraintRelation::Redundant;
8002
-
8003
- // Otherwise, it conflicts.
8004
- return ConstraintRelation::Conflicting;
8005
- },
8006
- diag::requires_superclass_conflict,
8007
- diag::redundant_superclass_constraint,
8008
- diag::superclass_redundancy_here);
8009
-
8010
- // If we have a concrete type, check it.
8011
- // FIXME: Substitute into the concrete type.
8012
- if (equivClass->concreteType ) {
8013
- Type resolvedConcreteType =
8014
- getCanonicalTypeInContext (equivClass->concreteType , genericParams);
8015
- auto existing = equivClass->findAnyConcreteConstraintAsWritten ();
8016
- // Make sure the concrete type fulfills the superclass requirement.
8017
- if (!equivClass->superclass ->isExactSuperclassOf (resolvedConcreteType)){
8018
- Impl->HadAnyError = true ;
8019
- if (existing) {
8020
- Diags.diagnose (existing->source ->getLoc (), diag::type_does_not_inherit,
8021
- existing->getSubjectDependentType (getGenericParams ()),
8022
- existing->value , equivClass->superclass );
8023
-
8024
- if (representativeConstraint.source ->getLoc ().isValid ()) {
8025
- Diags.diagnose (representativeConstraint.source ->getLoc (),
8026
- diag::superclass_redundancy_here,
8027
- representativeConstraint.source ->classifyDiagKind (),
8028
- representativeConstraint.getSubjectDependentType (
8029
- genericParams),
8030
- equivClass->superclass );
8031
- }
8032
- } else if (representativeConstraint.source ->getLoc ().isValid ()) {
8033
- Diags.diagnose (representativeConstraint.source ->getLoc (),
8034
- diag::type_does_not_inherit,
8035
- representativeConstraint.getSubjectDependentType (
8036
- genericParams),
8037
- resolvedConcreteType, equivClass->superclass );
8038
- }
8039
- } else if (representativeConstraint.source ->shouldDiagnoseRedundancy (true )
8040
- && existing &&
8041
- existing->source ->shouldDiagnoseRedundancy (false )) {
8042
- // It does fulfill the requirement; diagnose the redundancy.
8043
- Diags.diagnose (representativeConstraint.source ->getLoc (),
8044
- diag::redundant_superclass_constraint,
8045
- representativeConstraint.getSubjectDependentType (
8046
- genericParams),
8047
- representativeConstraint.value );
8048
-
8049
- Diags.diagnose (existing->source ->getLoc (),
8050
- diag::same_type_redundancy_here,
8051
- existing->source ->classifyDiagKind (),
8052
- existing->getSubjectDependentType (genericParams),
8053
- existing->value );
8054
- }
8055
- }
8125
+ removeSelfDerived (*this , equivClass->superclassConstraints , /* proto=*/ nullptr );
8056
8126
}
8057
8127
8058
8128
void GenericSignatureBuilder::checkLayoutConstraints (
0 commit comments