openlang

Adding label(Integer) breaks label(null) on rebuild

Small change, on paper. A library has label(String value) today, and the next release keeps it and adds label(Integer value).

Old compiled callers are fine. Their class files already name the String signature, and that is what they keep calling. Rebuilding is another story. An untouched label(null) compiled against the new pair stops compiling, because both overloads accept null and neither is more specific than the other. The original method never had to change for that to happen.

So the release note has two audiences. People who keep their binaries can skip it. People who rebuild from source may have to edit a line just to keep meaning what they meant yesterday. I'm not against overloads, but that's a real cost to hand to someone who asked for nothing.

What should the migration advice say, and at what point is a new method name simply the kinder option?

The conversation continues 4

Follow the reasoning
  1. Permalink

    New name. labelNumber(Integer value) and done. Making every existing caller cast its nulls spreads the cost into code that has nothing to do with this change, and the library patch stays smaller too. Sharing the name has to buy something concrete beyond a tidier method list, and I don't see it yet.

  2. Permalink

    Two artifacts, kept apart. One client binary compiled against the old declaration. Its source, kept as a rebuild fixture. They answer different questions.

    The binary shows which overload the old call site names, and nothing more. If the method body changed, review that on its own. For this release the evidence is the old binary run plus the source rebuild with label(null). Neither result stands in for the other.

  3. Permalink

    Agreed, and there's a bonus for whoever touches that caller next. labelNumber(null) says which operation was meant. A cast on label(null) keeps the old selection too, but to a later reader it looks like noise. Somebody tidying up will delete it as redundant and the build breaks again. If the cast route wins, the migration note needs a line explaining why the cast is there.

  4. Permalink

    A separate name is a sensible default. The migration text still has to tell apart two callers who want different things. One wants the old string behavior and can write label((String) null). The other wants the numeric operation and should call the numeric method. Both edits remove the ambiguity. They are not the same edit.

    The overload earns its place only if the shared name tells callers with typed arguments something useful about how the two operations relate. In that case the release note shows the broken null call, its explicit repair and the statement about existing binaries side by side. If nobody can describe that relationship with a real use, labelNumber is the better choice. It doesn't force a source decision on existing callers just to make the method list look uniform.

Other sides of the same question

  1. implicit vs given in a half-migrated Scala 3 file

    Honestly, keeping implicit in Scala 3 was the right call and it still annoys me every week. Right call because nobody had to…

    Replies 2scala