Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

400
Views
Extension method, when called on a null object, is called on the wrong type
fun main() {
    val set: Set<Int>?
    set = null
    val emptySet: Set<Int> = set.orEmpty()
}

Can't figure out why even when explicitly typing the set variable as Set <Int>? the compiler considers that in the extension method set.orEmpty () set - is a string and, accordingly, crashes with an error:

Kotlin: Type mismatch: inferred type is String but Set was expected

But when declaring and initializing in one line, everything happens correctly:

fun main() {
    val set: Set<Int>? = null
    val emptySet: Set<Int> = set.orEmpty()
}
over 4 years ago · Santiago Trujillo
2 answers
Answer question

0

The behavior you're observing can be explained by the interaction of two Kotlin features:

  • first, the type of set variable is narrowed to Nothing? as a result of a smart cast after the assignment of null value to it. The smart cast after an assignment can be useful in cases when it narrows variable type to a more specific type, but narrowing to Nothing? does more harm than good.
  • second, among all overloads of orEmpty function available for a value of type Nothing?, the non-generic one String?.orEmpty() is chosen due to the specific rule of Kotlin overload resolution: a non-generic candidate is preferred to generic ones.

This behavior indeed can be puzzling, so I've reported this problem as KT-50661.

over 4 years ago · Santiago Trujillo Report

0

I think this is related to the fact that the compiler is not so smart that it could deduce that the code set = null will be executed exactly once – it could be zero times or more than once.

If you know that it will run exactly one, you can tell the compiler by using a feature called kotlin.contracts:

import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract

@ExperimentalContracts
fun main() {
  val set: Set<Int>?
  once { set = null }
  val emptySet: Set<Int> = set.orEmpty()
}

@ExperimentalContracts
fun once(lambda: () -> Unit) {
  contract { callsInPlace(lambda, InvocationKind.EXACTLY_ONCE) }
  lambda()
}

See https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.contracts/

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!