@@ -154,14 +154,23 @@ using namespace rewriting;
154
154
// / Strip associated types from types used as keys to erase differences between
155
155
// / resolved types coming from the parent generic signature and unresolved types
156
156
// / coming from user-written requirements.
157
- static CanType stripBoundDependentMemberTypes (Type t) {
157
+ static Type stripBoundDependentMemberTypes (Type t) {
158
158
if (auto *depMemTy = t->getAs <DependentMemberType>()) {
159
- return CanType ( DependentMemberType::get (
159
+ return DependentMemberType::get (
160
160
stripBoundDependentMemberTypes (depMemTy->getBase ()),
161
- depMemTy->getName ())) ;
161
+ depMemTy->getName ());
162
162
}
163
163
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
+ });
165
174
}
166
175
167
176
namespace {
@@ -232,17 +241,18 @@ Optional<Type> ConcreteContraction::substTypeParameterRec(
232
241
// losing the requirement.
233
242
if (position == Position::BaseType ||
234
243
position == Position::ConformanceRequirement) {
244
+ auto key = stripBoundDependentMemberTypes (type)->getCanonicalType ();
235
245
236
246
Type concreteType;
237
247
{
238
- auto found = ConcreteTypes.find (stripBoundDependentMemberTypes (type) );
248
+ auto found = ConcreteTypes.find (key );
239
249
if (found != ConcreteTypes.end () && found->second .size () == 1 )
240
250
concreteType = *found->second .begin ();
241
251
}
242
252
243
253
Type superclass;
244
254
{
245
- auto found = Superclasses.find (stripBoundDependentMemberTypes (type) );
255
+ auto found = Superclasses.find (key );
246
256
if (found != Superclasses.end () && found->second .size () == 1 )
247
257
superclass = *found->second .begin ();
248
258
}
@@ -392,7 +402,8 @@ ConcreteContraction::substRequirement(const Requirement &req) const {
392
402
// 'T : Sendable' would be incorrect; we want to ensure that we only admit
393
403
// subclasses of 'C' which are 'Sendable'.
394
404
bool allowMissing = false ;
395
- if (ConcreteTypes.count (stripBoundDependentMemberTypes (firstType)) > 0 )
405
+ auto key = stripBoundDependentMemberTypes (firstType)->getCanonicalType ();
406
+ if (ConcreteTypes.count (key) > 0 )
396
407
allowMissing = true ;
397
408
398
409
if (!substFirstType->isTypeParameter ()) {
@@ -449,17 +460,18 @@ hasResolvedMemberTypeOfInterestingParameter(Type type) const {
449
460
if (memberTy->getAssocType () == nullptr )
450
461
return false ;
451
462
452
- auto baseTy = memberTy->getBase ();
463
+ auto key = stripBoundDependentMemberTypes (memberTy->getBase ())
464
+ ->getCanonicalType ();
453
465
Type concreteType;
454
466
{
455
- auto found = ConcreteTypes.find (stripBoundDependentMemberTypes (baseTy) );
467
+ auto found = ConcreteTypes.find (key );
456
468
if (found != ConcreteTypes.end () && found->second .size () == 1 )
457
469
return true ;
458
470
}
459
471
460
472
Type superclass;
461
473
{
462
- auto found = Superclasses.find (stripBoundDependentMemberTypes (baseTy) );
474
+ auto found = Superclasses.find (key );
463
475
if (found != Superclasses.end () && found->second .size () == 1 )
464
476
return true ;
465
477
}
@@ -496,14 +508,14 @@ bool ConcreteContraction::preserveSameTypeRequirement(
496
508
497
509
// One of the parent types of this type parameter should be subject
498
510
// to a superclass requirement.
499
- auto type = req.getFirstType ();
511
+ auto type = stripBoundDependentMemberTypes (req.getFirstType ())
512
+ ->getCanonicalType ();
500
513
while (true ) {
501
- if (Superclasses.find (stripBoundDependentMemberTypes (type))
502
- != Superclasses.end ())
514
+ if (Superclasses.find (type) != Superclasses.end ())
503
515
break ;
504
516
505
- if (auto * memberType = type-> getAs <DependentMemberType>()) {
506
- type = memberType-> getBase ();
517
+ if (auto memberType = dyn_cast <DependentMemberType>(type )) {
518
+ type = memberType. getBase ();
507
519
continue ;
508
520
}
509
521
@@ -546,23 +558,41 @@ bool ConcreteContraction::performConcreteContraction(
546
558
if (constraintType->isTypeParameter ())
547
559
break ;
548
560
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);
551
572
break ;
552
573
}
553
574
case RequirementKind::Superclass: {
554
575
auto constraintType = req.req .getSecondType ();
555
576
assert (!constraintType->isTypeParameter () &&
556
577
" You forgot to call desugarRequirement()" );
557
578
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);
560
590
break ;
561
591
}
562
592
case RequirementKind::Conformance: {
563
593
auto *protoDecl = req.req .getProtocolDecl ();
564
- Conformances[ stripBoundDependentMemberTypes (subjectType)]
565
- .push_back (protoDecl);
594
+ subjectType = stripBoundDependentMemberTypes (subjectType);
595
+ Conformances[subjectType-> getCanonicalType ()] .push_back (protoDecl);
566
596
567
597
break ;
568
598
}
@@ -588,7 +618,7 @@ bool ConcreteContraction::performConcreteContraction(
588
618
if (auto otherSuperclassTy = proto->getSuperclass ()) {
589
619
if (Debug) {
590
620
llvm::dbgs () << " @ Subject type of superclass requirement "
591
- << " τ_ " << subjectType << " : " << superclassTy
621
+ << subjectType << " : " << superclassTy
592
622
<< " conforms to " << proto->getName ()
593
623
<< " which has a superclass bound "
594
624
<< otherSuperclassTy << " \n " ;
0 commit comments