Skip to content

2.0: TypeName changes #1299

@ZacSweers

Description

@ZacSweers

(WIP, not ready for review yet)

In 1.0, our TypeName modeling is largely based on JavaPoet's. This mostly works, but falls short in some ways that don't map well onto Kotlin's own semantics.

Problems:

  • WildcardTypeName extends TypeName, whereas Kotlin offers KTypeProjection and it is not a subtype
  • Definitely not null types, which don't have an easy spot in the current system (see Support definitely non-nullable types #1268)
  • TypeName is currently sealed, but KType is not and I think it's clear they want to keep the option open
  • There is currently no support for intersection types
  • ParameterizedTypeName extends TypeName, but Kotlin doesn't differentiate these. KType contains a classifier and arguments.
  • Semantics do not currently line up

Proposal:

  • Replace WildcardTypeName with a projection type that does not extend TypeName.
class `KpTypeProjection(val variance: KModifier?, val type: TypeName?)`
  • Model TypeName more like KType, inline away ParameterizedTypeName.
interface KpType {
  val classifier: KpClassifier // KpClass or KpTypeParameter
  val arguments: List<KpTypeProjection>
  val isMarkedNullable: Boolean
}
  • Introduce IntersectionTypeName for intersection types. This should also cover definitely non-nullable types
  • Introduce upperBounds to KpTypeParameter, allowing support for intersection types
  • Introduce KType.makeNotNull(), which returns a special-case KpType that adds this extra notation. This matches how Kotlin handles it internally, as it's just a flag on the proto.
  • Make TypeName no longer sealed.
  • Rename to match Kotlin semantics
Before After
KpClassifier
TypeName KpType
ClassName KpClass
TypeVariableName KpTypeParameter
WildcardTypeName KpTypeProjection

Then common types could be implemented as such

KpClass

kpTypeOf<String>() // Returns KpType
String::class.kp // Returns KpClass
String::class.kpClassifier // Returns KpClassifier
String::class.kpType // Returns KpType

Generics

kpTypeOf<List<String>>() // Returns KpType
List::class.parameterizedBy(String::class) // Returns KpType
List::class.parameterizedBy(String::class.kp) // Returns KpType
List::class.parameterizedBy(String::class.kpType) // Returns KpType
List::class.parameterizedBy(KpTypeProjection<String>(OUT)) // Returns KpType

Intersection types

// Renders to T : Any, T : Runnable
KpTypeParameter("T", upperBounds = listOf(ANY, kpTypeOf<Runnable>())

// Other params include variance and isReified

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions