@@ -216,18 +216,13 @@ class TailRec extends MiniPhaseTransform with DenotTransformer with FullParamete
216
216
217
217
val (prefix, call, arguments, typeArguments, symbol) = receiverArgumentsAndSymbol(tree)
218
218
val hasConformingTargs = (typeArguments zip methTparams).forall{x => x._1.tpe <:< x._2.tpe}
219
- val recv = noTailTransform(prefix)
220
219
221
220
val targs = typeArguments.map(noTailTransform)
222
221
val argumentss = arguments.map(noTailTransforms)
223
222
224
- val recvWiden = recv.tpe.widenDealias
225
-
226
- val receiverIsSame = enclosingClass.typeRef.widenDealias =:= recvWiden
227
- val receiverIsSuper = (method.name eq sym) && enclosingClass.typeRef.widen <:< recvWiden
228
- val receiverIsThis = recv.tpe =:= thisType || recv.tpe.widen =:= thisType
229
-
230
223
val isRecursiveCall = (method eq sym)
224
+ val recvWiden = prefix.tpe.widenDealias
225
+
231
226
232
227
def continue = {
233
228
val method = noTailTransform(call)
@@ -244,40 +239,50 @@ class TailRec extends MiniPhaseTransform with DenotTransformer with FullParamete
244
239
continue
245
240
}
246
241
247
- def rewriteTailCall (recv : Tree ): Tree = {
248
- c.debuglog(" Rewriting tail recursive call: " + tree.pos)
249
- rewrote = true
250
- val receiver = noTailTransform(recv)
251
-
252
- val callTargs : List [tpd.Tree ] =
253
- if (abstractOverClass) {
254
- val classTypeArgs = recv.tpe.baseTypeWithArgs(enclosingClass).argInfos
255
- targs ::: classTypeArgs.map(x => ref(x.typeSymbol))
256
- } else targs
257
-
258
- val method = if (callTargs.nonEmpty) TypeApply (Ident (label.termRef), callTargs) else Ident (label.termRef)
259
- val thisPassed =
260
- if (this .method.owner.isClass)
261
- method.appliedTo(receiver.ensureConforms(method.tpe.widen.firstParamTypes.head))
262
- else method
263
-
264
- val res =
265
- if (thisPassed.tpe.widen.isParameterless) thisPassed
266
- else argumentss.foldLeft(thisPassed) {
267
- (met, ar) => Apply (met, ar) // Dotty deviation no auto-detupling yet.
268
- }
269
- res
270
- }
242
+
271
243
272
244
if (isRecursiveCall) {
273
245
if (ctx.tailPos) {
246
+ val receiverIsSame = enclosingClass.typeRef.widenDealias =:= recvWiden
247
+ val receiverIsThis = prefix.tpe =:= thisType || prefix.tpe.widen =:= thisType
248
+
249
+ def rewriteTailCall (recv : Tree ): Tree = {
250
+ c.debuglog(" Rewriting tail recursive call: " + tree.pos)
251
+ rewrote = true
252
+ val receiver = noTailTransform(recv)
253
+
254
+ val callTargs : List [tpd.Tree ] =
255
+ if (abstractOverClass) {
256
+ val classTypeArgs = recv.tpe.baseTypeWithArgs(enclosingClass).argInfos
257
+ targs ::: classTypeArgs.map(x => ref(x.typeSymbol))
258
+ } else targs
259
+
260
+ val method = if (callTargs.nonEmpty) TypeApply (Ident (label.termRef), callTargs) else Ident (label.termRef)
261
+ val thisPassed =
262
+ if (this .method.owner.isClass)
263
+ method.appliedTo(receiver.ensureConforms(method.tpe.widen.firstParamTypes.head))
264
+ else method
265
+
266
+ val res =
267
+ if (thisPassed.tpe.widen.isParameterless) thisPassed
268
+ else argumentss.foldLeft(thisPassed) {
269
+ (met, ar) => Apply (met, ar) // Dotty deviation no auto-detupling yet.
270
+ }
271
+ res
272
+ }
273
+
274
274
if (! hasConformingTargs) fail(" it changes type arguments on a polymorphic recursive call" )
275
- else if (recv eq EmptyTree ) rewriteTailCall(This (enclosingClass.asClass))
276
- else if (receiverIsSame || receiverIsThis) rewriteTailCall(recv)
277
- else fail(" it changes type of 'this' on a polymorphic recursive call" )
275
+ else {
276
+ val recv = noTailTransform(prefix)
277
+ if (recv eq EmptyTree ) rewriteTailCall(This (enclosingClass.asClass))
278
+ else if (receiverIsSame || receiverIsThis) rewriteTailCall(recv)
279
+ else fail(" it changes type of 'this' on a polymorphic recursive call" )
280
+ }
278
281
}
279
282
else fail(defaultReason)
280
283
} else {
284
+ val receiverIsSuper = (method.name eq sym) && enclosingClass.typeRef.widen <:< recvWiden
285
+
281
286
if (receiverIsSuper) fail(" it contains a recursive call targeting a supertype" )
282
287
else continue
283
288
}
0 commit comments