Skip to content
Source

Cool Story About Updating Coil

Not long ago we got around to updating some dependencies in the project for hygiene reasons. And it was coil's turn. Version 3.0 came out last November. We waited a bit, so to speak, updating now.

The project has view-based legacy, albeit not much. So coil is also used there, and in many places there was syntax roughly like this:

imageView.load(url) { // Here we enter a lambda where this is ImageLoader.Builder
  placeholder(drawable1) // Sets placeholder while image is loading
  error(drawable2) // Sets placeholder if loading fails
}

And in regression we saw crashes in runtime. Started digging. Turned out the coil folks, as part of KMP support (apparently), pulled the error(drawableRes) function out of the ImageLoader.Builder class itself into an extension function. Guess what could go wrong?

-- pause to think --

When you call a function on a builder, you don't need to write its import in the file. When you use an extension function - you need to write its import. Since there was no import there, the error function should have stopped compiling after this, right?) Yeah, if there wasn't a kotlin.error(Any) function that throws an exception and doesn't need to be explicitly imported.

In short, in simple words, for the compiler it looked like we wrote throw IllegalStateException() ourselves. And we're surprised why it crashes.

This lesson teaches us that when changing class functions to extension functions, you need to double-check that its name doesn't clash with some function from the standard library. And accepting Any in standard library functions is also an approach that raises questions. This is from the point of view of the function/class developer. What to do from the point of view of the library user, I can't even imagine)

Such a dumb situation, but so logical and funny because of it.