Skip to content

Fix keyOf to handle unresolved type variables#3675

Merged
adrw merged 3 commits intomasterfrom
adrw/fix-keyof-type-variable
Feb 17, 2026
Merged

Fix keyOf to handle unresolved type variables#3675
adrw merged 3 commits intomasterfrom
adrw/fix-keyof-type-variable

Conversation

@adrw
Copy link
Collaborator

@adrw adrw commented Feb 17, 2026

Summary

  • Fix keyOf<T>() to fall back to the erased class (T::class.java) when the resolved TypeLiteral contains unresolved TypeVariables
  • Fully specified generic types (e.g., keyOf<List<String>>()) still use TypeLiteral for proper generic type preservation

Problem

PR #3668 changed keyOf from Key.get(T::class.java, ...) to Key.get(object : TypeLiteral<T>() {}, ...). This breaks callers that pass generic types containing non-reified type parameters from enclosing classes, such as:

class BatchReceiverModule<R : BatchReceiver<T>, T : Any> : KAbstractModule() {
  override fun configure() {
    // T is a class type parameter, not reified — TypeLiteral captures it as TypeVariable
    val key = keyOf<DecodingBatchCloudEventReceiver<T>>(Names.named("..."))
  }
}

Guice rejects the resulting key with KeyNotFullySpecified because DecodingBatchCloudEventReceiver<T> contains an unresolved TypeVariable.

This breaks InjectorTest in cash-server's Yolodex service (and any other service using BatchReceiverModule, SuspendingBatchReceiverModule, or SuspendingReceiverModule).

Fix

Added a containsTypeVariable() extension on java.lang.reflect.Type that recursively checks for TypeVariable instances. keyOf now checks the TypeLiteral's type — if it contains any type variables, it falls back to the old erased-class behavior. Otherwise, it uses the TypeLiteral for full generic type preservation.

Test plan

  • Verified InjectorTest in cash-server Yolodex service fails with the current Misk version (2026.02.14.023725-1db1eee) — 3/3 tests fail with KeyNotFullySpecified
  • Verified all 48/48 Yolodex tests pass with this fix applied via local.properties include

adrw added 3 commits February 16, 2026 21:17
The recent change to use TypeLiteral<T>() in keyOf breaks callers that
pass generic types with non-reified type parameters from enclosing
classes (e.g., keyOf<DecodingBatchCloudEventReceiver<T>>() where T is a
class type parameter). TypeLiteral captures the unresolved TypeVariable,
causing Guice to reject it with KeyNotFullySpecified.

This adds a runtime check: if the TypeLiteral's type contains any
TypeVariable, fall back to the old T::class.java approach. Fully
specified generic types still benefit from the TypeLiteral improvement.
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a regression in keyOf<T>() introduced in PR #3668, where changing from T::class.java to TypeLiteral broke modules that use generic class type parameters (non-reified). The fix adds runtime detection of unresolved TypeVariables and falls back to the erased class when needed, while still preserving full generic type information for fully-specified types.

Changes:

  • Modified keyOf to conditionally use TypeLiteral or erased class based on whether unresolved type variables are present
  • Added containsTypeVariable() extension function on Type to recursively detect TypeVariable instances
  • Added comprehensive test coverage for both the fix and the helper function

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
misk-inject/src/main/kotlin/misk/inject/Guice.kt Implements conditional type handling in keyOf and adds containsTypeVariable() helper function
misk-inject/src/test/kotlin/misk/inject/KeyOfTest.kt Comprehensive test suite covering simple types, fully-specified generics, unresolved type variables, and the containsTypeVariable() function
misk-inject/api/misk-inject.api Exposes new containsTypeVariable function as public API

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@adrw adrw added this pull request to the merge queue Feb 17, 2026
Merged via the queue into master with commit 66b9464 Feb 17, 2026
30 checks passed
@adrw adrw deleted the adrw/fix-keyof-type-variable branch February 17, 2026 05:04
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

Successfully merging this pull request may close these issues.

3 participants

Comments