@@ -608,31 +608,41 @@ SILFunction *SILGenModule::emitProtocolWitness(
608
608
609
609
// The generic environment for the witness thunk.
610
610
auto *genericEnv = witness.getSyntheticEnvironment ();
611
+ CanGenericSignature genericSig;
612
+ if (genericEnv)
613
+ genericSig = genericEnv->getGenericSignature ()->getCanonicalSignature ();
611
614
612
615
// The type of the witness thunk.
613
- auto substReqtTy =
614
- cast<AnyFunctionType>(reqtOrigTy.subst (reqtSubMap)->getCanonicalType ());
615
-
616
- // If there's something to map to for the witness thunk, the conformance
617
- // should be phrased in the same terms. This particularly applies to classes
618
- // where a thunk for a method in a conformance like `extension Class: P where
619
- // T: Q` will go from its native signature of `<τ_0_0 where τ_0_0: Q>` (with T
620
- // canonicalised to τ_0_0), to `<τ_0_0, τ_1_0 where τ_0_0: Class<τ_1_0>,
621
- // τ_1_0: Q>` (with T now represented by τ_1_0). Find the right conformance by
622
- // looking for the conformance of 'Self'.
616
+ auto reqtSubstTy = cast<AnyFunctionType>(
617
+ reqtOrigTy->substGenericArgs (reqtSubMap)
618
+ ->getCanonicalType (genericSig));
619
+
620
+ // Generic signatures where all parameters are concrete are lowered away
621
+ // at the SILFunctionType level.
622
+ if (genericSig && genericSig->areAllParamsConcrete ()) {
623
+ genericSig = nullptr ;
624
+ genericEnv = nullptr ;
625
+ }
626
+
627
+ // Rewrite the conformance in terms of the requirement environment's Self
628
+ // type, which might have a different generic signature than the type
629
+ // itself.
630
+ //
631
+ // For example, if the conforming type is a class and the witness is defined
632
+ // in a protocol extension, the generic signature will have an additional
633
+ // generic parameter representing Self, so the generic parameters of the
634
+ // class will all be shifted down by one.
623
635
if (reqtSubMap) {
624
636
auto requirement = conformance.getRequirement ();
625
637
auto self = requirement->getSelfInterfaceType ()->getCanonicalType ();
626
638
627
639
conformance = *reqtSubMap.lookupConformance (self, requirement);
628
640
}
629
641
630
- CanAnyFunctionType reqtSubstTy =
631
- CanAnyFunctionType::get (genericEnv ? genericEnv->getGenericSignature ()
632
- ->getCanonicalSignature ()
633
- : nullptr ,
634
- substReqtTy->getParams (),
635
- substReqtTy.getResult (),
642
+ reqtSubstTy =
643
+ CanAnyFunctionType::get (genericSig,
644
+ reqtSubstTy->getParams (),
645
+ reqtSubstTy.getResult (),
636
646
reqtOrigTy->getExtInfo ());
637
647
638
648
// Coroutine lowering requires us to provide these substitutions
@@ -649,10 +659,6 @@ SILFunction *SILGenModule::emitProtocolWitness(
649
659
}
650
660
}
651
661
652
- // FIXME: this needs to pull out the conformances/witness-tables for any
653
- // conditional requirements from the witness table and pass them to the
654
- // underlying function in the thunk.
655
-
656
662
// Lower the witness thunk type with the requirement's abstraction level.
657
663
auto witnessSILFnType = getNativeSILFunctionType (
658
664
M, AbstractionPattern (reqtOrigTy), reqtSubstTy,
0 commit comments