@@ -5,6 +5,7 @@ import dotty.tools.dotc.ast.Trees._
55import dotty .tools .dotc .ast .{TreeTypeMap , tpd }
66import dotty .tools .dotc .config .Printers .tailrec
77import dotty .tools .dotc .core .Contexts .Context
8+ import dotty .tools .dotc .core .Constants .Constant
89import dotty .tools .dotc .core .Decorators ._
910import dotty .tools .dotc .core .Flags ._
1011import dotty .tools .dotc .core .NameKinds .{TailLabelName , TailLocalName , TailTempName }
@@ -174,6 +175,25 @@ class TailRec extends MiniPhase {
174175 ).transform(rhsSemiTransformed)
175176 }
176177
178+ // Is a simple this a simple recursive tail call, possibly with swapped or modified pure arguments
179+ def isInfiniteRecCall (tree : Tree ): Boolean = {
180+ def statOk (stat : Tree ): Boolean = stat match {
181+ case stat : ValDef if stat.name.is(TailTempName ) || ! stat.symbol.is(Mutable ) => statOk(stat.rhs)
182+ case Assign (lhs : Ident , rhs : Ident ) if lhs.symbol.name.is(TailLocalName ) => statOk(rhs)
183+ case stat : Ident if stat.symbol.name.is(TailLocalName ) => true
184+ case _ => tpd.isPureExpr(stat)
185+ }
186+ tree match {
187+ case Typed (expr, _) => isInfiniteRecCall(expr)
188+ case Return (Literal (Constant (())), label) => label.symbol == transformer.continueLabel
189+ case Block (stats, expr) => stats.forall(statOk) && isInfiniteRecCall(expr)
190+ case _ => false
191+ }
192+ }
193+
194+ if isInfiniteRecCall(rhsFullyTransformed) then
195+ ctx.warning(" Infinite recursive call" , tree.sourcePos)
196+
177197 cpy.DefDef (tree)(rhs =
178198 Block (
179199 initialVarDefs,
0 commit comments