hotkey
hotkey

Reputation: 148169

How to prohibit function calls with a certain subtype of a parameter type?

Suppose I have a generic function:

fun <T: Foo> bar(t: T) { ... }

Then, later at some point in time, I decided that it is meaningless (or even erroneous) to call bar(...) with T specialized as Qux, which is, of course, one of the Foo's subtypes. But I have a strong reason not to change the classes hierarchy (e.g. I don't have access to that code).

Is there a way to prohibit the calls to bar(t) with T specialized as Qux?

Upvotes: 1

Views: 89

Answers (1)

hotkey
hotkey

Reputation: 148169

There is a way to prohibit the calls for a certain generic type argument: the deprecation. Using the @Deprecated annotation in this case looks quite clumsy, but it solves the problem (*).

You can define an overload of bar(...) with a more concrete type and deprecate the overload with level DeprecationLevel.ERROR:

@Deprecated("bar should not be called with Qux", level = DeprecationLevel.ERROR)
fun <T : Qux> bar(t: T) = bar(t as Foo)

After that, when a bar(...) call is resolved for a Qux argument, the deprecated overload will take precedence because it features more concrete types. Therefore the calls will produce a compile-time error:

bar(Qux())
^ Using 'bar(T): Unit' is an error. bar should not be called with Qux

(*) Note, however, that this will only work for Qux as static type (the one used for the call resolution), and the function can still be called as bar(Qux() as Foo). Quite expectedly, you cannot produce a compile-time error if the argument type is only known at runtime.


The same approach can be used to produce errors or warnings for functions that should only react on nulls in some way, so that calling them with a not-null type makes no sense:

fun checkNotNull(x: Any?) = x ?: throw IllegalStateException("Should not be null")

@Deprecated("It is meaningless with a not-null argument.", DeprecationLevel.WARNING)
@JvmName("checkNotNull--notNullArgument")
fun checkNotNull(x: Any) = checkNotNull(x as Any?)

Upvotes: 3

Related Questions