星型注释

Annotation on star types

我有一个很简单的例子

@Retention(AnnotationRetention.SOURCE)
@Target(AnnotationTarget.TYPE, AnnotationTarget.EXPRESSION)
annotation class Test

data class MyClass(
    val setInt: Set<@Test Int>,
    val setStar: Set<@Test *>,
)

字段 setInt 被编译器接受得很好,但是对于字段 setStar 编译器产生错误 Type expected,尽管我的注释非常通用:它只适用于源和任何表达式。

这不可能吗?有解决办法吗?

更新: 这里是 playground

我看到你在 setStar 的末尾添加了一个额外的 ,

尝试删除它并且会正常工作。

不,这是syntax所不允许的。

simple user type 的语法是:

simpleUserType:
    simpleIdentifier [{NL} typeArguments]
typeArguments:
    '<'
    {NL}
    typeProjection
    {{NL} ',' {NL} typeProjection}
    [{NL} ',']
    {NL}
    '>'
typeProjection:
    ([typeProjectionModifiers] type)
    | '*'
typeProjectionModifiers:
    typeProjectionModifier {typeProjectionModifier}
typeProjectionModifier:
    (varianceModifier {NL})
    | annotation

具体来说,typeProjection 的生产规则(它是 typeArguments 的一部分)包括两个备选方案:另一种可选地以一些修饰符为前缀的类型(例如,您要添加的注释) , 或 * 字符本身。

* 不是类型或表达式。它是一个 projection,就像 in Intout String 是投影,而不是类型(尽管 IntString 是类型)。您不能注释投影,但可以注释投影中使用的类型。碰巧 * 是一个不使用任何类型的投影。

作为解决方法(至少对于 Set),您可以将星投影更改为 Any?,这在 Set 的情况下意味着相同的事情。

data class MyClass(
    val setInt: Set<@Test Int>,
    val setStar: Set<@Test Any?>,
)

现在你有一个类型可以注释了!

大多数情况下,您可以将星形投影重写为另一个使用类型的投影,请参阅 this 了解更多信息。