@@ -173,6 +173,10 @@ class ConcreteContraction {
173
173
Type substType (Type type) const ;
174
174
Requirement substRequirement (const Requirement &req) const ;
175
175
176
+ bool preserveSameTypeRequirement (const Requirement &req) const ;
177
+
178
+ bool hasResolvedMemberTypeOfInterestingParameter (Type t) const ;
179
+
176
180
public:
177
181
ConcreteContraction (bool debug) : Debug(debug) {}
178
182
@@ -384,6 +388,73 @@ ConcreteContraction::substRequirement(const Requirement &req) const {
384
388
}
385
389
}
386
390
391
+ bool ConcreteContraction::
392
+ hasResolvedMemberTypeOfInterestingParameter (Type type) const {
393
+ return type.findIf ([&](Type t) -> bool {
394
+ if (auto *memberTy = t->getAs <DependentMemberType>()) {
395
+ if (memberTy->getAssocType () == nullptr )
396
+ return false ;
397
+
398
+ auto baseTy = memberTy->getBase ();
399
+ if (auto *genericParam = baseTy->getAs <GenericTypeParamType>()) {
400
+ GenericParamKey key (genericParam);
401
+
402
+ Type concreteType;
403
+ {
404
+ auto found = ConcreteTypes.find (key);
405
+ if (found != ConcreteTypes.end () && found->second .size () == 1 )
406
+ return true ;
407
+ }
408
+
409
+ Type superclass;
410
+ {
411
+ auto found = Superclasses.find (key);
412
+ if (found != Superclasses.end () && found->second .size () == 1 )
413
+ return true ;
414
+ }
415
+ }
416
+ }
417
+
418
+ return false ;
419
+ });
420
+ }
421
+
422
+ // / Another silly GenericSignatureBuilder compatibility hack.
423
+ // /
424
+ // / Consider this code:
425
+ // /
426
+ // / class C<T> {
427
+ // / typealias A = T
428
+ // / }
429
+ // /
430
+ // / protocol P {
431
+ // / associatedtype A
432
+ // / }
433
+ // /
434
+ // / func f<X, T>(_: X, _: T) where X : P, X : C<T>, X.A == T {}
435
+ // /
436
+ // / The GenericSignatureBuilder would introduce an equivalence between
437
+ // / typealias A in class C and associatedtype A in protocol P, so the
438
+ // / requirement 'X.A == T' would effectively constrain _both_.
439
+ // /
440
+ // / Simulate this by keeping both the original and substituted same-type
441
+ // / requirement in a narrow case.
442
+ bool ConcreteContraction::preserveSameTypeRequirement (
443
+ const Requirement &req) const {
444
+ if (req.getKind () != RequirementKind::SameType)
445
+ return false ;
446
+
447
+ if (Superclasses.find (req.getFirstType ()->getRootGenericParam ())
448
+ == Superclasses.end ())
449
+ return false ;
450
+
451
+ if (hasResolvedMemberTypeOfInterestingParameter (req.getFirstType ()) ||
452
+ hasResolvedMemberTypeOfInterestingParameter (req.getSecondType ()))
453
+ return false ;
454
+
455
+ return true ;
456
+ }
457
+
387
458
// / Substitute all occurrences of generic parameters subject to superclass
388
459
// / or concrete type requirements with their corresponding superclass or
389
460
// / concrete type.
@@ -506,6 +577,18 @@ bool ConcreteContraction::performConcreteContraction(
506
577
llvm::dbgs () << " \n " ;
507
578
}
508
579
580
+ if (preserveSameTypeRequirement (req.req )) {
581
+ if (Debug) {
582
+ llvm::dbgs () << " @ Preserving original requirement: " ;
583
+ req.req .dump (llvm::dbgs ());
584
+ llvm::dbgs () << " \n " ;
585
+ }
586
+
587
+ // Make the duplicated requirement 'inferred' so that we don't diagnose
588
+ // it as redundant.
589
+ result.push_back ({req.req , SourceLoc (), /* inferred=*/ true });
590
+ }
591
+
509
592
// Substitute the requirement.
510
593
Optional<Requirement> substReq = substRequirement (req.req );
511
594
@@ -519,7 +602,7 @@ bool ConcreteContraction::performConcreteContraction(
519
602
llvm::dbgs () << " \n " ;
520
603
}
521
604
522
- return false ;
605
+ continue ;
523
606
}
524
607
525
608
if (Debug) {
0 commit comments