@@ -71,31 +71,50 @@ static bool isRecursiveCall(FullApplySite applySite) {
7171
7272 if (auto *CMI = dyn_cast<ClassMethodInst>(callee)) {
7373
74+ SILModule &module = parentFunc->getModule ();
75+ CanType classType = CMI->getOperand ()->getType ().getASTType ();
76+ if (auto mt = dyn_cast<MetatypeType>(classType)) {
77+ classType = mt.getInstanceType ();
78+ }
79+ ClassDecl *classDecl = classType.getClassOrBoundGenericClass ();
80+
7481 // FIXME: If we're not inside the module context of the method,
7582 // we may have to deserialize vtables. If the serialized tables
7683 // are damaged, the pass will crash.
7784 //
7885 // Though, this has the added bonus of not looking into vtables
7986 // outside the current module. Because we're not doing IPA, let
8087 // alone cross-module IPA, this is all well and good.
81- SILModule &module = parentFunc->getModule ();
82- CanType classType = CMI->getOperand ()->getType ().getASTType ();
83- ClassDecl *classDecl = classType.getClassOrBoundGenericClass ();
8488 if (classDecl && classDecl->getModuleContext () != module .getSwiftModule ())
8589 return false ;
8690
87- if (!calleesAreStaticallyKnowable (module , CMI->getMember ()))
91+ SILFunction *method = getTargetClassMethod (module , classDecl, CMI);
92+ if (method != parentFunc)
8893 return false ;
8994
90- // The "statically knowable" check just means that we have all the
91- // callee candidates available for analysis. We still need to check
92- // if the current function has a known override point.
93- auto *methodDecl = CMI->getMember ().getAbstractFunctionDecl ();
94- if (methodDecl->isOverridden ())
95- return false ;
95+ SILDeclRef member = CMI->getMember ();
96+ if (calleesAreStaticallyKnowable (module , member) &&
97+ // The "statically knowable" check just means that we have all the
98+ // callee candidates available for analysis. We still need to check
99+ // if the current function has a known override point.
100+ !member.getAbstractFunctionDecl ()->isOverridden ()) {
101+ return true ;
102+ }
96103
97- SILFunction *method = getTargetClassMethod (module , classDecl, CMI);
98- return method == parentFunc;
104+ // Even if the method is (or could be) overridden, it's a recursive call if
105+ // it's called on the self argument:
106+ // ```
107+ // class X {
108+ // // Even if foo() is overridden in a derived class, it'll end up in an
109+ // // infinite recursion if initially called on an instance of `X`.
110+ // func foo() { foo() }
111+ // }
112+ // ```
113+ if (parentFunc->hasSelfParam () &&
114+ CMI->getOperand () == SILValue (parentFunc->getSelfArgument ())) {
115+ return true ;
116+ }
117+ return false ;
99118 }
100119
101120 if (auto *WMI = dyn_cast<WitnessMethodInst>(callee)) {
0 commit comments