arrow-optics icon indicating copy to clipboard operation
arrow-optics copied to clipboard

["Request"] "overriding" a lens in companion object generates "extension is shadowed by member" warning

Open danwallach opened this issue 6 years ago • 4 comments

What version are you currently using? 0.8.2

What would you like to see? Suppress generation of extension method under the below conditions.

I decided to code up a simple turtle graphics example to play with Arrow's lenses:

@optics
data class Point(val x: Double, val y: Double) {
    companion object
}

@optics
data class Turtle(
    val penDown: Boolean = true,
    val color: Int = 0xffffff,
    val location: Point = Point(0.0, 0.0),
    val heading: Double = 0.0 /* radians */
) {
    companion object {
        val heading: Lens<Turtle, Double> = Lens(
                get = { it.heading },
                set = { t, h -> t.copy(heading = normalizeHeading(h)) })

        // useful function to clean up a heading, making sure it's in [0, 2pi)
        private fun normalizeHeading(heading: Double): Double {
            if (heading < 0) {
                val multiple = -floor(heading / (2 * PI))
                return heading + multiple * 2.0 * PI
            } else if (heading < PI * 2) {
                return heading
            } else {
                val multiple = floor(heading / (2 * PI))
                return heading - multiple * 2.0 * PI
            }
        }
    }
...
}

In this example, I'm being slightly clever in how my turtle is representing its heading field by normalizing the heading after every operation that might use it. The code compiles and works as expected, but generates a compiler warning:

Extension is shadowed by a member: public final val heading: Lens<Turtle, Double> /* = PLens<Turtle, Turtle, Double, Double> */

This is, of course, exactly what I want to do -- replace the "default" lens with my "smarter" lens and its associated additional behavior. The question is how to suppress the warning. My guess is that the desirable solution is for the code generator to observe when you've already declared Turtle.Companion.heading and then it suppresses its code generation for that particular lens. You may want to have an explicit annotation (@overrides?) to clarify when this is happening.

danwallach avatar Jan 14 '19 21:01 danwallach

This issue flew under the radar for me, apologies. I don't think we have anyone focused on lenses at the moment, but what I can tell you is that you can import the extension as an alias instead, and that would work. You cannot override extension functions as they're dynamically dispatched.

pakoito avatar Apr 04 '19 22:04 pakoito

The goal here is to specify my "custom" lens as the "official" lens. If the code generator could be clever enough to notice that I've declared a lens, it could suppress its own. I get the behavior I want as-is except for the warning.

danwallach avatar Apr 04 '19 23:04 danwallach

Oooooh I see. I believe well have to live with it for now, as it's a bit of work to generalize just to get rid of a warning. Isn't there a baseline like in detekt of warnings to ignore?

pakoito avatar Apr 04 '19 23:04 pakoito

I'm happy for now, but it's always a good thing to be able to get a clean compile with every possible warning enabled.

danwallach avatar Apr 05 '19 00:04 danwallach