@@ -679,29 +679,42 @@ DevirtualizationResult swift::tryDevirtualizeClassMethod(FullApplySite AI,
679
679
// Witness Method Optimization
680
680
// ===----------------------------------------------------------------------===//
681
681
682
- // / Generate a new apply of a function_ref to replace an apply of a
683
- // / witness_method when we've determined the actual function we'll end
684
- // / up calling.
685
- static ApplySite devirtualizeWitnessMethod (ApplySite AI, SILFunction *F,
686
- ArrayRef<Substitution> Subs) {
687
- // We know the witness thunk and the corresponding set of substitutions
688
- // required to invoke the protocol method at this point.
682
+ static void getWitnessMethodSubstitutions (ApplySite AI, SILFunction *F,
683
+ ArrayRef<Substitution> Subs,
684
+ SmallVectorImpl<Substitution> &NewSubs) {
689
685
auto &Module = AI.getModule ();
690
686
691
- // Collect all the required substitutions.
692
- //
693
- // The complete set of substitutions may be different, e.g. because the found
694
- // witness thunk F may have been created by a specialization pass and have
695
- // additional generic parameters.
696
- SmallVector<Substitution, 16 > NewSubstList (Subs.begin (), Subs.end ());
687
+ auto CalleeCanType = F->getLoweredFunctionType ();
688
+
689
+ ProtocolDecl *proto = nullptr ;
690
+ if (CalleeCanType->getRepresentation () ==
691
+ SILFunctionTypeRepresentation::WitnessMethod) {
692
+ proto = CalleeCanType->getDefaultWitnessMethodProtocol (
693
+ *Module.getSwiftModule ());
694
+ }
695
+
696
+ ArrayRef<Substitution> origSubs = AI.getSubstitutions ();
697
+
698
+ if (proto != nullptr ) {
699
+ // If the callee is a default witness method thunk, preserve substitutions
700
+ // from the call site.
701
+ NewSubs.append (origSubs.begin (), origSubs.end ());
702
+ return ;
703
+ }
704
+
705
+ // If the callee is a concrete witness method thunk, apply substitutions
706
+ // from the conformance, and drop any substitutions derived from the Self
707
+ // type.
708
+ NewSubs.append (Subs.begin (), Subs.end ());
709
+
697
710
if (auto generics = AI.getOrigCalleeType ()->getGenericSignature ()) {
698
- ArrayRef<Substitution> origSubs = AI.getSubstitutions ();
699
711
for (auto genericParam : generics->getAllDependentTypes ()) {
700
712
auto origSub = origSubs.front ();
701
713
origSubs = origSubs.slice (1 );
702
714
703
- // Ignore generic parameters derived from 'self', the generic
704
- // parameter at depth 0, index 0.
715
+ // If the callee is a concrete witness method thunk, we ignore
716
+ // generic parameters derived from 'self', the generic parameter at
717
+ // depth 0, index 0.
705
718
auto type = genericParam->getCanonicalType ();
706
719
while (auto memberType = dyn_cast<DependentMemberType>(type)) {
707
720
type = memberType.getBase ();
@@ -714,17 +727,36 @@ static ApplySite devirtualizeWitnessMethod(ApplySite AI, SILFunction *F,
714
727
}
715
728
716
729
// Okay, remember this substitution.
717
- NewSubstList .push_back (origSub);
730
+ NewSubs .push_back (origSub);
718
731
}
719
-
720
- assert (origSubs.empty () && " subs not parallel to dependent types" );
721
732
}
722
733
734
+ assert (origSubs.empty () && " subs not parallel to dependent types" );
735
+ }
736
+
737
+ // / Generate a new apply of a function_ref to replace an apply of a
738
+ // / witness_method when we've determined the actual function we'll end
739
+ // / up calling.
740
+ static ApplySite devirtualizeWitnessMethod (ApplySite AI, SILFunction *F,
741
+ ArrayRef<Substitution> Subs) {
742
+ // We know the witness thunk and the corresponding set of substitutions
743
+ // required to invoke the protocol method at this point.
744
+ auto &Module = AI.getModule ();
745
+
746
+ // Collect all the required substitutions.
747
+ //
748
+ // The complete set of substitutions may be different, e.g. because the found
749
+ // witness thunk F may have been created by a specialization pass and have
750
+ // additional generic parameters.
751
+ SmallVector<Substitution, 4 > NewSubs;
752
+
753
+ getWitnessMethodSubstitutions (AI, F, Subs, NewSubs);
754
+
723
755
// Figure out the exact bound type of the function to be called by
724
756
// applying all substitutions.
725
757
auto CalleeCanType = F->getLoweredFunctionType ();
726
758
auto SubstCalleeCanType = CalleeCanType->substGenericArgs (
727
- Module, Module.getSwiftModule (), NewSubstList );
759
+ Module, Module.getSwiftModule (), NewSubs );
728
760
729
761
// Collect arguments from the apply instruction.
730
762
auto Arguments = SmallVector<SILValue, 4 >();
@@ -754,15 +786,15 @@ static ApplySite devirtualizeWitnessMethod(ApplySite AI, SILFunction *F,
754
786
755
787
if (auto *A = dyn_cast<ApplyInst>(AI))
756
788
SAI = Builder.createApply (Loc, FRI, SubstCalleeSILType,
757
- ResultSILType, NewSubstList , Arguments,
789
+ ResultSILType, NewSubs , Arguments,
758
790
A->isNonThrowing ());
759
791
if (auto *TAI = dyn_cast<TryApplyInst>(AI))
760
792
SAI = Builder.createTryApply (Loc, FRI, SubstCalleeSILType,
761
- NewSubstList , Arguments,
793
+ NewSubs , Arguments,
762
794
TAI->getNormalBB (), TAI->getErrorBB ());
763
795
if (auto *PAI = dyn_cast<PartialApplyInst>(AI))
764
796
SAI = Builder.createPartialApply (Loc, FRI, SubstCalleeSILType,
765
- NewSubstList , Arguments, PAI->getType ());
797
+ NewSubs , Arguments, PAI->getType ());
766
798
767
799
NumWitnessDevirt++;
768
800
return SAI;
0 commit comments