@@ -5701,6 +5701,11 @@ GenericSignatureBuilder::isValidRequirementDerivationPath(
5701
5701
5702
5702
auto otherSubjectType = otherReq.getSubjectType ();
5703
5703
5704
+ auto *equivClass = resolveEquivalenceClass (otherSubjectType,
5705
+ ArchetypeResolutionKind::AlreadyKnown);
5706
+ assert (equivClass &&
5707
+ " Explicit requirement names an unknown equivalence class?" );
5708
+
5704
5709
// If our requirement is based on a path involving some other
5705
5710
// redundant requirement, see if we can derive the redundant
5706
5711
// requirement using requirements we haven't visited yet.
@@ -5720,11 +5725,6 @@ GenericSignatureBuilder::isValidRequirementDerivationPath(
5720
5725
if (!otherSource->isDerivedNonRootRequirement ())
5721
5726
return None;
5722
5727
5723
- auto *equivClass = resolveEquivalenceClass (otherSubjectType,
5724
- ArchetypeResolutionKind::AlreadyKnown);
5725
- assert (equivClass &&
5726
- " Explicit requirement names an unknown equivalence class?" );
5727
-
5728
5728
switch (otherReq.getKind ()) {
5729
5729
case RequirementKind::Conformance: {
5730
5730
auto *proto = otherReq.getRHS ().get <ProtocolDecl *>();
@@ -5804,20 +5804,22 @@ GenericSignatureBuilder::isValidRequirementDerivationPath(
5804
5804
}
5805
5805
}
5806
5806
5807
- if (auto *depMemType = otherSubjectType->getAs <DependentMemberType>()) {
5807
+ auto anchor = equivClass->getAnchor (*this , { });
5808
+
5809
+ if (auto *depMemType = anchor->getAs <DependentMemberType>()) {
5808
5810
// If 'req' is based on some other conformance requirement
5809
5811
// `T.[P.]A : Q', we want to make sure that we have a
5810
5812
// non-redundant derivation for 'T : P'.
5811
5813
auto baseType = depMemType->getBase ();
5812
5814
auto *proto = depMemType->getAssocType ()->getProtocol ();
5813
5815
5814
- auto *equivClass = resolveEquivalenceClass (baseType,
5816
+ auto *baseEquivClass = resolveEquivalenceClass (baseType,
5815
5817
ArchetypeResolutionKind::AlreadyKnown);
5816
- assert (equivClass &&
5818
+ assert (baseEquivClass &&
5817
5819
" Explicit requirement names an unknown equivalence class?" );
5818
5820
5819
- auto found = equivClass ->conformsTo .find (proto);
5820
- assert (found != equivClass ->conformsTo .end ());
5821
+ auto found = baseEquivClass ->conformsTo .find (proto);
5822
+ assert (found != baseEquivClass ->conformsTo .end ());
5821
5823
5822
5824
bool foundValidDerivation = false ;
5823
5825
for (const auto &constraint : found->second ) {
@@ -8279,24 +8281,42 @@ GenericSignature GenericSignatureBuilder::rebuildSignatureWithoutRedundantRequir
8279
8281
}
8280
8282
8281
8283
auto subjectType = req.getSubjectType ();
8282
- subjectType = stripBoundDependentMemberTypes (subjectType);
8283
- auto resolvedSubjectType =
8284
- resolveDependentMemberTypes (*this , subjectType,
8285
- ArchetypeResolutionKind::WellFormed);
8284
+ auto resolvedSubject =
8285
+ maybeResolveEquivalenceClass (subjectType,
8286
+ ArchetypeResolutionKind::WellFormed,
8287
+ /* wantExactPotentialArchetype=*/ false );
8288
+
8289
+ auto *resolvedEquivClass = resolvedSubject.getEquivalenceClass (*this );
8290
+ Type resolvedSubjectType;
8291
+ if (resolvedEquivClass != nullptr )
8292
+ resolvedSubjectType = resolvedEquivClass->getAnchor (*this , { });
8286
8293
8287
8294
// This can occur if the combination of a superclass requirement and
8288
8295
// protocol conformance requirement force a type to become concrete.
8289
8296
//
8290
8297
// FIXME: Is there a more principled formulation of this?
8291
- if (req.getKind () == RequirementKind::Superclass &&
8292
- !resolvedSubjectType->isTypeParameter ()) {
8293
- newBuilder.addRequirement (Requirement (RequirementKind::SameType,
8294
- subjectType, resolvedSubjectType),
8295
- getRebuiltSource (req.getSource ()), nullptr );
8296
- continue ;
8298
+ if (req.getKind () == RequirementKind::Superclass) {
8299
+ if (resolvedSubject.getAsConcreteType ()) {
8300
+ auto unresolvedSubjectType = stripBoundDependentMemberTypes (subjectType);
8301
+ newBuilder.addRequirement (Requirement (RequirementKind::SameType,
8302
+ unresolvedSubjectType,
8303
+ resolvedSubject.getAsConcreteType ()),
8304
+ getRebuiltSource (req.getSource ()), nullptr );
8305
+ continue ;
8306
+ }
8307
+
8308
+ if (resolvedEquivClass->concreteType ) {
8309
+ auto unresolvedSubjectType = stripBoundDependentMemberTypes (
8310
+ resolvedSubjectType);
8311
+ newBuilder.addRequirement (Requirement (RequirementKind::SameType,
8312
+ unresolvedSubjectType,
8313
+ resolvedEquivClass->concreteType ),
8314
+ getRebuiltSource (req.getSource ()), nullptr );
8315
+ continue ;
8316
+ }
8297
8317
}
8298
8318
8299
- assert (resolvedSubjectType->isTypeParameter ());
8319
+ assert (resolvedSubjectType && resolvedSubjectType ->isTypeParameter ());
8300
8320
8301
8321
if (auto optReq = createRequirement (req.getKind (), resolvedSubjectType,
8302
8322
req.getRHS (), getGenericParams ())) {
@@ -8335,6 +8355,40 @@ GenericSignature GenericSignatureBuilder::rebuildSignatureWithoutRedundantRequir
8335
8355
}
8336
8356
};
8337
8357
8358
+ // If we have a same-type requirement where the right hand side is concrete,
8359
+ // canonicalize the left hand side, in case dropping some redundant
8360
+ // conformance requirement turns the original left hand side into an
8361
+ // unresolvable type.
8362
+ if (!req.getRHS ().get <Type>()->isTypeParameter ()) {
8363
+ auto resolvedSubject =
8364
+ maybeResolveEquivalenceClass (req.getSubjectType (),
8365
+ ArchetypeResolutionKind::WellFormed,
8366
+ /* wantExactPotentialArchetype=*/ false );
8367
+
8368
+ auto *resolvedEquivClass = resolvedSubject.getEquivalenceClass (*this );
8369
+ auto resolvedSubjectType = resolvedEquivClass->getAnchor (*this , { });
8370
+
8371
+ auto constraintType = resolveType (req.getRHS ().get <Type>());
8372
+
8373
+ auto newReq = stripBoundDependentMemberTypes (
8374
+ Requirement (RequirementKind::SameType,
8375
+ resolvedSubjectType, constraintType));
8376
+
8377
+ if (Impl->DebugRedundantRequirements ) {
8378
+ llvm::dbgs () << " => " ;
8379
+ newReq.dump (llvm::dbgs ());
8380
+ llvm::dbgs () << " \n " ;
8381
+ }
8382
+ newBuilder.addRequirement (newReq, getRebuiltSource (req.getSource ()),
8383
+ nullptr );
8384
+
8385
+ continue ;
8386
+ }
8387
+
8388
+ // Otherwise, we can't canonicalize the two sides of the requirement, since
8389
+ // doing so will produce a trivial same-type requirement T == T. Instead,
8390
+ // apply some ad-hoc rules to improve the odds that the requirement will
8391
+ // resolve in the rebuilt GSB.
8338
8392
auto subjectType = resolveType (req.getSubjectType ());
8339
8393
auto constraintType = resolveType (req.getRHS ().get <Type>());
8340
8394
0 commit comments