Как и второе предупреждение
Рекурсивный вызов не является хвостовым вызовом
указывает, что этот вызов является рекурсивным, но не является хвостовым вызовом.
Это потому, что функция вызывается с другим экземпляром в качестве своей цели (next
, а не this
), поэтому tailrec
на самом деле не имеет эффекта в этом случае. Если вы замените цель на this
, компилятор прекратит выдавать любые предупреждения.
Я предполагаю, что функция расширения компилируется без каких-либо предупреждений, потому что они скомпилированы как функции stati c (то есть не экземпляра), где цель - просто другой параметр, означающий, что преобразованный код выглядит (примерно) как
@Nullable
public static final SLLNode2 getNodeForValue2(@NotNull SLLNode2 $this$getNodeForValue2, int valToFind) {
Intrinsics.checkParameterIsNotNull($this$getNodeForValue2, "$this$getNodeForValue2");
if ($this$getNodeForValue2.getValue() == valToFind) {
return $this$getNodeForValue2;
} else {
SLLNode2 var10000 = $this$getNodeForValue2.getNext();
return var10000 != null ? getNodeForValue2(var10000, valToFind) : null;
}
}
, который довольно ясно содержит рекурсивный вызов хвоста.
Однако я не убедитесь, что это различие является преднамеренным, поскольку способ компиляции функций расширения должен быть деталью реализации, а пример функции экземпляра должен (?) быть эквивалентно оптимизируемым.
Редактировать: это кажется, это на самом деле ошибка .