@@ -154,14 +154,23 @@ using namespace rewriting;
154154// / Strip associated types from types used as keys to erase differences between
155155// / resolved types coming from the parent generic signature and unresolved types
156156// / coming from user-written requirements.
157- static CanType stripBoundDependentMemberTypes (Type t) {
157+ static Type stripBoundDependentMemberTypes (Type t) {
158158 if (auto *depMemTy = t->getAs <DependentMemberType>()) {
159- return CanType ( DependentMemberType::get (
159+ return DependentMemberType::get (
160160 stripBoundDependentMemberTypes (depMemTy->getBase ()),
161- depMemTy->getName ())) ;
161+ depMemTy->getName ());
162162 }
163163
164- return t->getCanonicalType ();
164+ return t;
165+ }
166+
167+ // / Returns true if \p lhs appears as the base of a member type in \p rhs.
168+ static bool typeOccursIn (Type lhs, Type rhs) {
169+ return rhs.findIf ([lhs](Type t) -> bool {
170+ if (auto *memberType = t->getAs <DependentMemberType>())
171+ return memberType->getBase ()->isEqual (lhs);
172+ return false ;
173+ });
165174}
166175
167176namespace {
@@ -232,17 +241,18 @@ Optional<Type> ConcreteContraction::substTypeParameterRec(
232241 // losing the requirement.
233242 if (position == Position::BaseType ||
234243 position == Position::ConformanceRequirement) {
244+ auto key = stripBoundDependentMemberTypes (type)->getCanonicalType ();
235245
236246 Type concreteType;
237247 {
238- auto found = ConcreteTypes.find (stripBoundDependentMemberTypes (type) );
248+ auto found = ConcreteTypes.find (key );
239249 if (found != ConcreteTypes.end () && found->second .size () == 1 )
240250 concreteType = *found->second .begin ();
241251 }
242252
243253 Type superclass;
244254 {
245- auto found = Superclasses.find (stripBoundDependentMemberTypes (type) );
255+ auto found = Superclasses.find (key );
246256 if (found != Superclasses.end () && found->second .size () == 1 )
247257 superclass = *found->second .begin ();
248258 }
@@ -392,7 +402,8 @@ ConcreteContraction::substRequirement(const Requirement &req) const {
392402 // 'T : Sendable' would be incorrect; we want to ensure that we only admit
393403 // subclasses of 'C' which are 'Sendable'.
394404 bool allowMissing = false ;
395- if (ConcreteTypes.count (stripBoundDependentMemberTypes (firstType)) > 0 )
405+ auto key = stripBoundDependentMemberTypes (firstType)->getCanonicalType ();
406+ if (ConcreteTypes.count (key) > 0 )
396407 allowMissing = true ;
397408
398409 if (!substFirstType->isTypeParameter ()) {
@@ -449,17 +460,18 @@ hasResolvedMemberTypeOfInterestingParameter(Type type) const {
449460 if (memberTy->getAssocType () == nullptr )
450461 return false ;
451462
452- auto baseTy = memberTy->getBase ();
463+ auto key = stripBoundDependentMemberTypes (memberTy->getBase ())
464+ ->getCanonicalType ();
453465 Type concreteType;
454466 {
455- auto found = ConcreteTypes.find (stripBoundDependentMemberTypes (baseTy) );
467+ auto found = ConcreteTypes.find (key );
456468 if (found != ConcreteTypes.end () && found->second .size () == 1 )
457469 return true ;
458470 }
459471
460472 Type superclass;
461473 {
462- auto found = Superclasses.find (stripBoundDependentMemberTypes (baseTy) );
474+ auto found = Superclasses.find (key );
463475 if (found != Superclasses.end () && found->second .size () == 1 )
464476 return true ;
465477 }
@@ -496,14 +508,14 @@ bool ConcreteContraction::preserveSameTypeRequirement(
496508
497509 // One of the parent types of this type parameter should be subject
498510 // to a superclass requirement.
499- auto type = req.getFirstType ();
511+ auto type = stripBoundDependentMemberTypes (req.getFirstType ())
512+ ->getCanonicalType ();
500513 while (true ) {
501- if (Superclasses.find (stripBoundDependentMemberTypes (type))
502- != Superclasses.end ())
514+ if (Superclasses.find (type) != Superclasses.end ())
503515 break ;
504516
505- if (auto * memberType = type-> getAs <DependentMemberType>()) {
506- type = memberType-> getBase ();
517+ if (auto memberType = dyn_cast <DependentMemberType>(type )) {
518+ type = memberType. getBase ();
507519 continue ;
508520 }
509521
@@ -546,23 +558,41 @@ bool ConcreteContraction::performConcreteContraction(
546558 if (constraintType->isTypeParameter ())
547559 break ;
548560
549- ConcreteTypes[stripBoundDependentMemberTypes (subjectType)]
550- .insert (constraintType);
561+ subjectType = stripBoundDependentMemberTypes (subjectType);
562+ if (typeOccursIn (subjectType,
563+ stripBoundDependentMemberTypes (constraintType))) {
564+ if (Debug) {
565+ llvm::dbgs () << " @ Subject type of same-type requirement "
566+ << subjectType << " == " << constraintType << " "
567+ << " occurs in the constraint type, skipping\n " ;
568+ }
569+ break ;
570+ }
571+ ConcreteTypes[subjectType->getCanonicalType ()].insert (constraintType);
551572 break ;
552573 }
553574 case RequirementKind::Superclass: {
554575 auto constraintType = req.req .getSecondType ();
555576 assert (!constraintType->isTypeParameter () &&
556577 " You forgot to call desugarRequirement()" );
557578
558- Superclasses[stripBoundDependentMemberTypes (subjectType)]
559- .insert (constraintType);
579+ subjectType = stripBoundDependentMemberTypes (subjectType);
580+ if (typeOccursIn (subjectType,
581+ stripBoundDependentMemberTypes (constraintType))) {
582+ if (Debug) {
583+ llvm::dbgs () << " @ Subject type of superclass requirement "
584+ << subjectType << " : " << constraintType << " "
585+ << " occurs in the constraint type, skipping\n " ;
586+ }
587+ break ;
588+ }
589+ Superclasses[subjectType->getCanonicalType ()].insert (constraintType);
560590 break ;
561591 }
562592 case RequirementKind::Conformance: {
563593 auto *protoDecl = req.req .getProtocolDecl ();
564- Conformances[ stripBoundDependentMemberTypes (subjectType)]
565- .push_back (protoDecl);
594+ subjectType = stripBoundDependentMemberTypes (subjectType);
595+ Conformances[subjectType-> getCanonicalType ()] .push_back (protoDecl);
566596
567597 break ;
568598 }
@@ -588,7 +618,7 @@ bool ConcreteContraction::performConcreteContraction(
588618 if (auto otherSuperclassTy = proto->getSuperclass ()) {
589619 if (Debug) {
590620 llvm::dbgs () << " @ Subject type of superclass requirement "
591- << " τ_ " << subjectType << " : " << superclassTy
621+ << subjectType << " : " << superclassTy
592622 << " conforms to " << proto->getName ()
593623 << " which has a superclass bound "
594624 << otherSuperclassTy << " \n " ;
0 commit comments