@@ -704,13 +704,18 @@ struct GenericSignatureBuilder::Implementation {
704
704
SmallVector<Requirement, 2 > ExplicitSameTypeRequirements;
705
705
706
706
// / A mapping of redundant explicit requirements to the best root requirement
707
- // / that implies them.
707
+ // / that implies them. Built by computeRedundantRequirements().
708
708
using RedundantRequirementMap =
709
709
llvm::DenseMap<ExplicitRequirement,
710
710
llvm::SmallDenseSet<ExplicitRequirement, 2 >>;
711
711
712
712
RedundantRequirementMap RedundantRequirements;
713
713
714
+ // / Requirements which conflict with other requirements, for example if a
715
+ // / there are two unrelated superclass requirements on the same type,
716
+ // / the second one is recorded here. Built by computeRedundantRequirements().
717
+ llvm::DenseMap<ExplicitRequirement, RequirementRHS> ConflictingRequirements;
718
+
714
719
#ifndef NDEBUG
715
720
// / Whether we've already computed redundant requiremnts.
716
721
bool computedRedundantRequirements = false ;
@@ -5769,12 +5774,11 @@ class RedundantRequirementGraph {
5769
5774
SmallVector<VertexID, 2 > stack;
5770
5775
5771
5776
public:
5772
- template <typename T, typename Fn >
5777
+ template <typename T>
5773
5778
void addConstraintsFromEquivClass (
5774
- GenericSignatureBuilder &builder,
5775
- const std::vector<Constraint<T>> &constraints,
5776
5779
RequirementKind kind,
5777
- Fn filter) {
5780
+ SmallVectorImpl<Constraint<T>> &exact,
5781
+ SmallVectorImpl<Constraint<T>> &lessSpecific) {
5778
5782
// The set of 'redundant explicit requirements', which are known to be less
5779
5783
// specific than some other explicit requirements. An example is a type
5780
5784
// parameter with multiple superclass constraints:
@@ -5802,15 +5806,8 @@ class RedundantRequirementGraph {
5802
5806
// These 'root requirements' imply the 'explicit requirements'.
5803
5807
SmallVector<ExplicitRequirement, 1 > rootReqs;
5804
5808
5805
- for (auto constraint : constraints) {
5806
- auto *source = constraint.source ;
5807
-
5808
- if (source->isDerivedNonRootRequirement ()) {
5809
- // If the derived requirement was filtered by our predicate, it doesn't
5810
- // make our explicit requirements redundant.
5811
- if (filter (constraint))
5812
- continue ;
5813
-
5809
+ for (auto constraint : exact) {
5810
+ if (constraint.source ->isDerivedNonRootRequirement ()) {
5814
5811
auto req = ExplicitRequirement::fromDerivedConstraint (kind, constraint);
5815
5812
5816
5813
rootReqs.push_back (req);
@@ -5825,16 +5822,27 @@ class RedundantRequirementGraph {
5825
5822
#endif
5826
5823
(void ) v;
5827
5824
5828
- // If the explicit requirement was filtered by our predicate, it doesn't
5829
- // make the other explicit requirements redundant.
5830
- if (filter (constraint)) {
5831
- redundantExplicitReqs.push_back (req);
5832
- } else {
5833
- explicitReqs.push_back (req);
5834
- }
5825
+ explicitReqs.push_back (req);
5835
5826
}
5836
5827
}
5837
5828
5829
+ for (auto constraint : lessSpecific) {
5830
+ if (constraint.source ->isDerivedNonRootRequirement ())
5831
+ continue ;
5832
+
5833
+ auto req = ExplicitRequirement::fromExplicitConstraint (kind, constraint);
5834
+
5835
+ VertexID v = addVertex (req);
5836
+ #ifndef NDEBUG
5837
+ // Record that we saw an actual explicit requirement rooted at this vertex,
5838
+ // for verification purposes.
5839
+ vertices[v].sawVertex = true ;
5840
+ #endif
5841
+ (void ) v;
5842
+
5843
+ redundantExplicitReqs.push_back (req);
5844
+ }
5845
+
5838
5846
// If all requirements are derived, there is nothing to do.
5839
5847
if (explicitReqs.empty ()) {
5840
5848
if (!redundantExplicitReqs.empty ()) {
@@ -6208,111 +6216,171 @@ void GenericSignatureBuilder::computeRedundantRequirements() {
6208
6216
// source.
6209
6217
for (auto &equivClass : Impl->EquivalenceClasses ) {
6210
6218
for (auto &entry : equivClass.conformsTo ) {
6211
- graph.addConstraintsFromEquivClass (
6212
- *this , entry.second ,
6213
- RequirementKind::Conformance,
6214
- [&](Constraint<ProtocolDecl *> constraint) -> bool {
6215
- auto *source = constraint.source ;
6216
-
6217
- bool derivedViaConcrete = false ;
6218
- if (source->getMinimalConformanceSource (
6219
- *this , constraint.getSubjectDependentType ({ }), entry.first ,
6220
- derivedViaConcrete)
6221
- != source)
6222
- return true ;
6223
-
6224
- if (derivedViaConcrete)
6225
- return true ;
6219
+ SmallVector<Constraint<ProtocolDecl *>, 2 > exact;
6220
+ SmallVector<Constraint<ProtocolDecl *>, 2 > lessSpecific;
6226
6221
6227
- return false ;
6228
- });
6222
+ for (const auto &constraint : entry.second ) {
6223
+ auto *source = constraint.source ;
6224
+
6225
+ // FIXME: Remove this check.
6226
+ bool derivedViaConcrete = false ;
6227
+ if (source->getMinimalConformanceSource (
6228
+ *this , constraint.getSubjectDependentType ({ }), entry.first ,
6229
+ derivedViaConcrete)
6230
+ != source)
6231
+ continue ;
6232
+
6233
+ if (derivedViaConcrete)
6234
+ continue ;
6235
+
6236
+ // FIXME: Check for a conflict via the concrete type.
6237
+ exact.push_back (constraint);
6238
+ }
6239
+
6240
+ graph.addConstraintsFromEquivClass (RequirementKind::Conformance,
6241
+ exact, lessSpecific);
6229
6242
}
6230
6243
6231
6244
if (equivClass.concreteType ) {
6232
6245
Type resolvedConcreteType =
6233
6246
getCanonicalTypeInContext (equivClass.concreteType , { });
6234
- graph.addConstraintsFromEquivClass (
6235
- *this , equivClass.concreteTypeConstraints ,
6236
- RequirementKind::SameType,
6237
- [&](Constraint<Type> constraint) -> bool {
6238
- auto *source = constraint.source ;
6239
- Type t = constraint.value ;
6240
-
6241
- bool derivedViaConcrete = false ;
6242
- if (source->getMinimalConformanceSource (
6243
- *this , constraint.getSubjectDependentType ({ }), nullptr ,
6244
- derivedViaConcrete)
6245
- != source)
6246
- return true ;
6247
-
6248
- if (derivedViaConcrete)
6249
- return true ;
6250
-
6251
- if (t->isEqual (resolvedConcreteType))
6252
- return false ;
6253
-
6254
- auto resolvedType = getCanonicalTypeInContext (t, { });
6255
- if (resolvedType->isEqual (resolvedConcreteType))
6256
- return false ;
6257
-
6258
- // We have a less-specific constraint.
6259
- return true ;
6260
- });
6247
+
6248
+ SmallVector<Constraint<Type>, 2 > exact;
6249
+ SmallVector<Constraint<Type>, 2 > lessSpecific;
6250
+
6251
+ for (const auto &constraint : equivClass.concreteTypeConstraints ) {
6252
+ auto *source = constraint.source ;
6253
+ Type t = constraint.value ;
6254
+
6255
+ // FIXME: Remove this check.
6256
+ bool derivedViaConcrete = false ;
6257
+ if (source->getMinimalConformanceSource (
6258
+ *this , constraint.getSubjectDependentType ({ }), nullptr ,
6259
+ derivedViaConcrete)
6260
+ != source)
6261
+ continue ;
6262
+
6263
+ if (derivedViaConcrete)
6264
+ continue ;
6265
+
6266
+ if (t->isEqual (resolvedConcreteType)) {
6267
+ exact.push_back (constraint);
6268
+ continue ;
6269
+ }
6270
+
6271
+ auto resolvedType = getCanonicalTypeInContext (t, { });
6272
+ if (resolvedType->isEqual (resolvedConcreteType)) {
6273
+ exact.push_back (constraint);
6274
+ }
6275
+
6276
+ // Record the conflict.
6277
+ if (!source->isDerivedRequirement ()) {
6278
+ auto req =
6279
+ ExplicitRequirement::fromExplicitConstraint (
6280
+ RequirementKind::SameType, constraint);
6281
+ Impl->ConflictingRequirements .insert (
6282
+ std::make_pair (req, resolvedConcreteType));
6283
+ }
6284
+
6285
+ lessSpecific.push_back (constraint);
6286
+ }
6287
+
6288
+ graph.addConstraintsFromEquivClass (RequirementKind::SameType,
6289
+ exact, lessSpecific);
6261
6290
}
6262
6291
6263
6292
if (equivClass.superclass ) {
6264
6293
// Resolve any thus-far-unresolved dependent types.
6265
6294
Type resolvedSuperclass =
6266
6295
getCanonicalTypeInContext (equivClass.superclass , { });
6267
- graph.addConstraintsFromEquivClass (
6268
- *this , equivClass.superclassConstraints ,
6269
- RequirementKind::Superclass,
6270
- [&](Constraint<Type> constraint) -> bool {
6271
- auto *source = constraint.source ;
6272
- Type t = constraint.value ;
6273
-
6274
- bool derivedViaConcrete = false ;
6275
- if (source->getMinimalConformanceSource (
6276
- *this , constraint.getSubjectDependentType ({ }), nullptr ,
6277
- derivedViaConcrete)
6278
- != source)
6279
- return true ;
6280
-
6281
- if (derivedViaConcrete)
6282
- return true ;
6283
-
6284
- if (t->isEqual (resolvedSuperclass))
6285
- return false ;
6286
-
6287
- Type resolvedType = getCanonicalTypeInContext (t, { });
6288
- if (resolvedType->isEqual (resolvedSuperclass))
6289
- return false ;
6290
-
6291
- // We have a less-specific constraint.
6292
- return true ;
6293
- });
6296
+
6297
+ SmallVector<Constraint<Type>, 2 > exact;
6298
+ SmallVector<Constraint<Type>, 2 > lessSpecific;
6299
+
6300
+ for (const auto &constraint : equivClass.superclassConstraints ) {
6301
+ auto *source = constraint.source ;
6302
+ Type t = constraint.value ;
6303
+
6304
+ // FIXME: Remove this check.
6305
+ bool derivedViaConcrete = false ;
6306
+ if (source->getMinimalConformanceSource (
6307
+ *this , constraint.getSubjectDependentType ({ }), nullptr ,
6308
+ derivedViaConcrete)
6309
+ != source)
6310
+ continue ;
6311
+
6312
+ if (derivedViaConcrete)
6313
+ continue ;
6314
+
6315
+ if (t->isEqual (resolvedSuperclass)) {
6316
+ exact.push_back (constraint);
6317
+ continue ;
6318
+ }
6319
+
6320
+ Type resolvedType = getCanonicalTypeInContext (t, { });
6321
+ if (resolvedType->isEqual (resolvedSuperclass)) {
6322
+ exact.push_back (constraint);
6323
+ continue ;
6324
+ }
6325
+
6326
+ // Check for a conflict.
6327
+ if (!source->isDerivedRequirement () &&
6328
+ !resolvedType->isExactSuperclassOf (resolvedSuperclass)) {
6329
+ auto req =
6330
+ ExplicitRequirement::fromExplicitConstraint (
6331
+ RequirementKind::Superclass, constraint);
6332
+ Impl->ConflictingRequirements .insert (
6333
+ std::make_pair (req, resolvedSuperclass));
6334
+ }
6335
+
6336
+ // FIXME: Check for a conflict via the concrete type.
6337
+ lessSpecific.push_back (constraint);
6338
+ }
6339
+
6340
+ graph.addConstraintsFromEquivClass (RequirementKind::Superclass,
6341
+ exact, lessSpecific);
6294
6342
}
6295
6343
6296
6344
if (equivClass.layout ) {
6297
- graph.addConstraintsFromEquivClass (
6298
- *this , equivClass.layoutConstraints ,
6299
- RequirementKind::Layout,
6300
- [&](Constraint<LayoutConstraint> constraint) -> bool {
6301
- auto *source = constraint.source ;
6302
- auto layout = constraint.value ;
6303
-
6304
- bool derivedViaConcrete = false ;
6305
- if (source->getMinimalConformanceSource (
6306
- *this , constraint.getSubjectDependentType ({ }), nullptr ,
6307
- derivedViaConcrete)
6308
- != source)
6309
- return true ;
6310
-
6311
- if (derivedViaConcrete)
6312
- return true ;
6313
-
6314
- return layout != equivClass.layout ;
6315
- });
6345
+ SmallVector<Constraint<LayoutConstraint>, 2 > exact;
6346
+ SmallVector<Constraint<LayoutConstraint>, 2 > lessSpecific;
6347
+
6348
+ for (const auto &constraint : equivClass.layoutConstraints ) {
6349
+ auto *source = constraint.source ;
6350
+ auto layout = constraint.value ;
6351
+
6352
+ // FIXME: Remove this check.
6353
+ bool derivedViaConcrete = false ;
6354
+ if (source->getMinimalConformanceSource (
6355
+ *this , constraint.getSubjectDependentType ({ }), nullptr ,
6356
+ derivedViaConcrete)
6357
+ != source)
6358
+ continue ;
6359
+
6360
+ if (derivedViaConcrete)
6361
+ continue ;
6362
+
6363
+ if (layout == equivClass.layout ) {
6364
+ exact.push_back (constraint);
6365
+ continue ;
6366
+ }
6367
+
6368
+ // Check for a conflict.
6369
+ if (!source->isDerivedRequirement () &&
6370
+ !layout.merge (equivClass.layout )->isKnownLayout ()) {
6371
+ auto req =
6372
+ ExplicitRequirement::fromExplicitConstraint (
6373
+ RequirementKind::Layout, constraint);
6374
+ Impl->ConflictingRequirements .insert (
6375
+ std::make_pair (req, equivClass.layout ));
6376
+ }
6377
+
6378
+ // FIXME: Check for a conflict via the concrete type.
6379
+ lessSpecific.push_back (constraint);
6380
+ }
6381
+
6382
+ graph.addConstraintsFromEquivClass (RequirementKind::Layout,
6383
+ exact, lessSpecific);
6316
6384
}
6317
6385
}
6318
6386
0 commit comments