Как работает контракт компилятора с нулевой проверкой Kotlin?

У меня есть пара настраиваемых функций области видимости, которые все похожи на эту:

      @OptIn(ExperimentalContracts::class)
inline fun <R> R.applyIf(condition: Boolean, block: R.() -> Unit): R {
  contract {
    callsInPlace(block, InvocationKind.EXACTLY_ONCE)
  }

  if(condition) block()
  return this
}

Он имеет тот же эффект, что и apply(...), но блок выполняется только в том случае, если выполняется условие. Функция работает прекрасно, но есть один нюанс. Если условие содержит, например, проверки на null, эти ненулевые гарантии не переводятся в блок, который выполняется.

Так например:

      .applyIf(source != null) {
  sourceClassName = source.className
  sourceMethodName = source.methodName
})

Вышеупомянутое приводит к предупреждению компилятора, потому что я использую исходный код без?: И !! операторы. Всплывающая подсказка IntelliJ говорит

Только безопасные (?.) Или ненулевые утвержденные (!!.) Вызовы разрешены для обнуляемого получателя типа LogSource?(исходная переменная имеет тип LogSource)

Как лучше всего добиться того же поведения, что и в этом случае:

      if(source != null) { 
  [...].apply {
    sourceClassName = source.className
    sourceMethodName = source.methodName
  }
}

Я полагаю, что использование предиката или поставщика вместо логического было бы первым шагом, но каков правильный синтаксис контракта, чтобы синтаксически сказать: «если условие содержит проверки на null, подтвержденные ненулевые значения действительны в блоке и во всем блоке. разве изменено "?

0 ответов

Другие вопросы по тегам