@@ -71,31 +71,50 @@ static bool isRecursiveCall(FullApplySite applySite) {
71
71
72
72
if (auto *CMI = dyn_cast<ClassMethodInst>(callee)) {
73
73
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
+
74
81
// FIXME: If we're not inside the module context of the method,
75
82
// we may have to deserialize vtables. If the serialized tables
76
83
// are damaged, the pass will crash.
77
84
//
78
85
// Though, this has the added bonus of not looking into vtables
79
86
// outside the current module. Because we're not doing IPA, let
80
87
// 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 ();
84
88
if (classDecl && classDecl->getModuleContext () != module .getSwiftModule ())
85
89
return false ;
86
90
87
- if (!calleesAreStaticallyKnowable (module , CMI->getMember ()))
91
+ SILFunction *method = getTargetClassMethod (module , classDecl, CMI);
92
+ if (method != parentFunc)
88
93
return false ;
89
94
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
+ }
96
103
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 ;
99
118
}
100
119
101
120
if (auto *WMI = dyn_cast<WitnessMethodInst>(callee)) {
0 commit comments