Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2.0: TypeName changes #1299

Open
ZacSweers opened this issue Jun 28, 2022 · 0 comments
Open

2.0: TypeName changes #1299

ZacSweers opened this issue Jun 28, 2022 · 0 comments
Milestone

Comments

@ZacSweers
Copy link
Collaborator

ZacSweers commented Jun 28, 2022

(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
@ZacSweers ZacSweers added this to the 2.0 milestone Jun 28, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant