@@ -173,6 +173,10 @@ class ConcreteContraction {
173173 Type substType (Type type) const ;
174174 Requirement substRequirement (const Requirement &req) const ;
175175
176+ bool preserveSameTypeRequirement (const Requirement &req) const ;
177+
178+ bool hasResolvedMemberTypeOfInterestingParameter (Type t) const ;
179+
176180public:
177181 ConcreteContraction (bool debug) : Debug(debug) {}
178182
@@ -384,6 +388,73 @@ ConcreteContraction::substRequirement(const Requirement &req) const {
384388 }
385389}
386390
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+
387458// / Substitute all occurrences of generic parameters subject to superclass
388459// / or concrete type requirements with their corresponding superclass or
389460// / concrete type.
@@ -506,6 +577,18 @@ bool ConcreteContraction::performConcreteContraction(
506577 llvm::dbgs () << " \n " ;
507578 }
508579
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+
509592 // Substitute the requirement.
510593 Optional<Requirement> substReq = substRequirement (req.req );
511594
@@ -519,7 +602,7 @@ bool ConcreteContraction::performConcreteContraction(
519602 llvm::dbgs () << " \n " ;
520603 }
521604
522- return false ;
605+ continue ;
523606 }
524607
525608 if (Debug) {
0 commit comments