Upgrade dagger2 to dagger-2.51

This project was upgraded with external_updater.
Usage: tools/external_updater/updater.sh update dagger2
For more info, check https://cs.android.com/android/platform/superproject/+/main:tools/external_updater/README.md

Test: TreeHugger
Change-Id: I6a876e5d65cdd1d83ad3db931a09c349bdfa17cd
diff --git a/.github/actions/artifact-android-local-tests/action.yml b/.github/actions/artifact-android-local-tests/action.yml
index 5410985..c4b24eb 100644
--- a/.github/actions/artifact-android-local-tests/action.yml
+++ b/.github/actions/artifact-android-local-tests/action.yml
@@ -5,6 +5,18 @@
   agp:
     description: 'The version of AGP to test with.'
     required: true
+    type: choice
+    options:
+      - '7.0.0'
+      - '7.1.2'
+      - '8.1.0'
+  jdk:
+    description: 'The version of JDK to test with.'
+    required: true
+    type: choice
+    options:
+      - '11'
+      - '17'
 
 runs:
   using: "composite"
@@ -25,11 +37,11 @@
       with:
         name: local-snapshot
         path: ~/.m2/repository/com/google/dagger
-    - name: 'Install Java ${{ env.USE_JAVA_VERSION }}'
+    - name: 'Install Java ${{ inputs.jdk }}'
       uses: actions/setup-java@v3
       with:
         distribution: '${{ env.USE_JAVA_DISTRIBUTION }}'
-        java-version: '${{ env.USE_JAVA_VERSION }}'
+        java-version: '${{ inputs.jdk }}'
     - name: 'Gradle Android local tests (AGP ${{ inputs.agp }})'
       run: ./util/run-local-gradle-android-tests.sh "${{ inputs.agp }}"
       shell: bash
diff --git a/.github/actions/cleanup-caches/action.yml b/.github/actions/cleanup-caches/action.yml
new file mode 100644
index 0000000..294d624
--- /dev/null
+++ b/.github/actions/cleanup-caches/action.yml
@@ -0,0 +1,13 @@
+name: 'Clean up caches'
+description: 'Cleans up GitHub Action caches.'
+
+runs:
+  using: "composite"
+  steps:
+      - name: 'Check out repository'
+        uses: actions/checkout@v3
+      - name: 'Cleanup caches'
+        run: python ./util/cleanup-github-caches.py
+        shell: bash
+        env:
+          GITHUB_TOKEN: ${{ github.token }}
diff --git a/.github/actions/prechecks/action.yml b/.github/actions/prechecks/action.yml
index 3ff6ec0..09dc5d9 100644
--- a/.github/actions/prechecks/action.yml
+++ b/.github/actions/prechecks/action.yml
@@ -20,3 +20,10 @@
       shell: bash
       env:
         GH_TOKEN: ${{ github.token }}
+    - name: 'Check out repository'
+      uses: actions/checkout@v3
+    - name: 'Cleanup caches'
+      run: python ./util/cleanup-github-caches.py
+      shell: bash
+      env:
+        GITHUB_TOKEN: ${{ github.token }}
diff --git a/.github/actions/test-gradle-plugin/action.yml b/.github/actions/test-gradle-plugin/action.yml
index 5523278..bd57472 100644
--- a/.github/actions/test-gradle-plugin/action.yml
+++ b/.github/actions/test-gradle-plugin/action.yml
@@ -4,11 +4,11 @@
 runs:
   using: "composite"
   steps:
-    - name: 'Install Java ${{ env.USE_JAVA_VERSION }}'
+    - name: 'Install Java ${{ env.USE_JAVA_VERSION_FOR_PLUGIN }}'
       uses: actions/setup-java@v3
       with:
         distribution: '${{ env.USE_JAVA_DISTRIBUTION }}'
-        java-version: '${{ env.USE_JAVA_VERSION }}'
+        java-version: '${{ env.USE_JAVA_VERSION_FOR_PLUGIN }}'
     - name: 'Check out repository'
       uses: actions/checkout@v3
     - name: 'Cache local Maven repository'
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index f4650e7..d50fcec 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -11,9 +11,11 @@
 env:
   USE_JAVA_DISTRIBUTION: 'zulu'
   USE_JAVA_VERSION: '11'
-  # Our Bazel builds currently rely on 5.3.2. The version is set via
+  # This is required by AGP 8.3+.
+  USE_JAVA_VERSION_FOR_PLUGIN: '17'
+  # Our Bazel builds currently rely on 6.4.0. The version is set via
   # baselisk by USE_BAZEL_VERSION: https://github.com/bazelbuild/bazelisk.
-  USE_BAZEL_VERSION: '5.3.2'
+  USE_BAZEL_VERSION: '6.4.0'
   # The default Maven 3.9.0 has a regression so we manually install 3.8.7.
   # https://issues.apache.org/jira/browse/MNG-7679
   USE_MAVEN_VERSION: '3.8.7'
@@ -35,7 +37,9 @@
   bazel-test:
     name: 'Bazel tests'
     needs: validate-latest-dagger-version
-    runs-on: ubuntu-latest
+    runs-on:
+      group: large-runner
+      labels: ubuntu-22.04-16core
     steps:
       - uses: actions/checkout@v3
       - uses: ./.github/actions/bazel-test
@@ -59,24 +63,19 @@
     runs-on: ubuntu-latest
     strategy:
       matrix:
-        agp: ['7.0.0', '7.1.2']
+        include:
+          - agp: '7.0.0'
+            jdk: '11'
+          - agp: '7.1.2'
+            jdk: '11'
+          - agp: '8.1.0'
+            jdk: '17'
     steps:
       - uses: actions/checkout@v3
       - uses: ./.github/actions/artifact-android-local-tests
         with:
           agp: '${{ matrix.agp }}'
-  artifact-android-emulator-tests:
-    name: 'Artifact Android emulator tests (API 30)'
-    needs: bazel-build
-    # It's recommended to run emulator tests on macOS
-    # See https://github.com/marketplace/actions/android-emulator-runner
-    runs-on: macos-latest
-    steps:
-      - uses: actions/checkout@v3
-      - uses: ./.github/actions/artifact-android-emulator-tests
-        timeout-minutes: 30 # TODO(b/287486065) investigate whether there is performance regression
-        with:
-          api-level: '30'
+          jdk: '${{ matrix.jdk }}'
   artifact-android-emulator-legacy-api-tests:
     name: 'Artifact Android emulator tests (API ${{ matrix.api-level }})'
     # We only run this on master push (essentially a postsubmit) since these
@@ -88,11 +87,11 @@
     runs-on: macos-latest
     strategy:
       matrix: # Run on 16 (PreL), 21 (L), and 26 (O).
-        api-level: [16, 21, 26]
+        api-level: [16, 21, 26, 30]
     steps:
       - uses: actions/checkout@v3
       - uses: ./.github/actions/artifact-android-emulator-tests
-        timeout-minutes: 25
+        timeout-minutes: 35
         with:
           api-level: '${{ matrix.api-level }}'
   publish-snapshot:
@@ -174,3 +173,12 @@
       - uses: ./.github/actions/build-gradle-plugin
         with:
           agp: '+'
+  cleanup-caches:
+    name: 'Clean up GitHub Action caches'
+    # TODO(bcorso): Consider also waiting on artifact-android-emulator-tests
+    # and artifact-android-emulator-legacy-api-tests after checking flakiness.
+    needs: [bazel-test, artifact-java-local-tests, artifact-android-local-tests, test-gradle-plugin]
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v3
+      - uses: ./.github/actions/cleanup-caches
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index fd371b1..b16c0d5 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -10,9 +10,11 @@
 env:
   USE_JAVA_DISTRIBUTION: 'zulu'
   USE_JAVA_VERSION: '11'
-  # Our Bazel builds currently rely on 5.3.2. The version is set via
+  # This is required by AGP 8.3+.
+  USE_JAVA_VERSION_FOR_PLUGIN: '17'
+  # Our Bazel builds currently rely on 6.4.0. The version is set via
   # baselisk by USE_BAZEL_VERSION: https://github.com/bazelbuild/bazelisk.
-  USE_BAZEL_VERSION: '5.3.2'
+  USE_BAZEL_VERSION: '6.4.0'
   DAGGER_RELEASE_VERSION: "${{ github.event.inputs.dagger_release_version }}"
   # The default Maven 3.9.0 has a regression so we manually install 3.8.7.
   # https://issues.apache.org/jira/browse/MNG-7679
@@ -37,7 +39,9 @@
   bazel-test:
     name: 'Bazel tests'
     needs: validate-latest-dagger-version
-    runs-on: ubuntu-latest
+    runs-on:
+      group: large-runner
+      labels: ubuntu-22.04-16core
     steps:
       - uses: actions/checkout@v3
       - uses: ./.github/actions/bazel-test
@@ -61,12 +65,19 @@
     runs-on: ubuntu-latest
     strategy:
       matrix:
-        agp: ['7.0.0', '7.1.2']
+        include:
+          - agp: '7.0.0'
+            jdk: '11'
+          - agp: '7.1.2'
+            jdk: '11'
+          - agp: '8.1.0'
+            jdk: '17'
     steps:
       - uses: actions/checkout@v3
       - uses: ./.github/actions/artifact-android-local-tests
         with:
           agp: '${{ matrix.agp }}'
+          jdk: '${{ matrix.jdk }}'
   publish-artifacts:
     name: 'Publish Artifact'
     needs: [bazel-test, artifact-java-local-tests, artifact-android-local-tests, test-gradle-plugin]
diff --git a/BUILD b/BUILD
index d81eca9..2c70b01 100644
--- a/BUILD
+++ b/BUILD
@@ -76,17 +76,6 @@
 )
 
 jarjar_library(
-    name = "shaded_android_processor",
-    jars = [
-        "//java/dagger/android/processor",
-        "//third_party/java/auto:common",
-    ],
-    rules = [
-        "rule com.google.auto.common.** dagger.android.shaded.auto.common.@1",
-    ],
-)
-
-jarjar_library(
     name = "shaded_grpc_server_processor",
     jars = [
         "//java/dagger/grpc/server/processor",
diff --git a/METADATA b/METADATA
index 5a52462..3511a6c 100644
--- a/METADATA
+++ b/METADATA
@@ -1,23 +1,20 @@
 # This project was upgraded with external_updater.
-# Usage: tools/external_updater/updater.sh update dagger2
-# For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md
+# Usage: tools/external_updater/updater.sh update external/dagger2
+# For more info, check https://cs.android.com/android/platform/superproject/+/main:tools/external_updater/README.md
 
 name: "dagger2"
 description: "A fast dependency injector for Android and Java."
 third_party {
-  url {
-    type: HOMEPAGE
-    value: "https://dagger.dev"
-  }
-  url {
-    type: GIT
-    value: "https://github.com/google/dagger"
-  }
-  version: "dagger-2.47"
   license_type: NOTICE
   last_upgrade_date {
-    year: 2023
-    month: 8
-    day: 2
+    year: 2024
+    month: 3
+    day: 5
+  }
+  homepage: "https://dagger.dev"
+  identifier {
+    type: "Git"
+    value: "https://github.com/google/dagger"
+    version: "dagger-2.51"
   }
 }
diff --git a/README.md b/README.md
index 01f3c91..4f5c014 100644
--- a/README.md
+++ b/README.md
@@ -38,8 +38,8 @@
 
 load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
 
-DAGGER_TAG = "2.46.1"
-DAGGER_SHA = "bbd75275faa3186ebaa08e6779dc5410741a940146d43ef532306eb2682c13f7"
+DAGGER_TAG = "2.50"
+DAGGER_SHA = "764993ba2465551c181b84b47e467f86fb367d8c0cd50154bd5519a4afb57753"
 http_archive(
     name = "dagger",
     strip_prefix = "dagger-dagger-%s" % DAGGER_TAG,
diff --git a/WORKSPACE b/WORKSPACE
index 860daf5..0e93e98 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -26,33 +26,19 @@
 )
 
 #############################
-# Load Bazel-Common repository
-#############################
-
-http_archive(
-    name = "google_bazel_common",
-    sha256 = "60a9aebe25f476646f61c041d1679a9b21076deffbd51526838c7f24d6468ac0",
-    strip_prefix = "bazel-common-227a23a508a2fab0fa67ffe2d9332ae536a40edc",
-    urls = ["https://github.com/google/bazel-common/archive/227a23a508a2fab0fa67ffe2d9332ae536a40edc.zip"],
-)
-
-load("@google_bazel_common//:workspace_defs.bzl", "google_common_workspace_rules")
-
-google_common_workspace_rules()
-
-#############################
 # Load Bazel Skylib rules
 #############################
 
-BAZEL_SKYLIB_VERSION = "1.2.1"
+BAZEL_SKYLIB_VERSION = "1.5.0"
 
-BAZEL_SKYLIB_SHA = "f7be3474d42aae265405a592bb7da8e171919d74c16f082a5457840f06054728"
+BAZEL_SKYLIB_SHA = "cd55a062e763b9349921f0f5db8c3933288dc8ba4f76dd9416aac68acee3cb94"
 
 http_archive(
     name = "bazel_skylib",
     sha256 = BAZEL_SKYLIB_SHA,
     urls = [
-        "https://github.com/bazelbuild/bazel-skylib/releases/download/{version}/bazel-skylib-{version}.tar.gz".format(version = BAZEL_SKYLIB_VERSION),
+        "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/%s/bazel-skylib-%s.tar.gz" % (BAZEL_SKYLIB_VERSION, BAZEL_SKYLIB_VERSION),
+        "https://github.com/bazelbuild/bazel-skylib/releases/download/%s/bazel-skylib-%s.tar.gz" % (BAZEL_SKYLIB_VERSION, BAZEL_SKYLIB_VERSION),
     ],
 )
 
@@ -60,6 +46,42 @@
 
 bazel_skylib_workspace()
 
+####################################################
+# Load Protobuf repository (needed by bazel-common)
+####################################################
+
+http_archive(
+    name = "rules_proto",
+    # output from `sha256sum` on the downloaded tar.gz file
+    sha256 = "66bfdf8782796239d3875d37e7de19b1d94301e8972b3cbd2446b332429b4df1",
+    strip_prefix = "rules_proto-4.0.0",
+    urls = [
+        "https://mirror.bazel.build/github.com/bazelbuild/rules_proto/archive/refs/tags/4.0.0.tar.gz",
+        "https://github.com/bazelbuild/rules_proto/archive/refs/tags/4.0.0.tar.gz",
+    ],
+)
+
+load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies", "rules_proto_toolchains")
+
+rules_proto_dependencies()
+
+rules_proto_toolchains()
+
+#############################
+# Load Bazel-Common repository
+#############################
+
+http_archive(
+    name = "google_bazel_common",
+    sha256 = "82a49fb27c01ad184db948747733159022f9464fc2e62da996fa700594d9ea42",
+    strip_prefix = "bazel-common-2a6b6406e12208e02b2060df0631fb30919080f3",
+    urls = ["https://github.com/google/bazel-common/archive/2a6b6406e12208e02b2060df0631fb30919080f3.zip"],
+)
+
+load("@google_bazel_common//:workspace_defs.bzl", "google_common_workspace_rules")
+
+google_common_workspace_rules()
+
 #############################
 # Load Protobuf dependencies
 #############################
@@ -107,9 +129,9 @@
 # Load Kotlin repository
 #############################
 
-RULES_KOTLIN_TAG = "v1.8-RC-1"
+RULES_KOTLIN_TAG = "v1.8"
 
-RULES_KOTLIN_SHA = "1779628569eb3b0fe97a3fb5c3ed8090e6503e425600b401c7b1afb6b23a3098"
+RULES_KOTLIN_SHA = "01293740a16e474669aba5b5a1fe3d368de5832442f164e4fbfc566815a8bc3a"
 
 http_archive(
     name = "io_bazel_rules_kotlin",
@@ -119,10 +141,10 @@
 
 load("@io_bazel_rules_kotlin//kotlin:repositories.bzl", "kotlin_repositories", "kotlinc_version")
 
-KOTLIN_VERSION = "1.8.0"
+KOTLIN_VERSION = "1.9.20"
 
 # Get from https://github.com/JetBrains/kotlin/releases/
-KOTLINC_RELEASE_SHA = "0bb9419fac9832a56a3a19cad282f8f2d6f1237d2d467dc8dfe9bd4a2a43c42e"
+KOTLINC_RELEASE_SHA = "15a8a2825b74ccf6c44e04e97672db802d2df75ce2fbb63ef0539bf3ae5006f0"
 
 kotlin_repositories(
     compiler_release = kotlinc_version(
@@ -139,9 +161,9 @@
 # Load Maven dependencies
 #############################
 
-RULES_JVM_EXTERNAL_TAG = "4.2"
+RULES_JVM_EXTERNAL_TAG = "4.5"
 
-RULES_JVM_EXTERNAL_SHA = "cd1a77b7b02e8e008439ca76fd34f5b07aecb8c752961f9640dea15e9e5ba1ca"
+RULES_JVM_EXTERNAL_SHA = "b17d7388feb9bfa7f2fa09031b32707df529f26c91ab9e5d909eb1676badd9a6"
 
 http_archive(
     name = "rules_jvm_external",
@@ -159,7 +181,7 @@
 # NOTE(bcorso): Even though we set the version here, our Guava version in
 #  processor code will use whatever version is built into JavaBuilder, which is
 #  tied to the version of Bazel we're using.
-GUAVA_VERSION = "27.1"
+GUAVA_VERSION = "33.0.0"
 
 GRPC_VERSION = "1.2.0"
 
@@ -171,11 +193,12 @@
 
 ERROR_PRONE_VERSION = "2.14.0"
 
-KSP_VERSION = KOTLIN_VERSION + "-1.0.9"
+KSP_VERSION = KOTLIN_VERSION + "-1.0.14"
 
 maven_install(
     artifacts = [
         "androidx.annotation:annotation:1.1.0",
+        "androidx.annotation:annotation-experimental:1.3.1",
         "androidx.appcompat:appcompat:1.3.1",
         "androidx.activity:activity:1.5.1",
         "androidx.fragment:fragment:1.5.1",
@@ -220,7 +243,7 @@
         "com.google.guava:guava-beta-checker:1.0",
         "com.google.protobuf:protobuf-java:3.7.0",
         "com.google.testing.compile:compile-testing:0.18",
-        "com.google.truth:truth:1.1",
+        "com.google.truth:truth:1.4.0",
         "com.squareup:javapoet:1.13.0",
         "com.squareup:kotlinpoet:1.11.0",
         "io.github.java-diff-utils:java-diff-utils:4.11",
@@ -246,6 +269,7 @@
         "org.jetbrains.kotlin:kotlin-daemon-embeddable:%s" % KOTLIN_VERSION,
         "org.jetbrains.kotlin:kotlin-stdlib:%s" % KOTLIN_VERSION,
         "org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.6.2",
+        "org.jspecify:jspecify:0.3.0",
         "org.mockito:mockito-core:2.28.2",
         "org.objenesis:objenesis:1.0",
         "org.robolectric:robolectric:4.4",
diff --git a/examples/bazel/WORKSPACE b/examples/bazel/WORKSPACE
index 3291f3a..3ad378c 100644
--- a/examples/bazel/WORKSPACE
+++ b/examples/bazel/WORKSPACE
@@ -42,9 +42,7 @@
 android_sdk_repository(
     name = "androidsdk",
     api_level = 32,
-    # Need to upgrade Bazel before upgrading tools
-    # https://github.com/bazelbuild/bazel/issues/13989
-    build_tools_version = "30.0.3",
+    build_tools_version = "32.0.0",
 )
 
 #############################
diff --git a/java/dagger/BUILD b/java/dagger/BUILD
index 4675e30..9183408 100644
--- a/java/dagger/BUILD
+++ b/java/dagger/BUILD
@@ -22,8 +22,7 @@
     "JAVA_RELEASE_MIN",
     "POM_VERSION",
 )
-load("//tools:maven.bzl", "pom_file")
-load("@google_bazel_common//tools/javadoc:javadoc.bzl", "javadoc_library")
+load("//tools:maven.bzl", "gen_maven_artifact")
 
 package(default_visibility = ["//:src"])
 
@@ -38,22 +37,21 @@
     ],
 )
 
-pom_file(
-    name = "pom",
-    artifact_id = "dagger",
+gen_maven_artifact(
+    name = "artifact",
+    artifact_coordinates = "com.google.dagger:dagger:" + POM_VERSION,
     artifact_name = "Dagger",
-    targets = [":core"],
+    artifact_target = ":core",
+    artifact_target_maven_deps = [
+        "javax.inject:javax.inject",
+    ],
+    javadoc_root_packages = ["dagger"],
+    javadoc_srcs = [":javadoc-srcs"],
+    proguard_specs = [":proguard.pro"],
+    r8_specs = [":r8.pro"],
 )
 
 filegroup(
     name = "javadoc-srcs",
     srcs = glob(["**/*"]),
 )
-
-javadoc_library(
-    name = "core-javadoc",
-    srcs = [":javadoc-srcs"],
-    exclude_packages = ["dagger.internal"],
-    root_packages = ["dagger"],
-    deps = ["//third_party/java/jsr330_inject"],
-)
diff --git a/java/dagger/android/BUILD b/java/dagger/android/BUILD
index ef41dde..686e6ae 100644
--- a/java/dagger/android/BUILD
+++ b/java/dagger/android/BUILD
@@ -17,14 +17,14 @@
 
 load(
     "//:build_defs.bzl",
-    "DOCLINT_HTML_AND_SYNTAX",
-    "DOCLINT_REFERENCES",
-    "JAVA_RELEASE_MIN",
     "POM_VERSION",
 )
 load("//tools:dejetify.bzl", "dejetified_library")
-load("//tools:maven.bzl", "pom_file")
-load("@google_bazel_common//tools/javadoc:javadoc.bzl", "javadoc_library")
+load(
+    "//tools:maven.bzl",
+    "gen_maven_artifact",
+    "pom_file",
+)
 
 package(default_visibility = ["//:src"])
 
@@ -43,8 +43,6 @@
 android_library(
     name = "android",
     srcs = SRCS,
-    javacopts = JAVA_RELEASE_MIN + DOCLINT_HTML_AND_SYNTAX + DOCLINT_REFERENCES,
-    manifest = "AndroidManifest.xml",
     plugins = [
         "//java/dagger/android/internal/proguard:plugin",
     ],
@@ -60,17 +58,28 @@
     ],
 )
 
-pom_file(
-    name = "pom",
-    artifact_id = "dagger-android",
+gen_maven_artifact(
+    name = "artifact",
+    artifact_coordinates = "com.google.dagger:dagger-android:" + POM_VERSION,
     artifact_name = "Dagger Android",
+    artifact_target = ":android",
+    artifact_target_maven_deps = [
+        "androidx.annotation:annotation",
+        "com.google.dagger:dagger",
+        "com.google.dagger:dagger-lint-aar",
+    ],
+    javadoc_android_api_level = 32,
+    javadoc_root_packages = [
+        "dagger.android",
+    ],
+    javadoc_srcs = [":android-srcs"],
+    manifest = "AndroidManifest.xml",
     packaging = "aar",
-    targets = [":android"],
 )
 
 dejetified_library(
     name = "dejetified-android",
-    input = ":android.aar",
+    input = ":artifact.aar",
     output = "android-legacy.aar",
 )
 
@@ -92,12 +101,3 @@
     packaging = "aar",
     targets = [":legacy-deps"],
 )
-
-javadoc_library(
-    name = "android-javadoc",
-    srcs = [":android-srcs"],
-    android_api_level = 30,
-    exclude_packages = ["dagger.android.internal"],
-    root_packages = ["dagger.android"],
-    deps = [":android"],
-)
diff --git a/java/dagger/android/internal/proguard/BUILD b/java/dagger/android/internal/proguard/BUILD
index 5a85279..7cb2cbc 100644
--- a/java/dagger/android/internal/proguard/BUILD
+++ b/java/dagger/android/internal/proguard/BUILD
@@ -22,10 +22,19 @@
 
 java_library(
     name = "proguard-processor",
-    srcs = ["ProguardProcessor.java"],
+    srcs = [
+        "KspProguardProcessor.java",
+        "ProguardProcessingStep.java",
+        "ProguardProcessor.java",
+    ],
     javacopts = DOCLINT_HTML_AND_SYNTAX + DOCLINT_REFERENCES,
     deps = [
+        "//java/dagger/android/processor:base_processing_step",
+        "//java/dagger/internal/codegen/xprocessing",
         "//third_party/java/auto:service",
+        "//third_party/java/guava/collect",
+        "//third_party/java/javapoet",
+        "@maven//:com_google_devtools_ksp_symbol_processing_api",
     ],
 )
 
diff --git a/java/dagger/android/internal/proguard/KspProguardProcessor.java b/java/dagger/android/internal/proguard/KspProguardProcessor.java
new file mode 100644
index 0000000..e2d4c4c
--- /dev/null
+++ b/java/dagger/android/internal/proguard/KspProguardProcessor.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2024 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.android.internal.proguard;
+
+import androidx.room.compiler.processing.XProcessingEnv;
+import androidx.room.compiler.processing.XProcessingEnvConfig;
+import androidx.room.compiler.processing.XProcessingStep;
+import androidx.room.compiler.processing.ksp.KspBasicAnnotationProcessor;
+import com.google.auto.service.AutoService;
+import com.google.common.collect.ImmutableList;
+import com.google.devtools.ksp.processing.SymbolProcessor;
+import com.google.devtools.ksp.processing.SymbolProcessorEnvironment;
+import com.google.devtools.ksp.processing.SymbolProcessorProvider;
+
+/**
+ * An annotation processor to generate dagger-android's specific proguard needs. This is only
+ * intended to run over the dagger-android project itself, as the alternative is to create an
+ * intermediary java_library for proguard rules to be consumed by the project.
+ *
+ * <p>Basic structure looks like this:
+ *
+ * <pre><code>
+ *   resources/META-INF/com.android.tools/proguard/dagger-android.pro
+ *   resources/META-INF/com.android.tools/r8/dagger-android.pro
+ *   resources/META-INF/proguard/dagger-android.pro
+ * </code></pre>
+ */
+public final class KspProguardProcessor extends KspBasicAnnotationProcessor {
+  private static final XProcessingEnvConfig PROCESSING_ENV_CONFIG =
+      new XProcessingEnvConfig.Builder().build();
+  private XProcessingEnv env;
+
+  private KspProguardProcessor(SymbolProcessorEnvironment symbolProcessorEnvironment) {
+    super(symbolProcessorEnvironment, PROCESSING_ENV_CONFIG);
+  }
+
+  @Override
+  public void initialize(XProcessingEnv env) {
+    this.env = env;
+  }
+
+  @Override
+  public Iterable<XProcessingStep> processingSteps() {
+    return ImmutableList.of(new ProguardProcessingStep(env));
+  }
+
+  /** Provides the {@link KspProguardProcessor}. */
+  @AutoService(SymbolProcessorProvider.class)
+  public static final class Provider implements SymbolProcessorProvider {
+    @Override
+    public SymbolProcessor create(SymbolProcessorEnvironment symbolProcessorEnvironment) {
+      return new KspProguardProcessor(symbolProcessorEnvironment);
+    }
+  }
+}
diff --git a/java/dagger/android/internal/proguard/ProguardProcessingStep.java b/java/dagger/android/internal/proguard/ProguardProcessingStep.java
new file mode 100644
index 0000000..c4cc061
--- /dev/null
+++ b/java/dagger/android/internal/proguard/ProguardProcessingStep.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2024 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.android.internal.proguard;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import androidx.room.compiler.processing.XElement;
+import androidx.room.compiler.processing.XFiler;
+import androidx.room.compiler.processing.XProcessingEnv;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.squareup.javapoet.ClassName;
+import dagger.android.processor.BaseProcessingStep;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.nio.file.Path;
+
+/**
+ * A annotation processing step to generate dagger-android's specific proguard needs. This is only
+ * intended to run over the dagger-android project itself, as the alternative is to create an
+ * intermediary java_library for proguard rules to be consumed by the project.
+ *
+ * <p>Basic structure looks like this:
+ *
+ * <pre><code>
+ *   resources/META-INF/com.android.tools/proguard/dagger-android.pro
+ *   resources/META-INF/com.android.tools/r8/dagger-android.pro
+ *   resources/META-INF/proguard/dagger-android.pro
+ * </code></pre>
+ */
+public final class ProguardProcessingStep extends BaseProcessingStep {
+  private final XProcessingEnv processingEnv;
+
+  ProguardProcessingStep(XProcessingEnv processingEnv) {
+    this.processingEnv = processingEnv;
+  }
+
+  static final ClassName GENERATE_RULES_ANNOTATION_NAME =
+      ClassName.get("dagger.android.internal", "GenerateAndroidInjectionProguardRules");
+
+  @Override
+  public ImmutableSet<ClassName> annotationClassNames() {
+    return ImmutableSet.of(GENERATE_RULES_ANNOTATION_NAME);
+  }
+
+  @Override
+  public void process(XElement element, ImmutableSet<ClassName> annotationNames) {
+    XFiler filer = processingEnv.getFiler();
+
+    String errorProneRule = "-dontwarn com.google.errorprone.annotations.**\n";
+    String androidInjectionKeysRule =
+        "-identifiernamestring class dagger.android.internal.AndroidInjectionKeys {\n"
+            + "  java.lang.String of(java.lang.String);\n"
+            + "}\n";
+
+    writeFile(filer, "com.android.tools/proguard", errorProneRule);
+    writeFile(filer, "com.android.tools/r8", errorProneRule + androidInjectionKeysRule);
+    writeFile(filer, "proguard", errorProneRule);
+  }
+
+  private void writeFile(XFiler filer, String intermediatePath, String contents) {
+    try (OutputStream outputStream =
+            filer.writeResource(
+                Path.of("META-INF/" + intermediatePath + "/dagger-android.pro"),
+                ImmutableList.<XElement>of(),
+                XFiler.Mode.Isolating);
+        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream, UTF_8))) {
+      writer.write(contents);
+    } catch (IOException e) {
+      throw new IllegalStateException(e);
+    }
+  }
+}
diff --git a/java/dagger/android/internal/proguard/ProguardProcessor.java b/java/dagger/android/internal/proguard/ProguardProcessor.java
index 49274e9..8677bf1 100644
--- a/java/dagger/android/internal/proguard/ProguardProcessor.java
+++ b/java/dagger/android/internal/proguard/ProguardProcessor.java
@@ -16,19 +16,13 @@
 
 package dagger.android.internal.proguard;
 
-import static javax.tools.StandardLocation.CLASS_OUTPUT;
-
+import androidx.room.compiler.processing.XProcessingEnv;
+import androidx.room.compiler.processing.XProcessingStep;
+import androidx.room.compiler.processing.javac.JavacBasicAnnotationProcessor;
 import com.google.auto.service.AutoService;
-import java.io.IOException;
-import java.io.Writer;
-import java.util.Set;
-import javax.annotation.processing.AbstractProcessor;
-import javax.annotation.processing.Filer;
+import com.google.common.collect.ImmutableList;
 import javax.annotation.processing.Processor;
-import javax.annotation.processing.RoundEnvironment;
-import javax.annotation.processing.SupportedAnnotationTypes;
 import javax.lang.model.SourceVersion;
-import javax.lang.model.element.TypeElement;
 
 /**
  * An {@linkplain Processor annotation processor} to generate dagger-android's specific proguard
@@ -44,46 +38,17 @@
  * </code></pre>
  */
 @AutoService(Processor.class)
-@SupportedAnnotationTypes(ProguardProcessor.GENERATE_RULES_ANNOTATION_NAME)
-public final class ProguardProcessor extends AbstractProcessor {
-
-  static final String GENERATE_RULES_ANNOTATION_NAME =
-      "dagger.android.internal.GenerateAndroidInjectionProguardRules";
+public final class ProguardProcessor extends JavacBasicAnnotationProcessor {
+  private XProcessingEnv env;
 
   @Override
-  public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
-    roundEnv
-        .getElementsAnnotatedWith(
-            processingEnv.getElementUtils().getTypeElement(GENERATE_RULES_ANNOTATION_NAME))
-        .forEach(element -> generate());
-
-    return false;
+  public void initialize(XProcessingEnv env) {
+    this.env = env;
   }
 
-  private void generate() {
-    Filer filer = processingEnv.getFiler();
-
-    String errorProneRule = "-dontwarn com.google.errorprone.annotations.**\n";
-    String androidInjectionKeysRule =
-        "-identifiernamestring class dagger.android.internal.AndroidInjectionKeys {\n"
-            + "  java.lang.String of(java.lang.String);\n"
-            + "}\n";
-
-    writeFile(filer, "com.android.tools/proguard", errorProneRule);
-    writeFile(filer, "com.android.tools/r8", errorProneRule + androidInjectionKeysRule);
-    writeFile(filer, "proguard", errorProneRule);
-  }
-
-  private static void writeFile(Filer filer, String intermediatePath, String contents) {
-    try (Writer writer =
-        filer
-            .createResource(
-                CLASS_OUTPUT, "", "META-INF/" + intermediatePath + "/dagger-android.pro")
-            .openWriter()) {
-      writer.write(contents);
-    } catch (IOException e) {
-      throw new IllegalStateException(e);
-    }
+  @Override
+  public Iterable<XProcessingStep> processingSteps() {
+    return ImmutableList.of(new ProguardProcessingStep(env));
   }
 
   @Override
diff --git a/java/dagger/android/processor/AndroidInjectorDescriptor.java b/java/dagger/android/processor/AndroidInjectorDescriptor.java
index 12f2edf..758d895 100644
--- a/java/dagger/android/processor/AndroidInjectorDescriptor.java
+++ b/java/dagger/android/processor/AndroidInjectorDescriptor.java
@@ -16,29 +16,23 @@
 
 package dagger.android.processor;
 
-import static com.google.auto.common.AnnotationMirrors.getAnnotationValue;
-import static dagger.android.processor.MoreDaggerElements.getAnnotatedAnnotations;
-import static java.util.stream.Collectors.toList;
-import static javax.lang.model.element.Modifier.ABSTRACT;
-
-import com.google.auto.common.MoreElements;
-import com.google.auto.common.MoreTypes;
+import androidx.room.compiler.processing.JavaPoetExtKt;
+import androidx.room.compiler.processing.XAnnotation;
+import androidx.room.compiler.processing.XAnnotationValue;
+import androidx.room.compiler.processing.XElement;
+import androidx.room.compiler.processing.XExecutableElement;
+import androidx.room.compiler.processing.XMessager;
+import androidx.room.compiler.processing.XMethodElement;
+import androidx.room.compiler.processing.XType;
+import androidx.room.compiler.processing.XTypeElement;
 import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Sets;
 import com.squareup.javapoet.AnnotationSpec;
 import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.TypeName;
-import java.util.List;
+import dagger.internal.codegen.xprocessing.XElements;
 import java.util.Optional;
-import javax.annotation.processing.Messager;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.AnnotationValue;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.TypeMirror;
-import javax.lang.model.util.SimpleAnnotationValueVisitor8;
 import javax.tools.Diagnostic.Kind;
 
 /**
@@ -60,7 +54,7 @@
   abstract ClassName enclosingModule();
 
   /** The method annotated with {@code ContributesAndroidInjector}. */
-  abstract ExecutableElement method();
+  abstract XExecutableElement method();
 
   @AutoValue.Builder
   abstract static class Builder {
@@ -72,15 +66,15 @@
 
     abstract Builder enclosingModule(ClassName enclosingModule);
 
-    abstract Builder method(ExecutableElement method);
+    abstract Builder method(XExecutableElement method);
 
     abstract AndroidInjectorDescriptor build();
   }
 
   static final class Validator {
-    private final Messager messager;
+    private final XMessager messager;
 
-    Validator(Messager messager) {
+    Validator(XMessager messager) {
       this.messager = messager;
     }
 
@@ -88,10 +82,10 @@
      * Validates a {@code ContributesAndroidInjector} method, returning an {@link
      * AndroidInjectorDescriptor} if it is valid, or {@link Optional#empty()} otherwise.
      */
-    Optional<AndroidInjectorDescriptor> createIfValid(ExecutableElement method) {
+    Optional<AndroidInjectorDescriptor> createIfValid(XMethodElement method) {
       ErrorReporter reporter = new ErrorReporter(method, messager);
 
-      if (!method.getModifiers().contains(ABSTRACT)) {
+      if (!method.isAbstract()) {
         reporter.reportError("@ContributesAndroidInjector methods must be abstract");
       }
 
@@ -101,41 +95,40 @@
 
       AndroidInjectorDescriptor.Builder builder =
           new AutoValue_AndroidInjectorDescriptor.Builder().method(method);
-      TypeElement enclosingElement = MoreElements.asType(method.getEnclosingElement());
-      if (!MoreDaggerElements.isAnnotationPresent(enclosingElement, TypeNames.MODULE)) {
+      XTypeElement enclosingElement = XElements.asTypeElement(method.getEnclosingElement());
+      if (!enclosingElement.hasAnnotation(TypeNames.MODULE)) {
         reporter.reportError("@ContributesAndroidInjector methods must be in a @Module");
       }
-      builder.enclosingModule(ClassName.get(enclosingElement));
+      builder.enclosingModule(enclosingElement.getClassName());
 
-      TypeMirror injectedType = method.getReturnType();
-      if (MoreTypes.asDeclared(injectedType).getTypeArguments().isEmpty()) {
-        builder.injectedType(ClassName.get(MoreTypes.asTypeElement(injectedType)));
+      XType injectedType = method.getReturnType();
+      if (injectedType.getTypeArguments().isEmpty()) {
+        builder.injectedType(injectedType.getTypeElement().getClassName());
       } else {
         reporter.reportError(
             "@ContributesAndroidInjector methods cannot return parameterized types");
       }
 
-      AnnotationMirror annotation =
-          MoreDaggerElements.getAnnotationMirror(method, TypeNames.CONTRIBUTES_ANDROID_INJECTOR)
-              .get();
-      for (TypeMirror module :
-          getAnnotationValue(annotation, "modules").accept(new AllTypesVisitor(), null)) {
-        if (MoreDaggerElements.isAnnotationPresent(MoreTypes.asElement(module), TypeNames.MODULE)) {
-          builder.modulesBuilder().add((ClassName) TypeName.get(module));
+      XAnnotation annotation = method.getAnnotation(TypeNames.CONTRIBUTES_ANDROID_INJECTOR);
+      for (XType module : getTypeList(annotation.getAnnotationValue("modules"))) {
+        if (module.getTypeElement().hasAnnotation(TypeNames.MODULE)) {
+          builder.modulesBuilder().add((ClassName) module.getTypeName());
         } else {
           reporter.reportError(String.format("%s is not a @Module", module), annotation);
         }
       }
 
-      for (AnnotationMirror scope : Sets.union(
-          getAnnotatedAnnotations(method, TypeNames.SCOPE),
-          getAnnotatedAnnotations(method, TypeNames.SCOPE_JAVAX))) {
-        builder.scopesBuilder().add(AnnotationSpec.get(scope));
+      for (XAnnotation scope :
+          Sets.union(
+              method.getAnnotationsAnnotatedWith(TypeNames.SCOPE),
+              method.getAnnotationsAnnotatedWith(TypeNames.SCOPE_JAVAX))) {
+        builder.scopesBuilder().add(JavaPoetExtKt.toAnnotationSpec(scope));
       }
 
-      for (AnnotationMirror qualifier : Sets.union(
-          getAnnotatedAnnotations(method, TypeNames.QUALIFIER),
-          getAnnotatedAnnotations(method, TypeNames.QUALIFIER_JAVAX))) {
+      for (XAnnotation qualifier :
+          Sets.union(
+              method.getAnnotationsAnnotatedWith(TypeNames.QUALIFIER),
+              method.getAnnotationsAnnotatedWith(TypeNames.QUALIFIER_JAVAX))) {
         reporter.reportError(
             "@ContributesAndroidInjector methods cannot have qualifiers", qualifier);
       }
@@ -143,13 +136,23 @@
       return reporter.hasError ? Optional.empty() : Optional.of(builder.build());
     }
 
+    private static ImmutableList<XType> getTypeList(XAnnotationValue annotationValue) {
+      if (annotationValue.hasTypeListValue()) {
+        return ImmutableList.copyOf(annotationValue.asTypeList());
+      }
+      if (annotationValue.hasTypeValue()) {
+        return ImmutableList.of(annotationValue.asType());
+      }
+      throw new IllegalArgumentException("Does not have type list");
+    }
+
     // TODO(ronshapiro): use ValidationReport once it is moved out of the compiler
     private static class ErrorReporter {
-      private final Element subject;
-      private final Messager messager;
+      private final XElement subject;
+      private final XMessager messager;
       private boolean hasError;
 
-      ErrorReporter(Element subject, Messager messager) {
+      ErrorReporter(XElement subject, XMessager messager) {
         this.subject = subject;
         this.messager = messager;
       }
@@ -159,29 +162,10 @@
         messager.printMessage(Kind.ERROR, error, subject);
       }
 
-      void reportError(String error, AnnotationMirror annotation) {
+      void reportError(String error, XAnnotation annotation) {
         hasError = true;
         messager.printMessage(Kind.ERROR, error, subject, annotation);
       }
     }
   }
-
-  private static final class AllTypesVisitor
-      extends SimpleAnnotationValueVisitor8<ImmutableSet<TypeMirror>, Void> {
-    @Override
-    public ImmutableSet<TypeMirror> visitArray(List<? extends AnnotationValue> values, Void aVoid) {
-      return ImmutableSet.copyOf(
-          values.stream().flatMap(v -> v.accept(this, null).stream()).collect(toList()));
-    }
-
-    @Override
-    public ImmutableSet<TypeMirror> visitType(TypeMirror a, Void aVoid) {
-      return ImmutableSet.of(a);
-    }
-
-    @Override
-    protected ImmutableSet<TypeMirror> defaultAction(Object o, Void aVoid) {
-      throw new AssertionError(o);
-    }
-  }
 }
diff --git a/java/dagger/android/processor/AndroidMapKeyProcessingStep.java b/java/dagger/android/processor/AndroidMapKeyProcessingStep.java
new file mode 100644
index 0000000..8a7e83c
--- /dev/null
+++ b/java/dagger/android/processor/AndroidMapKeyProcessingStep.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2017 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.android.processor;
+
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static dagger.android.processor.AndroidMapKeys.injectedTypeFromMapKey;
+import static dagger.internal.codegen.xprocessing.XTypes.toStableString;
+
+import androidx.room.compiler.processing.XAnnotation;
+import androidx.room.compiler.processing.XElement;
+import androidx.room.compiler.processing.XMethodElement;
+import androidx.room.compiler.processing.XProcessingEnv;
+import androidx.room.compiler.processing.XType;
+import androidx.room.compiler.processing.XTypeElement;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+import com.squareup.javapoet.ClassName;
+import dagger.internal.codegen.xprocessing.XElements;
+import dagger.internal.codegen.xprocessing.XTypes;
+import javax.tools.Diagnostic.Kind;
+
+/** Validates the correctness of {@link dagger.MapKey}s used with {@code dagger.android}. */
+final class AndroidMapKeyProcessingStep extends BaseProcessingStep {
+  private final XProcessingEnv processingEnv;
+
+  AndroidMapKeyProcessingStep(XProcessingEnv processingEnv) {
+    this.processingEnv = processingEnv;
+  }
+
+  @Override
+  public ImmutableSet<ClassName> annotationClassNames() {
+    return ImmutableSet.of(TypeNames.ANDROID_INJECTION_KEY, TypeNames.CLASS_KEY);
+  }
+
+  @Override
+  public void process(XElement element, ImmutableSet<ClassName> annotationNames) {
+    for (ClassName annotationName : annotationNames) {
+      validateMethod(annotationName, XElements.asMethod(element));
+    }
+  }
+
+  private void validateMethod(ClassName annotation, XMethodElement method) {
+    if (!Sets.union(
+            method.getAnnotationsAnnotatedWith(TypeNames.QUALIFIER),
+            method.getAnnotationsAnnotatedWith(TypeNames.QUALIFIER_JAVAX))
+        .isEmpty()) {
+      return;
+    }
+
+    XType returnType = method.getReturnType();
+    if (!factoryElement().getType().getRawType().isAssignableFrom(returnType.getRawType())) {
+      // if returnType is not related to AndroidInjector.Factory, ignore the method
+      return;
+    }
+
+    if (!Sets.union(
+            method.getAnnotationsAnnotatedWith(TypeNames.SCOPE),
+            method.getAnnotationsAnnotatedWith(TypeNames.SCOPE_JAVAX))
+        .isEmpty()) {
+      XAnnotation suppressedWarnings = method.getAnnotation(ClassName.get(SuppressWarnings.class));
+      if (suppressedWarnings == null
+          || !ImmutableSet.copyOf(suppressedWarnings.getAsStringList("value"))
+              .contains("dagger.android.ScopedInjectorFactory")) {
+        XAnnotation mapKeyAnnotation =
+            getOnlyElement(method.getAnnotationsAnnotatedWith(TypeNames.MAP_KEY));
+        XTypeElement mapKeyValueElement =
+            processingEnv.requireTypeElement(injectedTypeFromMapKey(mapKeyAnnotation).get());
+        processingEnv
+            .getMessager()
+            .printMessage(
+                Kind.ERROR,
+                String.format(
+                    "%s bindings should not be scoped. Scoping this method may leak instances of"
+                        + " %s.",
+                    TypeNames.ANDROID_INJECTOR_FACTORY.canonicalName(),
+                    mapKeyValueElement.getQualifiedName()),
+                method);
+      }
+    }
+
+    validateReturnType(method);
+
+    // @Binds methods should only have one parameter, but we can't guarantee the order of Processors
+    // in javac, so do a basic check for valid form
+    if (method.hasAnnotation(TypeNames.BINDS) && method.getParameters().size() == 1) {
+      validateMapKeyMatchesBindsParameter(annotation, method);
+    }
+  }
+
+  /** Report an error if the method's return type is not {@code AndroidInjector.Factory<?>}. */
+  private void validateReturnType(XMethodElement method) {
+    XType returnType = method.getReturnType();
+    XType requiredReturnType = injectorFactoryOf(processingEnv.getWildcardType(null, null));
+
+    // TODO(b/311460276) use XType.isSameType when the bug is fixed.
+    if (!returnType.getTypeName().equals(requiredReturnType.getTypeName())) {
+      processingEnv
+          .getMessager()
+          .printMessage(
+              Kind.ERROR,
+              String.format(
+                  "%s should bind %s, not %s. See https://dagger.dev/android",
+                  method, toStableString(requiredReturnType), toStableString(returnType)),
+              method);
+    }
+  }
+
+  /**
+   * A valid @Binds method could bind an {@code AndroidInjector.Factory} for one type, while giving
+   * it a map key of a different type. The return type and parameter type would pass typical @Binds
+   * validation, but the map lookup in {@code DispatchingAndroidInjector} would retrieve the wrong
+   * injector factory.
+   *
+   * <pre>{@code
+   * {@literal @Binds}
+   * {@literal @IntoMap}
+   * {@literal @ClassKey(GreenActivity.class)}
+   * abstract AndroidInjector.Factory<?> bindBlueActivity(
+   *     BlueActivityComponent.Builder builder);
+   * }</pre>
+   */
+  private void validateMapKeyMatchesBindsParameter(
+      ClassName annotationName, XMethodElement method) {
+    XType parameterType = getOnlyElement(method.getParameters()).getType();
+    XAnnotation annotation = method.getAnnotation(annotationName);
+    XType mapKeyType =
+        processingEnv.requireTypeElement(injectedTypeFromMapKey(annotation).get()).getType();
+    if (!XTypes.isAssignableTo(parameterType, injectorFactoryOf(mapKeyType))) {
+      processingEnv
+          .getMessager()
+          .printMessage(
+              Kind.ERROR,
+              String.format(
+                  "%s does not implement AndroidInjector<%s>",
+                  toStableString(parameterType), toStableString(mapKeyType)),
+              method,
+              annotation);
+    }
+  }
+
+  /** Returns a {@link XType} for {@code AndroidInjector.Factory<implementationType>}. */
+  private XType injectorFactoryOf(XType implementationType) {
+    return processingEnv.getDeclaredType(factoryElement(), implementationType);
+  }
+
+  private XTypeElement factoryElement() {
+    return processingEnv.requireTypeElement(TypeNames.ANDROID_INJECTOR_FACTORY.canonicalName());
+  }
+}
diff --git a/java/dagger/android/processor/AndroidMapKeyValidator.java b/java/dagger/android/processor/AndroidMapKeyValidator.java
deleted file mode 100644
index 8d67466..0000000
--- a/java/dagger/android/processor/AndroidMapKeyValidator.java
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Copyright (C) 2017 The Dagger Authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package dagger.android.processor;
-
-import static com.google.auto.common.AnnotationMirrors.getAnnotatedAnnotations;
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static dagger.android.processor.AndroidMapKeys.injectedTypeFromMapKey;
-import static dagger.android.processor.MoreDaggerElements.getAnnotatedAnnotations;
-
-import com.google.auto.common.BasicAnnotationProcessor.Step;
-import com.google.auto.common.MoreElements;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.ImmutableSetMultimap;
-import com.google.common.collect.Sets;
-import com.squareup.javapoet.ClassName;
-import dagger.MapKey;
-import javax.annotation.processing.Messager;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.TypeMirror;
-import javax.lang.model.util.Elements;
-import javax.lang.model.util.Types;
-import javax.tools.Diagnostic.Kind;
-
-/** Validates the correctness of {@link dagger.MapKey}s used with {@code dagger.android}. */
-final class AndroidMapKeyValidator implements Step {
-  private static final ImmutableMap<String, ClassName> SUPPORTED_ANNOTATIONS =
-      ImmutableMap.of(
-          TypeNames.ANDROID_INJECTION_KEY.toString(), TypeNames.ANDROID_INJECTION_KEY,
-          TypeNames.CLASS_KEY.toString(), TypeNames.CLASS_KEY);
-
-  private final Elements elements;
-  private final Types types;
-  private final Messager messager;
-
-  AndroidMapKeyValidator(Elements elements, Types types, Messager messager) {
-    this.elements = elements;
-    this.types = types;
-    this.messager = messager;
-  }
-
-  @Override
-  public ImmutableSet<String> annotations() {
-    return SUPPORTED_ANNOTATIONS.keySet();
-  }
-
-  @Override
-  public ImmutableSet<Element> process(ImmutableSetMultimap<String, Element> elementsByAnnotation) {
-    ImmutableSet.Builder<Element> deferredElements = ImmutableSet.builder();
-    elementsByAnnotation
-        .entries()
-        .forEach(
-            entry -> {
-              try {
-                validateMethod(entry.getKey(), MoreElements.asExecutable(entry.getValue()));
-              } catch (TypeNotPresentException e) {
-                deferredElements.add(entry.getValue());
-              }
-            });
-    return deferredElements.build();
-  }
-
-  private void validateMethod(String annotation, ExecutableElement method) {
-    if (!Sets.union(getAnnotatedAnnotations(method, TypeNames.QUALIFIER),
-        getAnnotatedAnnotations(method, TypeNames.QUALIFIER_JAVAX)).isEmpty()) {
-      return;
-    }
-
-    TypeMirror returnType = method.getReturnType();
-    if (!types.isAssignable(types.erasure(returnType), factoryElement().asType())) {
-      // if returnType is not related to AndroidInjector.Factory, ignore the method
-      return;
-    }
-
-    if (!Sets.union(getAnnotatedAnnotations(method, TypeNames.SCOPE),
-          getAnnotatedAnnotations(method, TypeNames.SCOPE_JAVAX)).isEmpty()) {
-      SuppressWarnings suppressedWarnings = method.getAnnotation(SuppressWarnings.class);
-      if (suppressedWarnings == null
-          || !ImmutableSet.copyOf(suppressedWarnings.value())
-              .contains("dagger.android.ScopedInjectorFactory")) {
-        AnnotationMirror mapKeyAnnotation =
-            getOnlyElement(getAnnotatedAnnotations(method, MapKey.class));
-        TypeElement mapKeyValueElement =
-            elements.getTypeElement(injectedTypeFromMapKey(mapKeyAnnotation).get());
-        messager.printMessage(
-            Kind.ERROR,
-            String.format(
-                "%s bindings should not be scoped. Scoping this method may leak instances of %s.",
-                TypeNames.ANDROID_INJECTOR_FACTORY.canonicalName(),
-                mapKeyValueElement.getQualifiedName()),
-            method);
-      }
-    }
-
-    validateReturnType(method);
-
-    // @Binds methods should only have one parameter, but we can't guarantee the order of Processors
-    // in javac, so do a basic check for valid form
-    if (MoreDaggerElements.isAnnotationPresent(method, TypeNames.BINDS)
-        && method.getParameters().size() == 1) {
-      validateMapKeyMatchesBindsParameter(annotation, method);
-    }
-  }
-
-  /** Report an error if the method's return type is not {@code AndroidInjector.Factory<?>}. */
-  private void validateReturnType(ExecutableElement method) {
-    TypeMirror returnType = method.getReturnType();
-    DeclaredType requiredReturnType = injectorFactoryOf(types.getWildcardType(null, null));
-
-    if (!types.isSameType(returnType, requiredReturnType)) {
-      messager.printMessage(
-          Kind.ERROR,
-          String.format(
-              "%s should bind %s, not %s. See https://dagger.dev/android",
-              method, requiredReturnType, returnType),
-          method);
-    }
-  }
-
-  /**
-   * A valid @Binds method could bind an {@code AndroidInjector.Factory} for one type, while giving
-   * it a map key of a different type. The return type and parameter type would pass typical @Binds
-   * validation, but the map lookup in {@code DispatchingAndroidInjector} would retrieve the wrong
-   * injector factory.
-   *
-   * <pre>{@code
-   * {@literal @Binds}
-   * {@literal @IntoMap}
-   * {@literal @ClassKey(GreenActivity.class)}
-   * abstract AndroidInjector.Factory<?> bindBlueActivity(
-   *     BlueActivityComponent.Builder builder);
-   * }</pre>
-   */
-  private void validateMapKeyMatchesBindsParameter(String annotation, ExecutableElement method) {
-    TypeMirror parameterType = getOnlyElement(method.getParameters()).asType();
-    AnnotationMirror annotationMirror =
-        MoreDaggerElements.getAnnotationMirror(method, SUPPORTED_ANNOTATIONS.get(annotation)).get();
-    TypeMirror mapKeyType =
-        elements.getTypeElement(injectedTypeFromMapKey(annotationMirror).get()).asType();
-    if (!types.isAssignable(parameterType, injectorFactoryOf(mapKeyType))) {
-      messager.printMessage(
-          Kind.ERROR,
-          String.format("%s does not implement AndroidInjector<%s>", parameterType, mapKeyType),
-          method,
-          annotationMirror);
-    }
-  }
-
-  /** Returns a {@link DeclaredType} for {@code AndroidInjector.Factory<implementationType>}. */
-  private DeclaredType injectorFactoryOf(TypeMirror implementationType) {
-    return types.getDeclaredType(factoryElement(), implementationType);
-  }
-
-  private TypeElement factoryElement() {
-    return elements.getTypeElement(TypeNames.ANDROID_INJECTOR_FACTORY.canonicalName());
-  }
-}
diff --git a/java/dagger/android/processor/AndroidMapKeys.java b/java/dagger/android/processor/AndroidMapKeys.java
index 28da271..e3d890e 100644
--- a/java/dagger/android/processor/AndroidMapKeys.java
+++ b/java/dagger/android/processor/AndroidMapKeys.java
@@ -16,13 +16,9 @@
 
 package dagger.android.processor;
 
-import static com.google.auto.common.AnnotationMirrors.getAnnotationValue;
-
-import com.google.auto.common.MoreTypes;
+import androidx.room.compiler.processing.XAnnotation;
+import androidx.room.compiler.processing.XAnnotationValue;
 import java.util.Optional;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.TypeMirror;
 
 final class AndroidMapKeys {
   /**
@@ -30,13 +26,12 @@
    * it's {@link dagger.multibindings.ClassKey}, returns the fully-qualified class name of the
    * annotation value. Otherwise returns {@link Optional#empty()}.
    */
-  static Optional<String> injectedTypeFromMapKey(AnnotationMirror mapKey) {
-    Object mapKeyClass = getAnnotationValue(mapKey, "value").getValue();
-    if (mapKeyClass instanceof String) {
-      return Optional.of((String) mapKeyClass);
-    } else if (mapKeyClass instanceof TypeMirror) {
-      TypeElement type = MoreTypes.asTypeElement((TypeMirror) mapKeyClass);
-      return Optional.of(type.getQualifiedName().toString());
+  static Optional<String> injectedTypeFromMapKey(XAnnotation mapKey) {
+    XAnnotationValue mapKeyClass = mapKey.getAnnotationValue("value");
+    if (mapKeyClass.hasStringValue()) {
+      return Optional.of(mapKeyClass.asString());
+    } else if (mapKeyClass.hasTypeValue()) {
+      return Optional.of(mapKeyClass.asType().getTypeElement().getQualifiedName());
     } else {
       return Optional.empty();
     }
diff --git a/java/dagger/android/processor/AndroidProcessor.java b/java/dagger/android/processor/AndroidProcessor.java
index 2a8ab34..beb8d0d 100644
--- a/java/dagger/android/processor/AndroidProcessor.java
+++ b/java/dagger/android/processor/AndroidProcessor.java
@@ -16,21 +16,15 @@
 
 package dagger.android.processor;
 
-import static javax.tools.Diagnostic.Kind.ERROR;
 import static net.ltgt.gradle.incap.IncrementalAnnotationProcessorType.ISOLATING;
 
-import com.google.auto.common.BasicAnnotationProcessor;
+import androidx.room.compiler.processing.XProcessingEnv;
+import androidx.room.compiler.processing.XProcessingStep;
+import androidx.room.compiler.processing.javac.JavacBasicAnnotationProcessor;
 import com.google.auto.service.AutoService;
-import com.google.common.base.Ascii;
-import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
-import java.util.Set;
-import javax.annotation.processing.Filer;
-import javax.annotation.processing.Messager;
 import javax.annotation.processing.Processor;
 import javax.lang.model.SourceVersion;
-import javax.lang.model.util.Elements;
-import javax.lang.model.util.Types;
 import net.ltgt.gradle.incap.IncrementalAnnotationProcessor;
 
 /**
@@ -49,51 +43,22 @@
  */
 @IncrementalAnnotationProcessor(ISOLATING)
 @AutoService(Processor.class)
-public final class AndroidProcessor extends BasicAnnotationProcessor {
-  private static final String FLAG_EXPERIMENTAL_USE_STRING_KEYS =
-      "dagger.android.experimentalUseStringKeys";
+public final class AndroidProcessor extends JavacBasicAnnotationProcessor {
+  private final DelegateAndroidProcessor delegate = new DelegateAndroidProcessor();
 
   @Override
-  protected Iterable<? extends Step> steps() {
-    Filer filer = processingEnv.getFiler();
-    Messager messager = processingEnv.getMessager();
-    Elements elements = processingEnv.getElementUtils();
-    Types types = processingEnv.getTypeUtils();
-
-    return ImmutableList.of(
-        new AndroidMapKeyValidator(elements, types, messager),
-        new ContributesAndroidInjectorGenerator(
-            new AndroidInjectorDescriptor.Validator(messager),
-            useStringKeys(),
-            filer,
-            elements,
-            processingEnv.getSourceVersion()));
-  }
-
-  private boolean useStringKeys() {
-    if (!processingEnv.getOptions().containsKey(FLAG_EXPERIMENTAL_USE_STRING_KEYS)) {
-      return false;
-    }
-    String flagValue = processingEnv.getOptions().get(FLAG_EXPERIMENTAL_USE_STRING_KEYS);
-    if (flagValue == null || Ascii.equalsIgnoreCase(flagValue, "true")) {
-      return true;
-    } else if (Ascii.equalsIgnoreCase(flagValue, "false")) {
-      return false;
-    } else {
-      processingEnv
-          .getMessager()
-          .printMessage(
-              ERROR,
-              String.format(
-                  "Unknown flag value: %s. %s must be set to either 'true' or 'false'.",
-                  flagValue, FLAG_EXPERIMENTAL_USE_STRING_KEYS));
-      return false;
-    }
+  public void initialize(XProcessingEnv env) {
+    delegate.initialize(env);
   }
 
   @Override
-  public Set<String> getSupportedOptions() {
-    return ImmutableSet.of(FLAG_EXPERIMENTAL_USE_STRING_KEYS);
+  public Iterable<XProcessingStep> processingSteps() {
+    return delegate.processingSteps();
+  }
+
+  @Override
+  public final ImmutableSet<String> getSupportedOptions() {
+    return ImmutableSet.of(DelegateAndroidProcessor.FLAG_EXPERIMENTAL_USE_STRING_KEYS);
   }
 
   @Override
diff --git a/java/dagger/android/processor/BUILD b/java/dagger/android/processor/BUILD
index d545ef8..f70c091 100644
--- a/java/dagger/android/processor/BUILD
+++ b/java/dagger/android/processor/BUILD
@@ -22,8 +22,7 @@
     "DOCLINT_REFERENCES",
     "POM_VERSION",
 )
-load("//tools:maven.bzl", "pom_file")
-load("@google_bazel_common//tools/javadoc:javadoc.bzl", "javadoc_library")
+load("//tools:maven.bzl", "gen_maven_artifact")
 
 package(default_visibility = ["//:src"])
 
@@ -33,29 +32,65 @@
 )
 
 java_library(
+    name = "base_processing_step",
+    srcs = ["BaseProcessingStep.java"],
+    deps = [
+        "//java/dagger/internal/codegen/extension",
+        "//java/dagger/internal/codegen/xprocessing",
+        "//third_party/java/guava/base",
+        "//third_party/java/guava/collect",
+        "//third_party/java/javapoet",
+    ],
+)
+
+java_library(
     name = "processor",
-    srcs = [":srcs"],
+    srcs = glob(
+        ["*.java"],
+        exclude = ["BaseProcessingStep.java"],
+    ),
     javacopts = DOCLINT_HTML_AND_SYNTAX + DOCLINT_REFERENCES,
     tags = ["maven_coordinates=com.google.dagger:dagger-android-processor:" + POM_VERSION],
     deps = [
+        ":base_processing_step",
         "//java/dagger:core",
-        "//java/dagger/internal/codegen/extension",
+        "//java/dagger/internal/codegen/xprocessing",
         "//java/dagger/spi",
-        "//third_party/java/auto:common",
         "//third_party/java/auto:service",
         "//third_party/java/auto:value",
         "//third_party/java/guava/base",
         "//third_party/java/guava/collect",
         "//third_party/java/incap",
         "//third_party/java/javapoet",
+        "@maven//:com_google_devtools_ksp_symbol_processing_api",
     ],
 )
 
-pom_file(
-    name = "pom",
-    artifact_id = "dagger-android-processor",
+gen_maven_artifact(
+    name = "artifact",
+    artifact_coordinates = "com.google.dagger:dagger-android-processor:" + POM_VERSION,
     artifact_name = "Dagger Android Processor",
-    targets = [":processor"],
+    artifact_target = ":processor",
+    artifact_target_libs = [
+        "//java/dagger/internal/codegen/xprocessing",
+        "//java/dagger/android/processor:base_processing_step",
+    ],
+    artifact_target_maven_deps = [
+        "com.google.dagger:dagger",
+        "com.google.devtools.ksp:symbol-processing-api",
+        "com.google.guava:guava",
+        "com.squareup:javapoet",
+        "com.google.code.findbugs:jsr305",
+        "com.google.dagger:dagger-spi",
+        "com.google.guava:failureaccess",
+        "com.squareup:kotlinpoet",
+        "net.ltgt.gradle.incap:incap",
+        "org.jetbrains.kotlin:kotlin-stdlib",
+    ],
+    javadoc_root_packages = [
+        "dagger.android.processor",
+    ],
+    javadoc_srcs = [":srcs"],
 )
 
 java_plugin(
@@ -64,10 +99,3 @@
     processor_class = "dagger.android.processor.AndroidProcessor",
     deps = [":processor"],
 )
-
-javadoc_library(
-    name = "processor-javadoc",
-    srcs = [":srcs"],
-    root_packages = ["dagger.android.processor"],
-    deps = [":processor"],
-)
diff --git a/java/dagger/android/processor/BaseProcessingStep.java b/java/dagger/android/processor/BaseProcessingStep.java
new file mode 100644
index 0000000..100ded0
--- /dev/null
+++ b/java/dagger/android/processor/BaseProcessingStep.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.android.processor;
+
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.collect.Sets.difference;
+import static dagger.internal.codegen.extension.DaggerStreams.toImmutableMap;
+import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
+
+import androidx.room.compiler.processing.XElement;
+import androidx.room.compiler.processing.XProcessingEnv;
+import androidx.room.compiler.processing.XProcessingStep;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSetMultimap;
+import com.google.common.collect.Maps;
+import com.squareup.javapoet.ClassName;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * A {@link XProcessingStep} that processes one element at a time and defers any for which {@link
+ * TypeNotPresentException} is thrown.
+ */
+public abstract class BaseProcessingStep implements XProcessingStep {
+  @Override
+  public final ImmutableSet<String> annotations() {
+    return annotationClassNames().stream().map(ClassName::canonicalName).collect(toImmutableSet());
+  }
+
+  // Subclass must ensure all annotated targets are of valid type.
+  @Override
+  public ImmutableSet<XElement> process(
+      XProcessingEnv env, Map<String, ? extends Set<? extends XElement>> elementsByAnnotation) {
+    ImmutableSet.Builder<XElement> deferredElements = ImmutableSet.builder();
+    inverse(elementsByAnnotation)
+        .forEach(
+            (element, annotations) -> {
+              try {
+                process(element, annotations);
+              } catch (TypeNotPresentException e) {
+                deferredElements.add(element);
+              }
+            });
+    return deferredElements.build();
+  }
+
+  /**
+   * Processes one element. If this method throws {@link TypeNotPresentException}, the element will
+   * be deferred until the next round of processing.
+   *
+   * @param annotations the subset of {@link XProcessingStep#annotations()} that annotate {@code
+   *     element}
+   */
+  protected abstract void process(XElement element, ImmutableSet<ClassName> annotations);
+
+  private ImmutableMap<XElement, ImmutableSet<ClassName>> inverse(
+      Map<String, ? extends Set<? extends XElement>> elementsByAnnotation) {
+    ImmutableMap<String, ClassName> annotationClassNames =
+        annotationClassNames().stream()
+            .collect(toImmutableMap(ClassName::canonicalName, className -> className));
+    checkState(
+        annotationClassNames.keySet().containsAll(elementsByAnnotation.keySet()),
+        "Unexpected annotations for %s: %s",
+        this.getClass().getCanonicalName(),
+        difference(elementsByAnnotation.keySet(), annotationClassNames.keySet()));
+
+    ImmutableSetMultimap.Builder<XElement, ClassName> builder = ImmutableSetMultimap.builder();
+    elementsByAnnotation.forEach(
+        (annotationName, elementSet) ->
+            elementSet.forEach(
+                element -> builder.put(element, annotationClassNames.get(annotationName))));
+
+    return ImmutableMap.copyOf(Maps.transformValues(builder.build().asMap(), ImmutableSet::copyOf));
+  }
+
+  /** Returns the set of annotations processed by this processing step. */
+  protected abstract Set<ClassName> annotationClassNames();
+}
diff --git a/java/dagger/android/processor/ContributesAndroidInjectorGenerator.java b/java/dagger/android/processor/ContributesAndroidInjectorProcessingStep.java
similarity index 66%
rename from java/dagger/android/processor/ContributesAndroidInjectorGenerator.java
rename to java/dagger/android/processor/ContributesAndroidInjectorProcessingStep.java
index f3f4d18..9e9ed2b 100644
--- a/java/dagger/android/processor/ContributesAndroidInjectorGenerator.java
+++ b/java/dagger/android/processor/ContributesAndroidInjectorProcessingStep.java
@@ -16,23 +16,27 @@
 
 package dagger.android.processor;
 
-import static com.google.auto.common.GeneratedAnnotationSpecs.generatedAnnotationSpec;
+import static androidx.room.compiler.processing.JavaPoetExtKt.addOriginatingElement;
 import static com.google.common.base.CaseFormat.LOWER_CAMEL;
 import static com.google.common.base.CaseFormat.UPPER_CAMEL;
 import static com.squareup.javapoet.MethodSpec.constructorBuilder;
 import static com.squareup.javapoet.MethodSpec.methodBuilder;
 import static com.squareup.javapoet.TypeSpec.classBuilder;
 import static com.squareup.javapoet.TypeSpec.interfaceBuilder;
+import static dagger.android.processor.DelegateAndroidProcessor.FLAG_EXPERIMENTAL_USE_STRING_KEYS;
 import static javax.lang.model.element.Modifier.ABSTRACT;
 import static javax.lang.model.element.Modifier.PRIVATE;
 import static javax.lang.model.element.Modifier.PUBLIC;
 import static javax.lang.model.element.Modifier.STATIC;
-import static javax.lang.model.util.ElementFilter.methodsIn;
+import static javax.tools.Diagnostic.Kind.ERROR;
 
-import com.google.auto.common.BasicAnnotationProcessor.Step;
+import androidx.room.compiler.processing.XElement;
+import androidx.room.compiler.processing.XFiler;
+import androidx.room.compiler.processing.XProcessingEnv;
+import androidx.room.compiler.processing.XTypeElement;
+import com.google.common.base.Ascii;
 import com.google.common.base.Joiner;
 import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.ImmutableSetMultimap;
 import com.squareup.javapoet.AnnotationSpec;
 import com.squareup.javapoet.ClassName;
 import com.squareup.javapoet.JavaFile;
@@ -41,52 +45,26 @@
 import com.squareup.javapoet.TypeName;
 import com.squareup.javapoet.TypeSpec;
 import com.squareup.javapoet.WildcardTypeName;
-import dagger.android.processor.AndroidInjectorDescriptor.Validator;
-import java.io.IOException;
-import javax.annotation.processing.Filer;
-import javax.lang.model.SourceVersion;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.util.Elements;
+import dagger.internal.codegen.xprocessing.XElements;
 
 /** Generates the implementation specified in {@code ContributesAndroidInjector}. */
-final class ContributesAndroidInjectorGenerator implements Step {
-
+final class ContributesAndroidInjectorProcessingStep extends BaseProcessingStep {
   private final AndroidInjectorDescriptor.Validator validator;
-  private final Filer filer;
-  private final Elements elements;
-  private final boolean useStringKeys;
-  private final SourceVersion sourceVersion;
+  private final XProcessingEnv processingEnv;
 
-  ContributesAndroidInjectorGenerator(
-      Validator validator,
-      boolean useStringKeys,
-      Filer filer,
-      Elements elements,
-      SourceVersion sourceVersion) {
-    this.validator = validator;
-    this.useStringKeys = useStringKeys;
-    this.filer = filer;
-    this.elements = elements;
-    this.sourceVersion = sourceVersion;
+  ContributesAndroidInjectorProcessingStep(XProcessingEnv processingEnv) {
+    this.processingEnv = processingEnv;
+    this.validator = new AndroidInjectorDescriptor.Validator(processingEnv.getMessager());
   }
 
   @Override
-  public ImmutableSet<String> annotations() {
-    return ImmutableSet.of(TypeNames.CONTRIBUTES_ANDROID_INJECTOR.toString());
+  public ImmutableSet<ClassName> annotationClassNames() {
+    return ImmutableSet.of(TypeNames.CONTRIBUTES_ANDROID_INJECTOR);
   }
 
   @Override
-  public ImmutableSet<Element> process(ImmutableSetMultimap<String, Element> elementsByAnnotation) {
-    ImmutableSet.Builder<Element> deferredElements = ImmutableSet.builder();
-    for (ExecutableElement method : methodsIn(elementsByAnnotation.values())) {
-      try {
-        validator.createIfValid(method).ifPresent(this::generate);
-      } catch (TypeNotPresentException e) {
-        deferredElements.add(method);
-      }
-    }
-    return deferredElements.build();
+  public void process(XElement element, ImmutableSet<ClassName> annotationNames) {
+    validator.createIfValid(XElements.asMethod(element)).ifPresent(this::generate);
   }
 
   private void generate(AndroidInjectorDescriptor descriptor) {
@@ -97,7 +75,7 @@
             .peerClass(
                 Joiner.on('_').join(descriptor.enclosingModule().simpleNames())
                     + "_"
-                    + LOWER_CAMEL.to(UPPER_CAMEL, descriptor.method().getSimpleName().toString()));
+                    + LOWER_CAMEL.to(UPPER_CAMEL, XElements.getSimpleName(descriptor.method())));
 
     String baseName = descriptor.injectedType().simpleName();
     ClassName subcomponentName = moduleName.nestedClass(baseName + "Subcomponent");
@@ -105,7 +83,6 @@
 
     TypeSpec.Builder module =
         classBuilder(moduleName)
-            .addOriginatingElement(descriptor.method())
             .addAnnotation(
                 AnnotationSpec.builder(TypeNames.MODULE)
                     .addMember("subcomponents", "$T.class", subcomponentName)
@@ -114,16 +91,45 @@
             .addMethod(bindAndroidInjectorFactory(descriptor, subcomponentFactoryName))
             .addType(subcomponent(descriptor, subcomponentName, subcomponentFactoryName))
             .addMethod(constructorBuilder().addModifiers(PRIVATE).build());
-    generatedAnnotationSpec(elements, sourceVersion, AndroidProcessor.class)
-        .ifPresent(module::addAnnotation);
 
-    try {
-      JavaFile.builder(moduleName.packageName(), module.build())
-          .skipJavaLangImports(true)
-          .build()
-          .writeTo(filer);
-    } catch (IOException e) {
-      throw new AssertionError(e);
+    addOriginatingElement(module, descriptor.method());
+
+    XTypeElement generatedAnnotation = processingEnv.findGeneratedAnnotation();
+    if (generatedAnnotation != null) {
+      module.addAnnotation(
+          AnnotationSpec.builder(generatedAnnotation.getClassName())
+              .addMember(
+                  "value", "$S", ClassName.get("dagger.android.processor", "AndroidProcessor"))
+              .build());
+    }
+
+    processingEnv
+        .getFiler()
+        .write(
+            JavaFile.builder(moduleName.packageName(), module.build())
+                .skipJavaLangImports(true)
+                .build(),
+            XFiler.Mode.Isolating);
+  }
+
+  private static boolean useStringKeys(XProcessingEnv processingEnv) {
+    if (!processingEnv.getOptions().containsKey(FLAG_EXPERIMENTAL_USE_STRING_KEYS)) {
+      return false;
+    }
+    String flagValue = processingEnv.getOptions().get(FLAG_EXPERIMENTAL_USE_STRING_KEYS);
+    if (flagValue == null || Ascii.equalsIgnoreCase(flagValue, "true")) {
+      return true;
+    } else if (Ascii.equalsIgnoreCase(flagValue, "false")) {
+      return false;
+    } else {
+      processingEnv
+          .getMessager()
+          .printMessage(
+              ERROR,
+              String.format(
+                  "Unknown flag value: %s. %s must be set to either 'true' or 'false'.",
+                  flagValue, FLAG_EXPERIMENTAL_USE_STRING_KEYS));
+      return false;
     }
   }
 
@@ -142,7 +148,7 @@
   }
 
   private AnnotationSpec androidInjectorMapKey(AndroidInjectorDescriptor descriptor) {
-    if (useStringKeys) {
+    if (useStringKeys(processingEnv)) {
       return AnnotationSpec.builder(TypeNames.ANDROID_INJECTION_KEY)
           .addMember("value", "$S", descriptor.injectedType().toString())
           .build();
diff --git a/java/dagger/android/processor/DelegateAndroidProcessor.java b/java/dagger/android/processor/DelegateAndroidProcessor.java
new file mode 100644
index 0000000..7c141f0
--- /dev/null
+++ b/java/dagger/android/processor/DelegateAndroidProcessor.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.android.processor;
+
+import androidx.room.compiler.processing.XProcessingEnv;
+import androidx.room.compiler.processing.XProcessingEnvConfig;
+import androidx.room.compiler.processing.XProcessingStep;
+import com.google.common.collect.ImmutableList;
+import dagger.BindsInstance;
+import dagger.Component;
+import javax.inject.Singleton;
+
+/** An implementation of Dagger Android processor that is shared between Javac and KSP. */
+final class DelegateAndroidProcessor {
+  static final XProcessingEnvConfig PROCESSING_ENV_CONFIG =
+      new XProcessingEnvConfig.Builder().build();
+  static final String FLAG_EXPERIMENTAL_USE_STRING_KEYS =
+      "dagger.android.experimentalUseStringKeys";
+
+  private XProcessingEnv env;
+
+  public void initialize(XProcessingEnv env) {
+    this.env = env;
+  }
+
+  public ImmutableList<XProcessingStep> processingSteps() {
+    return ImmutableList.of(
+        new AndroidMapKeyProcessingStep(env), new ContributesAndroidInjectorProcessingStep(env));
+  }
+
+  @Singleton
+  @Component
+  interface Injector {
+    void inject(DelegateAndroidProcessor delegateAndroidProcessor);
+
+    @Component.Factory
+    interface Factory {
+      Injector create(@BindsInstance XProcessingEnv env);
+    }
+  }
+}
diff --git a/java/dagger/android/processor/DuplicateAndroidInjectorsChecker.java b/java/dagger/android/processor/DuplicateAndroidInjectorsChecker.java
index bcc8e5a..2227038 100644
--- a/java/dagger/android/processor/DuplicateAndroidInjectorsChecker.java
+++ b/java/dagger/android/processor/DuplicateAndroidInjectorsChecker.java
@@ -16,34 +16,34 @@
 
 package dagger.android.processor;
 
-import static com.google.auto.common.AnnotationMirrors.getAnnotatedAnnotations;
 import static com.google.common.collect.Iterables.getOnlyElement;
 import static dagger.android.processor.AndroidMapKeys.injectedTypeFromMapKey;
 import static java.util.stream.Collectors.collectingAndThen;
 import static java.util.stream.Collectors.toList;
 import static javax.tools.Diagnostic.Kind.ERROR;
 
-import com.google.auto.common.MoreTypes;
+import androidx.room.compiler.processing.XAnnotation;
+import androidx.room.compiler.processing.XType;
 import com.google.auto.service.AutoService;
 import com.google.common.collect.ImmutableListMultimap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Multimaps;
-import dagger.MapKey;
-import dagger.model.Binding;
-import dagger.model.BindingGraph;
-import dagger.model.BindingKind;
-import dagger.model.Key;
-import dagger.spi.BindingGraphPlugin;
-import dagger.spi.DiagnosticReporter;
+import dagger.internal.codegen.xprocessing.DaggerElements;
+import dagger.internal.codegen.xprocessing.XElements;
+import dagger.internal.codegen.xprocessing.XTypes;
+import dagger.spi.model.Binding;
+import dagger.spi.model.BindingGraph;
+import dagger.spi.model.BindingGraphPlugin;
+import dagger.spi.model.BindingKind;
+import dagger.spi.model.DaggerProcessingEnv;
+import dagger.spi.model.DiagnosticReporter;
+import dagger.spi.model.Key;
 import java.util.Formatter;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.stream.Stream;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.type.TypeKind;
-import javax.lang.model.type.TypeMirror;
 
 /**
  * Validates that the two maps that {@code DispatchingAndroidInjector} injects have logically
@@ -53,6 +53,13 @@
  */
 @AutoService(BindingGraphPlugin.class)
 public final class DuplicateAndroidInjectorsChecker implements BindingGraphPlugin {
+  private DaggerProcessingEnv processingEnv;
+
+  @Override
+  public void init(DaggerProcessingEnv processingEnv, Map<String, String> options) {
+    this.processingEnv = processingEnv;
+  }
+
   @Override
   public void visitGraph(BindingGraph graph, DiagnosticReporter diagnosticReporter) {
     for (Binding binding : graph.bindings()) {
@@ -64,7 +71,10 @@
 
   private boolean isDispatchingAndroidInjector(Binding binding) {
     Key key = binding.key();
-    return MoreDaggerTypes.isTypeOf(TypeNames.DISPATCHING_ANDROID_INJECTOR, key.type())
+
+    return XTypes.isTypeOf(
+            DaggerElements.toXProcessing(key.type(), processingEnv),
+            TypeNames.DISPATCHING_ANDROID_INJECTOR)
         && !key.qualifier().isPresent();
   }
 
@@ -79,7 +89,7 @@
 
     ImmutableListMultimap.Builder<String, Binding> mapKeyIndex = ImmutableListMultimap.builder();
     for (Binding injectorFactory : injectorFactories) {
-      AnnotationMirror mapKey = mapKey(injectorFactory).get();
+      XAnnotation mapKey = mapKey(injectorFactory).get();
       Optional<String> injectedType = injectedTypeFromMapKey(mapKey);
       if (injectedType.isPresent()) {
         mapKeyIndex.put(injectedType.get(), injectorFactory);
@@ -113,21 +123,26 @@
         .filter(requestedBinding -> requestedBinding.kind().equals(BindingKind.MULTIBOUND_MAP))
         .filter(
             requestedBinding -> {
-              TypeMirror valueType =
-                  MoreTypes.asDeclared(requestedBinding.key().type()).getTypeArguments().get(1);
-              if (!MoreDaggerTypes.isTypeOf(TypeNames.PROVIDER, valueType)
-                  || !valueType.getKind().equals(TypeKind.DECLARED)) {
+              XType valueType =
+                  DaggerElements.toXProcessing(requestedBinding.key().type(), processingEnv)
+                      .getTypeArguments()
+                      .get(1);
+              if (!XTypes.isTypeOf(valueType, TypeNames.PROVIDER)
+                  || !XTypes.isDeclared(valueType)) {
                 return false;
               }
-              TypeMirror providedType = MoreTypes.asDeclared(valueType).getTypeArguments().get(0);
-              return MoreDaggerTypes.isTypeOf(TypeNames.ANDROID_INJECTOR_FACTORY, providedType);
+              XType providedType = valueType.getTypeArguments().get(0);
+              return XTypes.isTypeOf(providedType, TypeNames.ANDROID_INJECTOR_FACTORY);
             });
   }
 
-  private Optional<AnnotationMirror> mapKey(Binding binding) {
+  private Optional<XAnnotation> mapKey(Binding binding) {
     return binding
         .bindingElement()
-        .map(bindingElement -> getAnnotatedAnnotations(bindingElement, MapKey.class))
+        .map(
+            bindingElement ->
+                XElements.getAnnotatedAnnotations(
+                    DaggerElements.toXProcessing(bindingElement, processingEnv), TypeNames.MAP_KEY))
         .flatMap(
             annotations ->
                 annotations.isEmpty()
diff --git a/java/dagger/android/processor/KspAndroidProcessor.java b/java/dagger/android/processor/KspAndroidProcessor.java
new file mode 100644
index 0000000..7fe4f52
--- /dev/null
+++ b/java/dagger/android/processor/KspAndroidProcessor.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.android.processor;
+
+import androidx.room.compiler.processing.XProcessingEnv;
+import androidx.room.compiler.processing.XProcessingStep;
+import androidx.room.compiler.processing.ksp.KspBasicAnnotationProcessor;
+import com.google.auto.service.AutoService;
+import com.google.devtools.ksp.processing.SymbolProcessor;
+import com.google.devtools.ksp.processing.SymbolProcessorEnvironment;
+import com.google.devtools.ksp.processing.SymbolProcessorProvider;
+
+/** Ksp Processor for verifying usage of {@code dagger.android} code. */
+final class KspAndroidProcessor extends KspBasicAnnotationProcessor {
+  private final DelegateAndroidProcessor delegate = new DelegateAndroidProcessor();
+
+  private KspAndroidProcessor(SymbolProcessorEnvironment symbolProcessorEnvironment) {
+    super(symbolProcessorEnvironment, DelegateAndroidProcessor.PROCESSING_ENV_CONFIG);
+  }
+
+  @Override
+  public void initialize(XProcessingEnv env) {
+    delegate.initialize(env);
+  }
+
+  @Override
+  public Iterable<XProcessingStep> processingSteps() {
+    return delegate.processingSteps();
+  }
+
+  /** Provides the {@link KspAndroidProcessor}. */
+  @AutoService(SymbolProcessorProvider.class)
+  public static final class Provider implements SymbolProcessorProvider {
+    @Override
+    public SymbolProcessor create(SymbolProcessorEnvironment symbolProcessorEnvironment) {
+      return new KspAndroidProcessor(symbolProcessorEnvironment);
+    }
+  }
+}
diff --git a/java/dagger/android/processor/MoreDaggerElements.java b/java/dagger/android/processor/MoreDaggerElements.java
deleted file mode 100644
index 572caa3..0000000
--- a/java/dagger/android/processor/MoreDaggerElements.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2021 The Dagger Authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package dagger.android.processor;
-
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
-
-import com.google.auto.common.MoreElements;
-import com.google.common.collect.ImmutableSet;
-import com.squareup.javapoet.ClassName;
-import java.util.Optional;
-import javax.lang.model.element.AnnotationMirror;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.TypeElement;
-
-// TODO(bcorso): Dedupe with dagger/internal/codegen/langmodel/DaggerElements.java?
-// TODO(bcorso): Contribute upstream to auto common?
-/** Similar to auto common, but uses {@link ClassName} rather than {@link Class}. */
-final class MoreDaggerElements {
-  /**
-   * Returns {@code true} iff the given element has an {@link AnnotationMirror} whose {@linkplain
-   * AnnotationMirror#getAnnotationType() annotation type} has the same canonical name as that of
-   * {@code annotationClass}. This method is a safer alternative to calling {@link
-   * Element#getAnnotation} and checking for {@code null} as it avoids any interaction with
-   * annotation proxies.
-   */
-  public static boolean isAnnotationPresent(Element element, ClassName annotationName) {
-    return getAnnotationMirror(element, annotationName).isPresent();
-  }
-
-  /**
-   * Returns an {@link AnnotationMirror} for the annotation of type {@code annotationClass} on
-   * {@code element}, or {@link Optional#empty()} if no such annotation exists. This method is a
-   * safer alternative to calling {@link Element#getAnnotation} as it avoids any interaction with
-   * annotation proxies.
-   */
-  public static Optional<AnnotationMirror> getAnnotationMirror(
-      Element element, ClassName annotationName) {
-    String annotationClassName = annotationName.canonicalName();
-    for (AnnotationMirror annotationMirror : element.getAnnotationMirrors()) {
-      TypeElement annotationTypeElement =
-          MoreElements.asType(annotationMirror.getAnnotationType().asElement());
-      if (annotationTypeElement.getQualifiedName().contentEquals(annotationClassName)) {
-        return Optional.of(annotationMirror);
-      }
-    }
-    return Optional.empty();
-  }
-
-  public static ImmutableSet<AnnotationMirror> getAnnotatedAnnotations(
-      Element element, ClassName annotationName) {
-    return element.getAnnotationMirrors().stream()
-        .filter(input -> isAnnotationPresent(input.getAnnotationType().asElement(), annotationName))
-        .collect(toImmutableSet());
-  }
-
-  private MoreDaggerElements() {}
-}
diff --git a/java/dagger/android/processor/MoreDaggerTypes.java b/java/dagger/android/processor/MoreDaggerTypes.java
deleted file mode 100644
index 4bde405..0000000
--- a/java/dagger/android/processor/MoreDaggerTypes.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2021 The Dagger Authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package dagger.android.processor;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import com.google.auto.common.MoreElements;
-import com.squareup.javapoet.ArrayTypeName;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.TypeName;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.ArrayType;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.ErrorType;
-import javax.lang.model.type.NoType;
-import javax.lang.model.type.PrimitiveType;
-import javax.lang.model.type.TypeKind;
-import javax.lang.model.type.TypeMirror;
-import javax.lang.model.util.SimpleTypeVisitor8;
-
-// TODO(bcorso): Dedupe with dagger/internal/codegen/langmodel/DaggerTypes.java?
-// TODO(bcorso): Contribute upstream to auto common?
-/** Similar to auto common, but uses {@link ClassName} rather than {@link Class}. */
-final class MoreDaggerTypes {
-
-  /**
-   * Returns true if the raw type underlying the given {@link TypeMirror} represents the same raw
-   * type as the given {@link Class} and throws an IllegalArgumentException if the {@link
-   * TypeMirror} does not represent a type that can be referenced by a {@link Class}
-   */
-  public static boolean isTypeOf(final TypeName typeName, TypeMirror type) {
-    checkNotNull(typeName);
-    return type.accept(new IsTypeOf(typeName), null);
-  }
-
-  private static final class IsTypeOf extends SimpleTypeVisitor8<Boolean, Void> {
-    private final TypeName typeName;
-
-    IsTypeOf(TypeName typeName) {
-      this.typeName = typeName;
-    }
-
-    @Override
-    protected Boolean defaultAction(TypeMirror type, Void ignored) {
-      throw new IllegalArgumentException(type + " cannot be represented as a Class<?>.");
-    }
-
-    @Override
-    public Boolean visitNoType(NoType noType, Void p) {
-      if (noType.getKind().equals(TypeKind.VOID)) {
-        return typeName.equals(TypeName.VOID);
-      }
-      throw new IllegalArgumentException(noType + " cannot be represented as a Class<?>.");
-    }
-
-    @Override
-    public Boolean visitError(ErrorType errorType, Void p) {
-      return false;
-    }
-
-    @Override
-    public Boolean visitPrimitive(PrimitiveType type, Void p) {
-      switch (type.getKind()) {
-        case BOOLEAN:
-          return typeName.equals(TypeName.BOOLEAN);
-        case BYTE:
-          return typeName.equals(TypeName.BYTE);
-        case CHAR:
-          return typeName.equals(TypeName.CHAR);
-        case DOUBLE:
-          return typeName.equals(TypeName.DOUBLE);
-        case FLOAT:
-          return typeName.equals(TypeName.FLOAT);
-        case INT:
-          return typeName.equals(TypeName.INT);
-        case LONG:
-          return typeName.equals(TypeName.LONG);
-        case SHORT:
-          return typeName.equals(TypeName.SHORT);
-        default:
-          throw new IllegalArgumentException(type + " cannot be represented as a Class<?>.");
-      }
-    }
-
-    @Override
-    public Boolean visitArray(ArrayType array, Void p) {
-      return (typeName instanceof ArrayTypeName)
-          && isTypeOf(((ArrayTypeName) typeName).componentType, array.getComponentType());
-    }
-
-    @Override
-    public Boolean visitDeclared(DeclaredType type, Void ignored) {
-      TypeElement typeElement = MoreElements.asType(type.asElement());
-      return (typeName instanceof ClassName)
-          && typeElement.getQualifiedName().contentEquals(((ClassName) typeName).canonicalName());
-    }
-  }
-
-  private MoreDaggerTypes() {}
-}
diff --git a/java/dagger/android/support/BUILD b/java/dagger/android/support/BUILD
index 2fc9e2e..2f4c407 100644
--- a/java/dagger/android/support/BUILD
+++ b/java/dagger/android/support/BUILD
@@ -17,12 +17,14 @@
 
 load(
     "//:build_defs.bzl",
-    "JAVA_RELEASE_MIN",
     "POM_VERSION",
 )
 load("//tools:dejetify.bzl", "dejetified_library")
-load("//tools:maven.bzl", "pom_file")
-load("@google_bazel_common//tools/javadoc:javadoc.bzl", "javadoc_library")
+load(
+    "//tools:maven.bzl",
+    "gen_maven_artifact",
+    "pom_file",
+)
 
 package(default_visibility = ["//:src"])
 
@@ -34,8 +36,6 @@
 android_library(
     name = "support",
     srcs = glob(["*.java"]),
-    javacopts = JAVA_RELEASE_MIN,
-    manifest = "AndroidManifest.xml",
     tags = ["maven_coordinates=com.google.dagger:dagger-android-support:" + POM_VERSION],
     deps = [
         "//:dagger_with_compiler",
@@ -51,17 +51,34 @@
     ],
 )
 
-pom_file(
-    name = "pom",
-    artifact_id = "dagger-android-support",
+gen_maven_artifact(
+    name = "artifact",
+    artifact_coordinates = "com.google.dagger:dagger-android-support:" + POM_VERSION,
     artifact_name = "Dagger Android Support",
+    artifact_target = ":support",
+    artifact_target_maven_deps = [
+        "androidx.activity:activity",
+        "androidx.annotation:annotation",
+        "androidx.appcompat:appcompat",
+        "androidx.fragment:fragment",
+        "androidx.lifecycle:lifecycle-common",
+        "androidx.lifecycle:lifecycle-viewmodel",
+        "androidx.lifecycle:lifecycle-viewmodel-savedstate",
+        "com.google.dagger:dagger",
+        "com.google.dagger:dagger-android",
+    ],
+    javadoc_android_api_level = 32,
+    javadoc_root_packages = [
+        "dagger.android.support",
+    ],
+    javadoc_srcs = [":support-srcs"],
+    manifest = "AndroidManifest.xml",
     packaging = "aar",
-    targets = [":support"],
 )
 
 dejetified_library(
     name = "dejetified-support",
-    input = ":support.aar",
+    input = ":artifact.aar",
     output = "support-legacy.aar",
 )
 
@@ -85,11 +102,3 @@
     packaging = "aar",
     targets = [":legacy-deps"],
 )
-
-javadoc_library(
-    name = "support-javadoc",
-    srcs = [":support-srcs"],
-    android_api_level = 32,
-    root_packages = ["dagger.android.support"],
-    deps = [":support"],
-)
diff --git a/java/dagger/hilt/android/BUILD b/java/dagger/hilt/android/BUILD
index ca950a3..b30f662 100644
--- a/java/dagger/hilt/android/BUILD
+++ b/java/dagger/hilt/android/BUILD
@@ -15,8 +15,8 @@
 # Description:
 #   A library based on Hilt that provides standard components and automated injection for Android.
 load("//:build_defs.bzl", "POM_VERSION")
-load("//tools:maven.bzl", "gen_maven_artifact")
 load("//tools:bazel_compat.bzl", "compat_kt_android_library")
+load("//tools:maven.bzl", "gen_maven_artifact")
 
 package(default_visibility = ["//:src"])
 
@@ -39,6 +39,7 @@
         "//java/dagger/hilt/android/internal/managers:component_supplier",
         "//java/dagger/hilt/android/internal/modules",
         "//java/dagger/hilt/android/lifecycle:hilt_view_model",
+        "//java/dagger/hilt/android/lifecycle:hilt_view_model_extensions",
         "//java/dagger/hilt/codegen:originating_element",
         "//java/dagger/hilt/internal:component_entry_point",
         "//java/dagger/hilt/internal:component_manager",
@@ -146,6 +147,14 @@
     ],
 )
 
+android_library(
+    name = "unstable_api",
+    srcs = ["UnstableApi.java"],
+    deps = [
+        "@maven//:androidx_annotation_annotation_experimental",
+    ],
+)
+
 java_library(
     name = "package_info",
     srcs = ["package-info.java"],
@@ -163,6 +172,7 @@
         ":entry_point_accessors",
         ":hilt_android_app",
         ":package_info",
+        ":unstable_api",
         "//java/dagger/hilt:artifact-core-lib",
         "//java/dagger/hilt/android/migration:custom_inject",
         "//java/dagger/hilt/android/migration:optional_inject",
@@ -180,6 +190,7 @@
         "//java/dagger/hilt/android:activity_retained_lifecycle",
         "//java/dagger/hilt/android:android_entry_point",
         "//java/dagger/hilt/android:hilt_android_app",
+        "//java/dagger/hilt/android:unstable_api",
         "//java/dagger/hilt/android:early_entry_point",
         "//java/dagger/hilt/android:package_info",
         "//java/dagger/hilt/android:view_model_lifecycle",
@@ -193,10 +204,13 @@
         "//java/dagger/hilt/android/internal/lifecycle",
         "//java/dagger/hilt/android/internal/managers",
         "//java/dagger/hilt/android/internal/managers:component_supplier",
+        "//java/dagger/hilt/android/internal/managers:saved_state_handle_holder",
         "//java/dagger/hilt/android/internal/migration:has_custom_inject",
         "//java/dagger/hilt/android/internal/migration:injected_by_hilt",
         "//java/dagger/hilt/android/internal/modules",
+        "//java/dagger/hilt/android/lifecycle:activity_retained_saved_state",
         "//java/dagger/hilt/android/lifecycle:hilt_view_model",
+        "//java/dagger/hilt/android/lifecycle:hilt_view_model_extensions",
         "//java/dagger/hilt/android/lifecycle:package_info",
         "//java/dagger/hilt/android/lifecycle:retained_lifecycle",
         "//java/dagger/hilt/android/migration:custom_inject",
@@ -216,6 +230,7 @@
     artifact_target_maven_deps = [
         "androidx.activity:activity",
         "androidx.annotation:annotation",
+        "androidx.annotation:annotation-experimental",
         "androidx.fragment:fragment",
         "androidx.lifecycle:lifecycle-common",
         "androidx.lifecycle:lifecycle-viewmodel",
@@ -244,10 +259,9 @@
     ],
     manifest = "AndroidManifest.xml",
     packaging = "aar",
-    proguard_specs = [
+    proguard_and_r8_specs = [
         "//java/dagger/hilt:proguard-rules.pro",
-        ":proguard-rules.pro",
-        "//java/dagger/hilt/android/lifecycle:proguard-rules.pro",
+        "//java/dagger/hilt/android:proguard-rules.pro",
         "//java/dagger/hilt/internal:proguard-rules.pro",
     ],
 )
diff --git a/java/dagger/hilt/android/UnstableApi.java b/java/dagger/hilt/android/UnstableApi.java
new file mode 100644
index 0000000..dd328ec
--- /dev/null
+++ b/java/dagger/hilt/android/UnstableApi.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.hilt.android;
+
+import androidx.annotation.RequiresOptIn;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/** Mark unstable Api usage. */
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.METHOD, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
+@RequiresOptIn(level = RequiresOptIn.Level.ERROR)
+public @interface UnstableApi {}
diff --git a/java/dagger/hilt/android/internal/BUILD b/java/dagger/hilt/android/internal/BUILD
index ae8a066..4a231a8 100644
--- a/java/dagger/hilt/android/internal/BUILD
+++ b/java/dagger/hilt/android/internal/BUILD
@@ -21,6 +21,7 @@
     name = "internal",
     srcs = [
         "Contexts.java",
+        "OnReceiveBytecodeInjectionMarker.java",
         "ThreadUtil.java",
     ],
 )
diff --git a/java/dagger/hilt/android/internal/OnReceiveBytecodeInjectionMarker.java b/java/dagger/hilt/android/internal/OnReceiveBytecodeInjectionMarker.java
new file mode 100644
index 0000000..ed5abbe
--- /dev/null
+++ b/java/dagger/hilt/android/internal/OnReceiveBytecodeInjectionMarker.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.hilt.android.internal;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * The marker annotation used to denote that we need to inject super.onReceive() call
+ * to the @AndroidEntryPoint-annotated BroadcastReceiver's onReceive() method.
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target(ElementType.TYPE)
+public @interface OnReceiveBytecodeInjectionMarker { }
+
diff --git a/java/dagger/hilt/android/internal/builders/ActivityRetainedComponentBuilder.java b/java/dagger/hilt/android/internal/builders/ActivityRetainedComponentBuilder.java
index 110b3fe..ff5998c 100644
--- a/java/dagger/hilt/android/internal/builders/ActivityRetainedComponentBuilder.java
+++ b/java/dagger/hilt/android/internal/builders/ActivityRetainedComponentBuilder.java
@@ -16,11 +16,17 @@
 
 package dagger.hilt.android.internal.builders;
 
+import dagger.BindsInstance;
 import dagger.hilt.DefineComponent;
 import dagger.hilt.android.components.ActivityRetainedComponent;
+import dagger.hilt.android.internal.managers.SavedStateHandleHolder;
 
 /** Interface for creating a {@link ActivityRetainedComponent}. */
 @DefineComponent.Builder
 public interface ActivityRetainedComponentBuilder {
+
+  ActivityRetainedComponentBuilder savedStateHandleHolder(
+      @BindsInstance SavedStateHandleHolder savedStateHandleHolder);
+
   ActivityRetainedComponent build();
 }
diff --git a/java/dagger/hilt/android/internal/builders/BUILD b/java/dagger/hilt/android/internal/builders/BUILD
index 598503e..7f26e1d 100644
--- a/java/dagger/hilt/android/internal/builders/BUILD
+++ b/java/dagger/hilt/android/internal/builders/BUILD
@@ -25,6 +25,7 @@
         "//java/dagger/hilt:define_component",
         "//java/dagger/hilt/android:view_model_lifecycle",
         "//java/dagger/hilt/android/components",
+        "//java/dagger/hilt/android/internal/managers:saved_state_handle_holder",
         "@maven//:androidx_activity_activity",
         "@maven//:androidx_fragment_fragment",
         "@maven//:androidx_lifecycle_lifecycle_common",
diff --git a/java/dagger/hilt/android/internal/lifecycle/BUILD b/java/dagger/hilt/android/internal/lifecycle/BUILD
index f7314d2..7afd1dd 100644
--- a/java/dagger/hilt/android/internal/lifecycle/BUILD
+++ b/java/dagger/hilt/android/internal/lifecycle/BUILD
@@ -38,6 +38,7 @@
         "@maven//:androidx_lifecycle_lifecycle_viewmodel",
         "@maven//:androidx_lifecycle_lifecycle_viewmodel_savedstate",
         "@maven//:androidx_savedstate_savedstate",
+        "@maven//:org_jetbrains_kotlin_kotlin_stdlib",
     ],
 )
 
diff --git a/java/dagger/hilt/android/internal/lifecycle/DefaultViewModelFactories.java b/java/dagger/hilt/android/internal/lifecycle/DefaultViewModelFactories.java
index 78b8eb1..67e68e7 100644
--- a/java/dagger/hilt/android/internal/lifecycle/DefaultViewModelFactories.java
+++ b/java/dagger/hilt/android/internal/lifecycle/DefaultViewModelFactories.java
@@ -29,7 +29,7 @@
 import dagger.hilt.android.components.FragmentComponent;
 import dagger.hilt.android.internal.builders.ViewModelComponentBuilder;
 import dagger.multibindings.Multibinds;
-import java.util.Set;
+import java.util.Map;
 import javax.inject.Inject;
 
 /**
@@ -69,12 +69,12 @@
   /** Internal factory for the Hilt ViewModel Factory. */
   public static final class InternalFactoryFactory {
 
-    private final Set<String> keySet;
+    private final Map<Class<?>, Boolean> keySet;
     private final ViewModelComponentBuilder viewModelComponentBuilder;
 
     @Inject
     InternalFactoryFactory(
-        @HiltViewModelMap.KeySet Set<String> keySet,
+        @HiltViewModelMap.KeySet Map<Class<?>, Boolean> keySet,
         ViewModelComponentBuilder viewModelComponentBuilder) {
       this.keySet = keySet;
       this.viewModelComponentBuilder = viewModelComponentBuilder;
@@ -103,7 +103,7 @@
   interface ActivityModule {
     @Multibinds
     @HiltViewModelMap.KeySet
-    abstract Set<String> viewModelKeys();
+    abstract Map<Class<?>, Boolean> viewModelKeys();
   }
 
   /** The activity entry point to retrieve the factory. */
diff --git a/java/dagger/hilt/android/internal/lifecycle/HiltViewModelAssistedMap.java b/java/dagger/hilt/android/internal/lifecycle/HiltViewModelAssistedMap.java
new file mode 100644
index 0000000..69bb2b1
--- /dev/null
+++ b/java/dagger/hilt/android/internal/lifecycle/HiltViewModelAssistedMap.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.hilt.android.internal.lifecycle;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import javax.inject.Qualifier;
+
+/**
+ * Internal qualifier for the multibinding map of assisted factories for @AssistedInject-annotated
+ * ViewModels used by the {@link dagger.hilt.android.lifecycle.HiltViewModelFactory}.
+ */
+@Qualifier
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.METHOD, ElementType.PARAMETER})
+public @interface HiltViewModelAssistedMap {}
diff --git a/java/dagger/hilt/android/internal/lifecycle/HiltViewModelFactory.java b/java/dagger/hilt/android/internal/lifecycle/HiltViewModelFactory.java
index 52f31b9..6819c24 100644
--- a/java/dagger/hilt/android/internal/lifecycle/HiltViewModelFactory.java
+++ b/java/dagger/hilt/android/internal/lifecycle/HiltViewModelFactory.java
@@ -16,12 +16,12 @@
 
 package dagger.hilt.android.internal.lifecycle;
 
+import static androidx.lifecycle.SavedStateHandleSupport.createSavedStateHandle;
+
 import android.app.Activity;
 import android.os.Bundle;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
-import androidx.lifecycle.AbstractSavedStateViewModelFactory;
-import androidx.lifecycle.SavedStateHandle;
 import androidx.lifecycle.ViewModel;
 import androidx.lifecycle.ViewModelProvider;
 import androidx.lifecycle.viewmodel.CreationExtras;
@@ -35,8 +35,8 @@
 import dagger.hilt.android.internal.builders.ViewModelComponentBuilder;
 import dagger.multibindings.Multibinds;
 import java.util.Map;
-import java.util.Set;
 import javax.inject.Provider;
+import kotlin.jvm.functions.Function1;
 
 /**
  * View Model Provider Factory for the Hilt Extension.
@@ -54,54 +54,110 @@
   @InstallIn(ViewModelComponent.class)
   public interface ViewModelFactoriesEntryPoint {
     @HiltViewModelMap
-    Map<String, Provider<ViewModel>> getHiltViewModelMap();
+    Map<Class<?>, Provider<ViewModel>> getHiltViewModelMap();
+
+    // From ViewModel class names to user defined @AssistedFactory-annotated implementations.
+    @HiltViewModelAssistedMap
+    Map<Class<?>, Object> getHiltViewModelAssistedMap();
   }
 
+  /** Creation extra key for the callbacks that create @AssistedInject-annotated ViewModels. */
+  public static final CreationExtras.Key<Function1<Object, ViewModel>> CREATION_CALLBACK_KEY =
+      new CreationExtras.Key<Function1<Object, ViewModel>>() {};
+
   /** Hilt module for providing the empty multi-binding map of ViewModels. */
   @Module
   @InstallIn(ViewModelComponent.class)
   interface ViewModelModule {
     @Multibinds
     @HiltViewModelMap
-    Map<String, ViewModel> hiltViewModelMap();
+    Map<Class<?>, ViewModel> hiltViewModelMap();
+
+    @Multibinds
+    @HiltViewModelAssistedMap
+    Map<Class<?>, Object> hiltViewModelAssistedMap();
   }
 
-  private final Set<String> hiltViewModelKeys;
+  private final Map<Class<?>, Boolean> hiltViewModelKeys;
   private final ViewModelProvider.Factory delegateFactory;
-  private final AbstractSavedStateViewModelFactory hiltViewModelFactory;
+  private final ViewModelProvider.Factory hiltViewModelFactory;
 
   public HiltViewModelFactory(
-      @NonNull Set<String> hiltViewModelKeys,
+      @NonNull Map<Class<?>, Boolean> hiltViewModelKeys,
       @NonNull ViewModelProvider.Factory delegateFactory,
       @NonNull ViewModelComponentBuilder viewModelComponentBuilder) {
     this.hiltViewModelKeys = hiltViewModelKeys;
     this.delegateFactory = delegateFactory;
     this.hiltViewModelFactory =
-        new AbstractSavedStateViewModelFactory() {
+        new ViewModelProvider.Factory() {
           @NonNull
           @Override
-          @SuppressWarnings("unchecked")
-          protected <T extends ViewModel> T create(
-              @NonNull String key, @NonNull Class<T> modelClass, @NonNull SavedStateHandle handle) {
+          public <T extends ViewModel> T create(
+              @NonNull Class<T> modelClass, @NonNull CreationExtras extras) {
             RetainedLifecycleImpl lifecycle = new RetainedLifecycleImpl();
-            ViewModelComponent component = viewModelComponentBuilder
-                .savedStateHandle(handle)
-                .viewModelLifecycle(lifecycle)
-                .build();
+            ViewModelComponent component =
+                viewModelComponentBuilder
+                    .savedStateHandle(createSavedStateHandle(extras))
+                    .viewModelLifecycle(lifecycle)
+                    .build();
+            T viewModel = createViewModel(component, modelClass, extras);
+            viewModel.addCloseable(lifecycle::dispatchOnCleared);
+            return viewModel;
+          }
+
+          private <T extends ViewModel> T createViewModel(
+              @NonNull ViewModelComponent component,
+              @NonNull Class<T> modelClass,
+              @NonNull CreationExtras extras) {
             Provider<? extends ViewModel> provider =
                 EntryPoints.get(component, ViewModelFactoriesEntryPoint.class)
                     .getHiltViewModelMap()
-                    .get(modelClass.getName());
-            if (provider == null) {
-              throw new IllegalStateException(
-                  "Expected the @HiltViewModel-annotated class '"
-                      + modelClass.getName()
-                      + "' to be available in the multi-binding of "
-                      + "@HiltViewModelMap but none was found.");
+                    .get(modelClass);
+            Function1<Object, ViewModel> creationCallback = extras.get(CREATION_CALLBACK_KEY);
+            Object assistedFactory =
+                EntryPoints.get(component, ViewModelFactoriesEntryPoint.class)
+                    .getHiltViewModelAssistedMap()
+                    .get(modelClass);
+
+            if (assistedFactory == null) {
+              if (creationCallback == null) {
+                if (provider == null) {
+                  throw new IllegalStateException(
+                      "Expected the @HiltViewModel-annotated class "
+                          + modelClass.getName()
+                          + " to be available in the multi-binding of "
+                          + "@HiltViewModelMap"
+                          + " but none was found.");
+                } else {
+                  return (T) provider.get();
+                }
+              } else {
+                // Provider could be null or non-null.
+                throw new IllegalStateException(
+                    "Found creation callback but class "
+                        + modelClass.getName()
+                        + " does not have an assisted factory specified in @HiltViewModel.");
+              }
+            } else {
+              if (provider == null) {
+                if (creationCallback == null) {
+                  throw new IllegalStateException(
+                      "Found @HiltViewModel-annotated class "
+                          + modelClass.getName()
+                          + " using @AssistedInject but no creation callback"
+                          + " was provided in CreationExtras.");
+                } else {
+                  return (T) creationCallback.invoke(assistedFactory);
+                }
+              } else {
+                // Creation callback could be null or non-null.
+                throw new AssertionError(
+                    "Found the @HiltViewModel-annotated class "
+                        + modelClass.getName()
+                        + " in both the multi-bindings of "
+                        + "@HiltViewModelMap and @HiltViewModelAssistedMap.");
+              }
             }
-            ViewModel viewModel = provider.get();
-            viewModel.addCloseable(lifecycle::dispatchOnCleared);
-            return (T) viewModel;
           }
         };
   }
@@ -110,7 +166,7 @@
   @Override
   public <T extends ViewModel> T create(
       @NonNull Class<T> modelClass, @NonNull CreationExtras extras) {
-    if (hiltViewModelKeys.contains(modelClass.getName())) {
+    if (hiltViewModelKeys.containsKey(modelClass)) {
       return hiltViewModelFactory.create(modelClass, extras);
     } else {
       return delegateFactory.create(modelClass, extras);
@@ -120,7 +176,7 @@
   @NonNull
   @Override
   public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
-    if (hiltViewModelKeys.contains(modelClass.getName())) {
+    if (hiltViewModelKeys.containsKey(modelClass)) {
       return hiltViewModelFactory.create(modelClass);
     } else {
       return delegateFactory.create(modelClass);
@@ -131,7 +187,8 @@
   @InstallIn(ActivityComponent.class)
   interface ActivityCreatorEntryPoint {
     @HiltViewModelMap.KeySet
-    Set<String> getViewModelKeys();
+    Map<Class<?>, Boolean> getViewModelKeys();
+
     ViewModelComponentBuilder getViewModelComponentBuilder();
   }
 
diff --git a/java/dagger/hilt/android/internal/managers/ActivityComponentManager.java b/java/dagger/hilt/android/internal/managers/ActivityComponentManager.java
index 50e4ce1..3fa4910 100644
--- a/java/dagger/hilt/android/internal/managers/ActivityComponentManager.java
+++ b/java/dagger/hilt/android/internal/managers/ActivityComponentManager.java
@@ -70,6 +70,12 @@
     return component;
   }
 
+  public final SavedStateHandleHolder getSavedStateHandleHolder() {
+    // This will only be used on base activity that extends ComponentActivity.
+    return ((ActivityRetainedComponentManager) activityRetainedComponentManager)
+        .getSavedStateHandleHolder();
+  }
+
   protected Object createComponent() {
     if (!(activity.getApplication() instanceof GeneratedComponentManager)) {
       throw new IllegalStateException(
diff --git a/java/dagger/hilt/android/internal/managers/ActivityRetainedComponentManager.java b/java/dagger/hilt/android/internal/managers/ActivityRetainedComponentManager.java
index df63bd3..dc3539c 100644
--- a/java/dagger/hilt/android/internal/managers/ActivityRetainedComponentManager.java
+++ b/java/dagger/hilt/android/internal/managers/ActivityRetainedComponentManager.java
@@ -23,6 +23,7 @@
 import androidx.lifecycle.ViewModel;
 import androidx.lifecycle.ViewModelProvider;
 import androidx.lifecycle.ViewModelStoreOwner;
+import androidx.lifecycle.viewmodel.CreationExtras;
 import dagger.Module;
 import dagger.Provides;
 import dagger.hilt.EntryPoint;
@@ -57,15 +58,22 @@
 
   static final class ActivityRetainedComponentViewModel extends ViewModel {
     private final ActivityRetainedComponent component;
+    private final SavedStateHandleHolder savedStateHandleHolder;
 
-    ActivityRetainedComponentViewModel(ActivityRetainedComponent component) {
+    ActivityRetainedComponentViewModel(
+        ActivityRetainedComponent component, SavedStateHandleHolder savedStateHandleHolder) {
       this.component = component;
+      this.savedStateHandleHolder = savedStateHandleHolder;
     }
 
     ActivityRetainedComponent getComponent() {
       return component;
     }
 
+    SavedStateHandleHolder getSavedStateHandleHolder() {
+      return savedStateHandleHolder;
+    }
+
     @Override
     protected void onCleared() {
       super.onCleared();
@@ -95,13 +103,17 @@
           @NonNull
           @Override
           @SuppressWarnings("unchecked")
-          public <T extends ViewModel> T create(@NonNull Class<T> aClass) {
+          public <T extends ViewModel> T create(
+              @NonNull Class<T> aClass, CreationExtras creationExtras) {
+            SavedStateHandleHolder savedStateHandleHolder =
+                new SavedStateHandleHolder(creationExtras);
             ActivityRetainedComponent component =
                 EntryPointAccessors.fromApplication(
-                    context, ActivityRetainedComponentBuilderEntryPoint.class)
+                        context, ActivityRetainedComponentBuilderEntryPoint.class)
                     .retainedComponentBuilder()
+                    .savedStateHandleHolder(savedStateHandleHolder)
                     .build();
-            return (T) new ActivityRetainedComponentViewModel(component);
+            return (T) new ActivityRetainedComponentViewModel(component, savedStateHandleHolder);
           }
         });
   }
@@ -118,6 +130,12 @@
     return component;
   }
 
+  public SavedStateHandleHolder getSavedStateHandleHolder() {
+    return getViewModelProvider(viewModelStoreOwner, context)
+        .get(ActivityRetainedComponentViewModel.class)
+        .getSavedStateHandleHolder();
+  }
+
   private ActivityRetainedComponent createComponent() {
     return getViewModelProvider(viewModelStoreOwner, context)
         .get(ActivityRetainedComponentViewModel.class)
diff --git a/java/dagger/hilt/android/internal/managers/BUILD b/java/dagger/hilt/android/internal/managers/BUILD
index e553c6e..950b511 100644
--- a/java/dagger/hilt/android/internal/managers/BUILD
+++ b/java/dagger/hilt/android/internal/managers/BUILD
@@ -30,25 +30,46 @@
         "ApplicationComponentManager.java",
         "BroadcastReceiverComponentManager.java",
         "FragmentComponentManager.java",
+        "SavedStateHandleModule.java",
         "ServiceComponentManager.java",
         "ViewComponentManager.java",
     ],
+    exports = [":saved_state_handle_holder"],
     deps = [
         ":component_supplier",
+        ":saved_state_handle_holder",
         "//:dagger_with_compiler",
         "//java/dagger/hilt:entry_point",
         "//java/dagger/hilt:install_in",
         "//java/dagger/hilt/android:activity_retained_lifecycle",
         "//java/dagger/hilt/android:entry_point_accessors",
+        "//java/dagger/hilt/android:unstable_api",
         "//java/dagger/hilt/android/components",
         "//java/dagger/hilt/android/internal",
         "//java/dagger/hilt/android/internal/builders",
         "//java/dagger/hilt/android/internal/lifecycle",
+        "//java/dagger/hilt/android/lifecycle:activity_retained_saved_state",
         "//java/dagger/hilt/android/scopes",
         "//java/dagger/hilt/internal:component_manager",
         "//java/dagger/hilt/internal:preconditions",
         "@maven//:androidx_activity_activity",
         "@maven//:androidx_annotation_annotation",
+        "@maven//:androidx_annotation_annotation_experimental",
+        "@maven//:androidx_fragment_fragment",
+        "@maven//:androidx_lifecycle_lifecycle_common",
+        "@maven//:androidx_lifecycle_lifecycle_viewmodel",
+        "@maven//:androidx_lifecycle_lifecycle_viewmodel_savedstate",
+    ],
+)
+
+android_library(
+    name = "saved_state_handle_holder",
+    srcs = ["SavedStateHandleHolder.java"],
+    deps = [
+        "//java/dagger/hilt/android/internal",
+        "//java/dagger/hilt/internal:preconditions",
+        "@maven//:androidx_activity_activity",
+        "@maven//:androidx_annotation_annotation",
         "@maven//:androidx_fragment_fragment",
         "@maven//:androidx_lifecycle_lifecycle_common",
         "@maven//:androidx_lifecycle_lifecycle_viewmodel",
diff --git a/java/dagger/hilt/android/internal/managers/SavedStateHandleHolder.java b/java/dagger/hilt/android/internal/managers/SavedStateHandleHolder.java
new file mode 100644
index 0000000..8350159
--- /dev/null
+++ b/java/dagger/hilt/android/internal/managers/SavedStateHandleHolder.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.hilt.android.internal.managers;
+
+import static dagger.hilt.internal.Preconditions.checkNotNull;
+import static dagger.hilt.internal.Preconditions.checkState;
+
+import android.os.Bundle;
+import androidx.annotation.Nullable;
+import androidx.lifecycle.SavedStateHandle;
+import androidx.lifecycle.SavedStateHandleSupport;
+import androidx.lifecycle.viewmodel.CreationExtras;
+import androidx.lifecycle.viewmodel.MutableCreationExtras;
+import dagger.hilt.android.internal.ThreadUtil;
+
+/** Implementation for SavedStateHandleHolder. */
+public final class SavedStateHandleHolder {
+  private CreationExtras extras;
+  private SavedStateHandle handle;
+  private final boolean nonComponentActivity;
+
+  SavedStateHandleHolder(@Nullable CreationExtras extras) {
+    nonComponentActivity = (extras == null);
+    this.extras = extras;
+  }
+
+  SavedStateHandle getSavedStateHandle() {
+    ThreadUtil.ensureMainThread();
+    checkState(
+        !nonComponentActivity,
+        "Activity that does not extend ComponentActivity cannot use SavedStateHandle");
+    if (handle != null) {
+      return handle;
+    }
+    checkNotNull(
+        extras,
+        "The first access to SavedStateHandle should happen between super.onCreate() and"
+            + " super.onDestroy()");
+    // Clean up default args, since those are unused and we don't want to duplicate those for each
+    // SavedStateHandle
+    MutableCreationExtras mutableExtras = new MutableCreationExtras(extras);
+    mutableExtras.set(SavedStateHandleSupport.DEFAULT_ARGS_KEY, Bundle.EMPTY);
+    extras = mutableExtras;
+    handle = SavedStateHandleSupport.createSavedStateHandle(extras);
+
+    extras = null;
+    return handle;
+  }
+
+  public void clear() {
+    extras = null;
+  }
+
+  public void setExtras(CreationExtras extras) {
+    if (handle != null) {
+      // If handle is already created, we don't need to store CreationExtras.
+      return;
+    }
+    this.extras = extras;
+  }
+
+  public boolean isInvalid() {
+    return handle == null && extras == null;
+  }
+}
diff --git a/java/dagger/hilt/android/internal/managers/SavedStateHandleModule.java b/java/dagger/hilt/android/internal/managers/SavedStateHandleModule.java
new file mode 100644
index 0000000..18ca508
--- /dev/null
+++ b/java/dagger/hilt/android/internal/managers/SavedStateHandleModule.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.hilt.android.internal.managers;
+
+import androidx.annotation.OptIn;
+import androidx.lifecycle.SavedStateHandle;
+import dagger.Module;
+import dagger.Provides;
+import dagger.hilt.InstallIn;
+import dagger.hilt.android.UnstableApi;
+import dagger.hilt.android.components.ActivityRetainedComponent;
+import dagger.hilt.android.lifecycle.ActivityRetainedSavedState;
+import dagger.hilt.android.scopes.ActivityRetainedScoped;
+
+/** Module providing SavedStateHandle from ActivityRetainedComponent. */
+@Module
+@InstallIn(ActivityRetainedComponent.class)
+abstract class SavedStateHandleModule {
+  @OptIn(markerClass = UnstableApi.class)
+  @ActivityRetainedSavedState
+  @ActivityRetainedScoped
+  @Provides
+  static SavedStateHandle provideSavedStateHandle(SavedStateHandleHolder savedStateHandleHolder) {
+    return savedStateHandleHolder.getSavedStateHandle();
+  }
+}
diff --git a/java/dagger/hilt/android/lifecycle/ActivityRetainedSavedState.java b/java/dagger/hilt/android/lifecycle/ActivityRetainedSavedState.java
new file mode 100644
index 0000000..6298435
--- /dev/null
+++ b/java/dagger/hilt/android/lifecycle/ActivityRetainedSavedState.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.hilt.android.lifecycle;
+
+import dagger.hilt.android.UnstableApi;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import javax.inject.Qualifier;
+
+/** Qualifies a binding that belongs to ActivityRetainedComponent. */
+@Qualifier
+@Target({ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD})
+@UnstableApi
+@Retention(RetentionPolicy.CLASS)
+public @interface ActivityRetainedSavedState {}
diff --git a/java/dagger/hilt/android/lifecycle/BUILD b/java/dagger/hilt/android/lifecycle/BUILD
index 456dbe7..26394f0 100644
--- a/java/dagger/hilt/android/lifecycle/BUILD
+++ b/java/dagger/hilt/android/lifecycle/BUILD
@@ -15,6 +15,8 @@
 # Description:
 #   Hilt ViewModel integration.
 
+load("//tools:bazel_compat.bzl", "compat_kt_android_library")
+
 package(default_visibility = ["//:src"])
 
 java_library(
@@ -31,7 +33,6 @@
     exported_plugins = [
         "//java/dagger/hilt/android/processor/internal/viewmodel:processor",
     ],
-    proguard_specs = ["proguard-rules.pro"],
     exports = [
         "//:dagger_with_compiler",
         "//java/dagger/hilt:install_in",
@@ -54,6 +55,26 @@
     ],
 )
 
+android_library(
+    name = "activity_retained_saved_state",
+    srcs = ["ActivityRetainedSavedState.java"],
+    deps = [
+        "//java/dagger/hilt/android:unstable_api",
+        "//third_party/java/jsr330_inject",
+    ],
+)
+
+compat_kt_android_library(
+    name = "hilt_view_model_extensions",
+    srcs = ["HiltViewModelExtensions.kt"],
+    deps = [
+        ":package_info",
+        "//java/dagger/hilt/android/internal/lifecycle",
+        "@maven//:androidx_annotation_annotation",
+        "@maven//:androidx_lifecycle_lifecycle_viewmodel",
+    ],
+)
+
 filegroup(
     name = "srcs_filegroup",
     srcs = glob(["*"]),
diff --git a/java/dagger/hilt/android/lifecycle/HiltViewModel.java b/java/dagger/hilt/android/lifecycle/HiltViewModel.java
index 198ec8a..a5e486f 100644
--- a/java/dagger/hilt/android/lifecycle/HiltViewModel.java
+++ b/java/dagger/hilt/android/lifecycle/HiltViewModel.java
@@ -53,7 +53,46 @@
  * }
  * </pre>
  *
- * <p>Exactly one constructor in the {@code ViewModel} must be annotated with {@code Inject}.
+ * <p>{@code ViewModel}s annotated with {@link HiltViewModel} can also be used with assisted
+ * injection:
+ *
+ * <pre>
+ * &#64;HiltViewModel(assistedFactory = DonutViewModel.Factory.class)
+ * public class DonutViewModel extends ViewModel {
+ *     &#64;AssistedInject
+ *     public DonutViewModel(
+ *         SavedStateHandle handle,
+ *         RecipeRepository repository, 
+ *         $#64;Assisted int donutId
+ *     ) {
+ *         // ...
+ *     }
+ *
+ *     &#64;AssistedFactory
+ *     public interface Factory {
+ *         DonutViewModel create(int donutId);
+ *     }
+ * }
+ * </pre>
+ *
+ * <pre>
+ * &#64;AndroidEntryPoint
+ * public class CookingActivity extends AppCompatActivity {
+ *     public void onCreate(Bundle savedInstanceState) {
+ *         DonutViewModel vm = new ViewModelProvider(
+ *             getViewModelStore(),
+ *             getDefaultViewModelProviderFactory(),
+ *             HiltViewModelExtensions.withCreationCallback(
+ *                 getDefaultViewModelCreationExtras(),
+ *                 (DonutViewModel.Factory factory) -> factory.create(1)
+ *             )
+ *         ).get(DonutViewModel.class);
+ *     }
+ * }
+ * </pre>
+ *
+ * <p>Exactly one constructor in the {@code ViewModel} must be annotated with {@code Inject} or
+ * {@code AssistedInject}.
  *
  * <p>Only dependencies available in the {@link dagger.hilt.android.components.ViewModelComponent}
  * can be injected into the {@code ViewModel}.
@@ -65,4 +104,11 @@
 @Target(ElementType.TYPE)
 @Retention(RetentionPolicy.CLASS)
 @GeneratesRootInput
-public @interface HiltViewModel {}
+public @interface HiltViewModel {
+  /**
+   * Returns a factory class that can be used to create this ViewModel with assisted injection. The
+   * default value `Object.class` denotes that no factory is specified and the ViewModel is not
+   * assisted injected.
+   */
+  Class<?> assistedFactory() default Object.class;
+}
diff --git a/java/dagger/hilt/android/lifecycle/HiltViewModelExtensions.kt b/java/dagger/hilt/android/lifecycle/HiltViewModelExtensions.kt
new file mode 100644
index 0000000..f212c58
--- /dev/null
+++ b/java/dagger/hilt/android/lifecycle/HiltViewModelExtensions.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@file:JvmName("HiltViewModelExtensions")
+
+package dagger.hilt.android.lifecycle
+
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewmodel.CreationExtras
+import androidx.lifecycle.viewmodel.MutableCreationExtras
+import dagger.hilt.android.internal.lifecycle.HiltViewModelFactory
+
+/**
+ * Returns a new {@code CreationExtras} with the original entries plus the passed in creation
+ * callback. The callback is used by Hilt to create {@link AssistedInject}-annotated {@link
+ * HiltViewModel}s.
+ *
+ * @param callback A creation callback that takes an assisted factory and returns a {@code
+ *   ViewModel}.
+ */
+fun <VMF> CreationExtras.withCreationCallback(callback: (VMF) -> ViewModel): CreationExtras =
+  MutableCreationExtras(this).addCreationCallback(callback)
+
+/**
+ * Returns the {@code MutableCreationExtras} with the passed in creation callback added. The
+ * callback is used by Hilt to create {@link AssistedInject}-annotated {@link HiltViewModel}s.
+ *
+ * @param callback A creation callback that takes an assisted factory and returns a {@code
+ *   ViewModel}.
+ */
+@Suppress("UNCHECKED_CAST")
+fun <VMF> MutableCreationExtras.addCreationCallback(callback: (VMF) -> ViewModel): CreationExtras =
+  this.apply {
+    this[HiltViewModelFactory.CREATION_CALLBACK_KEY] = { factory -> callback(factory as VMF) }
+  }
diff --git a/java/dagger/hilt/android/lifecycle/proguard-rules.pro b/java/dagger/hilt/android/lifecycle/proguard-rules.pro
deleted file mode 100644
index 6c647f1..0000000
--- a/java/dagger/hilt/android/lifecycle/proguard-rules.pro
+++ /dev/null
@@ -1,2 +0,0 @@
-# Keep class names of Hilt injected ViewModels since their name are used as a multibinding map key.
--keepnames @dagger.hilt.android.lifecycle.HiltViewModel class * extends androidx.lifecycle.ViewModel
\ No newline at end of file
diff --git a/java/dagger/hilt/android/plugin/agp-wrapper-7-0/build.gradle b/java/dagger/hilt/android/plugin/agp-wrapper-7-0/build.gradle
index 3c03495..5509261 100644
--- a/java/dagger/hilt/android/plugin/agp-wrapper-7-0/build.gradle
+++ b/java/dagger/hilt/android/plugin/agp-wrapper-7-0/build.gradle
@@ -2,8 +2,10 @@
   id 'org.jetbrains.kotlin.jvm'
 }
 
-kotlin {
-  jvmToolchain(11)
+compileKotlin {
+  kotlinOptions {
+    jvmTarget = 11
+  }
 }
 
 dependencies {
diff --git a/java/dagger/hilt/android/plugin/agp-wrapper-7-1/build.gradle b/java/dagger/hilt/android/plugin/agp-wrapper-7-1/build.gradle
index 5bc8d3d..982949a 100644
--- a/java/dagger/hilt/android/plugin/agp-wrapper-7-1/build.gradle
+++ b/java/dagger/hilt/android/plugin/agp-wrapper-7-1/build.gradle
@@ -2,8 +2,10 @@
   id 'org.jetbrains.kotlin.jvm'
 }
 
-kotlin {
-  jvmToolchain(11)
+compileKotlin {
+  kotlinOptions {
+    jvmTarget = 11
+  }
 }
 
 dependencies {
diff --git a/java/dagger/hilt/android/plugin/agp-wrapper-7-2/build.gradle b/java/dagger/hilt/android/plugin/agp-wrapper-7-2/build.gradle
index a413301..e0331c2 100644
--- a/java/dagger/hilt/android/plugin/agp-wrapper-7-2/build.gradle
+++ b/java/dagger/hilt/android/plugin/agp-wrapper-7-2/build.gradle
@@ -2,8 +2,10 @@
   id 'org.jetbrains.kotlin.jvm'
 }
 
-kotlin {
-  jvmToolchain(11)
+compileKotlin {
+  kotlinOptions {
+    jvmTarget = 11
+  }
 }
 
 dependencies {
diff --git a/java/dagger/hilt/android/plugin/agp-wrapper-impl/build.gradle b/java/dagger/hilt/android/plugin/agp-wrapper-impl/build.gradle
index 3ad558a..f270efb 100644
--- a/java/dagger/hilt/android/plugin/agp-wrapper-impl/build.gradle
+++ b/java/dagger/hilt/android/plugin/agp-wrapper-impl/build.gradle
@@ -2,8 +2,10 @@
   id 'org.jetbrains.kotlin.jvm'
 }
 
-kotlin {
-  jvmToolchain(11)
+compileKotlin {
+  kotlinOptions {
+    jvmTarget = 11
+  }
 }
 
 dependencies {
diff --git a/java/dagger/hilt/android/plugin/agp-wrapper/build.gradle b/java/dagger/hilt/android/plugin/agp-wrapper/build.gradle
index 71ea724..d8238e8 100644
--- a/java/dagger/hilt/android/plugin/agp-wrapper/build.gradle
+++ b/java/dagger/hilt/android/plugin/agp-wrapper/build.gradle
@@ -2,8 +2,10 @@
   id 'org.jetbrains.kotlin.jvm'
 }
 
-kotlin {
-  jvmToolchain(11)
+compileKotlin {
+ kotlinOptions {
+   jvmTarget = 11
+ }
 }
 
 dependencies {
diff --git a/java/dagger/hilt/android/plugin/agp-wrapper/src/main/kotlin/dagger/hilt/android/plugin/util/ComponentCompat.kt b/java/dagger/hilt/android/plugin/agp-wrapper/src/main/kotlin/dagger/hilt/android/plugin/util/ComponentCompat.kt
index acc59e7..1f0d589 100644
--- a/java/dagger/hilt/android/plugin/agp-wrapper/src/main/kotlin/dagger/hilt/android/plugin/util/ComponentCompat.kt
+++ b/java/dagger/hilt/android/plugin/agp-wrapper/src/main/kotlin/dagger/hilt/android/plugin/util/ComponentCompat.kt
@@ -20,6 +20,8 @@
 import com.android.build.api.instrumentation.FramesComputationMode
 import com.android.build.api.instrumentation.InstrumentationParameters
 import com.android.build.api.instrumentation.InstrumentationScope
+import java.io.File
+import org.gradle.api.Project
 
 /**
  * Compatibility version of [com.android.build.api.variant.Component]
diff --git a/java/dagger/hilt/android/plugin/build.gradle b/java/dagger/hilt/android/plugin/build.gradle
index 869d885..685ea7e 100644
--- a/java/dagger/hilt/android/plugin/build.gradle
+++ b/java/dagger/hilt/android/plugin/build.gradle
@@ -1,8 +1,8 @@
 buildscript {
   ext {
-    kotlin_version = "1.8.20"
+    kotlin_version = "1.9.20"
     agp_version = System.getenv('AGP_VERSION') ?: "7.2.0"
-    ksp_version = "$kotlin_version-1.0.11"
+    ksp_version = "$kotlin_version-1.0.14"
     pluginArtifactId = 'hilt-android-gradle-plugin'
     pluginId = 'com.google.dagger.hilt.android'
   }
@@ -24,7 +24,12 @@
     mavenCentral()
   }
 }
+
+// Avoids conflict with BUILD file
+project.buildDir = 'buildOut'
+
 subprojects {
+    project.buildDir = 'buildOut'
     afterEvaluate {
         dependencies {
             // This is needed to align older versions of kotlin-stdlib.
diff --git a/java/dagger/hilt/android/plugin/main/build.gradle b/java/dagger/hilt/android/plugin/main/build.gradle
index 96a28b9..035ecea 100644
--- a/java/dagger/hilt/android/plugin/main/build.gradle
+++ b/java/dagger/hilt/android/plugin/main/build.gradle
@@ -65,16 +65,16 @@
   compileOnly "com.android.tools.build:gradle:$agp_version"
   compileOnly "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
   compileOnly "com.google.devtools.ksp:symbol-processing-gradle-plugin:$ksp_version"
-  implementation 'org.ow2.asm:asm:9.0'
+  implementation 'org.ow2.asm:asm:9.6'
   implementation "com.squareup:javapoet:1.13.0"
 
   testImplementation gradleTestKit()
   testImplementation 'junit:junit:4.12'
   testImplementation 'com.google.truth:truth:1.0.1'
   testImplementation 'org.javassist:javassist:3.26.0-GA'
-  testPluginCompile 'com.android.tools.build:gradle:7.1.2'
-  testPluginCompile 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.0'
-  testPluginCompile 'com.google.devtools.ksp:symbol-processing-gradle-plugin:1.8.0-1.0.9'
+  testPluginCompile "com.android.tools.build:gradle:$agp_version"
+  testPluginCompile "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+  testPluginCompile "com.google.devtools.ksp:symbol-processing-gradle-plugin:$ksp_version"
 }
 
 // Configure the generating task of plugin-under-test-metadata.properties to
@@ -85,14 +85,11 @@
   it.pluginClasspath.from(configurations.testPluginCompile)
 }
 
-kotlin {
-  jvmToolchain(11)
-}
-
 compileKotlin {
   kotlinOptions {
     allWarningsAsErrors = true
     freeCompilerArgs += [ "-opt-in=kotlin.ExperimentalStdlibApi" ]
+    jvmTarget = 11
   }
 }
 
diff --git a/java/dagger/hilt/android/plugin/main/src/main/kotlin/dagger/hilt/android/plugin/AndroidEntryPointClassVisitor.kt b/java/dagger/hilt/android/plugin/main/src/main/kotlin/dagger/hilt/android/plugin/AndroidEntryPointClassVisitor.kt
index da5fb3c..16e4af9 100644
--- a/java/dagger/hilt/android/plugin/main/src/main/kotlin/dagger/hilt/android/plugin/AndroidEntryPointClassVisitor.kt
+++ b/java/dagger/hilt/android/plugin/main/src/main/kotlin/dagger/hilt/android/plugin/AndroidEntryPointClassVisitor.kt
@@ -36,15 +36,10 @@
 class AndroidEntryPointClassVisitor(
   private val apiVersion: Int,
   nextClassVisitor: ClassVisitor,
-  private val additionalClasses: File
+  private val classContext: ClassContext
 ) : ClassVisitor(apiVersion, nextClassVisitor) {
 
-  interface AndroidEntryPointParams : InstrumentationParameters {
-    @get:Internal
-    val additionalClassesDir: Property<File>
-  }
-
-  abstract class Factory : AsmClassVisitorFactory<AndroidEntryPointParams> {
+  abstract class Factory : AsmClassVisitorFactory<InstrumentationParameters.None> {
     override fun createClassVisitor(
       classContext: ClassContext,
       nextClassVisitor: ClassVisitor
@@ -52,7 +47,7 @@
       return AndroidEntryPointClassVisitor(
         apiVersion = instrumentationContext.apiVersion.get(),
         nextClassVisitor = nextClassVisitor,
-        additionalClasses = parameters.get().additionalClassesDir.get()
+        classContext = classContext
       )
     }
 
@@ -198,34 +193,21 @@
   }
 
   /**
-   * Check if Hilt generated class is a BroadcastReceiver with the marker field which means
+   * Check if Hilt generated class is a BroadcastReceiver with the marker annotation which means
    * a super.onReceive invocation has to be inserted in the implementation.
    */
-  private fun hasOnReceiveBytecodeInjectionMarker() =
-    findAdditionalClassFile(newSuperclassName).inputStream().use {
-      var hasMarker = false
-      ClassReader(it).accept(
-        object : ClassVisitor(apiVersion) {
-          override fun visitField(
-            access: Int,
-            name: String,
-            descriptor: String,
-            signature: String?,
-            value: Any?
-          ): FieldVisitor? {
-            if (name == "onReceiveBytecodeInjectionMarker") {
-              hasMarker = true
-            }
-            return null
-          }
-        },
-        ClassReader.SKIP_CODE or ClassReader.SKIP_DEBUG or ClassReader.SKIP_FRAMES
-      )
-      return@use hasMarker
-    }
+  private fun hasOnReceiveBytecodeInjectionMarker(): Boolean {
+    val newSuperclassFQName = newSuperclassName.toFQName()
+    return classContext.loadClassData(newSuperclassFQName)
+      ?.classAnnotations?.contains(ON_RECEIVE_MARKER_ANNOTATION)
+      ?: error("Cannot load class $newSuperclassFQName!")
+  }
 
-  private fun findAdditionalClassFile(className: String) =
-    File(additionalClasses, "$className.class")
+  /**
+   * Return a fully qualified name from an internal name.
+   * See https://asm.ow2.io/javadoc/org/objectweb/asm/Type.html#getInternalName()
+   */
+  private fun String.toFQName() = this.replace('/', '.')
 
   companion object {
     val ANDROID_ENTRY_POINT_ANNOTATIONS = setOf(
@@ -235,5 +217,6 @@
     const val ON_RECEIVE_METHOD_NAME = "onReceive"
     const val ON_RECEIVE_METHOD_DESCRIPTOR =
       "(Landroid/content/Context;Landroid/content/Intent;)V"
+    const val ON_RECEIVE_MARKER_ANNOTATION = "dagger.hilt.android.internal.OnReceiveBytecodeInjectionMarker"
   }
 }
diff --git a/java/dagger/hilt/android/plugin/main/src/main/kotlin/dagger/hilt/android/plugin/HiltGradlePlugin.kt b/java/dagger/hilt/android/plugin/main/src/main/kotlin/dagger/hilt/android/plugin/HiltGradlePlugin.kt
index 4e2b878..7b03e43 100644
--- a/java/dagger/hilt/android/plugin/main/src/main/kotlin/dagger/hilt/android/plugin/HiltGradlePlugin.kt
+++ b/java/dagger/hilt/android/plugin/main/src/main/kotlin/dagger/hilt/android/plugin/HiltGradlePlugin.kt
@@ -38,7 +38,6 @@
 import dagger.hilt.android.plugin.util.getKspConfigName
 import dagger.hilt.android.plugin.util.isKspTask
 import dagger.hilt.processor.internal.optionvalues.GradleProjectType
-import java.io.File
 import javax.inject.Inject
 import org.gradle.api.JavaVersion
 import org.gradle.api.Plugin
@@ -246,12 +245,9 @@
     fun registerTransform(androidComponent: ComponentCompat) {
       androidComponent.transformClassesWith(
         classVisitorFactoryImplClass = AndroidEntryPointClassVisitor.Factory::class.java,
-        scope = InstrumentationScope.PROJECT
-      ) { params ->
-        val classesDir =
-          File(project.buildDir, "intermediates/javac/${androidComponent.name}/classes")
-        params.additionalClassesDir.set(classesDir)
-      }
+        scope = InstrumentationScope.PROJECT,
+        instrumentationParamsConfig = {}
+      )
       androidComponent.setAsmFramesComputationMode(
         FramesComputationMode.COMPUTE_FRAMES_FOR_INSTRUMENTED_METHODS
       )
diff --git a/java/dagger/hilt/android/plugin/main/src/main/kotlin/dagger/hilt/android/plugin/util/CopyTransform.kt b/java/dagger/hilt/android/plugin/main/src/main/kotlin/dagger/hilt/android/plugin/util/CopyTransform.kt
index 7c8326b..f7c33dc 100644
--- a/java/dagger/hilt/android/plugin/main/src/main/kotlin/dagger/hilt/android/plugin/util/CopyTransform.kt
+++ b/java/dagger/hilt/android/plugin/main/src/main/kotlin/dagger/hilt/android/plugin/util/CopyTransform.kt
@@ -16,7 +16,6 @@
 
 package dagger.hilt.android.plugin.util
 
-import org.gradle.api.artifacts.transform.CacheableTransform
 import org.gradle.api.artifacts.transform.InputArtifact
 import org.gradle.api.artifacts.transform.TransformAction
 import org.gradle.api.artifacts.transform.TransformOutputs
@@ -24,12 +23,13 @@
 import org.gradle.api.file.FileSystemLocation
 import org.gradle.api.provider.Provider
 import org.gradle.api.tasks.Classpath
+import org.gradle.work.DisableCachingByDefault
 
 /**
  * A transform that registers the input file (usually a jar or a class) as an output and thus
  * changing from one artifact type to another.
  */
-@CacheableTransform
+@DisableCachingByDefault(because = "Copying files does not benefit from caching")
 abstract class CopyTransform : TransformAction<TransformParameters.None> {
   @get:Classpath
   @get:InputArtifact
diff --git a/java/dagger/hilt/android/plugin/main/src/main/kotlin/dagger/hilt/android/plugin/util/Tasks.kt b/java/dagger/hilt/android/plugin/main/src/main/kotlin/dagger/hilt/android/plugin/util/Tasks.kt
index 2c803b7..a91ce35 100644
--- a/java/dagger/hilt/android/plugin/main/src/main/kotlin/dagger/hilt/android/plugin/util/Tasks.kt
+++ b/java/dagger/hilt/android/plugin/main/src/main/kotlin/dagger/hilt/android/plugin/util/Tasks.kt
@@ -38,8 +38,20 @@
   component: ComponentCompat,
   produceArgProvider: (Task) -> CommandLineArgumentProvider
 ) = project.plugins.withId("kotlin-kapt") {
+  checkClass("org.jetbrains.kotlin.gradle.internal.KaptTask") {
+    """
+    The KAPT plugin was detected to be applied but its task class could not be found.
+
+    This is an indicator that the Hilt Gradle Plugin is using a different class loader because
+    it was declared at the root while KAPT was declared in a sub-project. To fix this, declare
+    both plugins in the same scope, i.e. either at the root (without applying them) or at the
+    sub-projects.
+    """.trimIndent()
+  }
   project.tasks.withType(KaptTask::class.java) { task ->
-    if (task.name == "kapt${component.name.capitalize()}Kotlin") {
+    if (task.name == "kapt${component.name.capitalize()}Kotlin" ||
+        // Task names in shared/src/AndroidMain in KMP projects has a platform suffix.
+        task.name == "kapt${component.name.capitalize()}KotlinAndroid") {
       val argProvider = produceArgProvider.invoke(task)
       // TODO: Update once KT-58009 is fixed.
       try {
@@ -60,16 +72,39 @@
   component: ComponentCompat,
   produceArgProvider: (Task) -> CommandLineArgumentProvider
 ) = project.plugins.withId("com.google.devtools.ksp") {
+  checkClass("com.google.devtools.ksp.gradle.KspTaskJvm") {
+    """
+    The KSP plugin was detected to be applied but its task class could not be found.
+
+    This is an indicator that the Hilt Gradle Plugin is using a different class loader because
+    it was declared at the root while KSP was declared in a sub-project. To fix this, declare
+    both plugins in the same scope, i.e. either at the root (without applying them) or at the
+    sub-projects.
+
+    See https://github.com/google/dagger/issues/3965 for more details.
+    """.trimIndent()
+  }
   project.tasks.withType(KspTaskJvm::class.java) { task ->
-    if (task.name == "ksp${component.name.capitalize()}Kotlin") {
+    if (task.name == "ksp${component.name.capitalize()}Kotlin" ||
+        // Task names in shared/src/AndroidMain in KMP projects has a platform suffix.
+        task.name == "ksp${component.name.capitalize()}KotlinAndroid") {
       task.commandLineArgumentProviders.add(produceArgProvider.invoke(task))
     }
   }
 }
 
+private inline fun checkClass(fqn: String, msg: () -> String) {
+  try {
+    Class.forName(fqn)
+  } catch (ex: ClassNotFoundException) {
+    throw IllegalStateException(msg.invoke(), ex)
+  }
+}
+
 internal fun Task.isKspTask(): Boolean = try {
   val kspTaskClass = Class.forName("com.google.devtools.ksp.gradle.KspTask")
   kspTaskClass.isAssignableFrom(this::class.java)
 } catch (ex: ClassNotFoundException) {
   false
-}
\ No newline at end of file
+}
+
diff --git a/java/dagger/hilt/android/plugin/main/src/test/data/android-libraryA/build.gradle b/java/dagger/hilt/android/plugin/main/src/test/data/android-libraryA/build.gradle
index e0ec230..9e8a097 100644
--- a/java/dagger/hilt/android/plugin/main/src/test/data/android-libraryA/build.gradle
+++ b/java/dagger/hilt/android/plugin/main/src/test/data/android-libraryA/build.gradle
@@ -4,12 +4,12 @@
 }
 
 android {
-    compileSdkVersion 32
-    buildToolsVersion "32.0.0"
+    compileSdkVersion 33
+    buildToolsVersion "33.0.0"
 
     defaultConfig {
         minSdkVersion 21
-        targetSdkVersion 32
+        targetSdkVersion 33
         versionCode 1
         versionName "1.0"
     }
diff --git a/java/dagger/hilt/android/plugin/main/src/test/data/android-libraryC/build.gradle b/java/dagger/hilt/android/plugin/main/src/test/data/android-libraryC/build.gradle
index 68c6a97..450f128 100644
--- a/java/dagger/hilt/android/plugin/main/src/test/data/android-libraryC/build.gradle
+++ b/java/dagger/hilt/android/plugin/main/src/test/data/android-libraryC/build.gradle
@@ -4,12 +4,12 @@
 }
 
 android {
-    compileSdkVersion 32
-    buildToolsVersion "32.0.0"
+    compileSdkVersion 33
+    buildToolsVersion "33.0.0"
 
     defaultConfig {
         minSdkVersion 21
-        targetSdkVersion 32
+        targetSdkVersion 33
         versionCode 1
         versionName "1.0"
     }
diff --git a/java/dagger/hilt/android/plugin/main/src/test/data/flavored-project/app/build.gradle b/java/dagger/hilt/android/plugin/main/src/test/data/flavored-project/app/build.gradle
index 23cd028..954e209 100644
--- a/java/dagger/hilt/android/plugin/main/src/test/data/flavored-project/app/build.gradle
+++ b/java/dagger/hilt/android/plugin/main/src/test/data/flavored-project/app/build.gradle
@@ -20,8 +20,8 @@
 }
 
 android {
-    compileSdkVersion 32
-    buildToolsVersion "32.0.0"
+    compileSdkVersion 33
+    buildToolsVersion "33.0.0"
 
     flavorDimensions 'api', 'version'
     productFlavors {
@@ -46,7 +46,7 @@
     defaultConfig {
         applicationId "simple.app"
         minSdkVersion 21
-        targetSdkVersion 32
+        targetSdkVersion 33
     }
 
     compileOptions {
diff --git a/java/dagger/hilt/android/plugin/main/src/test/data/flavored-project/feature/build.gradle b/java/dagger/hilt/android/plugin/main/src/test/data/flavored-project/feature/build.gradle
index 8e34951..068d402 100644
--- a/java/dagger/hilt/android/plugin/main/src/test/data/flavored-project/feature/build.gradle
+++ b/java/dagger/hilt/android/plugin/main/src/test/data/flavored-project/feature/build.gradle
@@ -20,8 +20,8 @@
 }
 
 android {
-    compileSdkVersion 32
-    buildToolsVersion "32.0.0"
+    compileSdkVersion 33
+    buildToolsVersion "33.0.0"
 
     flavorDimensions 'api', 'version'
     productFlavors {
@@ -45,7 +45,7 @@
 
     defaultConfig {
         minSdkVersion 16
-        targetSdkVersion 32
+        targetSdkVersion 33
     }
 
     compileOptions {
diff --git a/java/dagger/hilt/android/plugin/main/src/test/data/simple-project-for-agp-test/app/build.gradle b/java/dagger/hilt/android/plugin/main/src/test/data/simple-project-for-agp-test/app/build.gradle
index 2173a82..506d40a 100644
--- a/java/dagger/hilt/android/plugin/main/src/test/data/simple-project-for-agp-test/app/build.gradle
+++ b/java/dagger/hilt/android/plugin/main/src/test/data/simple-project-for-agp-test/app/build.gradle
@@ -20,13 +20,13 @@
 }
 
 android {
-    compileSdkVersion 32
-    buildToolsVersion "32.0.0"
+    compileSdkVersion 33
+    namespace "simple.app"
 
     defaultConfig {
         applicationId "simple.app"
         minSdkVersion 21
-        targetSdkVersion 32
+        targetSdkVersion 33
     }
 
     compileOptions {
diff --git a/java/dagger/hilt/android/plugin/main/src/test/data/simple-project-for-agp-test/app/src/main/AndroidManifest.xml b/java/dagger/hilt/android/plugin/main/src/test/data/simple-project-for-agp-test/app/src/main/AndroidManifest.xml
index da45ecc..ce521fb 100644
--- a/java/dagger/hilt/android/plugin/main/src/test/data/simple-project-for-agp-test/app/src/main/AndroidManifest.xml
+++ b/java/dagger/hilt/android/plugin/main/src/test/data/simple-project-for-agp-test/app/src/main/AndroidManifest.xml
@@ -16,5 +16,7 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="simple.app">
   <application android:name=".SimpleApp" android:label="Flavored App">
+    <receiver android:name=".SimpleReceiver" android:exported="false">
+    </receiver>
   </application>
 </manifest>
\ No newline at end of file
diff --git a/java/dagger/spi/model/CompilerEnvironment.java b/java/dagger/hilt/android/plugin/main/src/test/data/simple-project-for-agp-test/app/src/main/java/simple/app/SimpleReceiver.java
similarity index 61%
copy from java/dagger/spi/model/CompilerEnvironment.java
copy to java/dagger/hilt/android/plugin/main/src/test/data/simple-project-for-agp-test/app/src/main/java/simple/app/SimpleReceiver.java
index 28553e4..ce483ad 100644
--- a/java/dagger/spi/model/CompilerEnvironment.java
+++ b/java/dagger/hilt/android/plugin/main/src/test/data/simple-project-for-agp-test/app/src/main/java/simple/app/SimpleReceiver.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Dagger Authors.
+ * Copyright (C) 2023 The Dagger Authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,10 +14,15 @@
  * limitations under the License.
  */
 
-package dagger.spi.model;
+package simple.app;
 
-/** Types for the compiler in use for annotation processing. */
-public enum CompilerEnvironment {
-  JAVA,
-  KSP
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import dagger.hilt.android.AndroidEntryPoint;
+
+@AndroidEntryPoint
+class SimpleReceiver extends BroadcastReceiver {
+  @Override
+  public void onReceive(Context context, Intent intent) {}
 }
diff --git a/java/dagger/hilt/android/plugin/main/src/test/data/simple-project-for-agp-test/feature/build.gradle b/java/dagger/hilt/android/plugin/main/src/test/data/simple-project-for-agp-test/feature/build.gradle
index e19f1d5..57f7a74 100644
--- a/java/dagger/hilt/android/plugin/main/src/test/data/simple-project-for-agp-test/feature/build.gradle
+++ b/java/dagger/hilt/android/plugin/main/src/test/data/simple-project-for-agp-test/feature/build.gradle
@@ -20,12 +20,12 @@
 }
 
 android {
-    compileSdkVersion 32
-    buildToolsVersion "32.0.0"
+    compileSdkVersion 33
+    namespace "simple.library"
 
     defaultConfig {
         minSdkVersion 16
-        targetSdkVersion 32
+        targetSdkVersion 33
     }
 
     compileOptions {
diff --git a/java/dagger/hilt/android/plugin/main/src/test/kotlin/AGPCompatibilityTest.kt b/java/dagger/hilt/android/plugin/main/src/test/kotlin/AGPCompatibilityTest.kt
index d5bc488..f488fb3 100644
--- a/java/dagger/hilt/android/plugin/main/src/test/kotlin/AGPCompatibilityTest.kt
+++ b/java/dagger/hilt/android/plugin/main/src/test/kotlin/AGPCompatibilityTest.kt
@@ -26,11 +26,13 @@
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
 
-const val TASK = ":app:hiltJavaCompileDebug"
+// `hiltJavaCompileDebug` gets to run as well as `transformDebugClassesWithAsm` depends on it.
+const val TASK = ":app:transformDebugClassesWithAsm"
 
 @RunWith(Parameterized::class)
 class AGPCompatibilityTest(
-  private val agpVersion: String
+  private val agpVersion: String,
+  private val gradleVersion: String
 ) {
   @get:Rule val testProjectDir = TemporaryFolder()
 
@@ -75,18 +77,21 @@
       GradleRunner.create()
         .withProjectDir(testProjectDir.root)
         .withArguments(*args)
+        .withGradleVersion(gradleVersion)
         .forwardOutput()
     return gradleRunner.build()
   }
 
   companion object {
     @JvmStatic
-    @Parameterized.Parameters(name = "agpVersion = {0}")
+    @Parameterized.Parameters(name = "agpVersion = {0}, gradleVersion = {1}")
     fun parameters() =
       listOf(
-        arrayOf("7.2.0"),
-        arrayOf("7.1.0"),
-        arrayOf("7.0.0"),
+        // AGP 8.3 requires Gradle 8.4 and JDK 17.
+        arrayOf("8.3.0-alpha11", "8.4"),
+        arrayOf("7.2.0", "7.4.2"),
+        arrayOf("7.1.0", "7.4.2"),
+        arrayOf("7.0.0", "7.4.2"),
       )
   }
 }
diff --git a/java/dagger/hilt/android/plugin/main/src/test/kotlin/BuildCacheTest.kt b/java/dagger/hilt/android/plugin/main/src/test/kotlin/BuildCacheTest.kt
index 4c34dd6..c5a67af 100644
--- a/java/dagger/hilt/android/plugin/main/src/test/kotlin/BuildCacheTest.kt
+++ b/java/dagger/hilt/android/plugin/main/src/test/kotlin/BuildCacheTest.kt
@@ -82,8 +82,6 @@
     val secondResult = secondGradleRunner.build()
     val cacheableTasks: List<String> =
       mutableListOf<String>().apply {
-        add(":checkDebugAarMetadata")
-        add(":checkDebugDuplicateClasses")
         add(":compileDebugJavaWithJavac")
         add(":compressDebugAssets")
         add(":desugarDebugFileDependencies")
@@ -105,9 +103,6 @@
         add(":mergeProjectDexDebug")
         add(":processDebugManifestForPackage")
         add(":transformDebugClassesWithAsm")
-        add(":validateSigningDebug")
-        add(":writeDebugAppMetadata")
-        add(":writeDebugSigningConfigVersions")
       }
 
     val tasksFromCache =
diff --git a/java/dagger/hilt/android/plugin/main/src/test/kotlin/GradleTestRunner.kt b/java/dagger/hilt/android/plugin/main/src/test/kotlin/GradleTestRunner.kt
index fb47bdb..221dfcf 100644
--- a/java/dagger/hilt/android/plugin/main/src/test/kotlin/GradleTestRunner.kt
+++ b/java/dagger/hilt/android/plugin/main/src/test/kotlin/GradleTestRunner.kt
@@ -156,13 +156,13 @@
         }
 
         android {
-          compileSdkVersion 32
-          buildToolsVersion "32.0.0"
+          compileSdkVersion 33
+          buildToolsVersion "33.0.0"
 
           defaultConfig {
             ${ if (isAppProject) "applicationId \"plugin.test\"" else "" }
             minSdkVersion 21
-            targetSdkVersion 32
+            targetSdkVersion 33
           }
 
           compileOptions {
@@ -189,7 +189,8 @@
           ${hiltOptions.joinToString(separator = "\n")}
         }
         ${additionalClosures.joinToString(separator = "\n")}
-        """.trimIndent()
+        """
+            .trimIndent()
         )
       }
   }
@@ -198,9 +199,14 @@
     gradlePropertiesFile?.delete()
     gradlePropertiesFile =
       tempFolder.newFile("gradle.properties").apply {
-        writeText("""
+        writeText(
+          """
         android.useAndroidX=true
-        """.trimIndent())
+        // TODO(b/296583777): See if there's a better way to fix the OOM error.
+        org.gradle.jvmargs=-XX:MaxMetaspaceSize=1g
+        """
+            .trimIndent()
+        )
       }
   }
 
@@ -218,7 +224,8 @@
                 ${activities.joinToString(separator = "\n")}
             </application>
         </manifest>
-        """.trimIndent()
+        """
+            .trimIndent()
         )
       }
   }
diff --git a/java/dagger/hilt/android/plugin/main/src/test/kotlin/IncrementalProcessorTest.kt b/java/dagger/hilt/android/plugin/main/src/test/kotlin/IncrementalProcessorTest.kt
index 1e8490f..4fb25a0 100644
--- a/java/dagger/hilt/android/plugin/main/src/test/kotlin/IncrementalProcessorTest.kt
+++ b/java/dagger/hilt/android/plugin/main/src/test/kotlin/IncrementalProcessorTest.kt
@@ -34,11 +34,9 @@
 @RunWith(Parameterized::class)
 class IncrementalProcessorTest(private val incapMode: String) {
 
-  @get:Rule
-  val testProjectDir = TemporaryFolder()
+  @get:Rule val testProjectDir = TemporaryFolder()
 
-  @get:Rule
-  val expect: Expect = Expect.create()
+  @get:Rule val expect: Expect = Expect.create()
 
   // Original source files
   private lateinit var srcApp: File
@@ -108,16 +106,18 @@
   private lateinit var unchangedFiles: Set<File>
   private lateinit var deletedFiles: Set<File>
 
-  private val compileTaskName = if (incapMode == ISOLATING_MODE) {
-    ":hiltJavaCompileDebug"
-  } else {
-    ":compileDebugJavaWithJavac"
-  }
-  private val testCompileTaskName = if (incapMode == ISOLATING_MODE) {
-    ":hiltJavaCompileDebugUnitTest"
-  } else {
-    ":compileDebugUnitTestJavaWithJavac"
-  }
+  private val compileTaskName =
+    if (incapMode == ISOLATING_MODE) {
+      ":hiltJavaCompileDebug"
+    } else {
+      ":compileDebugJavaWithJavac"
+    }
+  private val testCompileTaskName =
+    if (incapMode == ISOLATING_MODE) {
+      ":hiltJavaCompileDebugUnitTest"
+    } else {
+      ":compileDebugUnitTestJavaWithJavac"
+    }
   private val aggregatingTaskName = ":hiltAggregateDepsDebug"
   private val testAggregatingTaskName = ":hiltAggregateDepsDebugUnitTest"
 
@@ -128,8 +128,9 @@
     File("src/test/data/simple-project").copyRecursively(projectRoot)
 
     // set up build file
-    File(projectRoot, "build.gradle").writeText(
-      """
+    File(projectRoot, "build.gradle")
+      .writeText(
+        """
       buildscript {
         repositories {
           google()
@@ -146,13 +147,13 @@
       }
 
       android {
-        compileSdkVersion 32
-        buildToolsVersion "32.0.0"
+        compileSdkVersion 33
+        buildToolsVersion "33.0.0"
 
         defaultConfig {
           applicationId "hilt.simple"
           minSdkVersion 21
-          targetSdkVersion 32
+          targetSdkVersion 33
           javaCompileOptions {
             annotationProcessorOptions {
                 arguments += ["dagger.hilt.shareTestComponents" : "true"]
@@ -190,32 +191,36 @@
       hilt {
         enableAggregatingTask = ${if (incapMode == ISOLATING_MODE) "true" else "false"}
       }
-      """.trimIndent()
-    )
+      """
+          .trimIndent()
+      )
 
     // Compute directory paths
     val defaultGenSrcDir = "build/generated/ap_generated_sources/debug/out/"
-    fun getComponentTreeDepsGenSrcDir(variant: String) = if (incapMode == ISOLATING_MODE) {
-      "build/generated/hilt/component_trees/$variant/"
-    } else {
-      "build/generated/ap_generated_sources/$variant/out/"
-    }
+    fun getComponentTreeDepsGenSrcDir(variant: String) =
+      if (incapMode == ISOLATING_MODE) {
+        "build/generated/hilt/component_trees/$variant/"
+      } else {
+        "build/generated/ap_generated_sources/$variant/out/"
+      }
     val componentTreeDepsGenSrcDir = getComponentTreeDepsGenSrcDir("debug")
     val testComponentTreeDepsGenSrcDir = getComponentTreeDepsGenSrcDir("debugUnitTest")
-    fun getRootGenSrcDir(variant: String) = if (incapMode == ISOLATING_MODE) {
-      "build/generated/hilt/component_sources/$variant/"
-    } else {
-      "build/generated/ap_generated_sources/$variant/out/"
-    }
+    fun getRootGenSrcDir(variant: String) =
+      if (incapMode == ISOLATING_MODE) {
+        "build/generated/hilt/component_sources/$variant/"
+      } else {
+        "build/generated/ap_generated_sources/$variant/out/"
+      }
     val rootGenSrcDir = getRootGenSrcDir("debug")
     val testRootGenSrcDir = getRootGenSrcDir("debugUnitTest")
     val defaultClassesDir = "build/intermediates/javac/debug/classes"
     val testDefaultClassesDir = "build/intermediates/javac/debugUnitTest/classes"
-    fun getRootClassesDir(variant: String) = if (incapMode == ISOLATING_MODE) {
-      "build/intermediates/hilt/component_classes/$variant/"
-    } else {
-      "build/intermediates/javac/$variant/classes"
-    }
+    fun getRootClassesDir(variant: String) =
+      if (incapMode == ISOLATING_MODE) {
+        "build/intermediates/hilt/component_classes/$variant/"
+      } else {
+        "build/intermediates/javac/$variant/classes"
+      }
     val rootClassesDir = getRootClassesDir("debug")
     val testRootClassesDir = getRootClassesDir("debugUnitTest")
 
@@ -236,59 +241,64 @@
       File(projectRoot, "$defaultGenSrcDir/simple/Activity1_GeneratedInjector.java")
     genActivityInjector2 =
       File(projectRoot, "$defaultGenSrcDir/simple/Activity2_GeneratedInjector.java")
-    genAppInjectorDeps = File(
-      projectRoot,
-      "$defaultGenSrcDir/hilt_aggregated_deps/_simple_SimpleApp_GeneratedInjector.java"
-    )
-    genActivityInjectorDeps1 = File(
-      projectRoot,
-      "$defaultGenSrcDir/hilt_aggregated_deps/_simple_Activity1_GeneratedInjector.java"
-    )
-    genActivityInjectorDeps2 = File(
-      projectRoot,
-      "$defaultGenSrcDir/hilt_aggregated_deps/_simple_Activity2_GeneratedInjector.java"
-    )
-    genModuleDeps1 = File(
-      projectRoot,
-      "$defaultGenSrcDir/hilt_aggregated_deps/_simple_Module1.java"
-    )
+    genAppInjectorDeps =
+      File(
+        projectRoot,
+        "$defaultGenSrcDir/hilt_aggregated_deps/_simple_SimpleApp_GeneratedInjector.java"
+      )
+    genActivityInjectorDeps1 =
+      File(
+        projectRoot,
+        "$defaultGenSrcDir/hilt_aggregated_deps/_simple_Activity1_GeneratedInjector.java"
+      )
+    genActivityInjectorDeps2 =
+      File(
+        projectRoot,
+        "$defaultGenSrcDir/hilt_aggregated_deps/_simple_Activity2_GeneratedInjector.java"
+      )
+    genModuleDeps1 =
+      File(projectRoot, "$defaultGenSrcDir/hilt_aggregated_deps/_simple_Module1.java")
     genModuleDeps2 =
       File(projectRoot, "$defaultGenSrcDir/hilt_aggregated_deps/_simple_Module2.java")
     genComponentTreeDeps =
       File(projectRoot, "$componentTreeDepsGenSrcDir/simple/SimpleApp_ComponentTreeDeps.java")
     genHiltComponents = File(projectRoot, "$rootGenSrcDir/simple/SimpleApp_HiltComponents.java")
-    genDaggerHiltApplicationComponent = File(
-      projectRoot,
-      "$rootGenSrcDir/simple/DaggerSimpleApp_HiltComponents_SingletonC.java"
-    )
-    genTest1ComponentTreeDeps = File(
-      projectRoot,
-      testComponentTreeDepsGenSrcDir +
-        "/dagger/hilt/android/internal/testing/root/Test1_ComponentTreeDeps.java"
-    )
-    genTest2ComponentTreeDeps = File(
-      projectRoot,
-      testComponentTreeDepsGenSrcDir +
-        "/dagger/hilt/android/internal/testing/root/Test2_ComponentTreeDeps.java"
-    )
-    genTest1HiltComponents = File(
-      projectRoot,
-      "$testRootGenSrcDir/dagger/hilt/android/internal/testing/root/Test1_HiltComponents.java"
-    )
-    genTest2HiltComponents = File(
-      projectRoot,
-      "$testRootGenSrcDir/dagger/hilt/android/internal/testing/root/Test2_HiltComponents.java"
-    )
-    genTest1DaggerHiltApplicationComponent = File(
-      projectRoot,
-      testRootGenSrcDir +
-        "/dagger/hilt/android/internal/testing/root/DaggerTest1_HiltComponents_SingletonC.java"
-    )
-    genTest2DaggerHiltApplicationComponent = File(
-      projectRoot,
-      testRootGenSrcDir +
-        "/dagger/hilt/android/internal/testing/root/DaggerTest2_HiltComponents_SingletonC.java"
-    )
+    genDaggerHiltApplicationComponent =
+      File(projectRoot, "$rootGenSrcDir/simple/DaggerSimpleApp_HiltComponents_SingletonC.java")
+    genTest1ComponentTreeDeps =
+      File(
+        projectRoot,
+        testComponentTreeDepsGenSrcDir +
+          "/dagger/hilt/android/internal/testing/root/Test1_ComponentTreeDeps.java"
+      )
+    genTest2ComponentTreeDeps =
+      File(
+        projectRoot,
+        testComponentTreeDepsGenSrcDir +
+          "/dagger/hilt/android/internal/testing/root/Test2_ComponentTreeDeps.java"
+      )
+    genTest1HiltComponents =
+      File(
+        projectRoot,
+        "$testRootGenSrcDir/dagger/hilt/android/internal/testing/root/Test1_HiltComponents.java"
+      )
+    genTest2HiltComponents =
+      File(
+        projectRoot,
+        "$testRootGenSrcDir/dagger/hilt/android/internal/testing/root/Test2_HiltComponents.java"
+      )
+    genTest1DaggerHiltApplicationComponent =
+      File(
+        projectRoot,
+        testRootGenSrcDir +
+          "/dagger/hilt/android/internal/testing/root/DaggerTest1_HiltComponents_SingletonC.java"
+      )
+    genTest2DaggerHiltApplicationComponent =
+      File(
+        projectRoot,
+        testRootGenSrcDir +
+          "/dagger/hilt/android/internal/testing/root/DaggerTest2_HiltComponents_SingletonC.java"
+      )
 
     classSrcApp = File(projectRoot, "$defaultClassesDir/simple/SimpleApp.class")
     classSrcActivity1 = File(projectRoot, "$defaultClassesDir/simple/Activity1.class")
@@ -302,70 +312,69 @@
     classGenHiltActivity2 = File(projectRoot, "$defaultClassesDir/simple/Hilt_Activity2.class")
     classGenAppInjector =
       File(projectRoot, "$defaultClassesDir/simple/SimpleApp_GeneratedInjector.class")
-    classGenActivityInjector1 = File(
-      projectRoot,
-      "$defaultClassesDir/simple/Activity1_GeneratedInjector.class"
-    )
-    classGenActivityInjector2 = File(
-      projectRoot,
-      "$defaultClassesDir/simple/Activity2_GeneratedInjector.class"
-    )
-    classGenAppInjectorDeps = File(
-      projectRoot,
-      "$defaultClassesDir/hilt_aggregated_deps/_simple_SimpleApp_GeneratedInjector.class"
-    )
-    classGenActivityInjectorDeps1 = File(
-      projectRoot,
-      "$defaultClassesDir/hilt_aggregated_deps/_simple_Activity1_GeneratedInjector.class"
-    )
-    classGenActivityInjectorDeps2 = File(
-      projectRoot,
-      "$defaultClassesDir/hilt_aggregated_deps/_simple_Activity2_GeneratedInjector.class"
-    )
+    classGenActivityInjector1 =
+      File(projectRoot, "$defaultClassesDir/simple/Activity1_GeneratedInjector.class")
+    classGenActivityInjector2 =
+      File(projectRoot, "$defaultClassesDir/simple/Activity2_GeneratedInjector.class")
+    classGenAppInjectorDeps =
+      File(
+        projectRoot,
+        "$defaultClassesDir/hilt_aggregated_deps/_simple_SimpleApp_GeneratedInjector.class"
+      )
+    classGenActivityInjectorDeps1 =
+      File(
+        projectRoot,
+        "$defaultClassesDir/hilt_aggregated_deps/_simple_Activity1_GeneratedInjector.class"
+      )
+    classGenActivityInjectorDeps2 =
+      File(
+        projectRoot,
+        "$defaultClassesDir/hilt_aggregated_deps/_simple_Activity2_GeneratedInjector.class"
+      )
     classGenModuleDeps1 =
       File(projectRoot, "$defaultClassesDir/hilt_aggregated_deps/_simple_Module1.class")
     classGenModuleDeps2 =
       File(projectRoot, "$defaultClassesDir/hilt_aggregated_deps/_simple_Module2.class")
-    classGenComponentTreeDeps = File(
-      projectRoot,
-      "$rootClassesDir/simple/SimpleApp_ComponentTreeDeps.class"
-    )
-    classGenHiltComponents = File(
-      projectRoot,
-      "$rootClassesDir/simple/SimpleApp_HiltComponents.class"
-    )
-    classGenDaggerHiltApplicationComponent = File(
-      projectRoot,
-      "$rootClassesDir/simple/DaggerSimpleApp_HiltComponents_SingletonC.class"
-    )
-    classGenTest1ComponentTreeDeps = File(
-      projectRoot,
-      testRootClassesDir +
-        "/dagger/hilt/android/internal/testing/root/Test1_ComponentTreeDeps.class"
-    )
-    classGenTest2ComponentTreeDeps = File(
-      projectRoot,
-      testRootClassesDir +
-        "/dagger/hilt/android/internal/testing/root/Test2_ComponentTreeDeps.class"
-    )
-    classGenTest1HiltComponents = File(
-      projectRoot,
-      "$testRootClassesDir/dagger/hilt/android/internal/testing/root/Test1_HiltComponents.class"
-    )
-    classGenTest2HiltComponents = File(
-      projectRoot,
-      "$testRootClassesDir/dagger/hilt/android/internal/testing/root/Test2_HiltComponents.class"
-    )
-    classGenTest1DaggerHiltApplicationComponent = File(
-      projectRoot,
-      testRootClassesDir +
-        "/dagger/hilt/android/internal/testing/root/DaggerTest1_HiltComponents_SingletonC.class"
-    )
-    classGenTest2DaggerHiltApplicationComponent = File(
-      projectRoot,
-      testRootClassesDir +
-        "/dagger/hilt/android/internal/testing/root/DaggerTest2_HiltComponents_SingletonC.class"
-    )
+    classGenComponentTreeDeps =
+      File(projectRoot, "$rootClassesDir/simple/SimpleApp_ComponentTreeDeps.class")
+    classGenHiltComponents =
+      File(projectRoot, "$rootClassesDir/simple/SimpleApp_HiltComponents.class")
+    classGenDaggerHiltApplicationComponent =
+      File(projectRoot, "$rootClassesDir/simple/DaggerSimpleApp_HiltComponents_SingletonC.class")
+    classGenTest1ComponentTreeDeps =
+      File(
+        projectRoot,
+        testRootClassesDir +
+          "/dagger/hilt/android/internal/testing/root/Test1_ComponentTreeDeps.class"
+      )
+    classGenTest2ComponentTreeDeps =
+      File(
+        projectRoot,
+        testRootClassesDir +
+          "/dagger/hilt/android/internal/testing/root/Test2_ComponentTreeDeps.class"
+      )
+    classGenTest1HiltComponents =
+      File(
+        projectRoot,
+        "$testRootClassesDir/dagger/hilt/android/internal/testing/root/Test1_HiltComponents.class"
+      )
+    classGenTest2HiltComponents =
+      File(
+        projectRoot,
+        "$testRootClassesDir/dagger/hilt/android/internal/testing/root/Test2_HiltComponents.class"
+      )
+    classGenTest1DaggerHiltApplicationComponent =
+      File(
+        projectRoot,
+        testRootClassesDir +
+          "/dagger/hilt/android/internal/testing/root/DaggerTest1_HiltComponents_SingletonC.class"
+      )
+    classGenTest2DaggerHiltApplicationComponent =
+      File(
+        projectRoot,
+        testRootClassesDir +
+          "/dagger/hilt/android/internal/testing/root/DaggerTest2_HiltComponents_SingletonC.class"
+      )
   }
 
   @Test
@@ -428,13 +437,15 @@
 
     // Change Activity 1 source
     searchAndReplace(
-      srcActivity1, "// Insert-change",
+      srcActivity1,
+      "// Insert-change",
       """
       @Override
       public void onResume() {
         super.onResume();
       }
-      """.trimIndent()
+      """
+        .trimIndent()
     )
 
     val result = runIncrementalBuild()
@@ -442,66 +453,69 @@
 
     // Check annotation processing outputs
     // * Only activity 1 sources are re-generated, isolation in modules and from other activities
-    val regeneratedSourceFiles = if (incapMode == ISOLATING_MODE) {
-      // * Aggregating task did not run, no change in deps
-      expect.that(result.task(aggregatingTaskName)!!.outcome).isEqualTo(TaskOutcome.UP_TO_DATE)
-      // * Components are re-generated due to a recompilation of a dep
-      listOf(
-        genHiltApp, // Re-gen because components got re-gen
-        genHiltActivity1,
-        genActivityInjector1,
-        genActivityInjectorDeps1,
-        genHiltComponents,
-        genDaggerHiltApplicationComponent
-      )
-    } else {
-      // * Root classes along with components are always re-generated (aggregated processor)
-      listOf(
-        genHiltApp,
-        genHiltActivity1,
-        genAppInjector,
-        genActivityInjector1,
-        genAppInjectorDeps,
-        genActivityInjectorDeps1,
-        genComponentTreeDeps,
-        genHiltComponents,
-        genDaggerHiltApplicationComponent
-      )
-    }
+    val regeneratedSourceFiles =
+      if (incapMode == ISOLATING_MODE) {
+        // * Aggregating task did not run, no change in deps
+        expect.that(result.task(aggregatingTaskName)!!.outcome).isEqualTo(TaskOutcome.UP_TO_DATE)
+        // * Components are re-generated due to a recompilation of a dep
+        listOf(
+          genHiltApp, // Re-gen because components got re-gen
+          genHiltActivity1,
+          genActivityInjector1,
+          genActivityInjectorDeps1,
+          genHiltComponents,
+          genDaggerHiltApplicationComponent
+        )
+      } else {
+        // * Root classes along with components are always re-generated (aggregated processor)
+        listOf(
+          genHiltApp,
+          genHiltActivity1,
+          genAppInjector,
+          genActivityInjector1,
+          genAppInjectorDeps,
+          genActivityInjectorDeps1,
+          genComponentTreeDeps,
+          genHiltComponents,
+          genDaggerHiltApplicationComponent
+        )
+      }
     assertChangedFiles(FileType.JAVA, regeneratedSourceFiles)
 
     val componentTreeDepsIncrementalBuild = genComponentTreeDeps.readText(Charsets.UTF_8)
-    expect.withMessage("Full build")
-        .that(componentTreeDepsFullBuild)
-        .isEqualTo(componentTreeDepsIncrementalBuild)
+    expect
+      .withMessage("Full build")
+      .that(componentTreeDepsFullBuild)
+      .isEqualTo(componentTreeDepsIncrementalBuild)
 
     // Check compilation outputs
     // * Gen sources from activity 1 are re-compiled
-    val recompiledClassFiles = if (incapMode == ISOLATING_MODE) {
-      listOf(
-        classSrcActivity1,
-        classGenHiltApp,
-        classGenHiltActivity1,
-        classGenActivityInjector1,
-        classGenActivityInjectorDeps1,
-        classGenHiltComponents,
-        classGenDaggerHiltApplicationComponent,
-      )
-    } else {
-      // * All aggregating processor gen sources are re-compiled
-      listOf(
-        classSrcActivity1,
-        classGenHiltApp,
-        classGenHiltActivity1,
-        classGenAppInjector,
-        classGenActivityInjector1,
-        classGenAppInjectorDeps,
-        classGenActivityInjectorDeps1,
-        classGenHiltComponents,
-        classGenComponentTreeDeps,
-        classGenDaggerHiltApplicationComponent
-      )
-    }
+    val recompiledClassFiles =
+      if (incapMode == ISOLATING_MODE) {
+        listOf(
+          classSrcActivity1,
+          classGenHiltApp,
+          classGenHiltActivity1,
+          classGenActivityInjector1,
+          classGenActivityInjectorDeps1,
+          classGenHiltComponents,
+          classGenDaggerHiltApplicationComponent,
+        )
+      } else {
+        // * All aggregating processor gen sources are re-compiled
+        listOf(
+          classSrcActivity1,
+          classGenHiltApp,
+          classGenHiltActivity1,
+          classGenAppInjector,
+          classGenActivityInjector1,
+          classGenAppInjectorDeps,
+          classGenActivityInjectorDeps1,
+          classGenHiltComponents,
+          classGenComponentTreeDeps,
+          classGenDaggerHiltApplicationComponent
+        )
+      }
     assertChangedFiles(FileType.CLASS, recompiledClassFiles)
   }
 
@@ -512,76 +526,82 @@
 
     // Change Activity 1 source
     searchAndReplace(
-      srcActivity1, "// Insert-change",
+      srcActivity1,
+      "// Insert-change",
       """
       private void foo() { }
-      """.trimIndent()
+      """
+        .trimIndent()
     )
 
     val result = runIncrementalBuild()
-    val expectedOutcome = if (incapMode == ISOLATING_MODE) {
-      // In isolating mode, changes that do not affect ABI will not cause re-compilation.
-      TaskOutcome.UP_TO_DATE
-    } else {
-      TaskOutcome.SUCCESS
-    }
+    val expectedOutcome =
+      if (incapMode == ISOLATING_MODE) {
+        // In isolating mode, changes that do not affect ABI will not cause re-compilation.
+        TaskOutcome.UP_TO_DATE
+      } else {
+        TaskOutcome.SUCCESS
+      }
     expect.that(result.task(compileTaskName)!!.outcome).isEqualTo(expectedOutcome)
 
     // Check annotation processing outputs
     // * Only activity 1 sources are re-generated, isolation in modules and from other activities
-    val regeneratedSourceFiles = if (incapMode == ISOLATING_MODE) {
-      // * Aggregating task did not run, no change in deps
-      expect.that(result.task(aggregatingTaskName)!!.outcome).isEqualTo(TaskOutcome.UP_TO_DATE)
-      listOf(
-        genHiltActivity1,
-        genActivityInjector1,
-        genActivityInjectorDeps1,
-      )
-    } else {
-      // * Root classes along with components are always re-generated (aggregated processor)
-      listOf(
-        genHiltApp,
-        genHiltActivity1,
-        genAppInjector,
-        genActivityInjector1,
-        genAppInjectorDeps,
-        genActivityInjectorDeps1,
-        genComponentTreeDeps,
-        genHiltComponents,
-        genDaggerHiltApplicationComponent
-      )
-    }
+    val regeneratedSourceFiles =
+      if (incapMode == ISOLATING_MODE) {
+        // * Aggregating task did not run, no change in deps
+        expect.that(result.task(aggregatingTaskName)!!.outcome).isEqualTo(TaskOutcome.UP_TO_DATE)
+        listOf(
+          genHiltActivity1,
+          genActivityInjector1,
+          genActivityInjectorDeps1,
+        )
+      } else {
+        // * Root classes along with components are always re-generated (aggregated processor)
+        listOf(
+          genHiltApp,
+          genHiltActivity1,
+          genAppInjector,
+          genActivityInjector1,
+          genAppInjectorDeps,
+          genActivityInjectorDeps1,
+          genComponentTreeDeps,
+          genHiltComponents,
+          genDaggerHiltApplicationComponent
+        )
+      }
     assertChangedFiles(FileType.JAVA, regeneratedSourceFiles)
 
     val componentTreeDepsIncrementalBuild = genComponentTreeDeps.readText(Charsets.UTF_8)
-    expect.withMessage("Full build")
-        .that(componentTreeDepsFullBuild)
-        .isEqualTo(componentTreeDepsIncrementalBuild)
+    expect
+      .withMessage("Full build")
+      .that(componentTreeDepsFullBuild)
+      .isEqualTo(componentTreeDepsIncrementalBuild)
 
     // Check compilation outputs
     // * Gen sources from activity 1 are re-compiled
-    val recompiledClassFiles = if (incapMode == ISOLATING_MODE) {
-      listOf(
-        classSrcActivity1,
-        classGenHiltActivity1,
-        classGenActivityInjector1,
-        classGenActivityInjectorDeps1
-      )
-    } else {
-      // * All aggregating processor gen sources are re-compiled
-      listOf(
-        classSrcActivity1,
-        classGenHiltApp,
-        classGenHiltActivity1,
-        classGenAppInjector,
-        classGenActivityInjector1,
-        classGenAppInjectorDeps,
-        classGenActivityInjectorDeps1,
-        classGenComponentTreeDeps,
-        classGenHiltComponents,
-        classGenDaggerHiltApplicationComponent
-      )
-    }
+    val recompiledClassFiles =
+      if (incapMode == ISOLATING_MODE) {
+        listOf(
+          classSrcActivity1,
+          classGenHiltActivity1,
+          classGenActivityInjector1,
+          classGenActivityInjectorDeps1
+        )
+      } else {
+        // * All aggregating processor gen sources are re-compiled
+        listOf(
+          classSrcActivity1,
+          classGenHiltApp,
+          classGenHiltActivity1,
+          classGenAppInjector,
+          classGenActivityInjector1,
+          classGenAppInjectorDeps,
+          classGenActivityInjectorDeps1,
+          classGenComponentTreeDeps,
+          classGenHiltComponents,
+          classGenDaggerHiltApplicationComponent
+        )
+      }
     assertChangedFiles(FileType.CLASS, recompiledClassFiles)
   }
 
@@ -592,13 +612,15 @@
 
     // Change Module 1 source
     searchAndReplace(
-      srcModule1, "// Insert-change",
+      srcModule1,
+      "// Insert-change",
       """
       @Provides
       static double provideDouble() {
         return 10.10;
       }
-      """.trimIndent()
+      """
+        .trimIndent()
     )
 
     val result = runIncrementalBuild()
@@ -606,58 +628,61 @@
 
     // Check annotation processing outputs
     // * Only module 1 sources are re-generated, isolation from other modules
-    val regeneratedSourceFiles = if (incapMode == ISOLATING_MODE) {
-      // * Aggregating task did not run, no change in deps
-      expect.that(result.task(aggregatingTaskName)!!.outcome).isEqualTo(TaskOutcome.UP_TO_DATE)
-      // * Components are re-generated due to a recompilation of a dep
-      listOf(
-        genHiltApp, // Re-generated because components got re-generated
-        genModuleDeps1,
-        genHiltComponents,
-        genDaggerHiltApplicationComponent
-      )
-    } else {
-      // * Root classes along with components are always re-generated (aggregated processor)
-      listOf(
-        genHiltApp,
-        genAppInjector,
-        genAppInjectorDeps,
-        genModuleDeps1,
-        genComponentTreeDeps,
-        genHiltComponents,
-        genDaggerHiltApplicationComponent
-      )
-    }
+    val regeneratedSourceFiles =
+      if (incapMode == ISOLATING_MODE) {
+        // * Aggregating task did not run, no change in deps
+        expect.that(result.task(aggregatingTaskName)!!.outcome).isEqualTo(TaskOutcome.UP_TO_DATE)
+        // * Components are re-generated due to a recompilation of a dep
+        listOf(
+          genHiltApp, // Re-generated because components got re-generated
+          genModuleDeps1,
+          genHiltComponents,
+          genDaggerHiltApplicationComponent
+        )
+      } else {
+        // * Root classes along with components are always re-generated (aggregated processor)
+        listOf(
+          genHiltApp,
+          genAppInjector,
+          genAppInjectorDeps,
+          genModuleDeps1,
+          genComponentTreeDeps,
+          genHiltComponents,
+          genDaggerHiltApplicationComponent
+        )
+      }
     assertChangedFiles(FileType.JAVA, regeneratedSourceFiles)
 
     val componentTreeDepsIncrementalBuild = genComponentTreeDeps.readText(Charsets.UTF_8)
-    expect.withMessage("Full build")
-        .that(componentTreeDepsFullBuild)
-        .isEqualTo(componentTreeDepsIncrementalBuild)
+    expect
+      .withMessage("Full build")
+      .that(componentTreeDepsFullBuild)
+      .isEqualTo(componentTreeDepsIncrementalBuild)
 
     // Check compilation outputs
     // * Gen sources from module 1 are re-compiled
-    val recompiledClassFiles = if (incapMode == ISOLATING_MODE) {
-      listOf(
-        classSrcModule1,
-        classGenHiltApp,
-        classGenModuleDeps1,
-        classGenHiltComponents,
-        classGenDaggerHiltApplicationComponent
-      )
-    } else {
-      // * All aggregating processor gen sources are re-compiled
-      listOf(
-        classSrcModule1,
-        classGenHiltApp,
-        classGenAppInjector,
-        classGenAppInjectorDeps,
-        classGenModuleDeps1,
-        classGenComponentTreeDeps,
-        classGenHiltComponents,
-        classGenDaggerHiltApplicationComponent
-      )
-    }
+    val recompiledClassFiles =
+      if (incapMode == ISOLATING_MODE) {
+        listOf(
+          classSrcModule1,
+          classGenHiltApp,
+          classGenModuleDeps1,
+          classGenHiltComponents,
+          classGenDaggerHiltApplicationComponent
+        )
+      } else {
+        // * All aggregating processor gen sources are re-compiled
+        listOf(
+          classSrcModule1,
+          classGenHiltApp,
+          classGenAppInjector,
+          classGenAppInjectorDeps,
+          classGenModuleDeps1,
+          classGenComponentTreeDeps,
+          classGenHiltComponents,
+          classGenDaggerHiltApplicationComponent
+        )
+      }
     assertChangedFiles(FileType.CLASS, recompiledClassFiles)
   }
 
@@ -668,13 +693,15 @@
 
     // Change Application source
     searchAndReplace(
-      srcApp, "// Insert-change",
+      srcApp,
+      "// Insert-change",
       """
       @Override
       public void onCreate() {
         super.onCreate();
       }
-      """.trimIndent()
+      """
+        .trimIndent()
     )
 
     val result = runIncrementalBuild()
@@ -682,57 +709,60 @@
 
     // Check annotation processing outputs
     // * No modules or activities (or any other non-root) classes should be generated
-    val regeneratedSourceFiles = if (incapMode == ISOLATING_MODE) {
-      // * Aggregating task did not run, no change in deps
-      expect.that(result.task(aggregatingTaskName)!!.outcome).isEqualTo(TaskOutcome.UP_TO_DATE)
-      // * Components are re-generated due to a recompilation of a dep
-      listOf(
-        genHiltApp, // Re-generated because components got re-generated
-        genAppInjector,
-        genAppInjectorDeps,
-        genHiltComponents,
-        genDaggerHiltApplicationComponent
-      )
-    } else {
-      // * Root classes along with components are always re-generated (aggregated processor)
-      listOf(
-        genHiltApp,
-        genAppInjector,
-        genAppInjectorDeps,
-        genComponentTreeDeps,
-        genHiltComponents,
-        genDaggerHiltApplicationComponent
-      )
-    }
+    val regeneratedSourceFiles =
+      if (incapMode == ISOLATING_MODE) {
+        // * Aggregating task did not run, no change in deps
+        expect.that(result.task(aggregatingTaskName)!!.outcome).isEqualTo(TaskOutcome.UP_TO_DATE)
+        // * Components are re-generated due to a recompilation of a dep
+        listOf(
+          genHiltApp, // Re-generated because components got re-generated
+          genAppInjector,
+          genAppInjectorDeps,
+          genHiltComponents,
+          genDaggerHiltApplicationComponent
+        )
+      } else {
+        // * Root classes along with components are always re-generated (aggregated processor)
+        listOf(
+          genHiltApp,
+          genAppInjector,
+          genAppInjectorDeps,
+          genComponentTreeDeps,
+          genHiltComponents,
+          genDaggerHiltApplicationComponent
+        )
+      }
     assertChangedFiles(FileType.JAVA, regeneratedSourceFiles)
 
     val componentTreeDepsIncrementalBuild = genComponentTreeDeps.readText(Charsets.UTF_8)
-    expect.withMessage("Full build")
-        .that(componentTreeDepsFullBuild)
-        .isEqualTo(componentTreeDepsIncrementalBuild)
+    expect
+      .withMessage("Full build")
+      .that(componentTreeDepsFullBuild)
+      .isEqualTo(componentTreeDepsIncrementalBuild)
 
     // Check compilation outputs
-    val recompiledClassFiles = if (incapMode == ISOLATING_MODE) {
-      listOf(
-        classSrcApp,
-        classGenHiltApp,
-        classGenAppInjector,
-        classGenAppInjectorDeps,
-        classGenHiltComponents,
-        classGenDaggerHiltApplicationComponent
-      )
-    } else {
-      // * All aggregating processor gen sources are re-compiled
-      listOf(
-        classSrcApp,
-        classGenHiltApp,
-        classGenAppInjector,
-        classGenAppInjectorDeps,
-        classGenComponentTreeDeps,
-        classGenHiltComponents,
-        classGenDaggerHiltApplicationComponent
-      )
-    }
+    val recompiledClassFiles =
+      if (incapMode == ISOLATING_MODE) {
+        listOf(
+          classSrcApp,
+          classGenHiltApp,
+          classGenAppInjector,
+          classGenAppInjectorDeps,
+          classGenHiltComponents,
+          classGenDaggerHiltApplicationComponent
+        )
+      } else {
+        // * All aggregating processor gen sources are re-compiled
+        listOf(
+          classSrcApp,
+          classGenHiltApp,
+          classGenAppInjector,
+          classGenAppInjectorDeps,
+          classGenComponentTreeDeps,
+          classGenHiltComponents,
+          classGenDaggerHiltApplicationComponent
+        )
+      }
     assertChangedFiles(FileType.CLASS, recompiledClassFiles)
   }
 
@@ -749,33 +779,28 @@
     // * All related gen classes from activity 2 should be deleted
     // * Unrelated activities and modules are in isolation and should be unchanged
     // * Root classes along with components are always re-generated (aggregated processor)
-    assertDeletedFiles(
-      listOf(
-        genHiltActivity2,
-        genActivityInjector2,
-        genActivityInjectorDeps2
-      )
-    )
-    val regeneratedSourceFiles = if (incapMode == ISOLATING_MODE) {
-      // * Aggregating task ran due to a change in dep
-      expect.that(result.task(aggregatingTaskName)!!.outcome).isEqualTo(TaskOutcome.SUCCESS)
-      // * Components are re-generated since there was a change in dep
-      listOf(
-        genHiltApp, // Re-generated because components got re-generated
-        genComponentTreeDeps,
-        genHiltComponents,
-        genDaggerHiltApplicationComponent
-      )
-    } else {
-      listOf(
-        genHiltApp,
-        genAppInjector,
-        genAppInjectorDeps,
-        genComponentTreeDeps,
-        genHiltComponents,
-        genDaggerHiltApplicationComponent
-      )
-    }
+    assertDeletedFiles(listOf(genHiltActivity2, genActivityInjector2, genActivityInjectorDeps2))
+    val regeneratedSourceFiles =
+      if (incapMode == ISOLATING_MODE) {
+        // * Aggregating task ran due to a change in dep
+        expect.that(result.task(aggregatingTaskName)!!.outcome).isEqualTo(TaskOutcome.SUCCESS)
+        // * Components are re-generated since there was a change in dep
+        listOf(
+          genHiltApp, // Re-generated because components got re-generated
+          genComponentTreeDeps,
+          genHiltComponents,
+          genDaggerHiltApplicationComponent
+        )
+      } else {
+        listOf(
+          genHiltApp,
+          genAppInjector,
+          genAppInjectorDeps,
+          genComponentTreeDeps,
+          genHiltComponents,
+          genDaggerHiltApplicationComponent
+        )
+      }
     assertChangedFiles(FileType.JAVA, regeneratedSourceFiles)
 
     // Check compilation outputs
@@ -789,23 +814,24 @@
         classGenActivityInjectorDeps2
       )
     )
-    val recompiledClassFiles = if (incapMode == ISOLATING_MODE) {
-      listOf(
-        classGenHiltApp,
-        classGenComponentTreeDeps,
-        classGenHiltComponents,
-        classGenDaggerHiltApplicationComponent
-      )
-    } else {
-      listOf(
-        classGenHiltApp,
-        classGenAppInjector,
-        classGenAppInjectorDeps,
-        classGenComponentTreeDeps,
-        classGenHiltComponents,
-        classGenDaggerHiltApplicationComponent
-      )
-    }
+    val recompiledClassFiles =
+      if (incapMode == ISOLATING_MODE) {
+        listOf(
+          classGenHiltApp,
+          classGenComponentTreeDeps,
+          classGenHiltComponents,
+          classGenDaggerHiltApplicationComponent
+        )
+      } else {
+        listOf(
+          classGenHiltApp,
+          classGenAppInjector,
+          classGenAppInjectorDeps,
+          classGenComponentTreeDeps,
+          classGenHiltComponents,
+          classGenDaggerHiltApplicationComponent
+        )
+      }
     assertChangedFiles(FileType.CLASS, recompiledClassFiles)
   }
 
@@ -822,58 +848,53 @@
     // * All related gen classes from module 2 should be deleted
     // * Unrelated activities and modules are in isolation and should be unchanged
 
-    assertDeletedFiles(
-      listOf(genModuleDeps2)
-    )
-    val regeneratedSourceFiles = if (incapMode == ISOLATING_MODE) {
-      // * Aggregating task ran due to a change in dep
-      expect.that(result.task(aggregatingTaskName)!!.outcome).isEqualTo(TaskOutcome.SUCCESS)
-      // * Components are re-generated since there was a change in dep
-      listOf(
-        genHiltApp, // Re-generated because components got re-generated
-        genComponentTreeDeps,
-        genHiltComponents,
-        genDaggerHiltApplicationComponent
-      )
-    } else {
-      // * Root classes along with components are always re-generated (aggregated processor)
-      listOf(
-        genHiltApp,
-        genAppInjector,
-        genAppInjectorDeps,
-        genComponentTreeDeps,
-        genHiltComponents,
-        genDaggerHiltApplicationComponent
-      )
-    }
+    assertDeletedFiles(listOf(genModuleDeps2))
+    val regeneratedSourceFiles =
+      if (incapMode == ISOLATING_MODE) {
+        // * Aggregating task ran due to a change in dep
+        expect.that(result.task(aggregatingTaskName)!!.outcome).isEqualTo(TaskOutcome.SUCCESS)
+        // * Components are re-generated since there was a change in dep
+        listOf(
+          genHiltApp, // Re-generated because components got re-generated
+          genComponentTreeDeps,
+          genHiltComponents,
+          genDaggerHiltApplicationComponent
+        )
+      } else {
+        // * Root classes along with components are always re-generated (aggregated processor)
+        listOf(
+          genHiltApp,
+          genAppInjector,
+          genAppInjectorDeps,
+          genComponentTreeDeps,
+          genHiltComponents,
+          genDaggerHiltApplicationComponent
+        )
+      }
     assertChangedFiles(FileType.JAVA, regeneratedSourceFiles)
 
     // Check compilation outputs
     // * All compiled classes from module 2 should be deleted
     // * Unrelated activities and modules are in isolation and should be unchanged
-    assertDeletedFiles(
-      listOf(
-        classSrcModule2,
-        classGenModuleDeps2
-      )
-    )
-    val recompiledClassFiles = if (incapMode == ISOLATING_MODE) {
-      listOf(
-        classGenHiltApp,
-        classGenComponentTreeDeps,
-        classGenHiltComponents,
-        classGenDaggerHiltApplicationComponent
-      )
-    } else {
-      listOf(
-        classGenHiltApp,
-        classGenAppInjector,
-        classGenAppInjectorDeps,
-        classGenComponentTreeDeps,
-        classGenHiltComponents,
-        classGenDaggerHiltApplicationComponent
-      )
-    }
+    assertDeletedFiles(listOf(classSrcModule2, classGenModuleDeps2))
+    val recompiledClassFiles =
+      if (incapMode == ISOLATING_MODE) {
+        listOf(
+          classGenHiltApp,
+          classGenComponentTreeDeps,
+          classGenHiltComponents,
+          classGenDaggerHiltApplicationComponent
+        )
+      } else {
+        listOf(
+          classGenHiltApp,
+          classGenAppInjector,
+          classGenAppInjectorDeps,
+          classGenComponentTreeDeps,
+          classGenHiltComponents,
+          classGenDaggerHiltApplicationComponent
+        )
+      }
     assertChangedFiles(FileType.CLASS, recompiledClassFiles)
   }
 
@@ -887,48 +908,52 @@
         package simple;
 
         public class Foo { }
-      """.trimIndent()
+      """
+        .trimIndent()
     )
 
     val result = runIncrementalBuild()
-    val expectedOutcome = if (incapMode == ISOLATING_MODE) {
-      // In isolating mode, component compile task does not re-compile.
-      TaskOutcome.UP_TO_DATE
-    } else {
-      TaskOutcome.SUCCESS
-    }
+    val expectedOutcome =
+      if (incapMode == ISOLATING_MODE) {
+        // In isolating mode, component compile task does not re-compile.
+        TaskOutcome.UP_TO_DATE
+      } else {
+        TaskOutcome.SUCCESS
+      }
     expect.that(result.task(compileTaskName)!!.outcome).isEqualTo(expectedOutcome)
 
-    val regeneratedSourceFiles = if (incapMode == ISOLATING_MODE) {
-      // * Aggregating task did not run, no change in deps
-      expect.that(result.task(aggregatingTaskName)!!.outcome).isEqualTo(TaskOutcome.UP_TO_DATE)
-      // * Non-DI related source causes no files to be generated
-      emptyList()
-    } else {
-      // * Root classes are always re-generated (aggregated processor)
-      listOf(
-        genHiltApp,
-        genAppInjector,
-        genAppInjectorDeps,
-        genComponentTreeDeps,
-        genHiltComponents,
-        genDaggerHiltApplicationComponent
-      )
-    }
+    val regeneratedSourceFiles =
+      if (incapMode == ISOLATING_MODE) {
+        // * Aggregating task did not run, no change in deps
+        expect.that(result.task(aggregatingTaskName)!!.outcome).isEqualTo(TaskOutcome.UP_TO_DATE)
+        // * Non-DI related source causes no files to be generated
+        emptyList()
+      } else {
+        // * Root classes are always re-generated (aggregated processor)
+        listOf(
+          genHiltApp,
+          genAppInjector,
+          genAppInjectorDeps,
+          genComponentTreeDeps,
+          genHiltComponents,
+          genDaggerHiltApplicationComponent
+        )
+      }
     assertChangedFiles(FileType.JAVA, regeneratedSourceFiles)
 
-    val recompiledClassFiles = if (incapMode == ISOLATING_MODE) {
-      emptyList()
-    } else {
-      listOf(
-        classGenHiltApp,
-        classGenAppInjector,
-        classGenAppInjectorDeps,
-        classGenComponentTreeDeps,
-        classGenHiltComponents,
-        classGenDaggerHiltApplicationComponent
-      )
-    }
+    val recompiledClassFiles =
+      if (incapMode == ISOLATING_MODE) {
+        emptyList()
+      } else {
+        listOf(
+          classGenHiltApp,
+          classGenAppInjector,
+          classGenAppInjectorDeps,
+          classGenComponentTreeDeps,
+          classGenHiltComponents,
+          classGenDaggerHiltApplicationComponent
+        )
+      }
     assertChangedFiles(FileType.CLASS, recompiledClassFiles)
   }
 
@@ -970,11 +995,13 @@
 
     // Change Test 1 source
     searchAndReplace(
-      srcTest1, "// Insert-change",
+      srcTest1,
+      "// Insert-change",
       """
       @Test
       public void newTest() { }
-      """.trimIndent()
+      """
+        .trimIndent()
     )
 
     val result = runIncrementalTestBuild()
@@ -983,49 +1010,53 @@
     // Check annotation processing outputs
     // * Unrelated test components should be unchanged
 
-    val regeneratedSourceFiles = if (incapMode == ISOLATING_MODE) {
-      listOf(
-        genTest1HiltComponents,
-        genTest1DaggerHiltApplicationComponent,
-      )
-    } else {
-      listOf(
-        genTest1ComponentTreeDeps,
-        genTest2ComponentTreeDeps,
-        genTest1HiltComponents,
-        genTest2HiltComponents,
-        genTest1DaggerHiltApplicationComponent,
-        genTest2DaggerHiltApplicationComponent,
-      )
-    }
+    val regeneratedSourceFiles =
+      if (incapMode == ISOLATING_MODE) {
+        listOf(
+          genTest1HiltComponents,
+          genTest1DaggerHiltApplicationComponent,
+        )
+      } else {
+        listOf(
+          genTest1ComponentTreeDeps,
+          genTest2ComponentTreeDeps,
+          genTest1HiltComponents,
+          genTest2HiltComponents,
+          genTest1DaggerHiltApplicationComponent,
+          genTest2DaggerHiltApplicationComponent,
+        )
+      }
     assertChangedFiles(FileType.JAVA, regeneratedSourceFiles)
 
     val test1ComponentTreeDepsIncrementalBuild = genTest1ComponentTreeDeps.readText(Charsets.UTF_8)
     val test2ComponentTreeDepsIncrementalBuild = genTest2ComponentTreeDeps.readText(Charsets.UTF_8)
-    expect.withMessage("Full build")
-        .that(test1ComponentTreeDepsFullBuild)
-        .isEqualTo(test1ComponentTreeDepsIncrementalBuild)
-    expect.withMessage("Full build")
-        .that(test2ComponentTreeDepsFullBuild)
-        .isEqualTo(test2ComponentTreeDepsIncrementalBuild)
+    expect
+      .withMessage("Full build")
+      .that(test1ComponentTreeDepsFullBuild)
+      .isEqualTo(test1ComponentTreeDepsIncrementalBuild)
+    expect
+      .withMessage("Full build")
+      .that(test2ComponentTreeDepsFullBuild)
+      .isEqualTo(test2ComponentTreeDepsIncrementalBuild)
 
-    val recompiledClassFiles = if (incapMode == ISOLATING_MODE) {
-      listOf(
-        classSrcTest1,
-        classGenTest1HiltComponents,
-        classGenTest1DaggerHiltApplicationComponent,
-      )
-    } else {
-      listOf(
-        classSrcTest1,
-        classGenTest1ComponentTreeDeps,
-        classGenTest2ComponentTreeDeps,
-        classGenTest1HiltComponents,
-        classGenTest2HiltComponents,
-        classGenTest1DaggerHiltApplicationComponent,
-        classGenTest2DaggerHiltApplicationComponent,
-      )
-    }
+    val recompiledClassFiles =
+      if (incapMode == ISOLATING_MODE) {
+        listOf(
+          classSrcTest1,
+          classGenTest1HiltComponents,
+          classGenTest1DaggerHiltApplicationComponent,
+        )
+      } else {
+        listOf(
+          classSrcTest1,
+          classGenTest1ComponentTreeDeps,
+          classGenTest2ComponentTreeDeps,
+          classGenTest1HiltComponents,
+          classGenTest2HiltComponents,
+          classGenTest1DaggerHiltApplicationComponent,
+          classGenTest2DaggerHiltApplicationComponent,
+        )
+      }
     assertChangedFiles(FileType.CLASS, recompiledClassFiles)
   }
 
@@ -1037,60 +1068,67 @@
 
     // Change Test 1 source
     searchAndReplace(
-      srcTest1, "// Insert-change",
+      srcTest1,
+      "// Insert-change",
       """
       private void newMethod() { }
-      """.trimIndent()
+      """
+        .trimIndent()
     )
 
     val result = runIncrementalTestBuild()
-    val expectedOutcome = if (incapMode == ISOLATING_MODE) {
-      // In isolating mode, changes that do not affect ABI will not cause re-compilation.
-      TaskOutcome.UP_TO_DATE
-    } else {
-      TaskOutcome.SUCCESS
-    }
+    val expectedOutcome =
+      if (incapMode == ISOLATING_MODE) {
+        // In isolating mode, changes that do not affect ABI will not cause re-compilation.
+        TaskOutcome.UP_TO_DATE
+      } else {
+        TaskOutcome.SUCCESS
+      }
     expect.that(result.task(testCompileTaskName)!!.outcome).isEqualTo(expectedOutcome)
 
     // Check annotation processing outputs
     // * Unrelated test components should be unchanged
 
-    val regeneratedSourceFiles = if (incapMode == ISOLATING_MODE) {
-      emptyList()
-    } else {
-      listOf(
-        genTest1ComponentTreeDeps,
-        genTest2ComponentTreeDeps,
-        genTest1HiltComponents,
-        genTest2HiltComponents,
-        genTest1DaggerHiltApplicationComponent,
-        genTest2DaggerHiltApplicationComponent,
-      )
-    }
+    val regeneratedSourceFiles =
+      if (incapMode == ISOLATING_MODE) {
+        emptyList()
+      } else {
+        listOf(
+          genTest1ComponentTreeDeps,
+          genTest2ComponentTreeDeps,
+          genTest1HiltComponents,
+          genTest2HiltComponents,
+          genTest1DaggerHiltApplicationComponent,
+          genTest2DaggerHiltApplicationComponent,
+        )
+      }
     assertChangedFiles(FileType.JAVA, regeneratedSourceFiles)
 
     val test1ComponentTreeDepsIncrementalBuild = genTest1ComponentTreeDeps.readText(Charsets.UTF_8)
     val test2ComponentTreeDepsIncrementalBuild = genTest2ComponentTreeDeps.readText(Charsets.UTF_8)
-    expect.withMessage("Full build")
-        .that(test1ComponentTreeDepsFullBuild)
-        .isEqualTo(test1ComponentTreeDepsIncrementalBuild)
-    expect.withMessage("Full build")
-        .that(test2ComponentTreeDepsFullBuild)
-        .isEqualTo(test2ComponentTreeDepsIncrementalBuild)
+    expect
+      .withMessage("Full build")
+      .that(test1ComponentTreeDepsFullBuild)
+      .isEqualTo(test1ComponentTreeDepsIncrementalBuild)
+    expect
+      .withMessage("Full build")
+      .that(test2ComponentTreeDepsFullBuild)
+      .isEqualTo(test2ComponentTreeDepsIncrementalBuild)
 
-    val recompiledClassFiles = if (incapMode == ISOLATING_MODE) {
-      listOf(classSrcTest1)
-    } else {
-      listOf(
-        classSrcTest1,
-        classGenTest1ComponentTreeDeps,
-        classGenTest2ComponentTreeDeps,
-        classGenTest1HiltComponents,
-        classGenTest2HiltComponents,
-        classGenTest1DaggerHiltApplicationComponent,
-        classGenTest2DaggerHiltApplicationComponent,
-      )
-    }
+    val recompiledClassFiles =
+      if (incapMode == ISOLATING_MODE) {
+        listOf(classSrcTest1)
+      } else {
+        listOf(
+          classSrcTest1,
+          classGenTest1ComponentTreeDeps,
+          classGenTest2ComponentTreeDeps,
+          classGenTest1HiltComponents,
+          classGenTest2HiltComponents,
+          classGenTest1DaggerHiltApplicationComponent,
+          classGenTest2DaggerHiltApplicationComponent,
+        )
+      }
     assertChangedFiles(FileType.CLASS, recompiledClassFiles)
   }
 
@@ -1129,83 +1167,93 @@
   }
 
   private fun recordTimestamps() {
-    val files = listOf(
-      genHiltApp,
-      genHiltActivity1,
-      genHiltActivity2,
-      genAppInjector,
-      genActivityInjector1,
-      genActivityInjector2,
-      genAppInjectorDeps,
-      genActivityInjectorDeps1,
-      genActivityInjectorDeps2,
-      genModuleDeps1,
-      genModuleDeps2,
-      genComponentTreeDeps,
-      genHiltComponents,
-      genDaggerHiltApplicationComponent,
-      genTest1ComponentTreeDeps,
-      genTest2ComponentTreeDeps,
-      genTest1HiltComponents,
-      genTest2HiltComponents,
-      genTest1DaggerHiltApplicationComponent,
-      genTest2DaggerHiltApplicationComponent,
-      classSrcApp,
-      classSrcActivity1,
-      classSrcActivity2,
-      classSrcModule1,
-      classSrcModule2,
-      classSrcTest1,
-      classSrcTest2,
-      classGenHiltApp,
-      classGenHiltActivity1,
-      classGenHiltActivity2,
-      classGenAppInjector,
-      classGenActivityInjector1,
-      classGenActivityInjector2,
-      classGenAppInjectorDeps,
-      classGenActivityInjectorDeps1,
-      classGenActivityInjectorDeps2,
-      classGenModuleDeps1,
-      classGenModuleDeps2,
-      classGenComponentTreeDeps,
-      classGenHiltComponents,
-      classGenDaggerHiltApplicationComponent,
-      classGenTest1ComponentTreeDeps,
-      classGenTest2ComponentTreeDeps,
-      classGenTest1HiltComponents,
-      classGenTest2HiltComponents,
-      classGenTest1DaggerHiltApplicationComponent,
-      classGenTest2DaggerHiltApplicationComponent,
-    )
+    val files =
+      listOf(
+        genHiltApp,
+        genHiltActivity1,
+        genHiltActivity2,
+        genAppInjector,
+        genActivityInjector1,
+        genActivityInjector2,
+        genAppInjectorDeps,
+        genActivityInjectorDeps1,
+        genActivityInjectorDeps2,
+        genModuleDeps1,
+        genModuleDeps2,
+        genComponentTreeDeps,
+        genHiltComponents,
+        genDaggerHiltApplicationComponent,
+        genTest1ComponentTreeDeps,
+        genTest2ComponentTreeDeps,
+        genTest1HiltComponents,
+        genTest2HiltComponents,
+        genTest1DaggerHiltApplicationComponent,
+        genTest2DaggerHiltApplicationComponent,
+        classSrcApp,
+        classSrcActivity1,
+        classSrcActivity2,
+        classSrcModule1,
+        classSrcModule2,
+        classSrcTest1,
+        classSrcTest2,
+        classGenHiltApp,
+        classGenHiltActivity1,
+        classGenHiltActivity2,
+        classGenAppInjector,
+        classGenActivityInjector1,
+        classGenActivityInjector2,
+        classGenAppInjectorDeps,
+        classGenActivityInjectorDeps1,
+        classGenActivityInjectorDeps2,
+        classGenModuleDeps1,
+        classGenModuleDeps2,
+        classGenComponentTreeDeps,
+        classGenHiltComponents,
+        classGenDaggerHiltApplicationComponent,
+        classGenTest1ComponentTreeDeps,
+        classGenTest2ComponentTreeDeps,
+        classGenTest1HiltComponents,
+        classGenTest2HiltComponents,
+        classGenTest1DaggerHiltApplicationComponent,
+        classGenTest2DaggerHiltApplicationComponent,
+      )
 
-    fileToTimestampMap = mutableMapOf<File, Long>().apply {
-      for (file in files) {
-        this[file] = file.lastModified()
+    fileToTimestampMap =
+      mutableMapOf<File, Long>().apply {
+        for (file in files) {
+          this[file] = file.lastModified()
+        }
       }
-    }
   }
 
   private fun recordFileChanges() {
-    changedFiles = fileToTimestampMap.filter { (file, previousTimestamp) ->
-      file.exists() && file.lastModified() != previousTimestamp
-    }.keys
+    changedFiles =
+      fileToTimestampMap
+        .filter { (file, previousTimestamp) ->
+          file.exists() && file.lastModified() != previousTimestamp
+        }
+        .keys
 
-    unchangedFiles = fileToTimestampMap.filter { (file, previousTimestamp) ->
-      file.exists() && file.lastModified() == previousTimestamp
-    }.keys
+    unchangedFiles =
+      fileToTimestampMap
+        .filter { (file, previousTimestamp) ->
+          file.exists() && file.lastModified() == previousTimestamp
+        }
+        .keys
 
     deletedFiles = fileToTimestampMap.filter { (file, _) -> !file.exists() }.keys
   }
 
   private fun assertFilesExist(files: Collection<File>) {
-    expect.withMessage("Existing files")
+    expect
+      .withMessage("Existing files")
       .that(files.filter { it.exists() })
       .containsExactlyElementsIn(files)
   }
 
   private fun assertChangedFiles(type: FileType, files: Collection<File>) {
-    expect.withMessage("Changed files")
+    expect
+      .withMessage("Changed files")
       .that(changedFiles.filter { it.name.endsWith(type.extension) })
       .containsExactlyElementsIn(files)
   }
@@ -1227,10 +1275,7 @@
 
     @JvmStatic
     @Parameterized.Parameters(name = "{0}")
-    fun parameters() = listOf(
-      ISOLATING_MODE,
-      AGGREGATING_MODE
-    )
+    fun parameters() = listOf(ISOLATING_MODE, AGGREGATING_MODE)
 
     private const val ISOLATING_MODE = "isolating"
     private const val AGGREGATING_MODE = "aggregating"
diff --git a/java/dagger/hilt/android/plugin/settings.gradle b/java/dagger/hilt/android/plugin/settings.gradle
index 55724bf..778bf22 100644
--- a/java/dagger/hilt/android/plugin/settings.gradle
+++ b/java/dagger/hilt/android/plugin/settings.gradle
@@ -21,3 +21,4 @@
 include ':agp-wrapper-7-0'
 include ':agp-wrapper-7-1'
 include ':agp-wrapper-7-2'
+
diff --git a/java/dagger/hilt/android/processor/BUILD b/java/dagger/hilt/android/processor/BUILD
index 6f45216..bf5a6c3 100644
--- a/java/dagger/hilt/android/processor/BUILD
+++ b/java/dagger/hilt/android/processor/BUILD
@@ -52,6 +52,7 @@
         "//java/dagger/hilt/processor/internal:component_names",
         "//java/dagger/hilt/processor/internal:components",
         "//java/dagger/hilt/processor/internal:hilt_processing_env_configs",
+        "//java/dagger/hilt/processor/internal:method_signature",
         "//java/dagger/hilt/processor/internal:processor_errors",
         "//java/dagger/hilt/processor/internal:processors",
         "//java/dagger/hilt/processor/internal/aggregateddeps:component_dependencies",
diff --git a/java/dagger/hilt/android/processor/internal/AndroidClassNames.java b/java/dagger/hilt/android/processor/internal/AndroidClassNames.java
index 2d95448..e37c6b7 100644
--- a/java/dagger/hilt/android/processor/internal/AndroidClassNames.java
+++ b/java/dagger/hilt/android/processor/internal/AndroidClassNames.java
@@ -99,6 +99,10 @@
       get("dagger.hilt.android.internal.managers", "ServiceComponentManager");
   public static final ClassName VIEW_COMPONENT_MANAGER =
       get("dagger.hilt.android.internal.managers", "ViewComponentManager");
+  public static final ClassName SAVED_STATE_HANDLE_ENTRY_POINTS =
+      get("dagger.hilt.android.internal.managers", "SavedStateHandleEntryPoints");
+  public static final ClassName SAVED_STATE_HANDLE_HOLDER =
+      get("dagger.hilt.android.internal.managers", "SavedStateHandleHolder");
 
   public static final ClassName HAS_CUSTOM_INJECT =
       get("dagger.hilt.android.internal.migration", "HasCustomInject");
@@ -114,6 +118,10 @@
       get("dagger.hilt.android.lifecycle", "HiltViewModel");
   public static final ClassName HILT_VIEW_MODEL_MAP_QUALIFIER =
       get("dagger.hilt.android.internal.lifecycle", "HiltViewModelMap");
+
+  public static final ClassName HILT_VIEW_MODEL_ASSISTED_FACTORY_MAP_QUALIFIER =
+      get("dagger.hilt.android.internal.lifecycle", "HiltViewModelAssistedMap");
+
   public static final ClassName HILT_VIEW_MODEL_KEYS_QUALIFIER =
       get("dagger.hilt.android.internal.lifecycle", "HiltViewModelMap", "KeySet");
   public static final ClassName VIEW_MODEL = get("androidx.lifecycle", "ViewModel");
@@ -121,9 +129,13 @@
       get("androidx.lifecycle", "ViewModelProvider", "Factory");
   public static final ClassName SAVED_STATE_HANDLE =
       get("androidx.lifecycle", "SavedStateHandle");
-
+  public static final ClassName DEFAULT_LIFECYCLE_OBSERVER =
+      get("androidx.lifecycle", "DefaultLifecycleObserver");
+  public static final ClassName LIFECYCLE_OWNER = get("androidx.lifecycle", "LifecycleOwner");
   public static final ClassName ON_CONTEXT_AVAILABLE_LISTENER =
       get("androidx.activity.contextaware", "OnContextAvailableListener");
+  public static final ClassName UI_THREAD = get("androidx.annotation", "UiThread");
+
   public static final ClassName INJECT_VIA_ON_CONTEXT_AVAILABLE_LISTENER =
       get("dagger.hilt.android", "InjectViaOnContextAvailableListener");
 
diff --git a/java/dagger/hilt/android/processor/internal/androidentrypoint/ActivityGenerator.java b/java/dagger/hilt/android/processor/internal/androidentrypoint/ActivityGenerator.java
index 49f439e..e1bf74f 100644
--- a/java/dagger/hilt/android/processor/internal/androidentrypoint/ActivityGenerator.java
+++ b/java/dagger/hilt/android/processor/internal/androidentrypoint/ActivityGenerator.java
@@ -16,22 +16,58 @@
 
 package dagger.hilt.android.processor.internal.androidentrypoint;
 
+import static com.google.common.base.Preconditions.checkState;
+import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
+import static kotlin.streams.jdk8.StreamsKt.asStream;
+
 import androidx.room.compiler.processing.JavaPoetExtKt;
+import androidx.room.compiler.processing.XAnnotated;
+import androidx.room.compiler.processing.XExecutableParameterElement;
 import androidx.room.compiler.processing.XFiler;
+import androidx.room.compiler.processing.XMethodElement;
 import androidx.room.compiler.processing.XProcessingEnv;
 import androidx.room.compiler.processing.XTypeParameterElement;
+import com.google.common.base.CaseFormat;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
 import com.squareup.javapoet.ClassName;
 import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.FieldSpec;
 import com.squareup.javapoet.JavaFile;
 import com.squareup.javapoet.MethodSpec;
+import com.squareup.javapoet.ParameterSpec;
+import com.squareup.javapoet.TypeName;
 import com.squareup.javapoet.TypeSpec;
 import dagger.hilt.android.processor.internal.AndroidClassNames;
+import dagger.hilt.processor.internal.ClassNames;
+import dagger.hilt.processor.internal.MethodSignature;
 import dagger.hilt.processor.internal.Processors;
+import dagger.internal.codegen.xprocessing.XElements;
 import java.io.IOException;
 import javax.lang.model.element.Modifier;
+import javax.tools.Diagnostic;
 
 /** Generates an Hilt Activity class for the @AndroidEntryPoint annotated class. */
 public final class ActivityGenerator {
+  private enum ActivityMethod {
+    ON_CREATE(AndroidClassNames.BUNDLE),
+    ON_STOP(),
+    ON_DESTROY();
+
+    @SuppressWarnings("ImmutableEnumChecker")
+    private final MethodSignature signature;
+
+    ActivityMethod(TypeName... parameterTypes) {
+      String methodName = CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, name());
+      this.signature = MethodSignature.of(methodName, parameterTypes);
+    }
+  }
+
+  private static final FieldSpec SAVED_STATE_HANDLE_HOLDER_FIELD =
+      FieldSpec.builder(AndroidClassNames.SAVED_STATE_HANDLE_HOLDER, "savedStateHandleHolder")
+          .addModifiers(Modifier.PRIVATE)
+          .build();
+
   private final XProcessingEnv env;
   private final AndroidEntryPointMetadata metadata;
   private final ClassName generatedClassName;
@@ -61,6 +97,13 @@
           CodeBlock.builder().addStatement("_initHiltInternal()").build(),
           builder);
       builder.addMethod(init());
+      if (!metadata.overridesAndroidEntryPointClass()) {
+        builder
+            .addField(SAVED_STATE_HANDLE_HOLDER_FIELD)
+            .addMethod(initSavedStateHandleHolderMethod())
+            .addMethod(onCreateComponentActivity())
+            .addMethod(onDestroyComponentActivity());
+      }
 
     metadata.baseElement().getTypeParameters().stream()
         .map(XTypeParameterElement::getTypeVariableName)
@@ -133,4 +176,119 @@
             AndroidClassNames.DEFAULT_VIEW_MODEL_FACTORIES)
         .build();
   }
+
+  // @Override
+  // public void onCreate(Bundle bundle) {
+  //   super.onCreate(savedInstanceState);
+  //   initSavedStateHandleHolder();
+  // }
+  //
+  private MethodSpec onCreateComponentActivity() {
+    XMethodElement nearestOverrideMethod =
+        requireNearestOverrideMethod(ActivityMethod.ON_CREATE, metadata);
+    if (nearestOverrideMethod.isFinal()) {
+      env.getMessager()
+          .printMessage(
+              Diagnostic.Kind.ERROR,
+              "Do not mark onCreate as final in base Activity class, as Hilt needs to override it"
+                  + " to inject SavedStateHandle.",
+              nearestOverrideMethod);
+    }
+    ParameterSpec.Builder parameterBuilder =
+        ParameterSpec.builder(AndroidClassNames.BUNDLE, "savedInstanceState");
+    MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder("onCreate");
+    // If the sub class is overriding onCreate with @Nullable parameter, then this generated
+    // method will also prefix the parameter with @Nullable.
+    if (isNullable(nearestOverrideMethod.getParameters().get(0))) {
+      parameterBuilder.addAnnotation(AndroidClassNames.NULLABLE);
+    }
+    if (nearestOverrideMethod.hasAnnotation(AndroidClassNames.UI_THREAD)) {
+      methodBuilder.addAnnotation(AndroidClassNames.UI_THREAD);
+    }
+    return methodBuilder
+        .addAnnotation(AndroidClassNames.CALL_SUPER)
+        .addAnnotation(Override.class)
+        .addModifiers(XElements.getModifiers(nearestOverrideMethod))
+        .addParameter(parameterBuilder.build())
+        .addStatement("super.onCreate(savedInstanceState)")
+        .addStatement("initSavedStateHandleHolder()")
+        .build();
+  }
+
+  // private void initSavedStateHandleHolder() {
+  //   savedStateHandleHolder = componentManager().getSavedStateHandleHolder();
+  //   if (savedStateHandleHolder.isInvalid()) {
+  //     savedStateHandleHolder.setExtras(getDefaultViewModelCreationExtras());
+  //   }
+  // }
+  private static MethodSpec initSavedStateHandleHolderMethod() {
+    return MethodSpec.methodBuilder("initSavedStateHandleHolder")
+        .addModifiers(Modifier.PRIVATE)
+        .beginControlFlow(
+            "if (getApplication() instanceof $T)", ClassNames.GENERATED_COMPONENT_MANAGER)
+        .addStatement(
+            "$N = componentManager().getSavedStateHandleHolder()", SAVED_STATE_HANDLE_HOLDER_FIELD)
+        .beginControlFlow("if ($N.isInvalid())", SAVED_STATE_HANDLE_HOLDER_FIELD)
+        .addStatement(
+            "$N.setExtras(getDefaultViewModelCreationExtras())", SAVED_STATE_HANDLE_HOLDER_FIELD)
+        .endControlFlow()
+        .endControlFlow()
+        .build();
+  }
+
+  private static boolean isNullable(XExecutableParameterElement element) {
+    return hasNullableAnnotation(element) || hasNullableAnnotation(element.getType());
+  }
+
+  private static boolean hasNullableAnnotation(XAnnotated element) {
+    return element.getAllAnnotations().stream()
+        .anyMatch(annotation -> annotation.getClassName().simpleName().equals("Nullable"));
+  }
+
+  // @Override
+  // public void onDestroy() {
+  //   super.onDestroy();
+  //   if (savedStateHandleHolder != null) {
+  //     savedStateHandleHolder.clear();
+  //   }
+  // }
+  private MethodSpec onDestroyComponentActivity() {
+    XMethodElement nearestOverrideMethod =
+        requireNearestOverrideMethod(ActivityMethod.ON_DESTROY, metadata);
+    if (nearestOverrideMethod.isFinal()) {
+      env.getMessager()
+          .printMessage(
+              Diagnostic.Kind.ERROR,
+              "Do not mark onDestroy as final in base Activity class, as Hilt needs to override it"
+                  + " to clean up SavedStateHandle.",
+              nearestOverrideMethod);
+    }
+    return MethodSpec.methodBuilder("onDestroy")
+        .addAnnotation(Override.class)
+        .addModifiers(XElements.getModifiers(nearestOverrideMethod))
+        .addStatement("super.onDestroy()")
+        .beginControlFlow("if ($N != null)", SAVED_STATE_HANDLE_HOLDER_FIELD)
+        .addStatement("$N.clear()", SAVED_STATE_HANDLE_HOLDER_FIELD)
+        .endControlFlow()
+        .build();
+  }
+
+  private static XMethodElement requireNearestOverrideMethod(
+      ActivityMethod activityMethod, AndroidEntryPointMetadata metadata) {
+    XMethodElement methodOnAndroidEntryPointElement =
+        metadata.element().getDeclaredMethods().stream()
+            .filter(method -> MethodSignature.of(method).equals(activityMethod.signature))
+            .findFirst()
+            .orElse(null);
+    if (methodOnAndroidEntryPointElement != null) {
+      return methodOnAndroidEntryPointElement;
+    }
+
+    ImmutableList<XMethodElement> methodOnBaseElement =
+        asStream(metadata.baseElement().getAllMethods())
+            .filter(method -> MethodSignature.of(method).equals(activityMethod.signature))
+            .collect(toImmutableList());
+    checkState(methodOnBaseElement.size() >= 1);
+    return Iterables.getLast(methodOnBaseElement);
+  }
 }
diff --git a/java/dagger/hilt/android/processor/internal/androidentrypoint/AndroidEntryPointMetadata.java b/java/dagger/hilt/android/processor/internal/androidentrypoint/AndroidEntryPointMetadata.java
index 6f925da..71ad88e 100644
--- a/java/dagger/hilt/android/processor/internal/androidentrypoint/AndroidEntryPointMetadata.java
+++ b/java/dagger/hilt/android/processor/internal/androidentrypoint/AndroidEntryPointMetadata.java
@@ -23,7 +23,6 @@
 import static dagger.hilt.processor.internal.HiltCompilerOptions.isAndroidSuperClassValidationDisabled;
 import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
 import static dagger.internal.codegen.xprocessing.XElements.asTypeElement;
-import static dagger.internal.codegen.xprocessing.XTypeElements.isKotlinSource;
 import static dagger.internal.codegen.xprocessing.XTypes.isDeclared;
 
 import androidx.room.compiler.processing.XAnnotation;
@@ -159,7 +158,7 @@
   public Modifier[] generatedClassModifiers() {
     // Note XElement#isPublic() refers to the jvm visibility. Since "internal" visibility is
     // represented as public in the jvm, we have to check XElement#isInternal() explicitly.
-    return isKotlinSource(element()) && element().isPublic() && !element().isInternal()
+    return element().isFromKotlin() && element().isPublic() && !element().isInternal()
         ? new Modifier[] {Modifier.ABSTRACT, Modifier.PUBLIC}
         : new Modifier[] {Modifier.ABSTRACT};
   }
diff --git a/java/dagger/hilt/android/processor/internal/androidentrypoint/BUILD b/java/dagger/hilt/android/processor/internal/androidentrypoint/BUILD
index 96beff3..327412b 100644
--- a/java/dagger/hilt/android/processor/internal/androidentrypoint/BUILD
+++ b/java/dagger/hilt/android/processor/internal/androidentrypoint/BUILD
@@ -71,11 +71,11 @@
         "//java/dagger/hilt/android/processor/internal:android_classnames",
         "//java/dagger/hilt/processor/internal:classnames",
         "//java/dagger/hilt/processor/internal:component_names",
+        "//java/dagger/hilt/processor/internal:method_signature",
         "//java/dagger/hilt/processor/internal:processor_errors",
         "//java/dagger/hilt/processor/internal:processors",
         "//java/dagger/internal/codegen/extension",
         "//java/dagger/internal/codegen/xprocessing",
-        "//third_party/java/auto:common",
         "//third_party/java/guava/base",
         "//third_party/java/guava/collect",
         "//third_party/java/javapoet",
diff --git a/java/dagger/hilt/android/processor/internal/androidentrypoint/BroadcastReceiverGenerator.java b/java/dagger/hilt/android/processor/internal/androidentrypoint/BroadcastReceiverGenerator.java
index 156842b..78a7976 100644
--- a/java/dagger/hilt/android/processor/internal/androidentrypoint/BroadcastReceiverGenerator.java
+++ b/java/dagger/hilt/android/processor/internal/androidentrypoint/BroadcastReceiverGenerator.java
@@ -30,13 +30,12 @@
 import androidx.room.compiler.processing.XTypeParameterElement;
 import com.google.common.collect.ImmutableSet;
 import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.FieldSpec;
 import com.squareup.javapoet.JavaFile;
 import com.squareup.javapoet.MethodSpec;
 import com.squareup.javapoet.ParameterSpec;
-import com.squareup.javapoet.TypeName;
 import com.squareup.javapoet.TypeSpec;
 import dagger.hilt.android.processor.internal.AndroidClassNames;
+import dagger.hilt.processor.internal.ClassNames;
 import dagger.hilt.processor.internal.Processors;
 import dagger.internal.codegen.xprocessing.XExecutableTypes;
 import java.io.IOException;
@@ -69,6 +68,13 @@
             .addModifiers(metadata.generatedClassModifiers())
             .addMethod(onReceiveMethod());
 
+    // Add an annotation used as a marker to let the bytecode injector know this receiver
+    // will need to be injected with a super.onReceive call. This is only necessary if no concrete
+    // onReceive call is implemented in any of the super classes.
+    if (metadata.requiresBytecodeInjection() && !isOnReceiveImplemented(metadata.baseElement())) {
+      builder.addAnnotation(ClassNames.ON_RECEIVE_BYTECODE_INJECTION_MARKER);
+    }
+
     JavaPoetExtKt.addOriginatingElement(builder, metadata.element());
     Generators.addGeneratedBaseClassJavadoc(builder, AndroidClassNames.ANDROID_ENTRY_POINT);
     Processors.addGeneratedAnnotation(builder, env, getClass());
@@ -82,20 +88,6 @@
     Generators.copyLintAnnotations(metadata.element(), builder);
     Generators.copySuppressAnnotations(metadata.element(), builder);
 
-    // Add an unused field used as a marker to let the bytecode injector know this receiver will
-    // need to be injected with a super.onReceive call. This is only necessary if no concrete
-    // onReceive call is implemented in any of the super classes.
-    if (metadata.requiresBytecodeInjection() && !isOnReceiveImplemented(metadata.baseElement())) {
-      builder.addField(
-          FieldSpec.builder(
-                  TypeName.BOOLEAN,
-                  "onReceiveBytecodeInjectionMarker",
-                  Modifier.PRIVATE,
-                  Modifier.FINAL)
-              .initializer("false")
-              .build());
-    }
-
     env.getFiler()
         .write(
             JavaFile.builder(generatedClassName.packageName(), builder.build()).build(),
diff --git a/java/dagger/hilt/android/processor/internal/bindvalue/BindValueMetadata.java b/java/dagger/hilt/android/processor/internal/bindvalue/BindValueMetadata.java
index 00a6402..b597609 100644
--- a/java/dagger/hilt/android/processor/internal/bindvalue/BindValueMetadata.java
+++ b/java/dagger/hilt/android/processor/internal/bindvalue/BindValueMetadata.java
@@ -33,8 +33,6 @@
 import dagger.hilt.processor.internal.ClassNames;
 import dagger.hilt.processor.internal.ProcessorErrors;
 import dagger.hilt.processor.internal.Processors;
-import dagger.hilt.processor.internal.kotlin.KotlinMetadataUtil;
-import dagger.hilt.processor.internal.kotlin.KotlinMetadataUtils;
 import dagger.internal.codegen.xprocessing.XAnnotations;
 import dagger.internal.codegen.xprocessing.XElements;
 import java.util.Collection;
@@ -111,12 +109,7 @@
           XElements.toStableString(element));
 
       XFieldElement field = asField(element);
-
-      KotlinMetadataUtil metadataUtil = KotlinMetadataUtils.getMetadataUtil();
-      Optional<XMethodElement> propertyGetter =
-          metadataUtil.hasMetadata(field)
-              ? metadataUtil.getPropertyGetter(field)
-              : Optional.empty();
+      Optional<XMethodElement> propertyGetter = Optional.ofNullable(field.getGetter());
       if (propertyGetter.isPresent()) {
         ProcessorErrors.checkState(
             !propertyGetter.get().isPrivate(),
diff --git a/java/dagger/hilt/android/processor/internal/viewmodel/BUILD b/java/dagger/hilt/android/processor/internal/viewmodel/BUILD
index f3686a1..90760ea 100644
--- a/java/dagger/hilt/android/processor/internal/viewmodel/BUILD
+++ b/java/dagger/hilt/android/processor/internal/viewmodel/BUILD
@@ -38,6 +38,7 @@
         "//java/dagger/hilt/android/processor/internal:android_classnames",
         "//java/dagger/hilt/processor/internal:base_processor",
         "//java/dagger/hilt/processor/internal:classnames",
+        "//java/dagger/hilt/processor/internal:compiler_options",
         "//java/dagger/hilt/processor/internal:processor_errors",
         "//java/dagger/hilt/processor/internal:processors",
         "//java/dagger/internal/codegen/xprocessing",
@@ -63,6 +64,7 @@
         "//:spi",
         "//java/dagger/hilt/android/processor/internal:android_classnames",
         "//java/dagger/hilt/processor/internal:dagger_models",
+        "//java/dagger/internal/codegen/xprocessing",
         "//third_party/java/auto:service",
         "//third_party/java/guava/graph",
         "//third_party/java/javapoet",
diff --git a/java/dagger/hilt/android/processor/internal/viewmodel/ViewModelMetadata.kt b/java/dagger/hilt/android/processor/internal/viewmodel/ViewModelMetadata.kt
index 49b35a7..920410a 100644
--- a/java/dagger/hilt/android/processor/internal/viewmodel/ViewModelMetadata.kt
+++ b/java/dagger/hilt/android/processor/internal/viewmodel/ViewModelMetadata.kt
@@ -16,83 +16,181 @@
 
 package dagger.hilt.android.processor.internal.viewmodel
 
+import androidx.room.compiler.codegen.XTypeName
+import androidx.room.compiler.codegen.toJavaPoet
 import androidx.room.compiler.processing.ExperimentalProcessingApi
+import androidx.room.compiler.processing.XMethodElement
 import androidx.room.compiler.processing.XProcessingEnv
 import androidx.room.compiler.processing.XTypeElement
 import com.squareup.javapoet.ClassName
 import dagger.hilt.android.processor.internal.AndroidClassNames
 import dagger.hilt.processor.internal.ClassNames
+import dagger.hilt.processor.internal.HiltCompilerOptions
 import dagger.hilt.processor.internal.ProcessorErrors
 import dagger.hilt.processor.internal.Processors
 import dagger.internal.codegen.xprocessing.XAnnotations
+import dagger.internal.codegen.xprocessing.XElements
+import dagger.internal.codegen.xprocessing.XTypeElements
 import dagger.internal.codegen.xprocessing.XTypes
 
 /** Data class that represents a Hilt injected ViewModel */
 @OptIn(ExperimentalProcessingApi::class)
-internal class ViewModelMetadata private constructor(val typeElement: XTypeElement) {
-  val className = typeElement.className
+internal class ViewModelMetadata
+private constructor(val viewModelElement: XTypeElement, val assistedFactory: XTypeElement) {
+  val className = viewModelElement.asClassName().toJavaPoet()
+
+  val assistedFactoryClassName: ClassName = assistedFactory.asClassName().toJavaPoet()
 
   val modulesClassName =
     ClassName.get(
-      typeElement.packageName,
+      viewModelElement.packageName,
       "${className.simpleNames().joinToString("_")}_HiltModules"
     )
 
   companion object {
+
+    private const val ASSISTED_FACTORY_VALUE = "assistedFactory"
+
+    fun getAssistedFactoryMethods(factory: XTypeElement?): List<XMethodElement> {
+      return XTypeElements.getAllNonPrivateInstanceMethods(factory)
+        .filter { it.isAbstract() }
+        .filter { !it.isJavaDefault() }
+    }
+
     internal fun create(
       processingEnv: XProcessingEnv,
-      typeElement: XTypeElement,
+      viewModelElement: XTypeElement,
     ): ViewModelMetadata? {
       ProcessorErrors.checkState(
-        XTypes.isSubtype(typeElement.type, processingEnv.requireType(AndroidClassNames.VIEW_MODEL)),
-        typeElement,
+        XTypes.isSubtype(
+          viewModelElement.type,
+          processingEnv.requireType(AndroidClassNames.VIEW_MODEL)
+        ),
+        viewModelElement,
         "@HiltViewModel is only supported on types that subclass %s.",
         AndroidClassNames.VIEW_MODEL
       )
 
-      typeElement
-        .getConstructors()
-        .filter { constructor ->
-          ProcessorErrors.checkState(
-            !constructor.hasAnnotation(ClassNames.ASSISTED_INJECT),
-            constructor,
-            "ViewModel constructor should be annotated with @Inject instead of @AssistedInject."
-          )
-          constructor.hasAnnotation(ClassNames.INJECT)
-        }
-        .let { injectConstructors ->
-          ProcessorErrors.checkState(
-            injectConstructors.size == 1,
-            typeElement,
-            "@HiltViewModel annotated class should contain exactly one @Inject " +
-              "annotated constructor."
-          )
+      val isAssistedInjectFeatureEnabled =
+        HiltCompilerOptions.isAssistedInjectViewModelsEnabled(viewModelElement)
 
-          injectConstructors.forEach { injectConstructor ->
+      val assistedFactoryType =
+        viewModelElement
+          .requireAnnotation(AndroidClassNames.HILT_VIEW_MODEL)
+          .getAsType(ASSISTED_FACTORY_VALUE)
+      val assistedFactory = assistedFactoryType.typeElement!!
+
+      if (assistedFactoryType.asTypeName() != XTypeName.ANY_OBJECT) {
+        ProcessorErrors.checkState(
+          isAssistedInjectFeatureEnabled,
+          viewModelElement,
+          "Specified assisted factory %s for %s in @HiltViewModel but compiler option 'enableAssistedInjectViewModels' was not enabled.",
+          assistedFactoryType.asTypeName().toJavaPoet(),
+          XElements.toStableString(viewModelElement),
+        )
+
+        ProcessorErrors.checkState(
+          assistedFactory.hasAnnotation(ClassNames.ASSISTED_FACTORY),
+          viewModelElement,
+          "Class %s is not annotated with @AssistedFactory.",
+          assistedFactoryType.asTypeName().toJavaPoet()
+        )
+
+        val assistedFactoryMethod = getAssistedFactoryMethods(assistedFactory).singleOrNull()
+
+        ProcessorErrors.checkState(
+          assistedFactoryMethod != null,
+          assistedFactory,
+          "Cannot find assisted factory method in %s.",
+          XElements.toStableString(assistedFactory)
+        )
+
+        val assistedFactoryMethodType = assistedFactoryMethod!!.asMemberOf(assistedFactoryType)
+
+        ProcessorErrors.checkState(
+          assistedFactoryMethodType.returnType.asTypeName() == viewModelElement.asClassName(),
+          assistedFactoryMethod,
+          "Class %s must have a factory method that returns a %s. Found %s.",
+          XElements.toStableString(assistedFactory),
+          XElements.toStableString(viewModelElement),
+          XTypes.toStableString(assistedFactoryMethodType.returnType)
+        )
+      }
+
+      val injectConstructors =
+        viewModelElement.getConstructors().filter { constructor ->
+          if (isAssistedInjectFeatureEnabled) {
+            constructor.hasAnnotation(ClassNames.INJECT) ||
+              constructor.hasAnnotation(ClassNames.ASSISTED_INJECT)
+          } else {
             ProcessorErrors.checkState(
-              !injectConstructor.isPrivate(),
-              injectConstructor,
-              "@Inject annotated constructors must not be private."
+              !constructor.hasAnnotation(ClassNames.ASSISTED_INJECT),
+              constructor,
+              "ViewModel constructor should be annotated with @Inject instead of @AssistedInject."
             )
+            constructor.hasAnnotation(ClassNames.INJECT)
           }
         }
 
+      val injectAnnotationsMessage =
+        if (isAssistedInjectFeatureEnabled) {
+          "@Inject or @AssistedInject"
+        } else {
+          "@Inject"
+        }
+
       ProcessorErrors.checkState(
-        !typeElement.isNested() || typeElement.isStatic(),
-        typeElement,
+        injectConstructors.size == 1,
+        viewModelElement,
+        "@HiltViewModel annotated class should contain exactly one %s annotated constructor.",
+        injectAnnotationsMessage
+      )
+
+      val injectConstructor = injectConstructors.single()
+
+      ProcessorErrors.checkState(
+        !injectConstructor.isPrivate(),
+        injectConstructor,
+        "%s annotated constructors must not be private.",
+        injectAnnotationsMessage
+      )
+
+      if (injectConstructor.hasAnnotation(ClassNames.ASSISTED_INJECT)) {
+        // If "enableAssistedInjectViewModels" is not enabled we'll get error:
+        // "ViewModel constructor should be annotated with @Inject instead of @AssistedInject."
+
+        ProcessorErrors.checkState(
+          assistedFactoryType.asTypeName() != XTypeName.ANY_OBJECT,
+          viewModelElement,
+          "%s must have a valid assisted factory specified in @HiltViewModel when used with assisted injection. Found %s.",
+          XElements.toStableString(viewModelElement),
+          XTypes.toStableString(assistedFactoryType)
+        )
+      } else {
+        ProcessorErrors.checkState(
+          assistedFactoryType.asTypeName() == XTypeName.ANY_OBJECT,
+          injectConstructor,
+          "Found assisted factory %s in @HiltViewModel but the constructor was annotated with @Inject instead of @AssistedInject.",
+          XTypes.toStableString(assistedFactoryType),
+        )
+      }
+
+      ProcessorErrors.checkState(
+        !viewModelElement.isNested() || viewModelElement.isStatic(),
+        viewModelElement,
         "@HiltViewModel may only be used on inner classes if they are static."
       )
 
-      Processors.getScopeAnnotations(typeElement).let { scopeAnnotations ->
+      Processors.getScopeAnnotations(viewModelElement).let { scopeAnnotations ->
         ProcessorErrors.checkState(
           scopeAnnotations.isEmpty(),
-          typeElement,
+          viewModelElement,
           "@HiltViewModel classes should not be scoped. Found: %s",
           scopeAnnotations.joinToString { XAnnotations.toStableString(it) }
         )
       }
 
-      return ViewModelMetadata(typeElement)
+      return ViewModelMetadata(viewModelElement, assistedFactory)
     }
   }
 }
diff --git a/java/dagger/hilt/android/processor/internal/viewmodel/ViewModelModuleGenerator.kt b/java/dagger/hilt/android/processor/internal/viewmodel/ViewModelModuleGenerator.kt
index 29f8c3c..6a156fa 100644
--- a/java/dagger/hilt/android/processor/internal/viewmodel/ViewModelModuleGenerator.kt
+++ b/java/dagger/hilt/android/processor/internal/viewmodel/ViewModelModuleGenerator.kt
@@ -16,6 +16,7 @@
 
 package dagger.hilt.android.processor.internal.viewmodel
 
+import androidx.room.compiler.codegen.XTypeName
 import androidx.room.compiler.processing.ExperimentalProcessingApi
 import androidx.room.compiler.processing.XProcessingEnv
 import androidx.room.compiler.processing.addOriginatingElement
@@ -23,6 +24,7 @@
 import com.squareup.javapoet.ClassName
 import com.squareup.javapoet.JavaFile
 import com.squareup.javapoet.MethodSpec
+import com.squareup.javapoet.TypeName
 import com.squareup.javapoet.TypeSpec
 import dagger.hilt.android.processor.internal.AndroidClassNames
 import dagger.hilt.processor.internal.ClassNames
@@ -40,18 +42,20 @@
  *   public static abstract class BindsModule {
  *     @Binds
  *     @IntoMap
- *     @StringKey("pkg.$")
+ *     @LazyClassKey(pkg.$)
  *     @HiltViewModelMap
  *     public abstract ViewModel bind($ vm)
  *   }
  *   @Module
  *   @InstallIn(ActivityRetainedComponent.class)
  *   public static final class KeyModule {
+ *     private static String className = "pkg.$";
  *     @Provides
- *     @IntoSet
+ *     @IntoMap
  *     @HiltViewModelMap.KeySet
- *     public static String provide() {
- *      return "pkg.$";
+ *     @LazyClassKey(pkg.$)
+ *     public static boolean provide() {
+ *       return true;
  *     }
  *   }
  * }
@@ -60,20 +64,20 @@
 @OptIn(ExperimentalProcessingApi::class)
 internal class ViewModelModuleGenerator(
   private val processingEnv: XProcessingEnv,
-  private val injectedViewModel: ViewModelMetadata
+  private val viewModelMetadata: ViewModelMetadata,
 ) {
   fun generate() {
     val modulesTypeSpec =
-      TypeSpec.classBuilder(injectedViewModel.modulesClassName)
+      TypeSpec.classBuilder(viewModelMetadata.modulesClassName)
         .apply {
-          addOriginatingElement(injectedViewModel.typeElement)
+          addOriginatingElement(viewModelMetadata.viewModelElement)
           Processors.addGeneratedAnnotation(this, processingEnv, ViewModelProcessor::class.java)
           addAnnotation(
             AnnotationSpec.builder(ClassNames.ORIGINATING_ELEMENT)
               .addMember(
                 "topLevelClass",
                 "$T.class",
-                injectedViewModel.className.topLevelClassName()
+                viewModelMetadata.className.topLevelClassName(),
               )
               .build()
           )
@@ -85,18 +89,24 @@
         .build()
 
     processingEnv.filer.write(
-      JavaFile.builder(injectedViewModel.modulesClassName.packageName(), modulesTypeSpec).build()
+      JavaFile.builder(viewModelMetadata.modulesClassName.packageName(), modulesTypeSpec).build()
     )
   }
 
   private fun getBindsModuleTypeSpec() =
     createModuleTypeSpec(
         className = "BindsModule",
-        component = AndroidClassNames.VIEW_MODEL_COMPONENT
+        component = AndroidClassNames.VIEW_MODEL_COMPONENT,
       )
       .addModifiers(Modifier.ABSTRACT)
       .addMethod(MethodSpec.constructorBuilder().addModifiers(Modifier.PRIVATE).build())
-      .addMethod(getViewModelBindsMethod())
+      .addMethod(
+        if (viewModelMetadata.assistedFactory.asClassName() != XTypeName.ANY_OBJECT) {
+          getAssistedViewModelBindsMethod()
+        } else {
+          getViewModelBindsMethod()
+        }
+      )
       .build()
 
   private fun getViewModelBindsMethod() =
@@ -104,20 +114,20 @@
       .addAnnotation(ClassNames.BINDS)
       .addAnnotation(ClassNames.INTO_MAP)
       .addAnnotation(
-        AnnotationSpec.builder(ClassNames.STRING_KEY)
-          .addMember("value", S, injectedViewModel.className.reflectionName())
+        AnnotationSpec.builder(ClassNames.LAZY_CLASS_KEY)
+          .addMember("value", "$T.class", viewModelMetadata.className)
           .build()
       )
       .addAnnotation(AndroidClassNames.HILT_VIEW_MODEL_MAP_QUALIFIER)
       .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
       .returns(AndroidClassNames.VIEW_MODEL)
-      .addParameter(injectedViewModel.className, "vm")
+      .addParameter(viewModelMetadata.className, "vm")
       .build()
 
   private fun getKeyModuleTypeSpec() =
     createModuleTypeSpec(
         className = "KeyModule",
-        component = AndroidClassNames.ACTIVITY_RETAINED_COMPONENT
+        component = AndroidClassNames.ACTIVITY_RETAINED_COMPONENT,
       )
       .addModifiers(Modifier.FINAL)
       .addMethod(MethodSpec.constructorBuilder().addModifiers(Modifier.PRIVATE).build())
@@ -127,16 +137,49 @@
   private fun getViewModelKeyProvidesMethod() =
     MethodSpec.methodBuilder("provide")
       .addAnnotation(ClassNames.PROVIDES)
-      .addAnnotation(ClassNames.INTO_SET)
+      .addAnnotation(ClassNames.INTO_MAP)
+      .addAnnotation(
+        AnnotationSpec.builder(ClassNames.LAZY_CLASS_KEY)
+          .addMember("value", "$T.class", viewModelMetadata.className)
+          .build()
+      )
       .addAnnotation(AndroidClassNames.HILT_VIEW_MODEL_KEYS_QUALIFIER)
       .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
-      .returns(String::class.java)
-      .addStatement("return $S", injectedViewModel.className.reflectionName())
+      .returns(Boolean::class.java)
+      .addStatement("return true")
+      .build()
+
+  /**
+   * Should generate:
+   * ```
+   * @Binds
+   * @IntoMap
+   * @LazyClassKey(pkg.FooViewModel.class)
+   * @HiltViewModelAssistedMap
+   * public abstract Object bind(FooViewModelAssistedFactory factory);
+   * ```
+   *
+   * So that we have a HiltViewModelAssistedMap that maps from fully qualified ViewModel names to
+   * its assisted factory instance.
+   */
+  private fun getAssistedViewModelBindsMethod() =
+    MethodSpec.methodBuilder("bind")
+      .addAnnotation(ClassNames.BINDS)
+      .addAnnotation(ClassNames.INTO_MAP)
+      .addAnnotation(
+        AnnotationSpec.builder(ClassNames.LAZY_CLASS_KEY)
+          .addMember("value", "$T.class", viewModelMetadata.className)
+          .build()
+      )
+      .addAnnotation(AndroidClassNames.HILT_VIEW_MODEL_ASSISTED_FACTORY_MAP_QUALIFIER)
+      .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
+      .addParameter(viewModelMetadata.assistedFactoryClassName, "factory")
+      .returns(TypeName.OBJECT)
       .build()
 
   private fun createModuleTypeSpec(className: String, component: ClassName) =
     TypeSpec.classBuilder(className)
-      .addOriginatingElement(injectedViewModel.typeElement)
+      .addOriginatingElement(viewModelMetadata.viewModelElement)
       .addAnnotation(ClassNames.MODULE)
       .addAnnotation(
         AnnotationSpec.builder(ClassNames.INSTALL_IN)
diff --git a/java/dagger/hilt/android/processor/internal/viewmodel/ViewModelProcessingStep.kt b/java/dagger/hilt/android/processor/internal/viewmodel/ViewModelProcessingStep.kt
index 69f7ac2..55cb289 100644
--- a/java/dagger/hilt/android/processor/internal/viewmodel/ViewModelProcessingStep.kt
+++ b/java/dagger/hilt/android/processor/internal/viewmodel/ViewModelProcessingStep.kt
@@ -28,16 +28,13 @@
 @OptIn(ExperimentalProcessingApi::class)
 /** Annotation processor for @ViewModelInject. */
 class ViewModelProcessingStep(env: XProcessingEnv) : BaseProcessingStep(env) {
+
   override fun annotationClassNames() = ImmutableSet.of(AndroidClassNames.HILT_VIEW_MODEL)
 
   override fun processEach(annotation: ClassName, element: XElement) {
     val typeElement = XElements.asTypeElement(element)
-    ViewModelMetadata.create(
-        processingEnv(),
-        typeElement,
-      )
-      ?.let { viewModelMetadata ->
-        ViewModelModuleGenerator(processingEnv(), viewModelMetadata).generate()
-      }
+    ViewModelMetadata.create(processingEnv(), typeElement)?.let { viewModelMetadata ->
+      ViewModelModuleGenerator(processingEnv(), viewModelMetadata).generate()
+    }
   }
 }
diff --git a/java/dagger/hilt/android/processor/internal/viewmodel/ViewModelValidationPlugin.kt b/java/dagger/hilt/android/processor/internal/viewmodel/ViewModelValidationPlugin.kt
index d5c3666..69094c9 100644
--- a/java/dagger/hilt/android/processor/internal/viewmodel/ViewModelValidationPlugin.kt
+++ b/java/dagger/hilt/android/processor/internal/viewmodel/ViewModelValidationPlugin.kt
@@ -14,27 +14,45 @@
  * limitations under the License.
  */
 
+@file:OptIn(ExperimentalProcessingApi::class)
+
 package dagger.hilt.android.processor.internal.viewmodel
 
+import androidx.room.compiler.processing.ExperimentalProcessingApi
+import androidx.room.compiler.processing.XMethodElement
+import androidx.room.compiler.processing.XProcessingEnv
+import androidx.room.compiler.processing.XProcessingEnv.Companion.create
+import androidx.room.compiler.processing.XType
+import androidx.room.compiler.processing.XTypeElement
+import androidx.room.compiler.processing.compat.XConverters.toXProcessing
 import com.google.auto.service.AutoService
 import com.google.common.graph.EndpointPair
 import com.google.common.graph.ImmutableNetwork
 import dagger.hilt.android.processor.internal.AndroidClassNames
-import dagger.hilt.processor.internal.asElement
 import dagger.hilt.processor.internal.getQualifiedName
 import dagger.hilt.processor.internal.hasAnnotation
+import dagger.internal.codegen.xprocessing.XTypeElements
 import dagger.spi.model.Binding
 import dagger.spi.model.BindingGraph
 import dagger.spi.model.BindingGraph.Edge
 import dagger.spi.model.BindingGraph.Node
 import dagger.spi.model.BindingGraphPlugin
 import dagger.spi.model.BindingKind
+import dagger.spi.model.DaggerProcessingEnv
+import dagger.spi.model.DaggerType
 import dagger.spi.model.DiagnosticReporter
 import javax.tools.Diagnostic.Kind
 
 /** Plugin to validate users do not inject @HiltViewModel classes. */
 @AutoService(BindingGraphPlugin::class)
 class ViewModelValidationPlugin : BindingGraphPlugin {
+
+  private lateinit var env: XProcessingEnv
+
+  override fun init(processingEnv: DaggerProcessingEnv, options: MutableMap<String, String>) {
+    env = processingEnv.toXProcessingEnv()
+  }
+
   override fun visitGraph(bindingGraph: BindingGraph, diagnosticReporter: DiagnosticReporter) {
     if (bindingGraph.rootComponentNode().isSubcomponent()) {
       // This check does not work with partial graphs since it needs to take into account the source
@@ -47,10 +65,10 @@
       val pair: EndpointPair<Node> = network.incidentNodes(edge)
       val target: Node = pair.target()
       val source: Node = pair.source()
-      if (
-        target is Binding &&
-        isHiltViewModelBinding(target) && !isInternalHiltViewModelUsage(source)
-      ) {
+      if (target !is Binding) {
+        return@forEach
+      }
+      if (isHiltViewModelBinding(target) && !isInternalHiltViewModelUsage(source)) {
         diagnosticReporter.reportDependency(
           Kind.ERROR,
           edge,
@@ -59,6 +77,17 @@
             "(e.g. ViewModelProvider) instead." +
             "\nInjected ViewModel: ${target.key().type()}\n"
         )
+      } else if (
+        isViewModelAssistedFactory(target) && !isInternalViewModelAssistedFactoryUsage(source)
+      ) {
+        diagnosticReporter.reportDependency(
+          Kind.ERROR,
+          edge,
+          "\nInjection of an assisted factory for Hilt ViewModel is prohibited since it " +
+            "can not be used to create a ViewModel instance correctly.\nAccess the ViewModel via " +
+            "the Android APIs (e.g. ViewModelProvider) instead." +
+            "\nInjected factory: ${target.key().type()}\n"
+        )
       }
     }
   }
@@ -67,7 +96,7 @@
     // Make sure this is from an @Inject constructor rather than an overridden binding like an
     // @Provides and that the class is annotated with @HiltViewModel.
     return target.kind() == BindingKind.INJECTION &&
-      target.key().type().asElement().hasAnnotation(AndroidClassNames.HILT_VIEW_MODEL)
+      target.key().type().hasAnnotation(AndroidClassNames.HILT_VIEW_MODEL)
   }
 
   private fun isInternalHiltViewModelUsage(source: Node): Boolean {
@@ -86,4 +115,58 @@
         AndroidClassNames.HILT_VIEW_MODEL_MAP_QUALIFIER.canonicalName() &&
       source.key().multibindingContributionIdentifier().isPresent()
   }
+
+  private fun isViewModelAssistedFactory(target: Binding): Boolean {
+    if (target.kind() != BindingKind.ASSISTED_FACTORY) return false
+    val factoryType = target.key().type()
+    return getAssistedInjectTypeElement(factoryType.toXType(env))
+      .hasAnnotation(AndroidClassNames.HILT_VIEW_MODEL)
+  }
+
+  private fun getAssistedInjectTypeElement(factoryType: XType): XTypeElement =
+    // The factory method and the type element for its return type cannot be
+    // null as the BindingGraph won't be created if the
+    // @AssistedFactory-annotated class is invalid.
+    getAssistedFactoryMethods(factoryType.typeElement)
+      .single()
+      .asMemberOf(factoryType)
+      .returnType
+      .typeElement!!
+
+  private fun getAssistedFactoryMethods(factory: XTypeElement?): List<XMethodElement> {
+    return XTypeElements.getAllNonPrivateInstanceMethods(factory)
+      .filter { it.isAbstract() }
+      .filter { !it.isJavaDefault() }
+  }
+
+  private fun isInternalViewModelAssistedFactoryUsage(source: Node): Boolean {
+    // We expect the only usage of the assisted factory for a Hilt ViewModel is in the
+    // code we generate:
+    // @Binds
+    // @IntoMap
+    // @StringKey(...)
+    // @HiltViewModelAssistedMap
+    // public abstract Object bind(FooFactory factory);
+    return source is Binding &&
+      source.key().qualifier().isPresent() &&
+      source.key().qualifier().get().getQualifiedName() ==
+        AndroidClassNames.HILT_VIEW_MODEL_ASSISTED_FACTORY_MAP_QUALIFIER.canonicalName() &&
+      source.key().multibindingContributionIdentifier().isPresent()
+  }
+}
+
+private fun DaggerType.toXType(processingEnv: XProcessingEnv): XType {
+  return when (backend()) {
+    DaggerProcessingEnv.Backend.JAVAC -> javac().toXProcessing(processingEnv)
+    DaggerProcessingEnv.Backend.KSP -> ksp().toXProcessing(processingEnv)
+    else -> error("Backend ${ backend() } not supported yet.")
+  }
+}
+
+private fun DaggerProcessingEnv.toXProcessingEnv(): XProcessingEnv {
+  return when (backend()) {
+    DaggerProcessingEnv.Backend.JAVAC -> create(javac())
+    DaggerProcessingEnv.Backend.KSP -> create(ksp(), resolver())
+    else -> error("Backend ${ backend() } not supported yet.")
+  }
 }
diff --git a/java/dagger/hilt/android/testing/BUILD b/java/dagger/hilt/android/testing/BUILD
index 6c3c6e5..ee3d78a 100644
--- a/java/dagger/hilt/android/testing/BUILD
+++ b/java/dagger/hilt/android/testing/BUILD
@@ -168,6 +168,15 @@
     ],
 )
 
+android_library(
+    name = "skip_test_injection",
+    testonly = 1,
+    srcs = ["SkipTestInjection.java"],
+    deps = [
+        ":package_info",
+    ],
+)
+
 java_library(
     name = "package_info",
     srcs = ["package-info.java"],
@@ -220,6 +229,7 @@
     artifact_target_maven_deps = [
         "androidx.activity:activity",
         "androidx.annotation:annotation",
+        "androidx.annotation:annotation-experimental",
         "androidx.fragment:fragment",
         "androidx.lifecycle:lifecycle-common",
         "androidx.lifecycle:lifecycle-viewmodel",
diff --git a/java/dagger/hilt/android/testing/SkipTestInjection.java b/java/dagger/hilt/android/testing/SkipTestInjection.java
new file mode 100644
index 0000000..f8e015b
--- /dev/null
+++ b/java/dagger/hilt/android/testing/SkipTestInjection.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2024 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.hilt.android.testing;
+
+import static java.lang.annotation.RetentionPolicy.CLASS;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation used for skipping test injection in a Hilt Android Test. This may be useful if
+ * building separate custom test infrastructure to inject the test class from another Hilt
+ * component. This may be used on either the test class or an annotation that annotates
+ * the test class.
+ */
+@Retention(CLASS)
+@Target({ElementType.TYPE})
+public @interface SkipTestInjection {}
diff --git a/java/dagger/hilt/android/testing/compile/HiltCompilerTests.java b/java/dagger/hilt/android/testing/compile/HiltCompilerTests.java
index 8f2abd3..89bf678 100644
--- a/java/dagger/hilt/android/testing/compile/HiltCompilerTests.java
+++ b/java/dagger/hilt/android/testing/compile/HiltCompilerTests.java
@@ -117,7 +117,7 @@
             .collect(toMap((Processor e) -> e.getClass(), (Processor e) -> e));
 
     // Adds extra processors, and allows overriding any processors of the same class.
-    extraProcessors.stream().forEach(processor -> processors.put(processor.getClass(), processor));
+    extraProcessors.forEach(processor -> processors.put(processor.getClass(), processor));
 
     return CompilerTests.compiler().withProcessors(processors.values());
   }
@@ -191,9 +191,9 @@
   private static ImmutableList<SymbolProcessorProvider> kspDefaultProcessors() {
     // TODO(bcorso): Add the rest of the KSP processors here.
     return ImmutableList.of(
-        new KspAndroidEntryPointProcessor.Provider(),
-        new KspAliasOfProcessor.Provider(),
         new KspAggregatedDepsProcessor.Provider(),
+        new KspAliasOfProcessor.Provider(),
+        new KspAndroidEntryPointProcessor.Provider(),
         new KspComponentProcessor.Provider(),
         new KspComponentTreeDepsProcessor.Provider(),
         new KspCustomTestApplicationProcessor.Provider(),
@@ -279,16 +279,14 @@
               "-P", "plugin:org.jetbrains.kotlin.kapt3:correctErrorTypes=true"),
           /* config= */ HiltProcessingEnvConfigs.CONFIGS,
           /* javacProcessors= */ ImmutableList.<Processor>builder()
-              .addAll(defaultProcessors())
-              .addAll(additionalJavacProcessors())
+              .addAll(mergeProcessors(defaultProcessors(), additionalJavacProcessors()))
               .addAll(
                   processingSteps().stream()
                       .map(HiltCompilerProcessors.JavacProcessor::new)
                       .collect(toImmutableList()))
               .build(),
           /* symbolProcessorProviders= */ ImmutableList.<SymbolProcessorProvider>builder()
-              .addAll(kspDefaultProcessors())
-              .addAll(additionalKspProcessors())
+              .addAll(mergeProcessors(kspDefaultProcessors(), additionalKspProcessors()))
               .addAll(
                   processingSteps().stream()
                       .map(HiltCompilerProcessors.KspProcessor.Provider::new)
@@ -300,6 +298,15 @@
           });
     }
 
+    private static <T> ImmutableList<T> mergeProcessors(
+        Collection<T> defaultProcessors, Collection<T> extraProcessors) {
+      Map<Class<?>, T> processors =
+          defaultProcessors.stream().collect(toMap((T e) -> e.getClass(), (T e) -> e));
+      // Adds extra processors, and allows overriding any processors of the same class.
+      extraProcessors.forEach(processor -> processors.put(processor.getClass(), processor));
+      return ImmutableList.copyOf(processors.values());
+    }
+
     /** Used to build a {@link HiltCompiler}. */
     @AutoValue.Builder
     public abstract static class Builder {
diff --git a/java/dagger/hilt/migration/BUILD b/java/dagger/hilt/migration/BUILD
index 446e7a2..27f472a 100644
--- a/java/dagger/hilt/migration/BUILD
+++ b/java/dagger/hilt/migration/BUILD
@@ -18,9 +18,7 @@
 
 java_library(
     name = "alias_of",
-    srcs = [
-        "AliasOf.java",
-    ],
+    srcs = ["AliasOf.java"],
     exported_plugins = [
         "//java/dagger/hilt/processor/internal/aliasof:processor",
     ],
diff --git a/java/dagger/hilt/processor/BUILD b/java/dagger/hilt/processor/BUILD
index ba7c9ee..ecbc294 100644
--- a/java/dagger/hilt/processor/BUILD
+++ b/java/dagger/hilt/processor/BUILD
@@ -74,6 +74,7 @@
         "//java/dagger/hilt/processor/internal:component_names",
         "//java/dagger/hilt/processor/internal:components",
         "//java/dagger/hilt/processor/internal:hilt_processing_env_configs",
+        "//java/dagger/hilt/processor/internal:method_signature",
         "//java/dagger/hilt/processor/internal:processor_errors",
         "//java/dagger/hilt/processor/internal:processors",
         "//java/dagger/hilt/processor/internal/aggregateddeps:component_dependencies",
diff --git a/java/dagger/hilt/processor/internal/BUILD b/java/dagger/hilt/processor/internal/BUILD
index a2746ba..8828227 100644
--- a/java/dagger/hilt/processor/internal/BUILD
+++ b/java/dagger/hilt/processor/internal/BUILD
@@ -57,9 +57,7 @@
         "ProcessorErrors.java",
     ],
     deps = [
-        "//java/dagger/internal/codegen/extension",
         "//java/dagger/internal/codegen/xprocessing",
-        "//third_party/java/auto:common",
         "//third_party/java/error_prone:annotations",
         "//third_party/java/guava/base",
         "//third_party/java/guava/collect",
@@ -87,6 +85,20 @@
 )
 
 java_library(
+    name = "method_signature",
+    srcs = [
+        "MethodSignature.java",
+    ],
+    deps = [
+        "//java/dagger/internal/codegen/extension",
+        "//java/dagger/internal/codegen/xprocessing",
+        "//third_party/java/auto:value",
+        "//third_party/java/guava/collect",
+        "//third_party/java/javapoet",
+    ],
+)
+
+java_library(
     name = "classnames",
     srcs = [
         "ClassNames.java",
diff --git a/java/dagger/hilt/processor/internal/ClassNames.java b/java/dagger/hilt/processor/internal/ClassNames.java
index ec2e73e..00de786 100644
--- a/java/dagger/hilt/processor/internal/ClassNames.java
+++ b/java/dagger/hilt/processor/internal/ClassNames.java
@@ -72,7 +72,11 @@
   public static final ClassName DEFINE_COMPONENT_CLASSES =
       get("dagger.hilt.internal.definecomponent", "DefineComponentClasses");
 
+  public static final ClassName IDENTIFIER_NAME_STRING =
+      get("dagger.internal", "IdentifierNameString");
+
   public static final ClassName ASSISTED_INJECT = get("dagger.assisted", "AssistedInject");
+  public static final ClassName ASSISTED_FACTORY = get("dagger.assisted", "AssistedFactory");
   public static final ClassName BINDS =
       get("dagger", "Binds");
   public static final ClassName BINDS_OPTIONAL_OF =
@@ -85,6 +89,7 @@
   public static final ClassName INTO_SET = get("dagger.multibindings", "IntoSet");
   public static final ClassName ELEMENTS_INTO_SET = get("dagger.multibindings", "ElementsIntoSet");
   public static final ClassName STRING_KEY = get("dagger.multibindings", "StringKey");
+  public static final ClassName LAZY_CLASS_KEY = get("dagger.multibindings", "LazyClassKey");
   public static final ClassName PROVIDES =
       get("dagger", "Provides");
   public static final ClassName COMPONENT = get("dagger", "Component");
@@ -169,6 +174,8 @@
       get("dagger.hilt.android.internal.testing", "TestInstanceHolder");
   public static final ClassName HILT_ANDROID_TEST =
       get("dagger.hilt.android.testing", "HiltAndroidTest");
+  public static final ClassName SKIP_TEST_INJECTION =
+      get("dagger.hilt.android.testing", "SkipTestInjection");
   public static final ClassName CUSTOM_TEST_APPLICATION =
       get("dagger.hilt.android.testing", "CustomTestApplication");
   public static final ClassName ON_COMPONENT_READY_RUNNER =
@@ -214,6 +221,9 @@
   public static final ClassName SUPPRESS_WARNINGS = get("java.lang", "SuppressWarnings");
   public static final ClassName KOTLIN_SUPPRESS = get("kotlin", "Suppress");
 
+  public static final ClassName ON_RECEIVE_BYTECODE_INJECTION_MARKER =
+      get("dagger.hilt.android.internal", "OnReceiveBytecodeInjectionMarker");
+
   // Kotlin-specific class names
   public static final ClassName KOTLIN_METADATA = get("kotlin", "Metadata");
 
diff --git a/java/dagger/hilt/processor/internal/DaggerModels.kt b/java/dagger/hilt/processor/internal/DaggerModels.kt
index 7d64d23..9fe0cf4 100644
--- a/java/dagger/hilt/processor/internal/DaggerModels.kt
+++ b/java/dagger/hilt/processor/internal/DaggerModels.kt
@@ -18,47 +18,37 @@
 
 import com.google.auto.common.MoreTypes
 import com.google.devtools.ksp.symbol.KSAnnotated
+import com.google.devtools.ksp.symbol.KSDeclaration
 import com.squareup.javapoet.ClassName
 import dagger.spi.model.DaggerAnnotation
 import dagger.spi.model.DaggerElement
 import dagger.spi.model.DaggerProcessingEnv
+import dagger.spi.model.DaggerProcessingEnv.Backend.JAVAC
+import dagger.spi.model.DaggerProcessingEnv.Backend.KSP
 import dagger.spi.model.DaggerType
 
 
-fun DaggerType.asElement(): DaggerElement =
+fun DaggerType.hasAnnotation(className: ClassName): Boolean =
   when (checkNotNull(backend())) {
-    DaggerProcessingEnv.Backend.JAVAC -> {
-      val javaType = checkNotNull(java())
-      DaggerElement.fromJavac(MoreTypes.asElement(javaType))
-    }
-    DaggerProcessingEnv.Backend.KSP -> {
-      val kspType = checkNotNull(ksp())
-      DaggerElement.fromKsp(kspType.declaration)
-    }
+    JAVAC -> Processors.hasAnnotation(MoreTypes.asTypeElement(javac()), className)
+    KSP -> ksp().declaration.hasAnnotation(className.canonicalName())
+  }
+
+fun KSDeclaration.hasAnnotation(annotationName: String): Boolean =
+  annotations.any {
+    it.annotationType.resolve().declaration.qualifiedName?.asString().equals(annotationName)
   }
 
 fun DaggerElement.hasAnnotation(className: ClassName) =
   when (checkNotNull(backend())) {
-    DaggerProcessingEnv.Backend.JAVAC -> {
-      val javaElement = checkNotNull(java())
-      Processors.hasAnnotation(javaElement, className)
-    }
-    DaggerProcessingEnv.Backend.KSP -> {
-      val kspAnnotated = checkNotNull(ksp())
-      kspAnnotated.hasAnnotation(className)
-    }
+    JAVAC -> Processors.hasAnnotation(javac(), className)
+    KSP -> ksp().hasAnnotation(className)
   }
 
 fun DaggerAnnotation.getQualifiedName() =
   when (checkNotNull(backend())) {
-    DaggerProcessingEnv.Backend.JAVAC -> {
-      val javaAnnotation = checkNotNull(java())
-      MoreTypes.asTypeElement(javaAnnotation.annotationType).qualifiedName.toString()
-    }
-    DaggerProcessingEnv.Backend.KSP -> {
-      val kspAnnotation = checkNotNull(ksp())
-      kspAnnotation.annotationType.resolve().declaration.qualifiedName!!.asString()
-    }
+    JAVAC -> MoreTypes.asTypeElement(javac().annotationType).qualifiedName.toString()
+    KSP -> ksp().annotationType.resolve().declaration.qualifiedName!!.asString()
   }
 
 private fun KSAnnotated.hasAnnotation(className: ClassName) =
diff --git a/java/dagger/hilt/processor/internal/HiltCompilerOptions.java b/java/dagger/hilt/processor/internal/HiltCompilerOptions.java
index cdb2d6c..9057559 100644
--- a/java/dagger/hilt/processor/internal/HiltCompilerOptions.java
+++ b/java/dagger/hilt/processor/internal/HiltCompilerOptions.java
@@ -21,6 +21,7 @@
 
 import androidx.room.compiler.processing.XProcessingEnv;
 import androidx.room.compiler.processing.XTypeElement;
+import androidx.room.compiler.processing.compat.XConverters;
 import com.google.common.collect.ImmutableSet;
 import dagger.hilt.processor.internal.optionvalues.BooleanValue;
 import dagger.hilt.processor.internal.optionvalues.GradleProjectType;
@@ -101,6 +102,13 @@
     return GRADLE_PROJECT_TYPE.get(env);
   }
 
+  public static boolean isAssistedInjectViewModelsEnabled(XTypeElement viewModelElement) {
+    boolean enabled =
+        ENABLE_ASSISTED_INJECT_VIEWMODELS.get(XConverters.getProcessingEnv(viewModelElement))
+            == BooleanValue.TRUE;
+    return enabled;
+  }
+
   /** Do not use! This is for internal use only. */
   private static final EnumOption<BooleanValue> DISABLE_ANDROID_SUPERCLASS_VALIDATION =
       new EnumOption<>("android.internal.disableAndroidSuperclassValidation", BooleanValue.FALSE);
@@ -124,6 +132,9 @@
   private static final EnumOption<GradleProjectType> GRADLE_PROJECT_TYPE =
       new EnumOption<>("android.internal.projectType", GradleProjectType.UNSET);
 
+  private static final EnumOption<BooleanValue> ENABLE_ASSISTED_INJECT_VIEWMODELS =
+      new EnumOption<>(
+          "enableAssistedInjectViewModels", BooleanValue.TRUE );
   private static final ImmutableSet<String> DEPRECATED_OPTIONS =
       ImmutableSet.of("dagger.hilt.android.useFragmentGetContextFix");
 
diff --git a/java/dagger/hilt/processor/internal/MethodSignature.java b/java/dagger/hilt/processor/internal/MethodSignature.java
new file mode 100644
index 0000000..7fffef2
--- /dev/null
+++ b/java/dagger/hilt/processor/internal/MethodSignature.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.hilt.processor.internal;
+
+import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
+import static java.util.stream.Collectors.joining;
+
+import androidx.room.compiler.processing.XExecutableElement;
+import androidx.room.compiler.processing.XMethodElement;
+import androidx.room.compiler.processing.XMethodType;
+import androidx.room.compiler.processing.XType;
+import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableList;
+import com.squareup.javapoet.MethodSpec;
+import com.squareup.javapoet.TypeName;
+import dagger.internal.codegen.xprocessing.XElements;
+
+/** Represents the method signature needed to uniquely identify a method. */
+@AutoValue
+public abstract class MethodSignature {
+  MethodSignature() {}
+
+  abstract String name();
+
+  abstract ImmutableList<TypeName> parameters();
+
+  /** Creates a {@link MethodSignature} from a method name and parameter {@link TypeNames} */
+  public static MethodSignature of(String methodName, TypeName... typeNames) {
+    return new AutoValue_MethodSignature(methodName, ImmutableList.copyOf(typeNames));
+  }
+
+  /** Creates a {@link MethodSignature} from a {@link MethodSpec} */
+  public static MethodSignature of(MethodSpec method) {
+    return new AutoValue_MethodSignature(
+        method.name, method.parameters.stream().map(p -> p.type).collect(toImmutableList()));
+  }
+
+  /** Creates a {@link MethodSignature} from an {@link XExecutableElement} */
+  public static MethodSignature of(XExecutableElement executableElement) {
+    return new AutoValue_MethodSignature(
+        XElements.getSimpleName(executableElement),
+        executableElement.getParameters().stream()
+            .map(p -> p.getType().getTypeName())
+            .collect(toImmutableList()));
+  }
+
+  /**
+   * Creates a {@link MethodSignature} from an {@link XMethodElement}.
+   *
+   * <p>This version will resolve type parameters as declared by {@code enclosing}.
+   */
+  static MethodSignature ofDeclaredType(XMethodElement method, XType enclosing) {
+    XMethodType executableType = method.asMemberOf(enclosing);
+    return new AutoValue_MethodSignature(
+        XElements.getSimpleName(method),
+        executableType.getParameterTypes().stream()
+            .map(XType::getTypeName)
+            .collect(toImmutableList()));
+  }
+
+  /** Returns a string in the format: METHOD_NAME(PARAM_TYPE1,PARAM_TYEP2,...) */
+  @Override
+  public final String toString() {
+    return String.format(
+        "%s(%s)", name(), parameters().stream().map(Object::toString).collect(joining(",")));
+  }
+}
diff --git a/java/dagger/hilt/processor/internal/definecomponent/KspDefineComponentValidationProcessor.java b/java/dagger/hilt/processor/internal/definecomponent/KspDefineComponentValidationProcessor.java
deleted file mode 100644
index d46921e..0000000
--- a/java/dagger/hilt/processor/internal/definecomponent/KspDefineComponentValidationProcessor.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2023 The Dagger Authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package dagger.hilt.processor.internal.definecomponent;
-
-import com.google.auto.service.AutoService;
-import com.google.devtools.ksp.processing.SymbolProcessor;
-import com.google.devtools.ksp.processing.SymbolProcessorEnvironment;
-import com.google.devtools.ksp.processing.SymbolProcessorProvider;
-import dagger.hilt.processor.internal.BaseProcessingStep;
-import dagger.hilt.processor.internal.KspBaseProcessingStepProcessor;
-
-/**
- * A processor for {@link dagger.hilt.DefineComponent} and {@link
- * dagger.hilt.DefineComponent.Builder}.
- */
-public final class KspDefineComponentValidationProcessor extends KspBaseProcessingStepProcessor {
-  public KspDefineComponentValidationProcessor(
-      SymbolProcessorEnvironment symbolProcessorEnvironment) {
-    super(symbolProcessorEnvironment);
-  }
-
-  @Override
-  protected BaseProcessingStep processingStep() {
-    return new DefineComponentValidationProcessingStep(getXProcessingEnv());
-  }
-
-  /** Provides the {@link KspDefineComponentValidationProcessor}. */
-  @AutoService(SymbolProcessorProvider.class)
-  public static final class Provider implements SymbolProcessorProvider {
-    @Override
-    public SymbolProcessor create(SymbolProcessorEnvironment symbolProcessorEnvironment) {
-      return new KspDefineComponentValidationProcessor(symbolProcessorEnvironment);
-    }
-  }
-}
diff --git a/java/dagger/hilt/processor/internal/kotlin/KotlinMetadataUtil.java b/java/dagger/hilt/processor/internal/kotlin/KotlinMetadataUtil.java
index 771a4b8..915a47d 100644
--- a/java/dagger/hilt/processor/internal/kotlin/KotlinMetadataUtil.java
+++ b/java/dagger/hilt/processor/internal/kotlin/KotlinMetadataUtil.java
@@ -34,7 +34,6 @@
 import dagger.hilt.processor.internal.ClassNames;
 import dagger.internal.codegen.xprocessing.XAnnotations;
 import dagger.internal.codegen.xprocessing.XElements;
-import java.util.Optional;
 import javax.inject.Inject;
 
 /** Utility class for interacting with Kotlin Metadata. */
@@ -133,10 +132,6 @@
         : ImmutableList.of();
   }
 
-  public Optional<XMethodElement> getPropertyGetter(XFieldElement fieldElement) {
-    return metadataFactory.create(fieldElement).getPropertyGetter(fieldElement);
-  }
-
   public boolean containsConstructorWithDefaultParam(XTypeElement typeElement) {
     return hasMetadata(typeElement)
         && metadataFactory.create(typeElement).containsConstructorWithDefaultParam();
diff --git a/java/dagger/hilt/processor/internal/root/RootGenerator.java b/java/dagger/hilt/processor/internal/root/RootGenerator.java
index 2868f7c..f433272 100644
--- a/java/dagger/hilt/processor/internal/root/RootGenerator.java
+++ b/java/dagger/hilt/processor/internal/root/RootGenerator.java
@@ -23,9 +23,7 @@
 import static javax.lang.model.element.Modifier.STATIC;
 
 import androidx.room.compiler.processing.JavaPoetExtKt;
-import androidx.room.compiler.processing.XFiler.Mode;
 import androidx.room.compiler.processing.XProcessingEnv;
-import androidx.room.compiler.processing.XProcessingEnv.Backend;
 import androidx.room.compiler.processing.XTypeElement;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
@@ -132,12 +130,7 @@
     JavaFile componentsWrapperJavaFile =
         JavaFile.builder(componentsWrapperClassName.packageName(), componentsWrapper.build())
             .build();
-    // TODO(danysantiago): Support formatting in KSP: b/288572563
-    if (env.getBackend() == Backend.KSP) {
-      env.getFiler().write(componentsWrapperJavaFile, Mode.Isolating);
-    } else {
-      RootFileFormatter.write(componentsWrapperJavaFile, env);
-    }
+    RootFileFormatter.write(componentsWrapperJavaFile, env);
   }
 
   private static ComponentTree filterDescriptors(ComponentTree componentTree) {
diff --git a/java/dagger/hilt/processor/internal/root/RootMetadata.java b/java/dagger/hilt/processor/internal/root/RootMetadata.java
index 8166d66..55f6e9c 100644
--- a/java/dagger/hilt/processor/internal/root/RootMetadata.java
+++ b/java/dagger/hilt/processor/internal/root/RootMetadata.java
@@ -21,7 +21,6 @@
 import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
 
 import androidx.room.compiler.processing.XConstructorElement;
-import androidx.room.compiler.processing.XMethodElement;
 import androidx.room.compiler.processing.XProcessingEnv;
 import androidx.room.compiler.processing.XTypeElement;
 import com.google.common.base.Supplier;
@@ -40,6 +39,7 @@
 
 /** Contains metadata about the given hilt root. */
 public final class RootMetadata {
+
   private static final ClassName APPLICATION_CONTEXT_MODULE =
       ClassName.get("dagger.hilt.android.internal.modules", "ApplicationContextModule");
 
@@ -195,33 +195,10 @@
   }
 
   private static boolean daggerCanConstruct(XTypeElement type) {
-    if (type.isKotlinObject()) {
-      // Treat Kotlin object modules as if Dagger can construct them (it technically can't, but it
-      // doesn't need to as it can use them since all their provision methods are static).
+    if (!Processors.requiresModuleInstance(type)) {
       return true;
     }
-
-    return !isInnerClass(type)
-        && !hasNonDaggerAbstractMethod(type)
-        && (hasOnlyStaticProvides(type) || hasVisibleEmptyConstructor(type));
-  }
-
-  private static boolean isInnerClass(XTypeElement type) {
-    return type.isNested() && !type.isStatic();
-  }
-
-  private static boolean hasNonDaggerAbstractMethod(XTypeElement type) {
-    // TODO(erichang): Actually this isn't really supported b/28989613
-    return type.getDeclaredMethods().stream()
-        .filter(XMethodElement::isAbstract)
-        .anyMatch(method -> !Processors.hasDaggerAbstractMethodAnnotation(method));
-  }
-
-  private static boolean hasOnlyStaticProvides(XTypeElement type) {
-    // TODO(erichang): Check for @Produces too when we have a producers story
-    return type.getDeclaredMethods().stream()
-        .filter(method -> method.hasAnnotation(ClassNames.PROVIDES))
-        .allMatch(XMethodElement::isStatic);
+    return hasVisibleEmptyConstructor(type) && (!type.isNested() || type.isStatic());
   }
 
   private static boolean hasVisibleEmptyConstructor(XTypeElement type) {
diff --git a/java/dagger/hilt/processor/internal/root/RootProcessingStep.java b/java/dagger/hilt/processor/internal/root/RootProcessingStep.java
index f281995..d6de432 100644
--- a/java/dagger/hilt/processor/internal/root/RootProcessingStep.java
+++ b/java/dagger/hilt/processor/internal/root/RootProcessingStep.java
@@ -57,6 +57,9 @@
 public final class RootProcessingStep extends BaseProcessingStep {
 
   private boolean processed;
+  // TODO(b/297889547) do not run preProcess and postProcess if supported annotation isn't present
+  // in the environment.
+  private boolean hasElementsToProcess = false;
   private GeneratesRootInputs generatesRootInputs;
 
   public RootProcessingStep(XProcessingEnv env) {
@@ -75,13 +78,16 @@
 
   @Override
   public void processEach(ClassName annotation, XElement element) throws Exception {
+    hasElementsToProcess = true;
     XTypeElement rootElement = XElements.asTypeElement(element);
     // TODO(bcorso): Move this logic into a separate isolating processor to avoid regenerating it
     // for unrelated changes in Gradle.
     RootType rootType = RootType.of(rootElement);
     if (rootType.isTestRoot()) {
-      new TestInjectorGenerator(processingEnv(), TestRootMetadata.of(processingEnv(), rootElement))
-          .generate();
+      TestRootMetadata testRootMetadata = TestRootMetadata.of(processingEnv(), rootElement);
+      if (testRootMetadata.skipTestInjectionAnnotation().isEmpty()) {
+        new TestInjectorGenerator(processingEnv(), testRootMetadata).generate();
+      }
     }
 
     XTypeElement originatingRootElement =
@@ -93,6 +99,9 @@
 
   @Override
   protected void postProcess(XProcessingEnv env, XRoundEnv roundEnv) throws Exception {
+    if (!hasElementsToProcess) {
+      return;
+    }
     if (!useAggregatingRootProcessor(processingEnv())) {
       return;
     }
diff --git a/java/dagger/hilt/processor/internal/root/TestComponentDataGenerator.java b/java/dagger/hilt/processor/internal/root/TestComponentDataGenerator.java
index 689dae7..bacb75b 100644
--- a/java/dagger/hilt/processor/internal/root/TestComponentDataGenerator.java
+++ b/java/dagger/hilt/processor/internal/root/TestComponentDataGenerator.java
@@ -25,6 +25,7 @@
 import static javax.lang.model.element.Modifier.STATIC;
 
 import androidx.room.compiler.processing.JavaPoetExtKt;
+import androidx.room.compiler.processing.XAnnotation;
 import androidx.room.compiler.processing.XConstructorElement;
 import androidx.room.compiler.processing.XFiler.Mode;
 import androidx.room.compiler.processing.XProcessingEnv;
@@ -41,6 +42,7 @@
 import dagger.hilt.processor.internal.Processors;
 import java.io.IOException;
 import java.util.List;
+import java.util.Optional;
 
 /** Generates an implementation of {@link dagger.hilt.android.internal.TestComponentData}. */
 public final class TestComponentDataGenerator {
@@ -222,6 +224,13 @@
   }
 
   private CodeBlock callInjectTest(XTypeElement testElement) {
+    Optional<XAnnotation> skipTestInjection =
+        rootMetadata.testRootMetadata().skipTestInjectionAnnotation();
+    if (skipTestInjection.isPresent()) {
+      return CodeBlock.of(
+          "throw new IllegalStateException(\"Cannot inject test when using @$L\")",
+          skipTestInjection.get().getName());
+    }
     return CodeBlock.of(
         "(($T) (($T) $T.getApplication($T.getApplicationContext()))"
             + ".generatedComponent()).injectTest(testInstance)",
diff --git a/java/dagger/hilt/processor/internal/root/TestRootMetadata.java b/java/dagger/hilt/processor/internal/root/TestRootMetadata.java
index 5dc6fee..b052303 100644
--- a/java/dagger/hilt/processor/internal/root/TestRootMetadata.java
+++ b/java/dagger/hilt/processor/internal/root/TestRootMetadata.java
@@ -16,6 +16,7 @@
 
 package dagger.hilt.processor.internal.root;
 
+import androidx.room.compiler.processing.XAnnotation;
 import androidx.room.compiler.processing.XElement;
 import androidx.room.compiler.processing.XProcessingEnv;
 import androidx.room.compiler.processing.XTypeElement;
@@ -25,6 +26,8 @@
 import dagger.hilt.processor.internal.ProcessorErrors;
 import dagger.hilt.processor.internal.Processors;
 import dagger.internal.codegen.xprocessing.XElements;
+import java.util.Optional;
+import java.util.Set;
 import javax.lang.model.element.TypeElement;
 
 /** Metadata class for {@code InternalTestRoot} annotated classes. */
@@ -57,6 +60,28 @@
     return Processors.append(Processors.getEnclosedClassName(testName()), "_GeneratedInjector");
   }
 
+  /**
+   * Returns either the SkipTestInjection annotation or the first annotation that was annotated
+   * with SkipTestInjection, if present.
+   */
+  Optional<XAnnotation> skipTestInjectionAnnotation() {
+    XAnnotation skipTestAnnotation = testElement().getAnnotation(ClassNames.SKIP_TEST_INJECTION);
+    if (skipTestAnnotation != null) {
+      return Optional.of(skipTestAnnotation);
+    }
+
+    Set<XAnnotation> annotatedAnnotations = testElement().getAnnotationsAnnotatedWith(
+        ClassNames.SKIP_TEST_INJECTION);
+    if (!annotatedAnnotations.isEmpty()) {
+      // Just return the first annotation that skips test injection if there are multiple since
+      // at this point it doesn't really matter and the specific annotation is only really useful
+      // for communicating back to the user.
+      return Optional.of(annotatedAnnotations.iterator().next());
+    }
+
+    return Optional.empty();
+  }
+
   static TestRootMetadata of(XProcessingEnv env, XElement element) {
 
     XTypeElement testElement = XElements.asTypeElement(element);
diff --git a/java/dagger/internal/AbstractMapFactory.java b/java/dagger/internal/AbstractMapFactory.java
index 1cf83fa..22512e9 100644
--- a/java/dagger/internal/AbstractMapFactory.java
+++ b/java/dagger/internal/AbstractMapFactory.java
@@ -22,7 +22,6 @@
 
 import java.util.LinkedHashMap;
 import java.util.Map;
-import javax.inject.Provider;
 
 /**
  * An {@code abstract} {@link Factory} implementation used to implement {@link Map} bindings.
diff --git a/java/dagger/internal/DelegateFactory.java b/java/dagger/internal/DelegateFactory.java
index 3b4a30f..bc5cd9a 100644
--- a/java/dagger/internal/DelegateFactory.java
+++ b/java/dagger/internal/DelegateFactory.java
@@ -17,12 +17,11 @@
 package dagger.internal;
 
 import static dagger.internal.Preconditions.checkNotNull;
-
-import javax.inject.Provider;
+import static dagger.internal.Providers.asDaggerProvider;
 
 /**
  * A DelegateFactory that is used to stitch Provider/Lazy indirection based dependency cycles.
- * 
+ *
  * @since 2.0.1
  */
 public final class DelegateFactory<T> implements Factory<T> {
@@ -44,18 +43,43 @@
   }
 
   /**
+   * Legacy javax version of the method to support libraries compiled with an older version of
+   * Dagger. Do not use directly.
+   */
+  @Deprecated
+  public void setDelegatedProvider(javax.inject.Provider<T> delegate) {
+    setDelegatedProvider(asDaggerProvider(delegate));
+  }
+
+  /**
    * Sets {@code delegateFactory}'s delegate provider to {@code delegate}.
    *
    * <p>{@code delegateFactory} must be an instance of {@link DelegateFactory}, otherwise this
    * method will throw a {@link ClassCastException}.
    */
   public static <T> void setDelegate(Provider<T> delegateFactory, Provider<T> delegate) {
-    checkNotNull(delegate);
     DelegateFactory<T> asDelegateFactory = (DelegateFactory<T>) delegateFactory;
-    if (asDelegateFactory.delegate != null) {
+    setDelegateInternal(asDelegateFactory, delegate);
+  }
+
+  /**
+   * Legacy javax version of the method to support libraries compiled with an older version of
+   * Dagger. Do not use directly.
+   */
+  @Deprecated
+  public static <T> void setDelegate(
+      javax.inject.Provider<T> delegateFactory, javax.inject.Provider<T> delegate) {
+    DelegateFactory<T> asDelegateFactory = (DelegateFactory<T>) delegateFactory;
+    setDelegateInternal(asDelegateFactory, asDaggerProvider(delegate));
+  }
+
+  private static <T> void setDelegateInternal(
+      DelegateFactory<T> delegateFactory, Provider<T> delegate) {
+    checkNotNull(delegate);
+    if (delegateFactory.delegate != null) {
       throw new IllegalStateException();
     }
-    asDelegateFactory.delegate = delegate;
+    delegateFactory.delegate = delegate;
   }
 
   /**
@@ -67,4 +91,3 @@
     return checkNotNull(delegate);
   }
 }
-
diff --git a/java/dagger/internal/DoubleCheck.java b/java/dagger/internal/DoubleCheck.java
index af7d7f6..6af8661 100644
--- a/java/dagger/internal/DoubleCheck.java
+++ b/java/dagger/internal/DoubleCheck.java
@@ -17,9 +17,9 @@
 package dagger.internal;
 
 import static dagger.internal.Preconditions.checkNotNull;
+import static dagger.internal.Providers.asDaggerProvider;
 
 import dagger.Lazy;
-import javax.inject.Provider;
 
 /**
  * A {@link Lazy} and {@link Provider} implementation that memoizes the value returned from a
@@ -73,7 +73,8 @@
   /** Returns a {@link Provider} that caches the value from the given delegate provider. */
   // This method is declared this way instead of "<T> Provider<T> provider(Provider<T> delegate)"
   // to work around an Eclipse type inference bug: https://github.com/google/dagger/issues/949.
-  public static <P extends Provider<T>, T> Provider<T> provider(P delegate) {
+  public static <P extends dagger.internal.Provider<T>, T> dagger.internal.Provider<T> provider(
+      P delegate) {
     checkNotNull(delegate);
     if (delegate instanceof DoubleCheck) {
       /* This should be a rare case, but if we have a scoped @Binds that delegates to a scoped
@@ -83,6 +84,16 @@
     return new DoubleCheck<T>(delegate);
   }
 
+  /**
+   * Legacy javax version of the method to support libraries compiled with an older version of
+   * Dagger. Do not use directly.
+   */
+  @Deprecated
+  public static <P extends javax.inject.Provider<T>, T> javax.inject.Provider<T> provider(
+      P delegate) {
+    return provider(asDaggerProvider(delegate));
+  }
+
   /** Returns a {@link Lazy} that caches the value from the given provider. */
   // This method is declared this way instead of "<T> Lazy<T> lazy(Provider<T> delegate)"
   // to work around an Eclipse type inference bug: https://github.com/google/dagger/issues/949.
@@ -99,4 +110,12 @@
     }
     return new DoubleCheck<T>(checkNotNull(provider));
   }
+
+  /**
+   * Legacy javax version of the method to support libraries compiled with an older version of
+   * Dagger. Do not use directly.
+   */
+  public static <P extends javax.inject.Provider<T>, T> Lazy<T> lazy(P provider) {
+    return lazy(asDaggerProvider(provider));
+  }
 }
diff --git a/java/dagger/internal/Factory.java b/java/dagger/internal/Factory.java
index 9c03f81..73bcfbc 100644
--- a/java/dagger/internal/Factory.java
+++ b/java/dagger/internal/Factory.java
@@ -18,7 +18,6 @@
 
 import dagger.Provides;
 import javax.inject.Inject;
-import javax.inject.Provider;
 import javax.inject.Scope;
 
 /**
diff --git a/java/dagger/internal/IdentifierNameString.java b/java/dagger/internal/IdentifierNameString.java
new file mode 100644
index 0000000..95d2bfa
--- /dev/null
+++ b/java/dagger/internal/IdentifierNameString.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2024 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.internal;
+
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.CLASS;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Annotates the dagger generated class that requires applying -identifiernamestring rule.
+ *
+ * <p>When applied, all the strings fields that corresponds to a class name within the annotated
+ * class will be obfuscated if its corresponding class is obfuscated. This only works with r8.
+ *
+ */
+@Documented
+@Retention(CLASS)
+@Target(TYPE)
+public @interface IdentifierNameString {}
diff --git a/java/dagger/internal/KeepFieldType.java b/java/dagger/internal/KeepFieldType.java
new file mode 100644
index 0000000..0905502
--- /dev/null
+++ b/java/dagger/internal/KeepFieldType.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2024 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.internal;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.RetentionPolicy.CLASS;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Annotates the dagger generated field that requires keeping the field types.
+ *
+ * <p>Annotating a field with this annotation, the field type's class name won't be discarded or
+ * obfuscated when compiles with proguard. Note:This will cause the containing class to be kept, and
+ * only works with proguard.
+ */
+@Documented
+@Retention(CLASS)
+@Target(FIELD)
+public @interface KeepFieldType {}
diff --git a/java/dagger/internal/LazyClassKeyMap.java b/java/dagger/internal/LazyClassKeyMap.java
new file mode 100644
index 0000000..dabf86f
--- /dev/null
+++ b/java/dagger/internal/LazyClassKeyMap.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2024 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.internal;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * A class keyed map that delegates to a string keyed map under the hood.
+ *
+ * <p>A {@code LazyClassKeyMap} is created for @LazyClassKey contributed map binding.
+ */
+public final class LazyClassKeyMap<V> implements Map<Class<?>, V> {
+  private final Map<String, V> delegate;
+
+  public static <V> Map<Class<?>, V> of(Map<String, V> delegate) {
+    return new LazyClassKeyMap<>(delegate);
+  }
+
+  private LazyClassKeyMap(Map<String, V> delegate) {
+    this.delegate = delegate;
+  }
+
+  @Override
+  public V get(Object key) {
+    if (!(key instanceof Class)) {
+      throw new IllegalArgumentException("Key must be a class");
+    }
+    return delegate.get(((Class<?>) key).getName());
+  }
+
+  @Override
+  public Set<Class<?>> keySet() {
+    // This method will load all class keys, therefore no need to use @LazyClassKey annotated
+    // bindings.
+    throw new UnsupportedOperationException(
+        "Maps created with @LazyClassKey do not support usage of keySet(). Consider @ClassKey"
+            + " instead.");
+  }
+
+  @Override
+  public Collection<V> values() {
+    return delegate.values();
+  }
+
+  @Override
+  public boolean isEmpty() {
+    return delegate.isEmpty();
+  }
+
+  @Override
+  public boolean containsKey(Object key) {
+    if (!(key instanceof Class)) {
+      throw new IllegalArgumentException("Key must be a class");
+    }
+    return delegate.containsKey(((Class<?>) key).getName());
+  }
+
+  @Override
+  public boolean containsValue(Object value) {
+    return delegate.containsValue(value);
+  }
+
+  @Override
+  public int size() {
+    return delegate.size();
+  }
+
+  @Override
+  public Set<Map.Entry<Class<?>, V>> entrySet() {
+    // This method will load all class keys, therefore no need to use @LazyClassKey annotated
+    // bindings.
+    throw new UnsupportedOperationException(
+        "Maps created with @LazyClassKey do not support usage of entrySet(). Consider @ClassKey"
+            + " instead.");
+  }
+
+  // The dagger map binding should be a immutable map.
+  @Override
+  public V remove(Object key) {
+    throw new UnsupportedOperationException("Dagger map bindings are immutable");
+  }
+
+  @Override
+  public void clear() {
+    throw new UnsupportedOperationException("Dagger map bindings are immutable");
+  }
+
+  @Override
+  public V put(Class<?> key, V value) {
+    throw new UnsupportedOperationException("Dagger map bindings are immutable");
+  }
+
+  @Override
+  public void putAll(Map<? extends Class<?>, ? extends V> map) {
+    throw new UnsupportedOperationException("Dagger map bindings are immutable");
+  }
+
+  /** A factory for {@code LazyClassKeyMap}. */
+  public static class Factory<V> implements Provider<Map<Class<?>, V>> {
+    MapFactory<String, V> delegate;
+
+    public static <V> Factory<V> of(MapFactory<String, V> delegate) {
+      return new Factory<>(delegate);
+    }
+
+    private Factory(MapFactory<String, V> delegate) {
+      this.delegate = delegate;
+    }
+
+    @Override
+    public Map<Class<?>, V> get() {
+      return LazyClassKeyMap.of(delegate.get());
+    }
+  }
+}
diff --git a/java/dagger/internal/MapFactory.java b/java/dagger/internal/MapFactory.java
index 39748c9..376cfdc 100644
--- a/java/dagger/internal/MapFactory.java
+++ b/java/dagger/internal/MapFactory.java
@@ -17,12 +17,12 @@
 package dagger.internal;
 
 import static dagger.internal.DaggerCollections.newLinkedHashMapWithExpectedSize;
+import static dagger.internal.Providers.asDaggerProvider;
 import static java.util.Collections.unmodifiableMap;
 
 import java.util.Collections;
 import java.util.Map;
 import java.util.Map.Entry;
-import javax.inject.Provider;
 
 /**
  * A {@link Factory} implementation used to implement {@link Map} bindings. This factory returns a
@@ -72,12 +72,30 @@
       return this;
     }
 
+    /**
+     * Legacy javax version of the method to support libraries compiled with an older version of
+     * Dagger. Do not use directly.
+     */
+    @Deprecated
+    public Builder<K, V> put(K key, javax.inject.Provider<V> providerOfValue) {
+      return put(key, asDaggerProvider(providerOfValue));
+    }
+
     @Override
     public Builder<K, V> putAll(Provider<Map<K, V>> mapFactory) {
       super.putAll(mapFactory);
       return this;
     }
 
+    /**
+     * Legacy javax version of the method to support libraries compiled with an older version of
+     * Dagger. Do not use directly.
+     */
+    @Deprecated
+    public Builder<K, V> putAll(javax.inject.Provider<Map<K, V>> mapFactory) {
+      return putAll(asDaggerProvider(mapFactory));
+    }
+
     /** Returns a new {@link MapProviderFactory}. */
     public MapFactory<K, V> build() {
       return new MapFactory<>(map);
diff --git a/java/dagger/internal/MapProviderFactory.java b/java/dagger/internal/MapProviderFactory.java
index 1fe4788..8491ffc 100644
--- a/java/dagger/internal/MapProviderFactory.java
+++ b/java/dagger/internal/MapProviderFactory.java
@@ -16,9 +16,12 @@
 
 package dagger.internal;
 
+import static dagger.internal.DaggerCollections.newLinkedHashMapWithExpectedSize;
+import static dagger.internal.Providers.asDaggerProvider;
+
 import dagger.Lazy;
+import java.util.Collections;
 import java.util.Map;
-import javax.inject.Provider;
 
 /**
  * A {@link Factory} implementation used to implement {@link Map} bindings. This factory returns a
@@ -57,12 +60,43 @@
       return this;
     }
 
+    /**
+     * Legacy javax version of the method to support libraries compiled with an older version of
+     * Dagger. Do not use directly.
+     */
+    @Deprecated
+    public Builder<K, V> put(K key, javax.inject.Provider<V> providerOfValue) {
+      return put(key, asDaggerProvider(providerOfValue));
+    }
+
     @Override
     public Builder<K, V> putAll(Provider<Map<K, Provider<V>>> mapProviderFactory) {
       super.putAll(mapProviderFactory);
       return this;
     }
 
+    /**
+     * Legacy javax version of the method to support libraries compiled with an older version of
+     * Dagger. Do not use directly.
+     */
+    @Deprecated
+    public Builder<K, V> putAll(
+        final javax.inject.Provider<Map<K, javax.inject.Provider<V>>> mapProviderFactory) {
+      return putAll(new Provider<Map<K, Provider<V>>>() {
+          @Override public Map<K, Provider<V>> get() {
+            Map<K, javax.inject.Provider<V>> javaxMap = mapProviderFactory.get();
+            if (javaxMap.isEmpty()) {
+              return Collections.emptyMap();
+            }
+            Map<K, Provider<V>> daggerMap = newLinkedHashMapWithExpectedSize(javaxMap.size());
+            for (Map.Entry<K, javax.inject.Provider<V>> e : javaxMap.entrySet()) {
+              daggerMap.put(e.getKey(), asDaggerProvider(e.getValue()));
+            }
+            return Collections.unmodifiableMap(daggerMap);
+          }
+      });
+    }
+
     /** Returns a new {@link MapProviderFactory}. */
     public MapProviderFactory<K, V> build() {
       return new MapProviderFactory<>(map);
diff --git a/java/dagger/internal/Provider.java b/java/dagger/internal/Provider.java
new file mode 100644
index 0000000..e388601
--- /dev/null
+++ b/java/dagger/internal/Provider.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.internal;
+
+/**
+ * Internal Provider interface to make support for {@code javax.inject.Provider} and
+ * {@code jakarta.inject.Provider} easier. Do not use outside of Dagger implementation code.
+ */
+// TODO(erichang): Make this also extend the Jakarta Provider
+public interface Provider<T> extends javax.inject.Provider<T> {
+}
diff --git a/java/dagger/internal/ProviderOfLazy.java b/java/dagger/internal/ProviderOfLazy.java
index 23b6afd..0430cbd 100644
--- a/java/dagger/internal/ProviderOfLazy.java
+++ b/java/dagger/internal/ProviderOfLazy.java
@@ -17,9 +17,9 @@
 package dagger.internal;
 
 import static dagger.internal.Preconditions.checkNotNull;
+import static dagger.internal.Providers.asDaggerProvider;
 
 import dagger.Lazy;
-import javax.inject.Provider;
 
 /**
  * A {@link Provider} of {@link Lazy} instances that each delegate to a given {@link Provider}.
@@ -51,4 +51,13 @@
   public static <T> Provider<Lazy<T>> create(Provider<T> provider) {
     return new ProviderOfLazy<T>(checkNotNull(provider));
   }
+
+  /**
+   * Legacy javax version of the method to support libraries compiled with an older version of
+   * Dagger. Do not use directly.
+   */
+  @Deprecated
+  public static <T> Provider<Lazy<T>> create(javax.inject.Provider<T> provider) {
+    return create(asDaggerProvider(provider));
+  }
 }
diff --git a/java/dagger/internal/Providers.java b/java/dagger/internal/Providers.java
new file mode 100644
index 0000000..60ec83f
--- /dev/null
+++ b/java/dagger/internal/Providers.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.internal;
+
+import static dagger.internal.Preconditions.checkNotNull;
+
+/** Helper class for utility functions dealing with Providers. */
+public final class Providers {
+
+  /** Converts a javax provider to a Dagger internal provider. */
+  public static <T> Provider<T> asDaggerProvider(final javax.inject.Provider<T> provider) {
+    checkNotNull(provider);
+    return new Provider<T>() {
+        @Override public T get() {
+          return provider.get();
+        }
+    };
+  }
+
+  private Providers() {}
+}
diff --git a/java/dagger/internal/SetFactory.java b/java/dagger/internal/SetFactory.java
index 349399b..f160767 100644
--- a/java/dagger/internal/SetFactory.java
+++ b/java/dagger/internal/SetFactory.java
@@ -20,6 +20,7 @@
 import static dagger.internal.DaggerCollections.newHashSetWithExpectedSize;
 import static dagger.internal.DaggerCollections.presizedList;
 import static dagger.internal.Preconditions.checkNotNull;
+import static dagger.internal.Providers.asDaggerProvider;
 import static java.util.Collections.emptySet;
 import static java.util.Collections.unmodifiableSet;
 
@@ -27,7 +28,6 @@
 import java.util.Collection;
 import java.util.List;
 import java.util.Set;
-import javax.inject.Provider;
 
 /**
  * A {@link Factory} implementation used to implement {@link Set} bindings. This factory always
@@ -73,6 +73,15 @@
       return this;
     }
 
+    /**
+     * Legacy javax version of the method to support libraries compiled with an older version of
+     * Dagger. Do not use directly.
+     */
+    @Deprecated
+    public Builder<T> addProvider(javax.inject.Provider<? extends T> individualProvider) {
+      return addProvider(asDaggerProvider(individualProvider));
+    }
+
     @SuppressWarnings("unchecked")
     public Builder<T> addCollectionProvider(
         Provider<? extends Collection<? extends T>> collectionProvider) {
@@ -81,6 +90,16 @@
       return this;
     }
 
+    /**
+     * Legacy javax version of the method to support libraries compiled with an older version of
+     * Dagger. Do not use directly.
+     */
+    @Deprecated
+    public Builder<T> addCollectionProvider(
+        javax.inject.Provider<? extends Collection<? extends T>> collectionProvider) {
+      return addCollectionProvider(asDaggerProvider(collectionProvider));
+    }
+
     public SetFactory<T> build() {
       assert !hasDuplicates(individualProviders)
           : "Codegen error?  Duplicates in the provider list";
diff --git a/java/dagger/internal/SingleCheck.java b/java/dagger/internal/SingleCheck.java
index 4128069..32ba83a 100644
--- a/java/dagger/internal/SingleCheck.java
+++ b/java/dagger/internal/SingleCheck.java
@@ -17,8 +17,7 @@
 package dagger.internal;
 
 import static dagger.internal.Preconditions.checkNotNull;
-
-import javax.inject.Provider;
+import static dagger.internal.Providers.asDaggerProvider;
 
 /**
  * A {@link Provider} implementation that memoizes the result of another {@link Provider} using
@@ -58,7 +57,7 @@
   }
 
   /** Returns a {@link Provider} that caches the value from the given delegate provider. */
-  // This method is declared this way instead of "<T> Provider<T> provider(Provider<T> provider)" 
+  // This method is declared this way instead of "<T> Provider<T> provider(Provider<T> provider)"
   // to work around an Eclipse type inference bug: https://github.com/google/dagger/issues/949.
   public static <P extends Provider<T>, T> Provider<T> provider(P provider) {
     // If a scoped @Binds delegates to a scoped binding, don't cache the value again.
@@ -67,4 +66,13 @@
     }
     return new SingleCheck<T>(checkNotNull(provider));
   }
+
+  /**
+   * Legacy javax version of the method to support libraries compiled with an older version of
+   * Dagger. Do not use directly.
+   */
+  public static <P extends javax.inject.Provider<T>, T> javax.inject.Provider<T> provider(
+      P delegate) {
+    return provider(asDaggerProvider(delegate));
+  }
 }
diff --git a/java/dagger/internal/codegen/BUILD b/java/dagger/internal/codegen/BUILD
index a3868b5..80ca8d7 100644
--- a/java/dagger/internal/codegen/BUILD
+++ b/java/dagger/internal/codegen/BUILD
@@ -43,7 +43,6 @@
         "//java/dagger/internal/codegen/compileroption",
         "//java/dagger/internal/codegen/componentgenerator",
         "//java/dagger/internal/codegen/kotlin",
-        "//java/dagger/internal/codegen/model",
         "//java/dagger/internal/codegen/processingstep",
         "//java/dagger/internal/codegen/validation",
         "//java/dagger/internal/codegen/writing",
@@ -89,7 +88,6 @@
     ],
     artifact_target_maven_deps = [
         "com.google.code.findbugs:jsr305",
-        "com.google.dagger:dagger-producers",
         "com.google.dagger:dagger-spi",
         "com.google.dagger:dagger",
         "com.google.devtools.ksp:symbol-processing-api",
diff --git a/java/dagger/internal/codegen/DelegateComponentProcessor.java b/java/dagger/internal/codegen/DelegateComponentProcessor.java
index 96d433b..432daa6 100644
--- a/java/dagger/internal/codegen/DelegateComponentProcessor.java
+++ b/java/dagger/internal/codegen/DelegateComponentProcessor.java
@@ -32,10 +32,13 @@
 import dagger.internal.codegen.base.ClearableCache;
 import dagger.internal.codegen.base.SourceFileGenerationException;
 import dagger.internal.codegen.base.SourceFileGenerator;
+import dagger.internal.codegen.base.SourceFileHjarGenerator;
 import dagger.internal.codegen.binding.BindingGraphFactory;
+import dagger.internal.codegen.binding.ComponentDescriptor;
 import dagger.internal.codegen.binding.InjectBindingRegistry;
 import dagger.internal.codegen.binding.MembersInjectionBinding;
 import dagger.internal.codegen.binding.ModuleDescriptor;
+import dagger.internal.codegen.binding.MonitoringModules;
 import dagger.internal.codegen.binding.ProductionBinding;
 import dagger.internal.codegen.binding.ProvisionBinding;
 import dagger.internal.codegen.bindinggraphvalidation.BindingGraphValidationModule;
@@ -53,7 +56,6 @@
 import dagger.internal.codegen.validation.InjectValidator;
 import dagger.internal.codegen.validation.ValidationBindingGraphPlugins;
 import dagger.internal.codegen.writing.FactoryGenerator;
-import dagger.internal.codegen.writing.HjarSourceFileGenerator;
 import dagger.internal.codegen.writing.MembersInjectorGenerator;
 import dagger.internal.codegen.writing.ModuleGenerator;
 import dagger.internal.codegen.writing.ModuleProxies.ModuleConstructorProxyGenerator;
@@ -98,8 +100,9 @@
                           + legacyPlugin.pluginName()
                           + ". Either compile with KAPT or migrate the plugin to implement "
                           + "dagger.spi.model.BindingGraphPlugin."));
-      // We've already reported warnings on the invalid legacy plugins above. We can't actually
-      // process these plugins in KSP, so just skip them to allow processing of the valid plugins.
+      // Even though we've reported an error, processing will still continue for the remainder of
+      // the processing round to try to catch other errors. We set the javac plugins to empty to
+      // skip processing since it would just result in ClassCastExceptions in KSP.
       legacyPlugins = ImmutableSet.of();
     }
     DaggerDelegateComponentProcessor_Injector.factory()
@@ -171,6 +174,14 @@
 
     @Binds
     @IntoSet
+    ClearableCache componentDescriptorFactory(ComponentDescriptor.Factory cache);
+
+    @Binds
+    @IntoSet
+    ClearableCache monitoringModules(MonitoringModules cache);
+
+    @Binds
+    @IntoSet
     ClearableCache bindingGraphFactory(BindingGraphFactory cache);
 
     @Binds
@@ -190,34 +201,44 @@
   interface SourceFileGeneratorsModule {
     @Provides
     static SourceFileGenerator<ProvisionBinding> factoryGenerator(
-        FactoryGenerator generator, CompilerOptions compilerOptions) {
-      return hjarWrapper(generator, compilerOptions);
+        FactoryGenerator generator,
+        CompilerOptions compilerOptions,
+        XProcessingEnv processingEnv) {
+      return hjarWrapper(generator, compilerOptions, processingEnv);
     }
 
     @Provides
     static SourceFileGenerator<ProductionBinding> producerFactoryGenerator(
-        ProducerFactoryGenerator generator, CompilerOptions compilerOptions) {
-      return hjarWrapper(generator, compilerOptions);
+        ProducerFactoryGenerator generator,
+        CompilerOptions compilerOptions,
+        XProcessingEnv processingEnv) {
+      return hjarWrapper(generator, compilerOptions, processingEnv);
     }
 
     @Provides
     static SourceFileGenerator<MembersInjectionBinding> membersInjectorGenerator(
-        MembersInjectorGenerator generator, CompilerOptions compilerOptions) {
-      return hjarWrapper(generator, compilerOptions);
+        MembersInjectorGenerator generator,
+        CompilerOptions compilerOptions,
+        XProcessingEnv processingEnv) {
+      return hjarWrapper(generator, compilerOptions, processingEnv);
     }
 
     @Provides
     @ModuleGenerator
     static SourceFileGenerator<XTypeElement> moduleConstructorProxyGenerator(
-        ModuleConstructorProxyGenerator generator, CompilerOptions compilerOptions) {
-      return hjarWrapper(generator, compilerOptions);
+        ModuleConstructorProxyGenerator generator,
+        CompilerOptions compilerOptions,
+        XProcessingEnv processingEnv) {
+      return hjarWrapper(generator, compilerOptions, processingEnv);
     }
   }
 
   private static <T> SourceFileGenerator<T> hjarWrapper(
-      SourceFileGenerator<T> generator, CompilerOptions compilerOptions) {
+      SourceFileGenerator<T> generator,
+      CompilerOptions compilerOptions,
+      XProcessingEnv processingEnv) {
     return compilerOptions.headerCompilation()
-        ? HjarSourceFileGenerator.wrap(generator)
+        ? SourceFileHjarGenerator.wrap(generator, processingEnv)
         : generator;
   }
 }
diff --git a/java/dagger/internal/codegen/base/ElementFormatter.java b/java/dagger/internal/codegen/base/ElementFormatter.java
index 16381e3..8e3edc9 100644
--- a/java/dagger/internal/codegen/base/ElementFormatter.java
+++ b/java/dagger/internal/codegen/base/ElementFormatter.java
@@ -36,7 +36,8 @@
  *
  * <p>Elements directly enclosed by a type are preceded by the enclosing type's qualified name.
  *
- * <p>Parameters are given with their enclosing executable, with other parameters elided.
+ * <p>If the element is a parameter, the returned string will include the enclosing executable,
+ * with other parameters elided.
  */
 public final class ElementFormatter extends Formatter<XElement> {
   @Inject
@@ -52,15 +53,29 @@
    *
    * <p>Elements directly enclosed by a type are preceded by the enclosing type's qualified name.
    *
-   * <p>Parameters are given with their enclosing executable, with other parameters elided.
+   * <p>If the element is a parameter, the returned string will include the enclosing executable,
+   * with other parameters elided.
    */
   public static String elementToString(XElement element) {
+    return elementToString(element, /* elideMethodParameterTypes= */ false);
+  }
+
+  /**
+   * Returns a useful string form for an element.
+   *
+   * <p>Elements directly enclosed by a type are preceded by the enclosing type's qualified name.
+   *
+   * <p>Parameters are given with their enclosing executable, with other parameters elided.
+   */
+  public static String elementToString(XElement element, boolean elideMethodParameterTypes) {
     if (isExecutable(element)) {
       return enclosingTypeAndMemberName(element)
           .append(
-              asExecutable(element).getParameters().stream()
-                  .map(parameter -> XTypes.toStableString(parameter.getType()))
-                  .collect(joining(", ", "(", ")")))
+              elideMethodParameterTypes
+                  ? (asExecutable(element).getParameters().isEmpty() ? "()" : "(…)")
+                  : asExecutable(element).getParameters().stream()
+                      .map(parameter -> XTypes.toStableString(parameter.getType()))
+                      .collect(joining(", ", "(", ")")))
           .toString();
     } else if (isMethodParameter(element)) {
       XExecutableElement methodOrConstructor = asMethodParameter(element).getEnclosingElement();
diff --git a/java/dagger/internal/codegen/base/FrameworkTypes.java b/java/dagger/internal/codegen/base/FrameworkTypes.java
index 59588ca..e39aeab 100644
--- a/java/dagger/internal/codegen/base/FrameworkTypes.java
+++ b/java/dagger/internal/codegen/base/FrameworkTypes.java
@@ -29,6 +29,7 @@
  * type that the framework itself defines.
  */
 public final class FrameworkTypes {
+  // TODO(erichang): Add the Jakarta Provider here
   private static final ImmutableSet<ClassName> PROVISION_TYPES =
       ImmutableSet.of(TypeNames.PROVIDER, TypeNames.LAZY, TypeNames.MEMBERS_INJECTOR);
 
diff --git a/java/dagger/internal/codegen/base/MapType.java b/java/dagger/internal/codegen/base/MapType.java
index 00401ed..c4ba838 100644
--- a/java/dagger/internal/codegen/base/MapType.java
+++ b/java/dagger/internal/codegen/base/MapType.java
@@ -115,6 +115,13 @@
     return isMap(key.type().xprocessing());
   }
 
+  public static boolean isMapOfProvider(XType keyType) {
+    if (MapType.isMap(keyType)) {
+      return MapType.from(keyType).valuesAreTypeOf(TypeNames.PROVIDER);
+    }
+    return false;
+  }
+
   /**
    * Returns a {@link MapType} for {@code type}.
    *
diff --git a/java/dagger/internal/codegen/base/OptionalType.java b/java/dagger/internal/codegen/base/OptionalType.java
index 79b638d..5544eae 100644
--- a/java/dagger/internal/codegen/base/OptionalType.java
+++ b/java/dagger/internal/codegen/base/OptionalType.java
@@ -20,6 +20,7 @@
 import static dagger.internal.codegen.extension.DaggerStreams.toImmutableMap;
 import static dagger.internal.codegen.extension.DaggerStreams.valuesOf;
 import static dagger.internal.codegen.xprocessing.XTypes.isDeclared;
+import static dagger.internal.codegen.xprocessing.XTypes.isTypeOf;
 
 import androidx.room.compiler.processing.XType;
 import androidx.room.compiler.processing.XTypeElement;
@@ -155,4 +156,14 @@
   public static OptionalType from(Key key) {
     return from(key.type().xprocessing());
   }
+
+  public static boolean isOptionalProviderType(XType type) {
+    if (OptionalType.isOptional(type)) {
+      OptionalType optionalType = OptionalType.from(type);
+      if (isTypeOf(optionalType.valueType(), TypeNames.PROVIDER)) {
+        return true;
+      }
+    }
+    return false;
+  }
 }
diff --git a/java/dagger/internal/codegen/base/SourceFileGenerator.java b/java/dagger/internal/codegen/base/SourceFileGenerator.java
index c43499a..dfe14b1 100644
--- a/java/dagger/internal/codegen/base/SourceFileGenerator.java
+++ b/java/dagger/internal/codegen/base/SourceFileGenerator.java
@@ -18,6 +18,7 @@
 
 import static androidx.room.compiler.processing.JavaPoetExtKt.addOriginatingElement;
 import static com.google.common.base.Preconditions.checkNotNull;
+import static dagger.internal.codegen.javapoet.AnnotationSpecs.Suppression.CAST;
 import static dagger.internal.codegen.javapoet.AnnotationSpecs.Suppression.KOTLIN_INTERNAL;
 import static dagger.internal.codegen.javapoet.AnnotationSpecs.Suppression.RAWTYPES;
 import static dagger.internal.codegen.javapoet.AnnotationSpecs.Suppression.UNCHECKED;
@@ -100,13 +101,12 @@
                         .build());
     generatedAnnotation.ifPresent(typeSpecBuilder::addAnnotation);
 
-    // TODO(b/134590785): Remove UNCHECKED/RAWTYPES and suppress locally where necessary.
     // TODO(b/263891456): Remove KOTLIN_INTERNAL and use Object/raw types where necessary.
     typeSpecBuilder.addAnnotation(
         AnnotationSpecs.suppressWarnings(
             ImmutableSet.<Suppression>builder()
                 .addAll(warningSuppressions())
-                .add(UNCHECKED, RAWTYPES, KOTLIN_INTERNAL)
+                .add(UNCHECKED, RAWTYPES, KOTLIN_INTERNAL, CAST)
                 .build()));
 
     String packageName = closestEnclosingTypeElement(originatingElement).getPackageName();
diff --git a/java/dagger/internal/codegen/base/SourceFileHjarGenerator.java b/java/dagger/internal/codegen/base/SourceFileHjarGenerator.java
new file mode 100644
index 0000000..6857c36
--- /dev/null
+++ b/java/dagger/internal/codegen/base/SourceFileHjarGenerator.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2017 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.internal.codegen.base;
+
+import static com.squareup.javapoet.MethodSpec.constructorBuilder;
+import static com.squareup.javapoet.MethodSpec.methodBuilder;
+import static com.squareup.javapoet.TypeSpec.classBuilder;
+import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
+import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
+import static dagger.internal.codegen.langmodel.Accessibility.isElementAccessibleFrom;
+import static dagger.internal.codegen.xprocessing.XElements.closestEnclosingTypeElement;
+import static javax.lang.model.element.Modifier.PRIVATE;
+
+import androidx.room.compiler.processing.XConstructorElement;
+import androidx.room.compiler.processing.XElement;
+import androidx.room.compiler.processing.XExecutableParameterElement;
+import androidx.room.compiler.processing.XProcessingEnv;
+import androidx.room.compiler.processing.XType;
+import androidx.room.compiler.processing.XTypeElement;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.FieldSpec;
+import com.squareup.javapoet.MethodSpec;
+import com.squareup.javapoet.TypeName;
+import com.squareup.javapoet.TypeSpec;
+import dagger.internal.codegen.javapoet.CodeBlocks;
+import dagger.internal.codegen.javapoet.TypeNames;
+import java.util.Optional;
+import javax.lang.model.element.Modifier;
+
+/**
+ * A source file generator that only writes the relevant code necessary for Bazel to create a
+ * correct header (ABI) jar.
+ */
+public final class SourceFileHjarGenerator<T> extends SourceFileGenerator<T> {
+  public static <T> SourceFileGenerator<T> wrap(
+      SourceFileGenerator<T> delegate, XProcessingEnv processingEnv) {
+    return new SourceFileHjarGenerator<>(delegate, processingEnv);
+  }
+
+  private final SourceFileGenerator<T> delegate;
+  private final XProcessingEnv processingEnv;
+
+  private SourceFileHjarGenerator(SourceFileGenerator<T> delegate, XProcessingEnv processingEnv) {
+    super(delegate);
+    this.delegate = delegate;
+    this.processingEnv = processingEnv;
+  }
+
+  @Override
+  public XElement originatingElement(T input) {
+    return delegate.originatingElement(input);
+  }
+
+  @Override
+  public ImmutableList<TypeSpec.Builder> topLevelTypes(T input) {
+    String packageName = closestEnclosingTypeElement(originatingElement(input)).getPackageName();
+    return delegate.topLevelTypes(input).stream()
+        .map(completeType -> skeletonType(packageName, completeType.build()))
+        .collect(toImmutableList());
+  }
+
+  private TypeSpec.Builder skeletonType(String packageName, TypeSpec completeType) {
+    TypeSpec.Builder skeleton =
+        classBuilder(completeType.name)
+            .addSuperinterfaces(completeType.superinterfaces)
+            .addTypeVariables(completeType.typeVariables)
+            .addModifiers(completeType.modifiers.toArray(new Modifier[0]))
+            .addAnnotations(completeType.annotations);
+
+    if (!completeType.superclass.equals(ClassName.OBJECT)) {
+      skeleton.superclass(completeType.superclass);
+    }
+
+    completeType.methodSpecs.stream()
+        .filter(method -> !method.modifiers.contains(PRIVATE) || method.isConstructor())
+        .map(completeMethod -> skeletonMethod(packageName, completeType, completeMethod))
+        .forEach(skeleton::addMethod);
+
+    completeType.fieldSpecs.stream()
+        .filter(field -> !field.modifiers.contains(PRIVATE))
+        .map(this::skeletonField)
+        .forEach(skeleton::addField);
+
+    completeType.typeSpecs.stream()
+        .map(type -> skeletonType(packageName, type).build())
+        .forEach(skeleton::addType);
+
+    completeType.alwaysQualifiedNames
+        .forEach(skeleton::alwaysQualify);
+
+    return skeleton;
+  }
+
+  private MethodSpec skeletonMethod(
+      String packageName, TypeSpec completeType, MethodSpec completeMethod) {
+    MethodSpec.Builder skeleton =
+        completeMethod.isConstructor()
+            ? constructorBuilder()
+            : methodBuilder(completeMethod.name).returns(completeMethod.returnType);
+
+    if (completeMethod.isConstructor()) {
+      getRequiredSuperCall(packageName, completeType)
+          .ifPresent(superCall -> skeleton.addStatement("$L", superCall));
+    } else if (!completeMethod.returnType.equals(TypeName.VOID)) {
+      skeleton.addStatement("return $L", getDefaultValueCodeBlock(completeMethod.returnType));
+    }
+
+    return skeleton
+        .addModifiers(completeMethod.modifiers)
+        .addTypeVariables(completeMethod.typeVariables)
+        .addParameters(completeMethod.parameters)
+        .addExceptions(completeMethod.exceptions)
+        .varargs(completeMethod.varargs)
+        .addAnnotations(completeMethod.annotations)
+        .build();
+  }
+
+  private Optional<CodeBlock> getRequiredSuperCall(String packageName, TypeSpec completeType) {
+    if (completeType.superclass.equals(TypeName.OBJECT)) {
+      return Optional.empty();
+    }
+
+    ClassName rawSuperClass = (ClassName) TypeNames.rawTypeName(completeType.superclass);
+    XTypeElement superTypeElement =
+        processingEnv.requireTypeElement(rawSuperClass.canonicalName());
+
+    ImmutableSet<XConstructorElement> accessibleConstructors =
+        superTypeElement.getConstructors().stream()
+            .filter(
+                constructor ->
+                    // isElementAccessibleFrom doesn't take protected into account so check manually
+                    constructor.isProtected()
+                        || isElementAccessibleFrom(constructor, packageName))
+            .collect(toImmutableSet());
+
+    // If there's an accessible default constructor we don't need to call super() manually.
+    if (accessibleConstructors.isEmpty()
+            || accessibleConstructors.stream()
+                .anyMatch(constructor -> constructor.getParameters().isEmpty())) {
+      return Optional.empty();
+    }
+
+    return Optional.of(
+        CodeBlock.of(
+            "super($L)",
+            CodeBlocks.makeParametersCodeBlock(
+                // We just choose the first constructor (it doesn't really matter since we're just
+                // trying to ensure the constructor body compiles).
+                accessibleConstructors.stream().findFirst().get().getParameters().stream()
+                    .map(XExecutableParameterElement::getType)
+                    .map(XType::getTypeName)
+                    .map(SourceFileHjarGenerator::getDefaultValueCodeBlock)
+                    .collect(toImmutableList()))));
+  }
+
+  /**
+   * Returns a {@link CodeBlock} containing the default value for the given {@code typeName}.
+   *
+   * <p>See https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html.
+   */
+  private static CodeBlock getDefaultValueCodeBlock(TypeName typeName) {
+    if (typeName.isPrimitive()) {
+      if (typeName.equals(TypeName.BOOLEAN)) {
+        return CodeBlock.of("false");
+      } else if (typeName.equals(TypeName.CHAR)) {
+        return CodeBlock.of("'\u0000'");
+      } else if (typeName.equals(TypeName.BYTE)) {
+        return CodeBlock.of("0");
+      } else if (typeName.equals(TypeName.SHORT)) {
+        return CodeBlock.of("0");
+      } else if (typeName.equals(TypeName.INT)) {
+        return CodeBlock.of("0");
+      } else if (typeName.equals(TypeName.LONG)) {
+        return CodeBlock.of("0L");
+      } else if (typeName.equals(TypeName.FLOAT)) {
+        return CodeBlock.of("0.0f");
+      } else if (typeName.equals(TypeName.DOUBLE)) {
+        return CodeBlock.of("0.0d");
+      } else {
+        throw new AssertionError("Unexpected type: " + typeName);
+      }
+    }
+    return CodeBlock.of("null");
+  }
+
+  private FieldSpec skeletonField(FieldSpec completeField) {
+    return FieldSpec.builder(
+            completeField.type,
+            completeField.name,
+            completeField.modifiers.toArray(new Modifier[0]))
+        .addAnnotations(completeField.annotations)
+        .build();
+  }
+}
diff --git a/java/dagger/internal/codegen/base/TarjanSCCs.java b/java/dagger/internal/codegen/base/TarjanSCCs.java
index ab9a0fd..b089333 100644
--- a/java/dagger/internal/codegen/base/TarjanSCCs.java
+++ b/java/dagger/internal/codegen/base/TarjanSCCs.java
@@ -20,6 +20,7 @@
 import static java.lang.Math.min;
 
 import com.google.common.collect.ImmutableCollection;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
@@ -39,7 +40,7 @@
 public final class TarjanSCCs {
 
   /** Returns the set of strongly connected components in reverse topological order. */
-  public static <NodeT> ImmutableSet<ImmutableSet<NodeT>> compute(
+  public static <NodeT> ImmutableList<ImmutableSet<NodeT>> compute(
       ImmutableCollection<NodeT> nodes, SuccessorsFunction<NodeT> successorsFunction) {
     return new TarjanSCC<>(nodes, successorsFunction).compute();
   }
@@ -62,14 +63,14 @@
       this.lowLinks = Maps.newHashMapWithExpectedSize(nodes.size());
     }
 
-    private ImmutableSet<ImmutableSet<NodeT>> compute() {
+    private ImmutableList<ImmutableSet<NodeT>> compute() {
       checkState(indexes.isEmpty(), "TarjanSCC#compute() can only be called once per instance!");
       for (NodeT node : nodes) {
         if (!indexes.containsKey(node)) {
           stronglyConnect(node);
         }
       }
-      return ImmutableSet.copyOf(stronglyConnectedComponents);
+      return ImmutableList.copyOf(stronglyConnectedComponents);
     }
 
     private void stronglyConnect(NodeT node) {
diff --git a/java/dagger/internal/codegen/binding/AnnotationExpression.java b/java/dagger/internal/codegen/binding/AnnotationExpression.java
index 6980c14..535a7ef 100644
--- a/java/dagger/internal/codegen/binding/AnnotationExpression.java
+++ b/java/dagger/internal/codegen/binding/AnnotationExpression.java
@@ -112,7 +112,7 @@
     } else if (value.hasAnnotationValue()) {
       return getAnnotationInstanceExpression(value.asAnnotation());
     } else if (value.hasTypeValue()) {
-      return CodeBlock.of("$T.class", value.asType().getTypeName());
+      return CodeBlock.of("$T.class", value.asType().getTypeElement().getClassName());
     } else if (value.hasStringValue()) {
       return CodeBlock.of("$S", value.asString());
     } else if (value.hasByteValue()) {
diff --git a/java/dagger/internal/codegen/binding/AssistedInjectionAnnotations.java b/java/dagger/internal/codegen/binding/AssistedInjectionAnnotations.java
index a8bca09..50a36b9 100644
--- a/java/dagger/internal/codegen/binding/AssistedInjectionAnnotations.java
+++ b/java/dagger/internal/codegen/binding/AssistedInjectionAnnotations.java
@@ -22,11 +22,11 @@
 import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
 import static dagger.internal.codegen.xprocessing.XElements.asConstructor;
 import static dagger.internal.codegen.xprocessing.XElements.asTypeElement;
-import static dagger.internal.codegen.xprocessing.XElements.getSimpleName;
 
 import androidx.room.compiler.processing.XConstructorElement;
 import androidx.room.compiler.processing.XConstructorType;
 import androidx.room.compiler.processing.XElement;
+import androidx.room.compiler.processing.XExecutableParameterElement;
 import androidx.room.compiler.processing.XHasModifiers;
 import androidx.room.compiler.processing.XMethodElement;
 import androidx.room.compiler.processing.XMethodType;
@@ -90,14 +90,15 @@
   }
 
   private static ImmutableList<ParameterSpec> assistedParameterSpecs(
-      List<? extends XVariableElement> paramElements, List<XType> paramTypes) {
+      List<? extends XExecutableParameterElement> paramElements, List<XType> paramTypes) {
     ImmutableList.Builder<ParameterSpec> assistedParameterSpecs = ImmutableList.builder();
     for (int i = 0; i < paramElements.size(); i++) {
-      XVariableElement paramElement = paramElements.get(i);
+      XExecutableParameterElement paramElement = paramElements.get(i);
       XType paramType = paramTypes.get(i);
       if (isAssistedParameter(paramElement)) {
         assistedParameterSpecs.add(
-            ParameterSpec.builder(paramType.getTypeName(), getSimpleName(paramElement)).build());
+            ParameterSpec.builder(paramType.getTypeName(), paramElement.getJvmName())
+                .build());
       }
     }
     return assistedParameterSpecs.build();
@@ -133,7 +134,7 @@
         .collect(toImmutableSet());
   }
 
-  public static ImmutableList<XVariableElement> assistedParameters(Binding binding) {
+  public static ImmutableList<XExecutableParameterElement> assistedParameters(Binding binding) {
     return binding.kind() == BindingKind.ASSISTED_INJECTION
         ? asConstructor(binding.bindingElement().get()).getParameters().stream()
             .filter(AssistedInjectionAnnotations::isAssistedParameter)
@@ -184,8 +185,10 @@
     public abstract ImmutableList<AssistedParameter> assistedFactoryAssistedParameters();
 
     @Memoized
-    public ImmutableMap<AssistedParameter, XVariableElement> assistedInjectAssistedParametersMap() {
-      ImmutableMap.Builder<AssistedParameter, XVariableElement> builder = ImmutableMap.builder();
+    public ImmutableMap<AssistedParameter, XExecutableParameterElement>
+        assistedInjectAssistedParametersMap() {
+      ImmutableMap.Builder<AssistedParameter, XExecutableParameterElement> builder =
+          ImmutableMap.builder();
       for (AssistedParameter assistedParameter : assistedInjectAssistedParameters()) {
         builder.put(assistedParameter, assistedParameter.element());
       }
@@ -193,9 +196,10 @@
     }
 
     @Memoized
-    public ImmutableMap<AssistedParameter, XVariableElement>
+    public ImmutableMap<AssistedParameter, XExecutableParameterElement>
         assistedFactoryAssistedParametersMap() {
-      ImmutableMap.Builder<AssistedParameter, XVariableElement> builder = ImmutableMap.builder();
+      ImmutableMap.Builder<AssistedParameter, XExecutableParameterElement> builder =
+          ImmutableMap.builder();
       for (AssistedParameter assistedParameter : assistedFactoryAssistedParameters()) {
         builder.put(assistedParameter, assistedParameter.element());
       }
@@ -211,7 +215,8 @@
    */
   @AutoValue
   public abstract static class AssistedParameter {
-    public static AssistedParameter create(XVariableElement parameter, XType parameterType) {
+    public static AssistedParameter create(
+        XExecutableParameterElement parameter, XType parameterType) {
       AssistedParameter assistedParameter =
           new AutoValue_AssistedInjectionAnnotations_AssistedParameter(
               Optional.ofNullable(parameter.getAnnotation(TypeNames.ASSISTED))
@@ -223,7 +228,7 @@
       return assistedParameter;
     }
 
-    private XVariableElement parameterElement;
+    private XExecutableParameterElement parameterElement;
     private XType parameterType;
 
     /** Returns the string qualifier from the {@link Assisted#value()}. */
@@ -237,7 +242,7 @@
       return parameterType;
     }
 
-    public final XVariableElement element() {
+    public final XExecutableParameterElement element() {
       return parameterElement;
     }
 
@@ -260,7 +265,7 @@
 
     ImmutableList.Builder<AssistedParameter> builder = ImmutableList.builder();
     for (int i = 0; i < assistedInjectConstructor.getParameters().size(); i++) {
-      XVariableElement parameter = assistedInjectConstructor.getParameters().get(i);
+      XExecutableParameterElement parameter = assistedInjectConstructor.getParameters().get(i);
       XType parameterType = assistedInjectConstructorType.getParameterTypes().get(i);
       if (parameter.hasAnnotation(TypeNames.ASSISTED)) {
         builder.add(AssistedParameter.create(parameter, parameterType));
@@ -273,7 +278,7 @@
       XMethodElement factoryMethod, XMethodType factoryMethodType) {
     ImmutableList.Builder<AssistedParameter> builder = ImmutableList.builder();
     for (int i = 0; i < factoryMethod.getParameters().size(); i++) {
-      XVariableElement parameter = factoryMethod.getParameters().get(i);
+      XExecutableParameterElement parameter = factoryMethod.getParameters().get(i);
       XType parameterType = factoryMethodType.getParameterTypes().get(i);
       builder.add(AssistedParameter.create(parameter, parameterType));
     }
diff --git a/java/dagger/internal/codegen/binding/BUILD b/java/dagger/internal/codegen/binding/BUILD
index e606eb4..7ba349e 100644
--- a/java/dagger/internal/codegen/binding/BUILD
+++ b/java/dagger/internal/codegen/binding/BUILD
@@ -31,11 +31,8 @@
         "//java/dagger/internal/codegen/extension",
         "//java/dagger/internal/codegen/javapoet",
         "//java/dagger/internal/codegen/kotlin",
-        "//java/dagger/internal/codegen/langmodel",
         "//java/dagger/internal/codegen/model",
         "//java/dagger/internal/codegen/xprocessing",
-        "//java/dagger/producers",
-        "//third_party/java/auto:common",
         "//third_party/java/auto:value",
         "//third_party/java/error_prone:annotations",
         "//third_party/java/guava/base",
diff --git a/java/dagger/internal/codegen/binding/BindingGraph.java b/java/dagger/internal/codegen/binding/BindingGraph.java
index 8dfe74f..0090b3d 100644
--- a/java/dagger/internal/codegen/binding/BindingGraph.java
+++ b/java/dagger/internal/codegen/binding/BindingGraph.java
@@ -149,7 +149,7 @@
 
     /** Returns the set of strongly connected nodes in this graph in reverse topological order. */
     @Memoized
-    public ImmutableSet<ImmutableSet<Node>> stronglyConnectedNodes() {
+    public ImmutableList<ImmutableSet<Node>> stronglyConnectedNodes() {
       return TarjanSCCs.<Node>compute(
           ImmutableSet.copyOf(network().nodes()),
           // NetworkBuilder does not have a stable successor order, so we have to roll our own
@@ -212,14 +212,7 @@
     // particular BindingNode.
     Map<Key, BindingNode> contributionBindings = new LinkedHashMap<>();
     Map<Key, BindingNode> membersInjectionBindings = new LinkedHashMap<>();
-
-    // Construct the maps of the ContributionBindings and MembersInjectionBindings by iterating
-    // bindings from this component and then from each successive parent. If a binding exists in
-    // multple components, this order ensures that the child-most binding is always chosen first.
-    Stream.iterate(componentNode.componentPath(), ComponentPath::parent)
-        // Stream.iterate is inifinte stream so we need limit it to the known size of the path.
-        .limit(componentNode.componentPath().components().size())
-        .flatMap(path -> topLevelBindingGraph.bindingsByComponent().get(path).stream())
+    topLevelBindingGraph.bindingsByComponent().get(componentNode.componentPath())
         .forEach(
             bindingNode -> {
               if (bindingNode.delegate() instanceof ContributionBinding) {
@@ -233,16 +226,19 @@
 
     BindingGraph bindingGraph = new AutoValue_BindingGraph(componentNode, topLevelBindingGraph);
 
-    ImmutableSet<ModuleDescriptor> modules =
-        ((ComponentNodeImpl) componentNode).componentDescriptor().modules();
+    ImmutableSet<XTypeElement> modules =
+        ((ComponentNodeImpl) componentNode).componentDescriptor().modules().stream()
+            .map(ModuleDescriptor::moduleElement)
+            .collect(toImmutableSet());
 
-    ImmutableSet<ModuleDescriptor> inheritedModules =
+    ImmutableSet<XTypeElement> inheritedModules =
         parent.isPresent()
             ? Sets.union(parent.get().ownedModules, parent.get().inheritedModules).immutableCopy()
             : ImmutableSet.of();
 
     // Set these fields directly on the instance rather than passing these in as input to the
     // AutoValue to prevent exposing this data outside of the class.
+    bindingGraph.parent = parent;
     bindingGraph.inheritedModules = inheritedModules;
     bindingGraph.ownedModules = Sets.difference(modules, inheritedModules).immutableCopy();
     bindingGraph.contributionBindings = ImmutableMap.copyOf(contributionBindings);
@@ -257,10 +253,11 @@
     return bindingGraph;
   }
 
+  private Optional<BindingGraph> parent;
   private ImmutableMap<Key, BindingNode> contributionBindings;
   private ImmutableMap<Key, BindingNode> membersInjectionBindings;
-  private ImmutableSet<ModuleDescriptor> inheritedModules;
-  private ImmutableSet<ModuleDescriptor> ownedModules;
+  private ImmutableSet<XTypeElement> inheritedModules;
+  private ImmutableSet<XTypeElement> ownedModules;
   private ImmutableSet<XTypeElement> bindingModules;
 
   BindingGraph() {}
@@ -287,9 +284,7 @@
    */
   public final Optional<Binding> localContributionBinding(Key key) {
     return contributionBindings.containsKey(key)
-        ? Optional.of(contributionBindings.get(key))
-            .filter(bindingNode -> bindingNode.componentPath().equals(componentPath()))
-            .map(BindingNode::delegate)
+        ? Optional.of(contributionBindings.get(key).delegate())
         : Optional.empty();
   }
 
@@ -299,15 +294,18 @@
    */
   public final Optional<Binding> localMembersInjectionBinding(Key key) {
     return membersInjectionBindings.containsKey(key)
-        ? Optional.of(membersInjectionBindings.get(key))
-            .filter(bindingNode -> bindingNode.componentPath().equals(componentPath()))
-            .map(BindingNode::delegate)
+        ? Optional.of(membersInjectionBindings.get(key).delegate())
         : Optional.empty();
   }
 
   /** Returns the {@link ContributionBinding} for the given {@link Key}. */
   public final ContributionBinding contributionBinding(Key key) {
-    return (ContributionBinding) contributionBindings.get(key).delegate();
+    if (contributionBindings.containsKey(key)) {
+      return (ContributionBinding) contributionBindings.get(key).delegate();
+    } else if (parent.isPresent()) {
+      return parent.get().contributionBinding(key);
+    }
+    throw new AssertionError("Contribution binding not found for key: " + key);
   }
 
   /**
@@ -315,9 +313,12 @@
    * Optional#empty()} if one does not exist.
    */
   public final Optional<MembersInjectionBinding> membersInjectionBinding(Key key) {
-    return membersInjectionBindings.containsKey(key)
-        ? Optional.of((MembersInjectionBinding) membersInjectionBindings.get(key).delegate())
-        : Optional.empty();
+    if (membersInjectionBindings.containsKey(key)) {
+      return Optional.of((MembersInjectionBinding) membersInjectionBindings.get(key).delegate());
+    } else if (parent.isPresent()) {
+      return parent.get().membersInjectionBinding(key);
+    }
+    return Optional.empty();
   }
 
   /** Returns the {@link XTypeElement} for the component this graph represents. */
@@ -334,9 +335,7 @@
    * ancestors.
    */
   public final ImmutableSet<XTypeElement> ownedModuleTypes() {
-    return ownedModules.stream()
-        .map(ModuleDescriptor::moduleElement)
-        .collect(toImmutableSet());
+    return ownedModules;
   }
 
   /**
@@ -394,7 +393,7 @@
     ImmutableSet<XTypeElement> requiredModules =
         stream(Traverser.forTree(BindingGraph::subgraphs).depthFirstPostOrder(this))
             .flatMap(graph -> graph.bindingModules.stream())
-            .filter(ownedModuleTypes()::contains)
+            .filter(ownedModules::contains)
             .collect(toImmutableSet());
     ImmutableSet.Builder<ComponentRequirement> requirements = ImmutableSet.builder();
     componentDescriptor().requirements().stream()
@@ -433,11 +432,18 @@
     return topLevelBindingGraph().bindingsByComponent().get(componentPath());
   }
 
-  @Memoized
+  // TODO(bcorso): This method can be costly. Consider removing this method and inlining it into its
+  // only usage, BindingGraphJsonGenerator.
   public ImmutableSet<BindingNode> bindingNodes() {
-    return ImmutableSet.<BindingNode>builder()
-        .addAll(contributionBindings.values())
-        .addAll(membersInjectionBindings.values())
-        .build();
+    // Construct the set of bindings by iterating bindings from this component and then from each
+    // successive parent. If a binding exists in multiple components, this order ensures that the
+    // child-most binding is always chosen first.
+    Map<Key, BindingNode> bindings = new LinkedHashMap<>();
+    Stream.iterate(componentPath(), ComponentPath::parent)
+        // Stream.iterate() is infinite stream so we need limit it to the known size of the path.
+        .limit(componentPath().components().size())
+        .flatMap(path -> topLevelBindingGraph().bindingsByComponent().get(path).stream())
+        .forEach(bindingNode -> bindings.putIfAbsent(bindingNode.key(), bindingNode));
+    return ImmutableSet.copyOf(bindings.values());
   }
 }
diff --git a/java/dagger/internal/codegen/binding/BindingGraphConverter.java b/java/dagger/internal/codegen/binding/BindingGraphConverter.java
index 5928b8f..adb4435 100644
--- a/java/dagger/internal/codegen/binding/BindingGraphConverter.java
+++ b/java/dagger/internal/codegen/binding/BindingGraphConverter.java
@@ -19,23 +19,19 @@
 import static com.google.common.base.Verify.verify;
 import static dagger.internal.codegen.binding.BindingRequest.bindingRequest;
 import static dagger.internal.codegen.extension.DaggerGraphs.unreachableNodes;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
 import static dagger.internal.codegen.model.BindingKind.SUBCOMPONENT_CREATOR;
 
-import androidx.room.compiler.processing.XMethodElement;
 import androidx.room.compiler.processing.XType;
 import androidx.room.compiler.processing.XTypeElement;
 import com.google.auto.value.AutoValue;
 import com.google.auto.value.extension.memoized.Memoized;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Iterators;
 import com.google.common.graph.ImmutableNetwork;
 import com.google.common.graph.MutableNetwork;
-import com.google.common.graph.Network;
 import com.google.common.graph.NetworkBuilder;
 import dagger.internal.codegen.binding.BindingGraph.TopLevelBindingGraph;
+import dagger.internal.codegen.binding.BindingGraphFactory.LegacyBindingGraph;
 import dagger.internal.codegen.binding.ComponentDescriptor.ComponentMethodDescriptor;
 import dagger.internal.codegen.model.BindingGraph.ComponentNode;
 import dagger.internal.codegen.model.BindingGraph.DependencyEdge;
@@ -43,7 +39,6 @@
 import dagger.internal.codegen.model.BindingGraph.MissingBinding;
 import dagger.internal.codegen.model.BindingGraph.Node;
 import dagger.internal.codegen.model.ComponentPath;
-import dagger.internal.codegen.model.DaggerExecutableElement;
 import dagger.internal.codegen.model.DaggerTypeElement;
 import dagger.internal.codegen.model.DependencyRequest;
 import dagger.internal.codegen.model.Key;
@@ -70,7 +65,7 @@
    */
   BindingGraph convert(LegacyBindingGraph legacyBindingGraph, boolean isFullBindingGraph) {
     MutableNetwork<Node, Edge> network = asNetwork(legacyBindingGraph);
-    ComponentNode rootNode = rootComponentNode(network);
+    ComponentNode rootNode = legacyBindingGraph.componentNode();
 
     // When bindings are copied down into child graphs because they transitively depend on local
     // multibindings or optional bindings, the parent-owned binding is still there. If that
@@ -92,47 +87,19 @@
     return converter.network;
   }
 
-  // TODO(dpb): Example of BindingGraph logic applied to derived networks.
-  private ComponentNode rootComponentNode(Network<Node, Edge> network) {
-    return (ComponentNode)
-        Iterables.find(
-            network.nodes(),
-            node -> node instanceof ComponentNode && node.componentPath().atRoot());
-  }
-
-  /**
-   * Used as a cache key to make sure resolved bindings are cached per component path.
-   * This is required so that binding nodes are not reused across different branches of the
-   * graph since the ResolvedBindings class only contains the component and not the path.
-   */
-  @AutoValue
-  abstract static class ResolvedBindingsWithPath {
-    abstract ResolvedBindings resolvedBindings();
-    abstract ComponentPath componentPath();
-
-    static ResolvedBindingsWithPath create(
-        ResolvedBindings resolvedBindings, ComponentPath componentPath) {
-      return new AutoValue_BindingGraphConverter_ResolvedBindingsWithPath(
-          resolvedBindings, componentPath);
-    }
-  }
-
   private final class Converter {
     /** The path from the root graph to the currently visited graph. */
     private final Deque<LegacyBindingGraph> bindingGraphPath = new ArrayDeque<>();
 
-    /** The {@link ComponentPath} for each component in {@link #bindingGraphPath}. */
-    private final Deque<ComponentPath> componentPaths = new ArrayDeque<>();
-
     private final MutableNetwork<Node, Edge> network =
         NetworkBuilder.directed().allowsParallelEdges(true).allowsSelfLoops(true).build();
     private final Set<BindingNode> bindings = new HashSet<>();
 
-    private final Map<ResolvedBindingsWithPath, ImmutableSet<BindingNode>> resolvedBindingsMap =
+    private final Map<ResolvedBindings, ImmutableSet<BindingNode>> resolvedBindingsMap =
         new HashMap<>();
 
     private void visitRootComponent(LegacyBindingGraph graph) {
-      visitComponent(graph, null);
+      visitComponent(graph);
     }
 
     /**
@@ -141,34 +108,23 @@
      * <p>This implementation does the following:
      *
      * <ol>
-     *   <li>If this component is installed in its parent by a subcomponent factory method, calls
-     *       {@link #visitSubcomponentFactoryMethod(ComponentNode, ComponentNode, XMethodElement)}.
-     *   <li>For each entry point in the component, calls {@link #visitEntryPoint(ComponentNode,
-     *       DependencyRequest)}.
-     *   <li>For each child component, calls {@link #visitComponent(LegacyBindingGraph,
-     *       ComponentNode)}, updating the traversal state.
+     *   <li>If this component is installed in its parent by a subcomponent factory method, adds
+     *       an edge between the parent and child components.
+     *   <li>For each entry point, adds an edge between the component and the entry point.
+     *   <li>For each child component, calls {@link #visitComponent(LegacyBindingGraph)},
+     *       updating the traversal state.
      * </ol>
      *
      * @param graph the currently visited graph
      */
-    private void visitComponent(LegacyBindingGraph graph, ComponentNode parentComponent) {
+    private void visitComponent(LegacyBindingGraph graph) {
       bindingGraphPath.addLast(graph);
-      ComponentPath graphPath =
-          ComponentPath.create(
-              bindingGraphPath.stream()
-                  .map(LegacyBindingGraph::componentDescriptor)
-                  .map(ComponentDescriptor::typeElement)
-                  .map(DaggerTypeElement::from)
-                  .collect(toImmutableList()));
-      componentPaths.addLast(graphPath);
-      ComponentNode currentComponent =
-          ComponentNodeImpl.create(componentPath(), graph.componentDescriptor());
 
-      network.addNode(currentComponent);
+      network.addNode(graph.componentNode());
 
       for (ComponentMethodDescriptor entryPointMethod :
           graph.componentDescriptor().entryPointMethods()) {
-        visitEntryPoint(currentComponent, entryPointMethod.dependencyRequest().get());
+        addDependencyEdges(graph.componentNode(), entryPointMethod.dependencyRequest().get());
       }
 
       for (ResolvedBindings resolvedBindings : graph.resolvedBindings()) {
@@ -180,7 +136,7 @@
             }
           }
           if (binding.kind().equals(SUBCOMPONENT_CREATOR)
-              && binding.componentPath().equals(currentComponent.componentPath())) {
+              && binding.componentPath().equals(graph.componentPath())) {
             network.addEdge(
                 binding,
                 subcomponentNode(binding.key().type().xprocessing(), graph),
@@ -190,51 +146,20 @@
         }
       }
 
-      if (bindingGraphPath.size() > 1) {
-        LegacyBindingGraph parent = Iterators.get(bindingGraphPath.descendingIterator(), 1);
-        parent
+      for (LegacyBindingGraph childGraph : graph.subgraphs()) {
+        visitComponent(childGraph);
+        graph
             .componentDescriptor()
-            .getFactoryMethodForChildComponent(graph.componentDescriptor())
+            .getFactoryMethodForChildComponent(childGraph.componentDescriptor())
             .ifPresent(
                 childFactoryMethod ->
-                    visitSubcomponentFactoryMethod(
-                        parentComponent, currentComponent, childFactoryMethod.methodElement()));
-      }
-
-      for (LegacyBindingGraph child : graph.subgraphs()) {
-        visitComponent(child, currentComponent);
+                    network.addEdge(
+                        graph.componentNode(),
+                        childGraph.componentNode(),
+                        new ChildFactoryMethodEdgeImpl(childFactoryMethod.methodElement())));
       }
 
       verify(bindingGraphPath.removeLast().equals(graph));
-      verify(componentPaths.removeLast().equals(graphPath));
-    }
-
-    /**
-     * Called once for each entry point in a component.
-     *
-     * @param componentNode the component that contains the entry point
-     * @param entryPoint the entry point to visit
-     */
-    private void visitEntryPoint(ComponentNode componentNode, DependencyRequest entryPoint) {
-      addDependencyEdges(componentNode, entryPoint);
-    }
-
-    /**
-     * Called if this component was installed in its parent by a subcomponent factory method.
-     *
-     * @param parentComponent the parent graph
-     * @param currentComponent the currently visited graph
-     * @param factoryMethod the factory method in the parent component that declares that the
-     *     current component is a child
-     */
-    private void visitSubcomponentFactoryMethod(
-        ComponentNode parentComponent,
-        ComponentNode currentComponent,
-        XMethodElement factoryMethod) {
-      network.addEdge(
-          parentComponent,
-          currentComponent,
-          new ChildFactoryMethodEdgeImpl(DaggerExecutableElement.from(factoryMethod)));
     }
 
     /**
@@ -242,7 +167,7 @@
      * component.
      */
     private ComponentPath componentPath() {
-      return componentPaths.getLast();
+      return bindingGraphPath.getLast().componentPath();
     }
 
     /**
@@ -250,9 +175,9 @@
      * component.
      */
     private ComponentPath pathFromRootToAncestor(XTypeElement ancestor) {
-      for (ComponentPath componentPath : componentPaths) {
-        if (componentPath.currentComponent().xprocessing().equals(ancestor)) {
-          return componentPath;
+      for (LegacyBindingGraph graph : bindingGraphPath) {
+        if (graph.componentDescriptor().typeElement().equals(ancestor)) {
+          return graph.componentPath();
         }
       }
       throw new IllegalArgumentException(
@@ -325,23 +250,18 @@
     }
 
     private ImmutableSet<BindingNode> bindingNodes(ResolvedBindings resolvedBindings) {
-      ResolvedBindingsWithPath resolvedBindingsWithPath =
-          ResolvedBindingsWithPath.create(resolvedBindings, componentPath());
-      return resolvedBindingsMap.computeIfAbsent(
-          resolvedBindingsWithPath, this::uncachedBindingNodes);
+      return resolvedBindingsMap.computeIfAbsent(resolvedBindings, this::uncachedBindingNodes);
     }
 
-    private ImmutableSet<BindingNode> uncachedBindingNodes(
-        ResolvedBindingsWithPath resolvedBindingsWithPath) {
+    private ImmutableSet<BindingNode> uncachedBindingNodes(ResolvedBindings resolvedBindings) {
       ImmutableSet.Builder<BindingNode> bindingNodes = ImmutableSet.builder();
-      resolvedBindingsWithPath.resolvedBindings()
+      resolvedBindings
           .allBindings()
           .asMap()
           .forEach(
               (component, bindings) -> {
                 for (Binding binding : bindings) {
-                  bindingNodes.add(
-                      bindingNode(resolvedBindingsWithPath.resolvedBindings(), binding, component));
+                  bindingNodes.add(bindingNode(resolvedBindings, binding, component));
                 }
               });
       return bindingNodes.build();
diff --git a/java/dagger/internal/codegen/binding/BindingGraphFactory.java b/java/dagger/internal/codegen/binding/BindingGraphFactory.java
index ba1157d..5034359 100644
--- a/java/dagger/internal/codegen/binding/BindingGraphFactory.java
+++ b/java/dagger/internal/codegen/binding/BindingGraphFactory.java
@@ -37,7 +37,6 @@
 import androidx.room.compiler.processing.XTypeElement;
 import com.google.common.collect.HashMultimap;
 import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.ImmutableSetMultimap;
 import com.google.common.collect.Iterables;
@@ -51,11 +50,15 @@
 import dagger.internal.codegen.base.OptionalType;
 import dagger.internal.codegen.compileroption.CompilerOptions;
 import dagger.internal.codegen.javapoet.TypeNames;
+import dagger.internal.codegen.model.BindingGraph.ComponentNode;
+import dagger.internal.codegen.model.BindingKind;
+import dagger.internal.codegen.model.ComponentPath;
+import dagger.internal.codegen.model.DaggerTypeElement;
 import dagger.internal.codegen.model.DependencyRequest;
 import dagger.internal.codegen.model.Key;
+import dagger.internal.codegen.model.RequestKind;
 import dagger.internal.codegen.model.Scope;
 import dagger.internal.codegen.xprocessing.XTypeElements;
-import dagger.producers.internal.ProductionExecutorModule;
 import java.util.ArrayDeque;
 import java.util.Deque;
 import java.util.HashMap;
@@ -182,7 +185,8 @@
     ImmutableSet.Builder<SubcomponentDeclaration> subcomponentDeclarations = ImmutableSet.builder();
 
     // Collect transitive module bindings and multibinding declarations.
-    for (ModuleDescriptor moduleDescriptor : modules(componentDescriptor, parentResolver)) {
+    ImmutableSet<ModuleDescriptor> modules = modules(componentDescriptor, parentResolver);
+    for (ModuleDescriptor moduleDescriptor : modules) {
       explicitBindingsBuilder.addAll(moduleDescriptor.bindings());
       multibindingDeclarations.addAll(moduleDescriptor.multibindingDeclarations());
       subcomponentDeclarations.addAll(moduleDescriptor.subcomponentDeclarations());
@@ -190,8 +194,14 @@
       optionalsBuilder.addAll(moduleDescriptor.optionalDeclarations());
     }
 
+    DaggerTypeElement component = DaggerTypeElement.from(componentDescriptor.typeElement());
+    ComponentPath componentPath =
+        parentResolver.isPresent()
+            ? parentResolver.get().componentPath.childPath(component)
+            : ComponentPath.create(ImmutableList.of(component));
     final Resolver requestResolver =
         new Resolver(
+            componentPath,
             parentResolver,
             componentDescriptor,
             indexBindingDeclarationsByKey(explicitBindingsBuilder.build()),
@@ -214,7 +224,7 @@
     if (createFullBindingGraph) {
       // Resolve the keys for all bindings in all modules, stripping any multibinding contribution
       // identifier so that the multibinding itself is resolved.
-      modules(componentDescriptor, parentResolver).stream()
+      modules.stream()
           .flatMap(module -> module.allBindingKeys().stream())
           .map(Key::withoutMultibindingContributionIdentifier)
           .forEach(requestResolver::resolve);
@@ -236,11 +246,7 @@
       }
     }
 
-    return new LegacyBindingGraph(
-        componentDescriptor,
-        ImmutableMap.copyOf(requestResolver.getResolvedContributionBindings()),
-        ImmutableMap.copyOf(requestResolver.getResolvedMembersInjectionBindings()),
-        ImmutableList.copyOf(subgraphs.build()));
+    return new LegacyBindingGraph(requestResolver, subgraphs.build());
   }
 
   /**
@@ -254,38 +260,23 @@
     return shouldIncludeImplicitProductionModules(componentDescriptor, parentResolver)
         ? new ImmutableSet.Builder<ModuleDescriptor>()
             .addAll(componentDescriptor.modules())
-            .add(descriptorForMonitoringModule(componentDescriptor.typeElement()))
-            .add(descriptorForProductionExecutorModule())
+            .add(
+                moduleDescriptorFactory.create(
+                    DaggerSuperficialValidation.requireTypeElement(
+                        processingEnv,
+                        generatedMonitoringModuleName(componentDescriptor.typeElement()))))
+            .add(
+                moduleDescriptorFactory.create(
+                    processingEnv.requireTypeElement(TypeNames.PRODUCTION_EXECTUTOR_MODULE)))
             .build()
         : componentDescriptor.modules();
   }
 
   private boolean shouldIncludeImplicitProductionModules(
-      ComponentDescriptor component, Optional<Resolver> parentResolver) {
-    return component.isProduction()
-        && ((!component.isSubcomponent() && component.isRealComponent())
-            || (parentResolver.isPresent()
-                && !parentResolver.get().componentDescriptor.isProduction()));
-  }
-
-  /**
-   * Returns a descriptor for a generated module that handles monitoring for production components.
-   * This module is generated in the {@link
-   * dagger.internal.codegen.validation.MonitoringModuleProcessingStep}.
-   *
-   * @throws TypeNotPresentException if the module has not been generated yet. This will cause the
-   *     processor to retry in a later processing round.
-   */
-  private ModuleDescriptor descriptorForMonitoringModule(XTypeElement componentDefinitionType) {
-    return moduleDescriptorFactory.create(
-        DaggerSuperficialValidation.requireTypeElement(
-            processingEnv, generatedMonitoringModuleName(componentDefinitionType)));
-  }
-
-  /** Returns a descriptor {@link ProductionExecutorModule}. */
-  private ModuleDescriptor descriptorForProductionExecutorModule() {
-    return moduleDescriptorFactory.create(
-        processingEnv.findTypeElement(TypeNames.PRODUCTION_EXECTUTOR_MODULE));
+      ComponentDescriptor componentDescriptor, Optional<Resolver> parentResolver) {
+    return componentDescriptor.isProduction()
+        && componentDescriptor.isRealComponent()
+        && (parentResolver.isEmpty() || !parentResolver.get().componentDescriptor.isProduction());
   }
 
   /** Indexes {@code bindingDeclarations} by {@link BindingDeclaration#key()}. */
@@ -299,7 +290,70 @@
     keysMatchingRequestCache.clear();
   }
 
+  /** Represents a fully resolved binding graph. */
+  static final class LegacyBindingGraph {
+    private final Resolver resolver;
+    private final ImmutableList<LegacyBindingGraph> resolvedSubgraphs;
+    private final ComponentNode componentNode;
+
+    LegacyBindingGraph(Resolver resolver, ImmutableList<LegacyBindingGraph> resolvedSubgraphs) {
+      this.resolver = resolver;
+      this.resolvedSubgraphs = resolvedSubgraphs;
+      this.componentNode =
+          ComponentNodeImpl.create(resolver.componentPath, resolver.componentDescriptor);
+    }
+
+    /** Returns the {@link ComponentNode} associated with this binding graph. */
+    ComponentNode componentNode() {
+      return componentNode;
+    }
+
+    /** Returns the {@link ComponentPath} associated with this binding graph. */
+    ComponentPath componentPath() {
+      return resolver.componentPath;
+    }
+
+    /** Returns the {@link ComponentDescriptor} associated with this binding graph. */
+    ComponentDescriptor componentDescriptor() {
+      return resolver.componentDescriptor;
+    }
+
+    /**
+     * Returns the {@link ResolvedBindings} in this graph or a parent graph that matches the given
+     * request.
+     *
+     * <p>An exception is thrown if there are no resolved bindings found for the request; however,
+     * this should never happen since all dependencies should have been resolved at this point.
+     */
+    ResolvedBindings resolvedBindings(BindingRequest request) {
+      return request.isRequestKind(RequestKind.MEMBERS_INJECTION)
+          ? resolver.getResolvedMembersInjectionBindings(request.key())
+          : resolver.getResolvedContributionBindings(request.key());
+    }
+
+    /**
+     * Returns all {@link ResolvedBindings} for the given request.
+     *
+     * <p>Note that this only returns the bindings resolved in this component. Bindings resolved in
+     * parent components are not included.
+     */
+    Iterable<ResolvedBindings> resolvedBindings() {
+      // Don't return an immutable collection - this is only ever used for looping over all bindings
+      // in the graph. Copying is wasteful, especially if is a hashing collection, since the values
+      // should all, by definition, be distinct.
+      return Iterables.concat(
+          resolver.resolvedMembersInjectionBindings.values(),
+          resolver.resolvedContributionBindings.values());
+    }
+
+    /** Returns the resolved subgraphs. */
+    ImmutableList<LegacyBindingGraph> subgraphs() {
+      return resolvedSubgraphs;
+    }
+  }
+
   private final class Resolver {
+    final ComponentPath componentPath;
     final Optional<Resolver> parentResolver;
     final ComponentDescriptor componentDescriptor;
     final ImmutableSetMultimap<Key, ContributionBinding> explicitBindings;
@@ -318,6 +372,7 @@
     final Queue<ComponentDescriptor> subcomponentsToResolve = new ArrayDeque<>();
 
     Resolver(
+        ComponentPath componentPath,
         Optional<Resolver> parentResolver,
         ComponentDescriptor componentDescriptor,
         ImmutableSetMultimap<Key, ContributionBinding> explicitBindings,
@@ -325,6 +380,7 @@
         ImmutableSetMultimap<Key, SubcomponentDeclaration> subcomponentDeclarations,
         ImmutableSetMultimap<Key, DelegateDeclaration> delegateDeclarations,
         ImmutableSetMultimap<Key, OptionalBindingDeclaration> optionalBindingDeclarations) {
+      this.componentPath = componentPath;
       this.parentResolver = parentResolver;
       this.componentDescriptor = checkNotNull(componentDescriptor);
       this.explicitBindings = checkNotNull(explicitBindings);
@@ -428,6 +484,7 @@
       }
 
       return ResolvedBindings.forContributionBindings(
+          componentPath,
           requestKey,
           Multimaps.index(bindings, binding -> getOwningComponent(requestKey, binding)),
           multibindingDeclarations,
@@ -466,8 +523,8 @@
           injectBindingRegistry.getOrFindMembersInjectionBinding(requestKey);
       return binding.isPresent()
           ? ResolvedBindings.forMembersInjectionBinding(
-              requestKey, componentDescriptor, binding.get())
-          : ResolvedBindings.noBindings(requestKey);
+              componentPath, requestKey, componentDescriptor, binding.get())
+          : ResolvedBindings.noBindings(componentPath, requestKey);
     }
 
     /**
@@ -577,8 +634,7 @@
      * ResolvedBindings#owningComponent(ContributionBinding)}.
      */
     private XTypeElement getOwningComponent(Key requestKey, ContributionBinding binding) {
-      if (isResolvedInParent(requestKey, binding)
-          && !new LocalDependencyChecker().dependsOnLocalBindings(binding)) {
+      if (isResolvedInParent(requestKey, binding) && !requiresResolution(binding)) {
         ResolvedBindings parentResolvedBindings =
             parentResolver.get().resolvedContributionBindings.get(requestKey);
         return parentResolvedBindings.owningComponent(binding);
@@ -799,11 +855,17 @@
         /* Resolve in the parent in case there are multibinding contributions or conflicts in some
          * component between this one and the previously-resolved one. */
         parentResolver.get().resolve(key);
-        if (!new LocalDependencyChecker().dependsOnLocalBindings(key)
-            && getLocalExplicitBindings(key).isEmpty()) {
+        ResolvedBindings previouslyResolvedBindings = getPreviouslyResolvedBindings(key).get();
+        // TODO(b/305748522): Allow caching for assisted injection bindings.
+        boolean isAssistedInjectionBinding =
+            previouslyResolvedBindings.bindings().stream()
+                .anyMatch(binding -> binding.kind() == BindingKind.ASSISTED_INJECTION);
+        if (!isAssistedInjectionBinding
+                && !requiresResolution(key)
+                && getLocalExplicitBindings(key).isEmpty()) {
           /* Cache the inherited parent component's bindings in case resolving at the parent found
            * bindings in some component between this one and the previously-resolved one. */
-          resolvedContributionBindings.put(key, getPreviouslyResolvedBindings(key).get());
+          resolvedContributionBindings.put(key, previouslyResolvedBindings);
           return;
         }
       }
@@ -830,26 +892,29 @@
       }
     }
 
-    /**
-     * Returns all of the {@link ResolvedBindings} for {@link ContributionBinding}s from this and
-     * all ancestor resolvers, indexed by {@link ResolvedBindings#key()}.
-     */
-    Map<Key, ResolvedBindings> getResolvedContributionBindings() {
-      Map<Key, ResolvedBindings> bindings = new LinkedHashMap<>();
-      parentResolver.ifPresent(parent -> bindings.putAll(parent.getResolvedContributionBindings()));
-      bindings.putAll(resolvedContributionBindings);
-      return bindings;
+    private ResolvedBindings getResolvedContributionBindings(Key key) {
+      if (resolvedContributionBindings.containsKey(key)) {
+        return resolvedContributionBindings.get(key);
+      }
+      if (parentResolver.isPresent()) {
+        return parentResolver.get().getResolvedContributionBindings(key);
+      }
+      throw new AssertionError("No resolved bindings for key: " + key);
     }
 
-    /**
-     * Returns all of the {@link ResolvedBindings} for {@link MembersInjectionBinding} from this
-     * resolvers, indexed by {@link ResolvedBindings#key()}.
-     */
-    ImmutableMap<Key, ResolvedBindings> getResolvedMembersInjectionBindings() {
-      return ImmutableMap.copyOf(resolvedMembersInjectionBindings);
+    private ResolvedBindings getResolvedMembersInjectionBindings(Key key) {
+      return resolvedMembersInjectionBindings.get(key);
     }
 
-    private final class LocalDependencyChecker {
+    private boolean requiresResolution(Key key) {
+      return new LegacyRequiresResolutionChecker().requiresResolution(key);
+    }
+
+    private boolean requiresResolution(Binding binding) {
+      return new LegacyRequiresResolutionChecker().requiresResolution(binding);
+    }
+
+    private final class LegacyRequiresResolutionChecker {
       private final Set<Object> cycleChecker = new HashSet<>();
 
       /**
@@ -863,14 +928,14 @@
        *
        * @throws IllegalArgumentException if {@link #getPreviouslyResolvedBindings(Key)} is empty
        */
-      private boolean dependsOnLocalBindings(Key key) {
+      private boolean requiresResolution(Key key) {
         // Don't recur infinitely if there are valid cycles in the dependency graph.
         // http://b/23032377
         if (!cycleChecker.add(key)) {
           return false;
         }
         return reentrantComputeIfAbsent(
-            keyDependsOnLocalBindingsCache, key, this::dependsOnLocalBindingsUncached);
+            keyDependsOnLocalBindingsCache, key, this::requiresResolutionUncached);
       }
 
       /**
@@ -882,75 +947,89 @@
        * <p>We don't care about non-reusable scoped dependencies because they will never depend on
        * multibindings with contributions from subcomponents.
        */
-      private boolean dependsOnLocalBindings(Binding binding) {
+      private boolean requiresResolution(Binding binding) {
         if (!cycleChecker.add(binding)) {
           return false;
         }
         return reentrantComputeIfAbsent(
-            bindingDependsOnLocalBindingsCache, binding, this::dependsOnLocalBindingsUncached);
+            bindingDependsOnLocalBindingsCache, binding, this::requiresResolutionUncached);
       }
 
-      private boolean dependsOnLocalBindingsUncached(Key key) {
+      private boolean requiresResolutionUncached(Key key) {
         checkArgument(
             getPreviouslyResolvedBindings(key).isPresent(),
             "no previously resolved bindings in %s for %s",
             Resolver.this,
             key);
         ResolvedBindings previouslyResolvedBindings = getPreviouslyResolvedBindings(key).get();
-        if (hasLocalMultibindingContributions(key)
-            || hasLocalOptionalBindingContribution(previouslyResolvedBindings)) {
+        if (hasLocalBindings(previouslyResolvedBindings)) {
           return true;
         }
 
         for (Binding binding : previouslyResolvedBindings.bindings()) {
-          if (dependsOnLocalBindings(binding)) {
+          if (requiresResolution(binding)) {
             return true;
           }
         }
         return false;
       }
 
-      private boolean dependsOnLocalBindingsUncached(Binding binding) {
+      private boolean requiresResolutionUncached(Binding binding) {
         if ((!binding.scope().isPresent() || binding.scope().get().isReusable())
             // TODO(beder): Figure out what happens with production subcomponents.
             && !binding.bindingType().equals(BindingType.PRODUCTION)) {
           for (DependencyRequest dependency : binding.dependencies()) {
-            if (dependsOnLocalBindings(dependency.key())) {
+            if (requiresResolution(dependency.key())) {
               return true;
             }
           }
         }
         return false;
       }
+    }
 
-      /**
-       * Returns {@code true} if there is at least one multibinding contribution declared within
-       * this component's modules that matches the key.
-       */
-      private boolean hasLocalMultibindingContributions(Key requestKey) {
-        return keysMatchingRequest(requestKey)
-            .stream()
-            .anyMatch(key -> !getLocalExplicitMultibindings(key).isEmpty());
-      }
+    private boolean hasLocalBindings(Binding binding) {
+      return hasLocalMultibindingContributions(binding.key())
+          || hasLocalOptionalBindingContribution(
+              binding.key(), ImmutableSet.of((ContributionBinding) binding));
+    }
 
-      /**
-       * Returns {@code true} if there is a contribution in this component for an {@code
-       * Optional<Foo>} key that has not been contributed in a parent.
-       */
-      private boolean hasLocalOptionalBindingContribution(ResolvedBindings resolvedBindings) {
-        if (resolvedBindings
-            .contributionBindings()
-            .stream()
-            .map(ContributionBinding::kind)
-            .anyMatch(isEqual(OPTIONAL))) {
-          return !getLocalExplicitBindings(keyFactory.unwrapOptional(resolvedBindings.key()).get())
-              .isEmpty();
-        } else {
-          // If a parent contributes a @Provides Optional<Foo> binding and a child has a
-          // @BindsOptionalOf Foo method, the two should conflict, even if there is no binding for
-          // Foo on its own
-          return !getOptionalBindingDeclarations(resolvedBindings.key()).isEmpty();
-        }
+    private boolean hasLocalBindings(ResolvedBindings resolvedBindings) {
+      return hasLocalMultibindingContributions(resolvedBindings.key())
+          || hasLocalOptionalBindingContribution(resolvedBindings);
+    }
+
+    /**
+     * Returns {@code true} if there is at least one multibinding contribution declared within
+     * this component's modules that matches the key.
+     */
+    private boolean hasLocalMultibindingContributions(Key requestKey) {
+      return keysMatchingRequest(requestKey)
+          .stream()
+          .anyMatch(key -> !getLocalExplicitMultibindings(key).isEmpty());
+    }
+
+    /**
+     * Returns {@code true} if there is a contribution in this component for an {@code
+     * Optional<Foo>} key that has not been contributed in a parent.
+     */
+    private boolean hasLocalOptionalBindingContribution(ResolvedBindings resolvedBindings) {
+      return hasLocalOptionalBindingContribution(
+          resolvedBindings.key(), resolvedBindings.contributionBindings());
+    }
+
+    private boolean hasLocalOptionalBindingContribution(
+          Key key, ImmutableSet<ContributionBinding> previousContributionBindings) {
+      if (previousContributionBindings.stream()
+          .map(ContributionBinding::kind)
+          .anyMatch(isEqual(OPTIONAL))) {
+        return !getLocalExplicitBindings(keyFactory.unwrapOptional(key).get())
+            .isEmpty();
+      } else {
+        // If a parent contributes a @Provides Optional<Foo> binding and a child has a
+        // @BindsOptionalOf Foo method, the two should conflict, even if there is no binding for
+        // Foo on its own
+        return !getOptionalBindingDeclarations(key).isEmpty();
       }
     }
   }
diff --git a/java/dagger/internal/codegen/binding/CancellationPolicy.java b/java/dagger/internal/codegen/binding/CancellationPolicy.java
new file mode 100644
index 0000000..7be42ff
--- /dev/null
+++ b/java/dagger/internal/codegen/binding/CancellationPolicy.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.internal.codegen.binding;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static dagger.internal.codegen.xprocessing.XElements.getSimpleName;
+
+import androidx.room.compiler.processing.XAnnotation;
+import dagger.internal.codegen.javapoet.TypeNames;
+import dagger.internal.codegen.xprocessing.XAnnotations;
+
+/**
+ * The cancellation policy for a {@link dagger.producers.ProductionComponent}.
+ *
+ * <p>@see dagger.producers.CancellationPolicy
+ */
+public enum CancellationPolicy {
+  PROPAGATE,
+  IGNORE;
+
+  static CancellationPolicy from(XAnnotation annotation) {
+    checkArgument(XAnnotations.getClassName(annotation).equals(TypeNames.CANCELLATION_POLICY));
+    return valueOf(getSimpleName(annotation.getAsEnum("fromSubcomponents")));
+  }
+}
diff --git a/java/dagger/internal/codegen/binding/ChildFactoryMethodEdgeImpl.java b/java/dagger/internal/codegen/binding/ChildFactoryMethodEdgeImpl.java
index 077f454..4b1e15e 100644
--- a/java/dagger/internal/codegen/binding/ChildFactoryMethodEdgeImpl.java
+++ b/java/dagger/internal/codegen/binding/ChildFactoryMethodEdgeImpl.java
@@ -18,6 +18,7 @@
 
 import static dagger.internal.codegen.base.ElementFormatter.elementToString;
 
+import androidx.room.compiler.processing.XMethodElement;
 import dagger.internal.codegen.model.BindingGraph.ChildFactoryMethodEdge;
 import dagger.internal.codegen.model.DaggerExecutableElement;
 
@@ -26,8 +27,8 @@
 
   private final DaggerExecutableElement factoryMethod;
 
-  ChildFactoryMethodEdgeImpl(DaggerExecutableElement factoryMethod) {
-    this.factoryMethod = factoryMethod;
+  ChildFactoryMethodEdgeImpl(XMethodElement factoryMethod) {
+    this.factoryMethod = DaggerExecutableElement.from(factoryMethod);
   }
 
   @Override
diff --git a/java/dagger/internal/codegen/binding/ComponentCreatorDescriptor.java b/java/dagger/internal/codegen/binding/ComponentCreatorDescriptor.java
index 0bc2209..254ca7e 100644
--- a/java/dagger/internal/codegen/binding/ComponentCreatorDescriptor.java
+++ b/java/dagger/internal/codegen/binding/ComponentCreatorDescriptor.java
@@ -41,6 +41,7 @@
 import dagger.internal.codegen.base.ComponentCreatorKind;
 import dagger.internal.codegen.javapoet.TypeNames;
 import dagger.internal.codegen.model.DependencyRequest;
+import dagger.internal.codegen.xprocessing.XElements;
 import java.util.List;
 
 /**
@@ -161,7 +162,12 @@
     for (XMethodElement method : getAllUnimplementedMethods(creator)) {
       XMethodType resolvedMethodType = method.asMemberOf(creator.getType());
       if (isSubtype(componentType, resolvedMethodType.getReturnType())) {
-        verify(factoryMethod == null); // validation should have ensured there's only 1.
+        verify(
+            factoryMethod == null,
+            "Expected a single factory method for %s but found multiple: [%s, %s]",
+            XElements.toStableString(creator),
+            XElements.toStableString(factoryMethod),
+            XElements.toStableString(method));
         factoryMethod = method;
       } else {
         XExecutableParameterElement parameter = getOnlyElement(method.getParameters());
@@ -171,7 +177,10 @@
             method);
       }
     }
-    verify(factoryMethod != null); // validation should have ensured this.
+    verify(
+        factoryMethod != null,
+        "Expected a single factory method for %s but found none.",
+        XElements.toStableString(creator));
 
     ImmutableSetMultimap.Builder<ComponentRequirement, XExecutableParameterElement>
         factoryParameters = ImmutableSetMultimap.builder();
diff --git a/java/dagger/internal/codegen/binding/ComponentDescriptor.java b/java/dagger/internal/codegen/binding/ComponentDescriptor.java
index a105608..b0a0183 100644
--- a/java/dagger/internal/codegen/binding/ComponentDescriptor.java
+++ b/java/dagger/internal/codegen/binding/ComponentDescriptor.java
@@ -21,14 +21,28 @@
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static dagger.internal.codegen.base.ComponentAnnotation.rootComponentAnnotation;
+import static dagger.internal.codegen.base.ComponentAnnotation.subcomponentAnnotation;
+import static dagger.internal.codegen.base.ComponentAnnotation.subcomponentAnnotations;
+import static dagger.internal.codegen.base.ComponentCreatorAnnotation.creatorAnnotationsFor;
+import static dagger.internal.codegen.base.ModuleAnnotation.moduleAnnotation;
+import static dagger.internal.codegen.base.Scopes.productionScope;
+import static dagger.internal.codegen.base.Util.reentrantComputeIfAbsent;
+import static dagger.internal.codegen.binding.ConfigurationAnnotations.enclosedAnnotatedTypes;
+import static dagger.internal.codegen.binding.ConfigurationAnnotations.isSubcomponentCreator;
 import static dagger.internal.codegen.extension.DaggerStreams.toImmutableMap;
 import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
 import static dagger.internal.codegen.javapoet.TypeNames.isFutureType;
 import static dagger.internal.codegen.xprocessing.XElements.getSimpleName;
+import static dagger.internal.codegen.xprocessing.XTypeElements.getAllUnimplementedMethods;
+import static dagger.internal.codegen.xprocessing.XTypes.isDeclared;
 
-import androidx.room.compiler.processing.XAnnotation;
 import androidx.room.compiler.processing.XElement;
 import androidx.room.compiler.processing.XMethodElement;
+import androidx.room.compiler.processing.XMethodType;
+import androidx.room.compiler.processing.XProcessingEnv;
+import androidx.room.compiler.processing.XType;
 import androidx.room.compiler.processing.XTypeElement;
 import com.google.auto.value.AutoValue;
 import com.google.auto.value.extension.memoized.Memoized;
@@ -44,16 +58,21 @@
 import dagger.Component;
 import dagger.Module;
 import dagger.Subcomponent;
+import dagger.internal.codegen.base.ClearableCache;
 import dagger.internal.codegen.base.ComponentAnnotation;
+import dagger.internal.codegen.base.DaggerSuperficialValidation;
+import dagger.internal.codegen.base.ModuleAnnotation;
 import dagger.internal.codegen.javapoet.TypeNames;
 import dagger.internal.codegen.model.DependencyRequest;
 import dagger.internal.codegen.model.Scope;
-import dagger.internal.codegen.xprocessing.XAnnotations;
+import dagger.internal.codegen.xprocessing.XTypeElements;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
 import java.util.stream.Stream;
+import javax.inject.Inject;
+import javax.inject.Singleton;
 
 /**
  * A component declaration.
@@ -68,53 +87,55 @@
 @CheckReturnValue
 @AutoValue
 public abstract class ComponentDescriptor {
-  /**
-   * The cancellation policy for a {@link dagger.producers.ProductionComponent}.
-   *
-   * <p>@see dagger.producers.CancellationPolicy
-   */
-  public enum CancellationPolicy {
-    PROPAGATE,
-    IGNORE;
-
-    private static CancellationPolicy from(XAnnotation annotation) {
-      checkArgument(XAnnotations.getClassName(annotation).equals(TypeNames.CANCELLATION_POLICY));
-      return valueOf(getSimpleName(annotation.getAsEnum("fromSubcomponents")));
-    }
-  }
-
-  /** Creates a {@link ComponentDescriptor}. */
-  static ComponentDescriptor create(
-      ComponentAnnotation componentAnnotation,
-      XTypeElement component,
-      ImmutableSet<ComponentRequirement> componentDependencies,
-      ImmutableSet<ModuleDescriptor> transitiveModules,
-      ImmutableMap<XMethodElement, ComponentRequirement> dependenciesByDependencyMethod,
-      ImmutableSet<Scope> scopes,
-      ImmutableSet<ComponentDescriptor> subcomponentsFromModules,
-      ImmutableBiMap<ComponentMethodDescriptor, ComponentDescriptor> subcomponentsByFactoryMethod,
-      ImmutableBiMap<ComponentMethodDescriptor, ComponentDescriptor> subcomponentsByBuilderMethod,
-      ImmutableSet<ComponentMethodDescriptor> componentMethods,
-      Optional<ComponentCreatorDescriptor> creator) {
-    ComponentDescriptor descriptor =
-        new AutoValue_ComponentDescriptor(
-            componentAnnotation,
-            component,
-            componentDependencies,
-            transitiveModules,
-            dependenciesByDependencyMethod,
-            scopes,
-            subcomponentsFromModules,
-            subcomponentsByFactoryMethod,
-            subcomponentsByBuilderMethod,
-            componentMethods,
-            creator);
-    return descriptor;
-  }
-
   /** The annotation that specifies that {@link #typeElement()} is a component. */
   public abstract ComponentAnnotation annotation();
 
+  /**
+   * The element that defines the component. This is the element to which the {@link #annotation()}
+   * was applied.
+   */
+  public abstract XTypeElement typeElement();
+
+  /**
+   * The set of component dependencies listed in {@link Component#dependencies} or {@link
+   * dagger.producers.ProductionComponent#dependencies()}.
+   */
+  public abstract ImmutableSet<ComponentRequirement> dependencies();
+
+  /**
+   * The {@link ModuleDescriptor modules} declared in {@link Component#modules()} and reachable by
+   * traversing {@link Module#includes()}.
+   */
+  public abstract ImmutableSet<ModuleDescriptor> modules();
+
+  /** The scopes of the component. */
+  public abstract ImmutableSet<Scope> scopes();
+
+  /**
+   * All {@linkplain Subcomponent direct child} components that are declared by a {@linkplain
+   * Module#subcomponents() module's subcomponents}.
+   */
+  abstract ImmutableSet<ComponentDescriptor> childComponentsDeclaredByModules();
+
+  /**
+   * All {@linkplain Subcomponent direct child} components that are declared by a subcomponent
+   * factory method.
+   */
+  public abstract ImmutableBiMap<ComponentMethodDescriptor, ComponentDescriptor>
+      childComponentsDeclaredByFactoryMethods();
+
+  /**
+   * All {@linkplain Subcomponent direct child} components that are declared by a subcomponent
+   * builder method.
+   */
+  abstract ImmutableMap<ComponentMethodDescriptor, ComponentDescriptor>
+      childComponentsDeclaredByBuilderEntryPoints();
+
+  public abstract ImmutableSet<ComponentMethodDescriptor> componentMethods();
+
+  /** Returns a descriptor for the creator type for this component type, if the user defined one. */
+  public abstract Optional<ComponentCreatorDescriptor> creatorDescriptor();
+
   /** Returns {@code true} if this is a subcomponent. */
   public final boolean isSubcomponent() {
     return annotation().isSubcomponent();
@@ -136,18 +157,6 @@
     return annotation().isRealComponent();
   }
 
-  /**
-   * The element that defines the component. This is the element to which the {@link #annotation()}
-   * was applied.
-   */
-  public abstract XTypeElement typeElement();
-
-  /**
-   * The set of component dependencies listed in {@link Component#dependencies} or {@link
-   * dagger.producers.ProductionComponent#dependencies()}.
-   */
-  public abstract ImmutableSet<ComponentRequirement> dependencies();
-
   /** The non-abstract {@link #modules()} and the {@link #dependencies()}. */
   public final ImmutableSet<ComponentRequirement> dependenciesAndConcreteModules() {
     return Stream.concat(
@@ -158,12 +167,6 @@
         .collect(toImmutableSet());
   }
 
-  /**
-   * The {@link ModuleDescriptor modules} declared in {@link Component#modules()} and reachable by
-   * traversing {@link Module#includes()}.
-   */
-  public abstract ImmutableSet<ModuleDescriptor> modules();
-
   /** The types of the {@link #modules()}. */
   public final ImmutableSet<XTypeElement> moduleTypes() {
     return modules().stream().map(ModuleDescriptor::moduleElement).collect(toImmutableSet());
@@ -198,13 +201,21 @@
   }
 
   /**
-   * This component's {@linkplain #dependencies() dependencies} keyed by each provision or
-   * production method defined by that dependency. Note that the dependencies' types are not simply
-   * the enclosing type of the method; a method may be declared by a supertype of the actual
-   * dependency.
+   * Returns this component's dependencies keyed by its provision/production method.
+   *
+   * <p>Note that the dependencies' types are not simply the enclosing type of the method; a method
+   * may be declared by a supertype of the actual dependency.
    */
-  public abstract ImmutableMap<XMethodElement, ComponentRequirement>
-      dependenciesByDependencyMethod();
+  @Memoized
+  public ImmutableMap<XMethodElement, ComponentRequirement> dependenciesByDependencyMethod() {
+    ImmutableMap.Builder<XMethodElement, ComponentRequirement> builder = ImmutableMap.builder();
+    for (ComponentRequirement componentDependency : dependencies()) {
+      XTypeElements.getAllMethods(componentDependency.typeElement()).stream()
+          .filter(ComponentDescriptor::isComponentContributionMethod)
+          .forEach(method -> builder.put(method, componentDependency));
+    }
+    return builder.buildOrThrow();
+  }
 
   /** The {@linkplain #dependencies() component dependency} that defines a method. */
   public final ComponentRequirement getDependencyThatDefinesMethod(XElement method) {
@@ -216,9 +227,6 @@
     return dependenciesByDependencyMethod().get(method);
   }
 
-  /** The scopes of the component. */
-  public abstract ImmutableSet<Scope> scopes();
-
   /**
    * All {@link Subcomponent}s which are direct children of this component. This includes
    * subcomponents installed from {@link Module#subcomponents()} as well as subcomponent {@linkplain
@@ -233,19 +241,6 @@
         .build();
   }
 
-  /**
-   * All {@linkplain Subcomponent direct child} components that are declared by a {@linkplain
-   * Module#subcomponents() module's subcomponents}.
-   */
-  abstract ImmutableSet<ComponentDescriptor> childComponentsDeclaredByModules();
-
-  /**
-   * All {@linkplain Subcomponent direct child} components that are declared by a subcomponent
-   * factory method.
-   */
-  public abstract ImmutableBiMap<ComponentMethodDescriptor, ComponentDescriptor>
-      childComponentsDeclaredByFactoryMethods();
-
   /** Returns a map of {@link #childComponents()} indexed by {@link #typeElement()}. */
   @Memoized
   public ImmutableMap<XTypeElement, ComponentDescriptor> childComponentsByElement() {
@@ -259,13 +254,6 @@
         childComponentsDeclaredByFactoryMethods().inverse().get(childComponent));
   }
 
-  /**
-   * All {@linkplain Subcomponent direct child} components that are declared by a subcomponent
-   * builder method.
-   */
-  abstract ImmutableBiMap<ComponentMethodDescriptor, ComponentDescriptor>
-      childComponentsDeclaredByBuilderEntryPoints();
-
   private final Supplier<ImmutableMap<XTypeElement, ComponentDescriptor>>
       childComponentsByBuilderType =
           Suppliers.memoize(
@@ -285,8 +273,6 @@
         builderType.getQualifiedName());
   }
 
-  public abstract ImmutableSet<ComponentMethodDescriptor> componentMethods();
-
   /** Returns the first component method associated with this binding request, if one exists. */
   public Optional<ComponentMethodDescriptor> firstMatchingComponentMethod(BindingRequest request) {
     return Optional.ofNullable(firstMatchingComponentMethods().get(request));
@@ -308,11 +294,6 @@
         .collect(toImmutableSet());
   }
 
-  // TODO(gak): Consider making this non-optional and revising the
-  // interaction between the spec & generation
-  /** Returns a descriptor for the creator type for this component type, if the user defined one. */
-  public abstract Optional<ComponentCreatorDescriptor> creatorDescriptor();
-
   /**
    * Returns {@code true} for components that have a creator, either because the user {@linkplain
    * #creatorDescriptor() specified one} or because it's a top-level component with an implicit
@@ -408,4 +389,204 @@
   static boolean isComponentProductionMethod(XMethodElement method) {
     return isComponentContributionMethod(method) && isFutureType(method.getReturnType());
   }
+
+  /** A factory for creating a {@link ComponentDescriptor}. */
+  @Singleton
+  public static final class Factory implements ClearableCache {
+    private final XProcessingEnv processingEnv;
+    private final DependencyRequestFactory dependencyRequestFactory;
+    private final ModuleDescriptor.Factory moduleDescriptorFactory;
+    private final InjectionAnnotations injectionAnnotations;
+    private final DaggerSuperficialValidation superficialValidation;
+    private final Map<XTypeElement, ComponentDescriptor> cache = new HashMap<>();
+
+    @Inject
+    Factory(
+        XProcessingEnv processingEnv,
+        DependencyRequestFactory dependencyRequestFactory,
+        ModuleDescriptor.Factory moduleDescriptorFactory,
+        InjectionAnnotations injectionAnnotations,
+        DaggerSuperficialValidation superficialValidation) {
+      this.processingEnv = processingEnv;
+      this.dependencyRequestFactory = dependencyRequestFactory;
+      this.moduleDescriptorFactory = moduleDescriptorFactory;
+      this.injectionAnnotations = injectionAnnotations;
+      this.superficialValidation = superficialValidation;
+    }
+
+    /** Returns a descriptor for a root component type. */
+    public ComponentDescriptor rootComponentDescriptor(XTypeElement typeElement) {
+      Optional<ComponentAnnotation> annotation =
+          rootComponentAnnotation(typeElement, superficialValidation);
+      checkArgument(annotation.isPresent(), "%s must have a component annotation", typeElement);
+      return create(typeElement, annotation.get());
+    }
+
+    /** Returns a descriptor for a subcomponent type. */
+    public ComponentDescriptor subcomponentDescriptor(XTypeElement typeElement) {
+      Optional<ComponentAnnotation> annotation =
+          subcomponentAnnotation(typeElement, superficialValidation);
+      checkArgument(annotation.isPresent(), "%s must have a subcomponent annotation", typeElement);
+      return create(typeElement, annotation.get());
+    }
+
+    /**
+     * Returns a descriptor for a fictional component based on a module type in order to validate
+     * its bindings.
+     */
+    public ComponentDescriptor moduleComponentDescriptor(XTypeElement typeElement) {
+      Optional<ModuleAnnotation> annotation = moduleAnnotation(typeElement, superficialValidation);
+      checkArgument(annotation.isPresent(), "%s must have a module annotation", typeElement);
+      return create(typeElement, ComponentAnnotation.fromModuleAnnotation(annotation.get()));
+    }
+
+    private ComponentDescriptor create(
+        XTypeElement typeElement, ComponentAnnotation componentAnnotation) {
+      return reentrantComputeIfAbsent(
+          cache, typeElement, unused -> createUncached(typeElement, componentAnnotation));
+    }
+
+    private ComponentDescriptor createUncached(
+        XTypeElement typeElement, ComponentAnnotation componentAnnotation) {
+      ImmutableSet<ComponentRequirement> componentDependencies =
+          componentAnnotation.dependencyTypes().stream()
+              .map(ComponentRequirement::forDependency)
+              .collect(toImmutableSet());
+
+      // Start with the component's modules. For fictional components built from a module, start
+      // with that module.
+      ImmutableSet<XTypeElement> modules =
+          componentAnnotation.isRealComponent()
+              ? componentAnnotation.modules()
+              : ImmutableSet.of(typeElement);
+
+      ImmutableSet<ModuleDescriptor> transitiveModules =
+          moduleDescriptorFactory.transitiveModules(modules);
+
+      ImmutableSet.Builder<ComponentMethodDescriptor> componentMethodsBuilder =
+          ImmutableSet.builder();
+      ImmutableBiMap.Builder<ComponentMethodDescriptor, ComponentDescriptor>
+          subcomponentsByFactoryMethod = ImmutableBiMap.builder();
+      ImmutableMap.Builder<ComponentMethodDescriptor, ComponentDescriptor>
+          subcomponentsByBuilderMethod = ImmutableBiMap.builder();
+      if (componentAnnotation.isRealComponent()) {
+        for (XMethodElement componentMethod : getAllUnimplementedMethods(typeElement)) {
+          ComponentMethodDescriptor componentMethodDescriptor =
+              getDescriptorForComponentMethod(componentAnnotation, typeElement, componentMethod);
+          componentMethodsBuilder.add(componentMethodDescriptor);
+          componentMethodDescriptor
+              .subcomponent()
+              .ifPresent(
+                  subcomponent -> {
+                    // If the dependency request is present, that means the method returns the
+                    // subcomponent factory.
+                    if (componentMethodDescriptor.dependencyRequest().isPresent()) {
+                      subcomponentsByBuilderMethod.put(componentMethodDescriptor, subcomponent);
+                    } else {
+                      subcomponentsByFactoryMethod.put(componentMethodDescriptor, subcomponent);
+                    }
+                  });
+        }
+      }
+
+      // Validation should have ensured that this set will have at most one element.
+      ImmutableSet<XTypeElement> enclosedCreators =
+          enclosedAnnotatedTypes(typeElement, creatorAnnotationsFor(componentAnnotation));
+      Optional<ComponentCreatorDescriptor> creatorDescriptor =
+          enclosedCreators.isEmpty()
+              ? Optional.empty()
+              : Optional.of(
+                  ComponentCreatorDescriptor.create(
+                      getOnlyElement(enclosedCreators), dependencyRequestFactory));
+
+      ImmutableSet<Scope> scopes = injectionAnnotations.getScopes(typeElement);
+      if (componentAnnotation.isProduction()) {
+        scopes =
+            ImmutableSet.<Scope>builder()
+                .addAll(scopes).add(productionScope(processingEnv))
+                .build();
+      }
+
+      ImmutableSet<ComponentDescriptor> subcomponentsFromModules =
+        transitiveModules.stream()
+            .flatMap(transitiveModule -> transitiveModule.subcomponentDeclarations().stream())
+            .map(SubcomponentDeclaration::subcomponentType)
+            .map(this::subcomponentDescriptor)
+            .collect(toImmutableSet());
+
+      return new AutoValue_ComponentDescriptor(
+          componentAnnotation,
+          typeElement,
+          componentDependencies,
+          transitiveModules,
+          scopes,
+          subcomponentsFromModules,
+          subcomponentsByFactoryMethod.buildOrThrow(),
+          subcomponentsByBuilderMethod.buildOrThrow(),
+          componentMethodsBuilder.build(),
+          creatorDescriptor);
+    }
+
+    private ComponentMethodDescriptor getDescriptorForComponentMethod(
+        ComponentAnnotation componentAnnotation,
+        XTypeElement componentElement,
+        XMethodElement componentMethod) {
+      ComponentMethodDescriptor.Builder descriptor =
+          ComponentMethodDescriptor.builder(componentMethod);
+
+      XMethodType resolvedComponentMethod = componentMethod.asMemberOf(componentElement.getType());
+      XType returnType = resolvedComponentMethod.getReturnType();
+      if (isDeclared(returnType)
+              && !injectionAnnotations.getQualifier(componentMethod).isPresent()) {
+        XTypeElement returnTypeElement = returnType.getTypeElement();
+        if (returnTypeElement.hasAnyAnnotation(subcomponentAnnotations())) {
+          // It's a subcomponent factory method. There is no dependency request, and there could be
+          // any number of parameters. Just return the descriptor.
+          return descriptor.subcomponent(subcomponentDescriptor(returnTypeElement)).build();
+        }
+        if (isSubcomponentCreator(returnTypeElement)) {
+          descriptor.subcomponent(
+              subcomponentDescriptor(returnTypeElement.getEnclosingTypeElement()));
+        }
+      }
+
+      switch (componentMethod.getParameters().size()) {
+        case 0:
+          checkArgument(
+              !isVoid(returnType), "component method cannot be void: %s", componentMethod);
+          descriptor.dependencyRequest(
+              componentAnnotation.isProduction()
+                  ? dependencyRequestFactory.forComponentProductionMethod(
+                      componentMethod, resolvedComponentMethod)
+                  : dependencyRequestFactory.forComponentProvisionMethod(
+                      componentMethod, resolvedComponentMethod));
+          break;
+
+        case 1:
+          checkArgument(
+              isVoid(returnType)
+                  // TODO(bcorso): Replace this with isSameType()?
+                  || returnType
+                      .getTypeName()
+                      .equals(resolvedComponentMethod.getParameterTypes().get(0).getTypeName()),
+              "members injection method must return void or parameter type: %s",
+              componentMethod);
+          descriptor.dependencyRequest(
+              dependencyRequestFactory.forComponentMembersInjectionMethod(
+                  componentMethod, resolvedComponentMethod));
+          break;
+
+        default:
+          throw new IllegalArgumentException(
+              "component method has too many parameters: " + componentMethod);
+      }
+
+      return descriptor.build();
+    }
+
+    @Override
+    public void clearCache() {
+      cache.clear();
+    }
+  }
 }
diff --git a/java/dagger/internal/codegen/binding/ComponentDescriptorFactory.java b/java/dagger/internal/codegen/binding/ComponentDescriptorFactory.java
deleted file mode 100644
index 1d09450..0000000
--- a/java/dagger/internal/codegen/binding/ComponentDescriptorFactory.java
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * Copyright (C) 2014 The Dagger Authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package dagger.internal.codegen.binding;
-
-import static androidx.room.compiler.processing.XTypeKt.isVoid;
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static dagger.internal.codegen.base.ComponentAnnotation.rootComponentAnnotation;
-import static dagger.internal.codegen.base.ComponentAnnotation.subcomponentAnnotation;
-import static dagger.internal.codegen.base.ComponentAnnotation.subcomponentAnnotations;
-import static dagger.internal.codegen.base.ComponentCreatorAnnotation.creatorAnnotationsFor;
-import static dagger.internal.codegen.base.ModuleAnnotation.moduleAnnotation;
-import static dagger.internal.codegen.base.Scopes.productionScope;
-import static dagger.internal.codegen.binding.ConfigurationAnnotations.enclosedAnnotatedTypes;
-import static dagger.internal.codegen.binding.ConfigurationAnnotations.isSubcomponentCreator;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
-import static dagger.internal.codegen.xprocessing.XTypeElements.getAllUnimplementedMethods;
-import static dagger.internal.codegen.xprocessing.XTypes.isDeclared;
-
-import androidx.room.compiler.processing.XMethodElement;
-import androidx.room.compiler.processing.XMethodType;
-import androidx.room.compiler.processing.XProcessingEnv;
-import androidx.room.compiler.processing.XType;
-import androidx.room.compiler.processing.XTypeElement;
-import com.google.common.collect.ImmutableBiMap;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import dagger.internal.codegen.base.ComponentAnnotation;
-import dagger.internal.codegen.base.DaggerSuperficialValidation;
-import dagger.internal.codegen.base.ModuleAnnotation;
-import dagger.internal.codegen.binding.ComponentDescriptor.ComponentMethodDescriptor;
-import dagger.internal.codegen.model.Scope;
-import dagger.internal.codegen.xprocessing.XTypeElements;
-import java.util.Optional;
-import javax.inject.Inject;
-
-/** A factory for {@link ComponentDescriptor}s. */
-public final class ComponentDescriptorFactory {
-  private final XProcessingEnv processingEnv;
-  private final DependencyRequestFactory dependencyRequestFactory;
-  private final ModuleDescriptor.Factory moduleDescriptorFactory;
-  private final InjectionAnnotations injectionAnnotations;
-  private final DaggerSuperficialValidation superficialValidation;
-
-  @Inject
-  ComponentDescriptorFactory(
-      XProcessingEnv processingEnv,
-      DependencyRequestFactory dependencyRequestFactory,
-      ModuleDescriptor.Factory moduleDescriptorFactory,
-      InjectionAnnotations injectionAnnotations,
-      DaggerSuperficialValidation superficialValidation) {
-    this.processingEnv = processingEnv;
-    this.dependencyRequestFactory = dependencyRequestFactory;
-    this.moduleDescriptorFactory = moduleDescriptorFactory;
-    this.injectionAnnotations = injectionAnnotations;
-    this.superficialValidation = superficialValidation;
-  }
-
-  /** Returns a descriptor for a root component type. */
-  public ComponentDescriptor rootComponentDescriptor(XTypeElement typeElement) {
-    Optional<ComponentAnnotation> annotation =
-        rootComponentAnnotation(typeElement, superficialValidation);
-    checkArgument(annotation.isPresent(), "%s must have a component annotation", typeElement);
-    return create(typeElement, annotation.get());
-  }
-
-  /** Returns a descriptor for a subcomponent type. */
-  public ComponentDescriptor subcomponentDescriptor(XTypeElement typeElement) {
-    Optional<ComponentAnnotation> annotation =
-        subcomponentAnnotation(typeElement, superficialValidation);
-    checkArgument(annotation.isPresent(), "%s must have a subcomponent annotation", typeElement);
-    return create(typeElement, annotation.get());
-  }
-
-  /**
-   * Returns a descriptor for a fictional component based on a module type in order to validate its
-   * bindings.
-   */
-  public ComponentDescriptor moduleComponentDescriptor(XTypeElement typeElement) {
-    Optional<ModuleAnnotation> annotation = moduleAnnotation(typeElement, superficialValidation);
-    checkArgument(annotation.isPresent(), "%s must have a module annotation", typeElement);
-    return create(typeElement, ComponentAnnotation.fromModuleAnnotation(annotation.get()));
-  }
-
-  private ComponentDescriptor create(
-      XTypeElement typeElement, ComponentAnnotation componentAnnotation) {
-    ImmutableSet<ComponentRequirement> componentDependencies =
-        componentAnnotation.dependencyTypes().stream()
-            .map(ComponentRequirement::forDependency)
-            .collect(toImmutableSet());
-
-    ImmutableMap.Builder<XMethodElement, ComponentRequirement> dependenciesByDependencyMethod =
-        ImmutableMap.builder();
-    for (ComponentRequirement componentDependency : componentDependencies) {
-      XTypeElements.getAllMethods(componentDependency.typeElement()).stream()
-          .filter(ComponentDescriptor::isComponentContributionMethod)
-          .forEach(method -> dependenciesByDependencyMethod.put(method, componentDependency));
-    }
-
-    // Start with the component's modules. For fictional components built from a module, start with
-    // that module.
-    ImmutableSet<XTypeElement> modules =
-        componentAnnotation.isRealComponent()
-            ? componentAnnotation.modules()
-            : ImmutableSet.of(typeElement);
-
-    ImmutableSet<ModuleDescriptor> transitiveModules =
-        moduleDescriptorFactory.transitiveModules(modules);
-
-    ImmutableSet<ComponentDescriptor> subcomponentsFromModules =
-        transitiveModules.stream()
-            .flatMap(transitiveModule -> transitiveModule.subcomponentDeclarations().stream())
-            .map(SubcomponentDeclaration::subcomponentType)
-            .map(this::subcomponentDescriptor)
-            .collect(toImmutableSet());
-
-    ImmutableSet.Builder<ComponentMethodDescriptor> componentMethodsBuilder =
-        ImmutableSet.builder();
-    ImmutableBiMap.Builder<ComponentMethodDescriptor, ComponentDescriptor>
-        subcomponentsByFactoryMethod = ImmutableBiMap.builder();
-    ImmutableBiMap.Builder<ComponentMethodDescriptor, ComponentDescriptor>
-        subcomponentsByBuilderMethod = ImmutableBiMap.builder();
-    if (componentAnnotation.isRealComponent()) {
-      for (XMethodElement componentMethod : getAllUnimplementedMethods(typeElement)) {
-        ComponentMethodDescriptor componentMethodDescriptor =
-            getDescriptorForComponentMethod(componentAnnotation, typeElement, componentMethod);
-        componentMethodsBuilder.add(componentMethodDescriptor);
-        componentMethodDescriptor
-            .subcomponent()
-            .ifPresent(
-                subcomponent -> {
-                  // If the dependency request is present, that means the method returns the
-                  // subcomponent factory.
-                  if (componentMethodDescriptor.dependencyRequest().isPresent()) {
-                    subcomponentsByBuilderMethod.put(componentMethodDescriptor, subcomponent);
-                  } else {
-                    subcomponentsByFactoryMethod.put(componentMethodDescriptor, subcomponent);
-                  }
-                });
-      }
-    }
-
-    // Validation should have ensured that this set will have at most one element.
-    ImmutableSet<XTypeElement> enclosedCreators =
-        enclosedAnnotatedTypes(typeElement, creatorAnnotationsFor(componentAnnotation));
-    Optional<ComponentCreatorDescriptor> creatorDescriptor =
-        enclosedCreators.isEmpty()
-            ? Optional.empty()
-            : Optional.of(
-                ComponentCreatorDescriptor.create(
-                    getOnlyElement(enclosedCreators), dependencyRequestFactory));
-
-    ImmutableSet<Scope> scopes = injectionAnnotations.getScopes(typeElement);
-    if (componentAnnotation.isProduction()) {
-      scopes =
-          ImmutableSet.<Scope>builder().addAll(scopes).add(productionScope(processingEnv)).build();
-    }
-
-    return ComponentDescriptor.create(
-        componentAnnotation,
-        typeElement,
-        componentDependencies,
-        transitiveModules,
-        dependenciesByDependencyMethod.build(),
-        scopes,
-        subcomponentsFromModules,
-        subcomponentsByFactoryMethod.build(),
-        subcomponentsByBuilderMethod.build(),
-        componentMethodsBuilder.build(),
-        creatorDescriptor);
-  }
-
-  private ComponentMethodDescriptor getDescriptorForComponentMethod(
-      ComponentAnnotation componentAnnotation,
-      XTypeElement componentElement,
-      XMethodElement componentMethod) {
-    ComponentMethodDescriptor.Builder descriptor =
-        ComponentMethodDescriptor.builder(componentMethod);
-
-    XMethodType resolvedComponentMethod = componentMethod.asMemberOf(componentElement.getType());
-    XType returnType = resolvedComponentMethod.getReturnType();
-    if (isDeclared(returnType) && !injectionAnnotations.getQualifier(componentMethod).isPresent()) {
-      XTypeElement returnTypeElement = returnType.getTypeElement();
-      if (returnTypeElement.hasAnyAnnotation(subcomponentAnnotations())) {
-        // It's a subcomponent factory method. There is no dependency request, and there could be
-        // any number of parameters. Just return the descriptor.
-        return descriptor.subcomponent(subcomponentDescriptor(returnTypeElement)).build();
-      }
-      if (isSubcomponentCreator(returnTypeElement)) {
-        descriptor.subcomponent(
-            subcomponentDescriptor(returnTypeElement.getEnclosingTypeElement()));
-      }
-    }
-
-    switch (componentMethod.getParameters().size()) {
-      case 0:
-        checkArgument(!isVoid(returnType), "component method cannot be void: %s", componentMethod);
-        descriptor.dependencyRequest(
-            componentAnnotation.isProduction()
-                ? dependencyRequestFactory.forComponentProductionMethod(
-                    componentMethod, resolvedComponentMethod)
-                : dependencyRequestFactory.forComponentProvisionMethod(
-                    componentMethod, resolvedComponentMethod));
-        break;
-
-      case 1:
-        checkArgument(
-            isVoid(returnType)
-                // TODO(bcorso): Replace this with isSameType()?
-                || returnType
-                    .getTypeName()
-                    .equals(resolvedComponentMethod.getParameterTypes().get(0).getTypeName()),
-            "members injection method must return void or parameter type: %s",
-            componentMethod);
-        descriptor.dependencyRequest(
-            dependencyRequestFactory.forComponentMembersInjectionMethod(
-                componentMethod, resolvedComponentMethod));
-        break;
-
-      default:
-        throw new IllegalArgumentException(
-            "component method has too many parameters: " + componentMethod);
-    }
-
-    return descriptor.build();
-  }
-}
diff --git a/java/dagger/internal/codegen/binding/ComponentRequirement.java b/java/dagger/internal/codegen/binding/ComponentRequirement.java
index df10577..1779ec1 100644
--- a/java/dagger/internal/codegen/binding/ComponentRequirement.java
+++ b/java/dagger/internal/codegen/binding/ComponentRequirement.java
@@ -145,7 +145,7 @@
    * <p>Alternatively, if the module is a Kotlin Object then the binding methods are considered
    * {@code static}, requiring no module instance.
    */
-  private boolean requiresModuleInstance() {
+  public boolean requiresModuleInstance() {
     if (typeElement().isKotlinObject() || typeElement().isCompanionObject()) {
       return false;
     }
diff --git a/java/dagger/internal/codegen/binding/DependencyRequestFormatter.java b/java/dagger/internal/codegen/binding/DependencyRequestFormatter.java
index 80591b1..853ee99 100644
--- a/java/dagger/internal/codegen/binding/DependencyRequestFormatter.java
+++ b/java/dagger/internal/codegen/binding/DependencyRequestFormatter.java
@@ -25,12 +25,10 @@
 import androidx.room.compiler.processing.XElement;
 import androidx.room.compiler.processing.XProcessingEnv;
 import com.google.errorprone.annotations.CanIgnoreReturnValue;
-import dagger.Provides;
 import dagger.internal.codegen.base.Formatter;
 import dagger.internal.codegen.model.DaggerAnnotation;
 import dagger.internal.codegen.model.DependencyRequest;
 import dagger.internal.codegen.xprocessing.XTypes;
-import dagger.producers.Produces;
 import java.util.Optional;
 import javax.inject.Inject;
 
@@ -43,8 +41,7 @@
  *   <dd>{@code @Qualifier SomeType is provided at\n ComponentType.method()}
  *   <dt>For component injection methods
  *   <dd>{@code SomeType is injected at\n ComponentType.method(foo)}
- *   <dt>For parameters to {@link Provides @Provides}, {@link Produces @Produces}, or {@link
- *       Inject @Inject} methods:
+ *   <dt>For parameters to {@code @Provides}, {@code @Produces}, or {@code @Inject} methods:
  *   <dd>{@code @Qualified ResolvedType is injected at\n EnclosingType.method([…, ]param[, …])}
  *   <dt>For parameters to {@link Inject @Inject} constructors:
  *   <dd>{@code @Qualified ResolvedType is injected at\n EnclosingType([…, ]param[, …])}
diff --git a/java/dagger/internal/codegen/binding/FrameworkField.java b/java/dagger/internal/codegen/binding/FrameworkField.java
index b1d1cf9..a9f3bbf 100644
--- a/java/dagger/internal/codegen/binding/FrameworkField.java
+++ b/java/dagger/internal/codegen/binding/FrameworkField.java
@@ -24,12 +24,14 @@
 import static dagger.internal.codegen.xprocessing.XElements.getSimpleName;
 
 import androidx.room.compiler.processing.XElement;
-import androidx.room.compiler.processing.XType;
 import com.google.auto.value.AutoValue;
 import com.google.common.base.CaseFormat;
+import com.google.common.base.Preconditions;
 import com.squareup.javapoet.ClassName;
 import com.squareup.javapoet.ParameterizedTypeName;
 import com.squareup.javapoet.TypeName;
+import dagger.internal.codegen.base.MapType;
+import dagger.internal.codegen.javapoet.TypeNames;
 import java.util.Optional;
 
 /**
@@ -49,16 +51,17 @@
   /**
    * Creates a framework field.
    *
-   * @param frameworkClassName the name of the framework class (e.g., {@link javax.inject.Provider})
-   * @param valueTypeName the name of the type parameter of the framework class (e.g., {@code Foo}
-   *     for {@code Provider<Foo>}
-   * @param fieldName the name of the field
+   * @param fieldType the type of the framework field (e.g., {@code Provider<Foo>}).
+   * @param fieldName the base name of the field. The name of the raw type of the field will be
+   *     added as a suffix
    */
-  public static FrameworkField create(
-      ClassName frameworkClassName, TypeName valueTypeName, String fieldName) {
-    String suffix = frameworkClassName.simpleName();
+  public static FrameworkField create(TypeName fieldType, String fieldName) {
+    Preconditions.checkState(
+        fieldType instanceof ClassName || fieldType instanceof ParameterizedTypeName,
+        "Can only create a field with a class name or parameterized type name");
+    String suffix = ((ClassName) TypeNames.rawTypeName(fieldType)).simpleName();
     return new AutoValue_FrameworkField(
-        ParameterizedTypeName.get(frameworkClassName, valueTypeName),
+        fieldType,
         fieldName.endsWith(suffix) ? fieldName : fieldName + suffix);
   }
 
@@ -71,15 +74,26 @@
   public static FrameworkField forBinding(
       ContributionBinding binding, Optional<ClassName> frameworkClassName) {
     return create(
-        frameworkClassName.orElse(binding.frameworkType().frameworkClassName()),
-        fieldValueType(binding).getTypeName(),
+        fieldType(binding, frameworkClassName.orElse(binding.frameworkType().frameworkClassName())),
         frameworkFieldName(binding));
   }
 
-  private static XType fieldValueType(ContributionBinding binding) {
-    return binding.contributionType().isMultibinding()
-        ? binding.contributedType()
-        : binding.key().type().xprocessing();
+  private static TypeName fieldType(ContributionBinding binding, ClassName frameworkClassName) {
+    if (binding.contributionType().isMultibinding()) {
+      return ParameterizedTypeName.get(frameworkClassName, binding.contributedType().getTypeName());
+    }
+
+    // If the binding key type is a Map<K, Provider<V>>, we need to change field type to a raw
+    // type. This is because it actually needs to be changed to Map<K, dagger.internal.Provider<V>>,
+    // but that gets into assignment issues when the field is passed to methods that expect
+    // Map<K, javax.inject.Provider<V>>. We could add casts everywhere, but it is easier to just
+    // make the field itself a raw type.
+    if (MapType.isMapOfProvider(binding.contributedType())) {
+      return frameworkClassName;
+    }
+
+    return ParameterizedTypeName.get(
+        frameworkClassName, binding.key().type().xprocessing().getTypeName());
   }
 
   private static String frameworkFieldName(ContributionBinding binding) {
@@ -104,7 +118,7 @@
     }
   }
 
-  public abstract ParameterizedTypeName type();
+  public abstract TypeName type();
 
   public abstract String name();
 }
diff --git a/java/dagger/internal/codegen/binding/FrameworkType.java b/java/dagger/internal/codegen/binding/FrameworkType.java
index ce3b149..c995948 100644
--- a/java/dagger/internal/codegen/binding/FrameworkType.java
+++ b/java/dagger/internal/codegen/binding/FrameworkType.java
@@ -96,7 +96,8 @@
 
         case PROVIDER_OF_LAZY:
           return Expression.create(
-              from.type().rewrapType(TypeNames.LAZY).wrapType(TypeNames.PROVIDER), codeBlock);
+              from.type().rewrapType(TypeNames.LAZY).wrapType(TypeNames.DAGGER_PROVIDER),
+              codeBlock);
 
         case FUTURE:
           return Expression.create(from.type().rewrapType(TypeNames.LISTENABLE_FUTURE), codeBlock);
@@ -178,7 +179,7 @@
   public ClassName frameworkClassName() {
     switch (this) {
       case PROVIDER:
-        return TypeNames.PROVIDER;
+        return TypeNames.DAGGER_PROVIDER;
       case PRODUCER_NODE:
         // TODO(cgdecker): Replace this with new class for representing internal producer nodes.
         // Currently the new class is CancellableProducer, but it may be changed to ProducerNode and
diff --git a/java/dagger/internal/codegen/binding/FrameworkTypeMapper.java b/java/dagger/internal/codegen/binding/FrameworkTypeMapper.java
index 0e17d96..bd439bf 100644
--- a/java/dagger/internal/codegen/binding/FrameworkTypeMapper.java
+++ b/java/dagger/internal/codegen/binding/FrameworkTypeMapper.java
@@ -19,12 +19,10 @@
 import static dagger.internal.codegen.binding.BindingType.PRODUCTION;
 
 import dagger.internal.codegen.model.RequestKind;
-import dagger.producers.Producer;
-import javax.inject.Provider;
 
 /**
  * A mapper for associating a {@link RequestKind} to a {@link FrameworkType}, dependent on the type
- * of code to be generated (e.g., for {@link Provider} or {@link Producer}).
+ * of code to be generated (e.g., for {@code Provider} or {@code Producer}).
  */
 public enum FrameworkTypeMapper {
   FOR_PROVIDER() {
diff --git a/java/dagger/internal/codegen/binding/InjectionAnnotations.java b/java/dagger/internal/codegen/binding/InjectionAnnotations.java
index a8adb15..d4e1f90 100644
--- a/java/dagger/internal/codegen/binding/InjectionAnnotations.java
+++ b/java/dagger/internal/codegen/binding/InjectionAnnotations.java
@@ -22,12 +22,13 @@
 import static androidx.room.compiler.processing.XElementKt.isMethodParameter;
 import static androidx.room.compiler.processing.XElementKt.isTypeElement;
 import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
 import static com.google.common.collect.Iterables.getOnlyElement;
 import static dagger.internal.codegen.binding.SourceFiles.factoryNameForElement;
 import static dagger.internal.codegen.binding.SourceFiles.memberInjectedFieldSignatureForVariable;
 import static dagger.internal.codegen.binding.SourceFiles.membersInjectorNameForType;
-import static dagger.internal.codegen.extension.DaggerCollectors.onlyElement;
 import static dagger.internal.codegen.extension.DaggerCollectors.toOptional;
+import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
 import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
 import static dagger.internal.codegen.xprocessing.XElements.asField;
 import static dagger.internal.codegen.xprocessing.XElements.asMethod;
@@ -42,14 +43,17 @@
 import androidx.room.compiler.processing.XFieldElement;
 import androidx.room.compiler.processing.XProcessingEnv;
 import androidx.room.compiler.processing.XTypeElement;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import com.squareup.javapoet.ClassName;
 import dagger.internal.codegen.base.DaggerSuperficialValidation;
+import dagger.internal.codegen.base.ElementFormatter;
 import dagger.internal.codegen.compileroption.CompilerOptions;
 import dagger.internal.codegen.javapoet.TypeNames;
 import dagger.internal.codegen.kotlin.KotlinMetadataUtil;
 import dagger.internal.codegen.model.DaggerAnnotation;
 import dagger.internal.codegen.model.Scope;
+import dagger.internal.codegen.xprocessing.XAnnotations;
 import java.util.Optional;
 import java.util.stream.Stream;
 import javax.inject.Inject;
@@ -100,18 +104,7 @@
   public ImmutableSet<Scope> getScopes(XElement element) {
     superficialValidation.validateTypeOf(element);
     ImmutableSet<Scope> scopes =
-        getScopesFromScopeMetadata(element)
-            .orElseGet(
-                () -> {
-                  // Validate the annotation types before we check for @Scope, otherwise the @Scope
-                  // annotation may appear to be missing (b/213880825).
-                  superficialValidation.validateAnnotationTypesOf(element);
-                  return element.getAllAnnotations().stream()
-                      .filter(InjectionAnnotations::hasScopeAnnotation)
-                      .map(DaggerAnnotation::from)
-                      .map(Scope::scope)
-                      .collect(toImmutableSet());
-                });
+        getScopesWithMetadata(element).orElseGet(() -> getScopesWithoutMetadata(element));
 
     // Fully validate each scope to ensure its values are also valid.
     scopes.stream()
@@ -120,7 +113,18 @@
     return scopes;
   }
 
-  private Optional<ImmutableSet<Scope>> getScopesFromScopeMetadata(XElement element) {
+  private ImmutableSet<Scope> getScopesWithoutMetadata(XElement element) {
+    // Validate the annotation types before we check for @Scope, otherwise the @Scope
+    // annotation may appear to be missing (b/213880825).
+    superficialValidation.validateAnnotationTypesOf(element);
+    return element.getAllAnnotations().stream()
+        .filter(InjectionAnnotations::hasScopeAnnotation)
+        .map(DaggerAnnotation::from)
+        .map(Scope::scope)
+        .collect(toImmutableSet());
+  }
+
+  private Optional<ImmutableSet<Scope>> getScopesWithMetadata(XElement element) {
     Optional<XAnnotation> scopeMetadata = getScopeMetadata(element);
     if (!scopeMetadata.isPresent()) {
       return Optional.empty();
@@ -129,13 +133,20 @@
     if (scopeName.isEmpty()) {
       return Optional.of(ImmutableSet.of());
     }
-    XAnnotation scopeAnnotation =
+    ImmutableList<XAnnotation> scopeAnnotations =
         element.getAllAnnotations().stream()
             .filter(
                 annotation ->
                     scopeName.contentEquals(
                         annotation.getType().getTypeElement().getQualifiedName()))
-            .collect(onlyElement());
+            .collect(toImmutableList());
+    checkState(
+        scopeAnnotations.size() == 1,
+        "Expected %s to have a scope annotation for %s but found: %s",
+        ElementFormatter.elementToString(element),
+        scopeName,
+        scopeAnnotations.stream().map(XAnnotations::toStableString).collect(toImmutableList()));
+    XAnnotation scopeAnnotation = getOnlyElement(scopeAnnotations);
     // Do superficial validation before we convert to a Scope, otherwise the @Scope annotation may
     // appear to be missing from the annotation if it's no longer on the classpath.
     superficialValidation.validateAnnotationTypeOf(element, scopeAnnotation);
@@ -170,7 +181,7 @@
     return Optional.empty();
   }
 
-  /*
+  /**
    * Returns the qualifier on the given element if it exists.
    *
    * <p>The {@code QualifierMetadata} is used to avoid superficial validation on unnecessary
@@ -203,16 +214,8 @@
   public ImmutableSet<XAnnotation> getQualifiers(XElement element) {
     superficialValidation.validateTypeOf(element);
     ImmutableSet<XAnnotation> qualifiers =
-        getQualifiersFromQualifierMetadata(element)
-            .orElseGet(
-                () -> {
-                  // Validate the annotation types before we check for @Qualifier, otherwise the
-                  // @Qualifier annotation may appear to be missing (b/213880825).
-                  superficialValidation.validateAnnotationTypesOf(element);
-                  return element.getAllAnnotations().stream()
-                      .filter(InjectionAnnotations::hasQualifierAnnotation)
-                      .collect(toImmutableSet());
-                });
+        getQualifiersWithMetadata(element)
+            .orElseGet(() -> getQualifiersWithoutMetadata(element));
 
     if (isField(element)) {
       XFieldElement field = asField(element);
@@ -237,7 +240,16 @@
     return qualifiers;
   }
 
-  private Optional<ImmutableSet<XAnnotation>> getQualifiersFromQualifierMetadata(XElement element) {
+  private ImmutableSet<XAnnotation> getQualifiersWithoutMetadata(XElement element) {
+    // Validate the annotation types before we check for @Qualifier, otherwise the
+    // @Qualifier annotation may appear to be missing (b/213880825).
+    superficialValidation.validateAnnotationTypesOf(element);
+    return element.getAllAnnotations().stream()
+        .filter(InjectionAnnotations::hasQualifierAnnotation)
+        .collect(toImmutableSet());
+  }
+
+  private Optional<ImmutableSet<XAnnotation>> getQualifiersWithMetadata(XElement element) {
     Optional<XAnnotation> qualifierMetadata = getQualifierMetadata(element);
     if (!qualifierMetadata.isPresent()) {
       return Optional.empty();
diff --git a/java/dagger/internal/codegen/binding/InjectionSiteFactory.java b/java/dagger/internal/codegen/binding/InjectionSiteFactory.java
index 5ede200..36e831b 100644
--- a/java/dagger/internal/codegen/binding/InjectionSiteFactory.java
+++ b/java/dagger/internal/codegen/binding/InjectionSiteFactory.java
@@ -68,10 +68,13 @@
       XTypeElement typeElement = currentType.get().getTypeElement();
       enclosingTypeElementOrder.put(typeElement, enclosingTypeElementOrder.size());
       for (XElement enclosedElement : typeElement.getEnclosedElements()) {
-        enclosedElementOrder.put(enclosedElement, enclosedElementOrder.size());
         injectionSiteVisitor
             .visit(enclosedElement, currentType.get())
-            .ifPresent(injectionSites::add);
+            .ifPresent(
+                injectionSite -> {
+                  enclosedElementOrder.put(enclosedElement, enclosedElementOrder.size());
+                  injectionSites.add(injectionSite);
+                });
       }
     }
     return ImmutableSortedSet.copyOf(
diff --git a/java/dagger/internal/codegen/binding/LegacyBindingGraph.java b/java/dagger/internal/codegen/binding/LegacyBindingGraph.java
deleted file mode 100644
index b38697e..0000000
--- a/java/dagger/internal/codegen/binding/LegacyBindingGraph.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2014 The Dagger Authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package dagger.internal.codegen.binding;
-
-import androidx.room.compiler.processing.XTypeElement;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Multimaps;
-import dagger.internal.codegen.model.Key;
-import dagger.internal.codegen.model.RequestKind;
-import java.util.Collection;
-import java.util.Map;
-
-// TODO(bcorso): Remove the LegacyBindingGraph after we've migrated to the new BindingGraph.
-/** The canonical representation of a full-resolved graph. */
-final class LegacyBindingGraph {
-  private final ComponentDescriptor componentDescriptor;
-  private final ImmutableMap<Key, ResolvedBindings> contributionBindings;
-  private final ImmutableMap<Key, ResolvedBindings> membersInjectionBindings;
-  private final ImmutableList<LegacyBindingGraph> subgraphs;
-
-  LegacyBindingGraph(
-      ComponentDescriptor componentDescriptor,
-      ImmutableMap<Key, ResolvedBindings> contributionBindings,
-      ImmutableMap<Key, ResolvedBindings> membersInjectionBindings,
-      ImmutableList<LegacyBindingGraph> subgraphs) {
-    this.componentDescriptor = componentDescriptor;
-    this.contributionBindings = contributionBindings;
-    this.membersInjectionBindings = membersInjectionBindings;
-    this.subgraphs = checkForDuplicates(subgraphs);
-  }
-
-  ComponentDescriptor componentDescriptor() {
-    return componentDescriptor;
-  }
-
-  ResolvedBindings resolvedBindings(BindingRequest request) {
-    return request.isRequestKind(RequestKind.MEMBERS_INJECTION)
-        ? membersInjectionBindings.get(request.key())
-        : contributionBindings.get(request.key());
-  }
-
-  Iterable<ResolvedBindings> resolvedBindings() {
-    // Don't return an immutable collection - this is only ever used for looping over all bindings
-    // in the graph. Copying is wasteful, especially if is a hashing collection, since the values
-    // should all, by definition, be distinct.
-    return Iterables.concat(membersInjectionBindings.values(), contributionBindings.values());
-  }
-
-  ImmutableList<LegacyBindingGraph> subgraphs() {
-    return subgraphs;
-  }
-
-  private static ImmutableList<LegacyBindingGraph> checkForDuplicates(
-      ImmutableList<LegacyBindingGraph> graphs) {
-    Map<XTypeElement, Collection<LegacyBindingGraph>> duplicateGraphs =
-        Maps.filterValues(
-            Multimaps.index(graphs, graph -> graph.componentDescriptor().typeElement()).asMap(),
-            overlapping -> overlapping.size() > 1);
-    if (!duplicateGraphs.isEmpty()) {
-      throw new IllegalArgumentException("Expected no duplicates: " + duplicateGraphs);
-    }
-    return graphs;
-  }
-}
diff --git a/java/dagger/internal/codegen/binding/MapKeys.java b/java/dagger/internal/codegen/binding/MapKeys.java
index c156dbb..61ef9f2 100644
--- a/java/dagger/internal/codegen/binding/MapKeys.java
+++ b/java/dagger/internal/codegen/binding/MapKeys.java
@@ -199,5 +199,26 @@
                     .build());
   }
 
+  /**
+   * Returns if this binding is a map binding and uses @LazyClassKey for contributing class keys.
+   *
+   * <p>@LazyClassKey won't co-exist with @ClassKey in the graph, since the same binding type cannot
+   * use more than one @MapKey annotation type and Dagger validation will fail.
+   */
+  public static boolean useLazyClassKey(Binding binding, BindingGraph graph) {
+    if (!binding.dependencies().isEmpty()) {
+      ContributionBinding contributionBinding =
+          graph.contributionBinding(binding.dependencies().iterator().next().key());
+      return contributionBinding.mapKey().isPresent()
+          && contributionBinding
+              .mapKey()
+              .get()
+              .xprocessing()
+              .getClassName()
+              .equals(TypeNames.LAZY_CLASS_KEY);
+    }
+    return false;
+  }
+
   private MapKeys() {}
 }
diff --git a/java/dagger/internal/codegen/binding/MethodSignatureFormatter.java b/java/dagger/internal/codegen/binding/MethodSignatureFormatter.java
index e98abcc..d7fea80 100644
--- a/java/dagger/internal/codegen/binding/MethodSignatureFormatter.java
+++ b/java/dagger/internal/codegen/binding/MethodSignatureFormatter.java
@@ -16,13 +16,14 @@
 
 package dagger.internal.codegen.binding;
 
+import static androidx.room.compiler.processing.compat.XConverters.getProcessingEnv;
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkState;
 import static dagger.internal.codegen.base.DiagnosticFormatting.stripCommonTypePrefixes;
+import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
 import static dagger.internal.codegen.xprocessing.XElements.closestEnclosingTypeElement;
 import static dagger.internal.codegen.xprocessing.XElements.getSimpleName;
 import static dagger.internal.codegen.xprocessing.XTypes.isDeclared;
-import static java.util.stream.Collectors.joining;
 
 import androidx.room.compiler.processing.XAnnotation;
 import androidx.room.compiler.processing.XExecutableElement;
@@ -33,12 +34,13 @@
 import androidx.room.compiler.processing.XType;
 import androidx.room.compiler.processing.XTypeElement;
 import androidx.room.compiler.processing.XVariableElement;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Streams;
 import com.squareup.javapoet.ClassName;
 import dagger.internal.codegen.base.Formatter;
 import dagger.internal.codegen.xprocessing.XAnnotations;
 import dagger.internal.codegen.xprocessing.XTypes;
 import java.util.Iterator;
-import java.util.List;
 import java.util.Optional;
 import javax.inject.Inject;
 
@@ -46,6 +48,8 @@
 public final class MethodSignatureFormatter extends Formatter<XExecutableElement> {
   private static final ClassName JET_BRAINS_NOT_NULL =
       ClassName.get("org.jetbrains.annotations", "NotNull");
+  private static final ClassName JET_BRAINS_NULLABLE =
+      ClassName.get("org.jetbrains.annotations", "Nullable");
 
   private final InjectionAnnotations injectionAnnotations;
 
@@ -106,15 +110,9 @@
       XTypeElement container,
       boolean includeReturnType) {
     StringBuilder builder = new StringBuilder();
-    List<XAnnotation> annotations = method.getAllAnnotations();
-    if (!annotations.isEmpty()) {
-      builder.append(
-          annotations.stream()
-              // Filter out @NotNull annotations added by KAPT to make error messages consistent
-              .filter(annotation -> !annotation.getClassName().equals(JET_BRAINS_NOT_NULL))
-              .map(MethodSignatureFormatter::formatAnnotation)
-              .collect(joining(" ")))
-          .append(" ");
+    ImmutableList<String> formattedAnnotations = formatedAnnotations(method);
+    if (!formattedAnnotations.isEmpty()) {
+      builder.append(String.join(" ", formattedAnnotations)).append(" ");
     }
     if (getSimpleName(method).contentEquals("<init>")) {
       builder.append(container.getQualifiedName());
@@ -154,6 +152,34 @@
     return stripCommonTypePrefixes(XTypes.toStableString(type));
   }
 
+  private static ImmutableList<String> formatedAnnotations(XExecutableElement executableElement) {
+    Nullability nullability = Nullability.of(executableElement);
+    ImmutableList<String> formattedAnnotations =
+        Streams.concat(
+                executableElement.getAllAnnotations().stream()
+                    // Filter out @NotNull annotations added by KAPT to make error messages
+                    // consistent
+                    .filter(annotation -> !annotation.getClassName().equals(JET_BRAINS_NOT_NULL))
+                    .map(MethodSignatureFormatter::formatAnnotation),
+                nullability.nullableAnnotations().stream()
+                    // Filter out @NotNull annotations added by KAPT to make error messages
+                    // consistent
+                    .filter(annotation -> !annotation.equals(JET_BRAINS_NOT_NULL))
+                    .map(annotation -> String.format("@%s", annotation.canonicalName())))
+            .distinct()
+            .collect(toImmutableList());
+    if (nullability.isKotlinTypeNullable()
+        && nullability.nullableAnnotations().stream().noneMatch(JET_BRAINS_NULLABLE::equals)
+        && getProcessingEnv(executableElement).findTypeElement(JET_BRAINS_NULLABLE) != null) {
+      formattedAnnotations =
+          ImmutableList.<String>builder()
+              .addAll(formattedAnnotations)
+              .add(String.format("@%s", JET_BRAINS_NULLABLE.canonicalName()))
+              .build();
+    }
+    return formattedAnnotations;
+  }
+
   private static String formatAnnotation(XAnnotation annotation) {
     return stripCommonTypePrefixes(XAnnotations.toString(annotation));
   }
diff --git a/java/dagger/internal/codegen/binding/MonitoringModules.java b/java/dagger/internal/codegen/binding/MonitoringModules.java
new file mode 100644
index 0000000..fc6dc02
--- /dev/null
+++ b/java/dagger/internal/codegen/binding/MonitoringModules.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.internal.codegen.binding;
+
+import com.squareup.javapoet.ClassName;
+import dagger.internal.codegen.base.ClearableCache;
+import java.util.HashSet;
+import java.util.Set;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/** Keeps track of modules generated in the current round by {@link MonitoringModuleGenerator}. */
+@Singleton
+public final class MonitoringModules implements ClearableCache {
+  Set<ClassName> cache = new HashSet<>();
+
+  @Inject
+  MonitoringModules() {}
+
+  public void add(ClassName module) {
+    cache.add(module);
+  }
+
+  public boolean isEmpty() {
+    return cache.isEmpty();
+  }
+
+  @Override
+  public void clearCache() {
+    cache.clear();
+  }
+}
diff --git a/java/dagger/internal/codegen/binding/Nullability.java b/java/dagger/internal/codegen/binding/Nullability.java
index 190227b..4231a8f 100644
--- a/java/dagger/internal/codegen/binding/Nullability.java
+++ b/java/dagger/internal/codegen/binding/Nullability.java
@@ -18,7 +18,7 @@
 
 import static androidx.room.compiler.processing.XElementKt.isMethod;
 import static androidx.room.compiler.processing.XElementKt.isVariableElement;
-import static dagger.internal.codegen.xprocessing.XAnnotations.getClassName;
+import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
 import static dagger.internal.codegen.xprocessing.XElements.asMethod;
 import static dagger.internal.codegen.xprocessing.XElements.asVariable;
 
@@ -27,7 +27,10 @@
 import androidx.room.compiler.processing.XNullability;
 import androidx.room.compiler.processing.XType;
 import com.google.auto.value.AutoValue;
-import java.util.Optional;
+import com.google.common.collect.ImmutableSet;
+import com.squareup.javapoet.ClassName;
+import dagger.internal.codegen.xprocessing.XAnnotations;
+import java.util.stream.Stream;
 
 /**
  * Contains information about the nullability of an element.
@@ -42,16 +45,43 @@
 @AutoValue
 public abstract class Nullability {
   /** A constant that can represent any non-null element. */
-  public static final Nullability NOT_NULLABLE = new AutoValue_Nullability(false, Optional.empty());
+  public static final Nullability NOT_NULLABLE =
+      new AutoValue_Nullability(false, ImmutableSet.of());
 
   public static Nullability of(XElement element) {
-    Optional<XAnnotation> nullableAnnotation = getNullableAnnotation(element);
-    boolean isNullable = isKotlinTypeNullable(element) || nullableAnnotation.isPresent();
-    return isNullable ? new AutoValue_Nullability(isNullable, nullableAnnotation) : NOT_NULLABLE;
+    return new AutoValue_Nullability(
+        /* isKotlinTypeNullable= */ isKotlinTypeNullable(element),
+        /* nullableAnnotations= */ getNullableAnnotations(element));
   }
 
+  private static ImmutableSet<ClassName> getNullableAnnotations(XElement element) {
+    return getNullableAnnotations(element.getAllAnnotations().stream(), ImmutableSet.of());
+  }
+
+  private static ImmutableSet<ClassName> getNullableAnnotations(
+      Stream<XAnnotation> annotations,
+      ImmutableSet<ClassName> filterSet) {
+    return annotations
+        .map(XAnnotations::getClassName)
+        .filter(annotation -> annotation.simpleName().contentEquals("Nullable"))
+        .filter(annotation -> !filterSet.contains(annotation))
+        .collect(toImmutableSet());
+  }
+
+  /**
+   * Returns {@code true} if the element's type is a Kotlin nullable type, e.g. {@code Foo?}.
+   *
+   * <p>Note that this method ignores any {@code @Nullable} type annotations and only looks for
+   * explicit {@code ?} usages on kotlin types.
+   */
   private static boolean isKotlinTypeNullable(XElement element) {
-    if (isMethod(element)) {
+    if (element.getClosestMemberContainer().isFromJava()) {
+      // Note: Technically, it isn't possible for Java sources to have nullable types like in Kotlin
+      // sources, but for some reason KSP treats certain types as nullable if they have a
+      // specific @Nullable (TYPE_USE target) annotation. Thus, to avoid inconsistencies with KAPT,
+      // just return false if this element is from a java source.
+      return false;
+    } else if (isMethod(element)) {
       return isKotlinTypeNullable(asMethod(element).getReturnType());
     } else if (isVariableElement(element)) {
       return isKotlinTypeNullable(asVariable(element).getType());
@@ -64,16 +94,13 @@
     return type.getNullability() == XNullability.NULLABLE;
   }
 
-  /** Returns the first type that specifies this' nullability, or empty if none. */
-  private static Optional<XAnnotation> getNullableAnnotation(XElement element) {
-    return element.getAllAnnotations().stream()
-        .filter(annotation -> getClassName(annotation).simpleName().contentEquals("Nullable"))
-        .findFirst();
+  public abstract boolean isKotlinTypeNullable();
+
+  public abstract ImmutableSet<ClassName> nullableAnnotations();
+
+  public final boolean isNullable() {
+    return isKotlinTypeNullable() || !nullableAnnotations().isEmpty();
   }
 
-  public abstract boolean isNullable();
-
-  public abstract Optional<XAnnotation> nullableAnnotation();
-
   Nullability() {}
 }
diff --git a/java/dagger/internal/codegen/binding/ResolvedBindings.java b/java/dagger/internal/codegen/binding/ResolvedBindings.java
index 8a35442..406ae41 100644
--- a/java/dagger/internal/codegen/binding/ResolvedBindings.java
+++ b/java/dagger/internal/codegen/binding/ResolvedBindings.java
@@ -27,6 +27,7 @@
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.ImmutableSetMultimap;
 import com.google.common.collect.Multimap;
+import dagger.internal.codegen.model.ComponentPath;
 import dagger.internal.codegen.model.Key;
 
 /**
@@ -40,6 +41,9 @@
  */
 @AutoValue
 abstract class ResolvedBindings {
+  /** The component path for the resolved bindings. */
+  abstract ComponentPath componentPath();
+
   /** The binding key for which the {@link #bindings()} have been resolved. */
   abstract Key key();
 
@@ -127,12 +131,14 @@
 
   /** Creates a {@link ResolvedBindings} for contribution bindings. */
   static ResolvedBindings forContributionBindings(
+      ComponentPath componentPath,
       Key key,
       Multimap<XTypeElement, ContributionBinding> contributionBindings,
       Iterable<MultibindingDeclaration> multibindings,
       Iterable<SubcomponentDeclaration> subcomponentDeclarations,
       Iterable<OptionalBindingDeclaration> optionalBindingDeclarations) {
     return new AutoValue_ResolvedBindings(
+        componentPath,
         key,
         ImmutableSetMultimap.copyOf(contributionBindings),
         ImmutableMap.of(),
@@ -145,10 +151,12 @@
    * Creates a {@link ResolvedBindings} for members injection bindings.
    */
   static ResolvedBindings forMembersInjectionBinding(
+      ComponentPath componentPath,
       Key key,
       ComponentDescriptor owningComponent,
       MembersInjectionBinding ownedMembersInjectionBinding) {
     return new AutoValue_ResolvedBindings(
+        componentPath,
         key,
         ImmutableSetMultimap.of(),
         ImmutableMap.of(owningComponent.typeElement(), ownedMembersInjectionBinding),
@@ -160,8 +168,9 @@
   /**
    * Creates a {@link ResolvedBindings} appropriate for when there are no bindings for the key.
    */
-  static ResolvedBindings noBindings(Key key) {
+  static ResolvedBindings noBindings(ComponentPath componentPath, Key key) {
     return new AutoValue_ResolvedBindings(
+        componentPath,
         key,
         ImmutableSetMultimap.of(),
         ImmutableMap.of(),
diff --git a/java/dagger/internal/codegen/binding/SourceFiles.java b/java/dagger/internal/codegen/binding/SourceFiles.java
index 19d316f..e8a1075 100644
--- a/java/dagger/internal/codegen/binding/SourceFiles.java
+++ b/java/dagger/internal/codegen/binding/SourceFiles.java
@@ -95,11 +95,23 @@
 
     return Maps.toMap(
         binding.dependencies(),
-        dependency ->
-            FrameworkField.create(
-                frameworkTypeMapper.getFrameworkType(dependency.kind()).frameworkClassName(),
-                dependency.key().type().xprocessing().getTypeName(),
-                DependencyVariableNamer.name(dependency)));
+        dependency -> {
+          ClassName frameworkClassName =
+              frameworkTypeMapper.getFrameworkType(dependency.kind()).frameworkClassName();
+          // Remap factory fields back to javax.inject.Provider to maintain backwards compatibility
+          // for now. In a future release, we should change this to Dagger Provider. This will still
+          // be a breaking change, but keeping compatibility for a while should reduce the
+          // likelihood of breakages as it would require components built at much older versions
+          // using factories built at newer versions to break.
+          if (frameworkClassName.equals(TypeNames.DAGGER_PROVIDER)) {
+            frameworkClassName = TypeNames.PROVIDER;
+          }
+          return FrameworkField.create(
+              ParameterizedTypeName.get(
+                  frameworkClassName,
+                  dependency.key().type().xprocessing().getTypeName()),
+              DependencyVariableNamer.name(dependency));
+        });
   }
 
   public CodeBlock frameworkTypeUsageStatement(
diff --git a/java/dagger/internal/codegen/bindinggraphvalidation/MissingBindingValidator.java b/java/dagger/internal/codegen/bindinggraphvalidation/MissingBindingValidator.java
index 774ee5d..fd9e42e 100644
--- a/java/dagger/internal/codegen/bindinggraphvalidation/MissingBindingValidator.java
+++ b/java/dagger/internal/codegen/bindinggraphvalidation/MissingBindingValidator.java
@@ -20,12 +20,13 @@
 import static com.google.common.base.Verify.verify;
 import static com.google.common.collect.Iterables.getLast;
 import static com.google.common.collect.Iterables.getOnlyElement;
+import static dagger.internal.codegen.base.ElementFormatter.elementToString;
+import static dagger.internal.codegen.base.Formatter.INDENT;
 import static dagger.internal.codegen.base.Keys.isValidImplicitProvisionKey;
 import static dagger.internal.codegen.base.Keys.isValidMembersInjectionKey;
 import static dagger.internal.codegen.base.RequestKinds.canBeSatisfiedByProductionBinding;
 import static dagger.internal.codegen.binding.DependencyRequestFormatter.DOUBLE_INDENT;
 import static dagger.internal.codegen.extension.DaggerStreams.instancesOf;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
 import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
 import static dagger.internal.codegen.xprocessing.XTypes.isDeclared;
 import static dagger.internal.codegen.xprocessing.XTypes.isWildcard;
@@ -38,6 +39,7 @@
 import com.google.common.collect.Lists;
 import com.squareup.javapoet.TypeName;
 import com.squareup.javapoet.WildcardTypeName;
+import dagger.internal.codegen.binding.ComponentNodeImpl;
 import dagger.internal.codegen.binding.DependencyRequestFormatter;
 import dagger.internal.codegen.binding.InjectBindingRegistry;
 import dagger.internal.codegen.model.Binding;
@@ -47,7 +49,6 @@
 import dagger.internal.codegen.model.BindingGraph.Edge;
 import dagger.internal.codegen.model.BindingGraph.MissingBinding;
 import dagger.internal.codegen.model.BindingGraph.Node;
-import dagger.internal.codegen.model.ComponentPath;
 import dagger.internal.codegen.model.DaggerAnnotation;
 import dagger.internal.codegen.model.DiagnosticReporter;
 import dagger.internal.codegen.model.Key;
@@ -103,62 +104,20 @@
     prunedGraph
         .missingBindings()
         .forEach(
-            missingBinding ->
-                reportMissingBinding(missingBinding, prunedGraph, fullGraph, diagnosticReporter));
+            missingBinding -> reportMissingBinding(missingBinding, fullGraph, diagnosticReporter));
   }
 
   private void reportMissingBinding(
       MissingBinding missingBinding,
-      BindingGraph prunedGraph,
-      BindingGraph fullGraph,
+      BindingGraph graph,
       DiagnosticReporter diagnosticReporter) {
-    ImmutableSet<Binding> wildcardAlternatives =
-        getSimilarTypeBindings(fullGraph, missingBinding.key());
-    String wildcardTypeErrorMessage = "";
-    if (!wildcardAlternatives.isEmpty()) {
-      wildcardTypeErrorMessage =
-          String.format(
-              "\nFound similar bindings:\n    %s",
-              String.join(
-                  "\n    ",
-                  wildcardAlternatives.stream()
-                      .map(
-                          binding -> binding.key().type() + " in [" + binding.componentPath() + "]")
-                      .collect(toImmutableSet())))
-                  + "\n(In Kotlin source, a type like 'Set<Foo>' may"
-                  + " be translated as 'Set<? extends Foo>'. To avoid this implicit"
-                  + " conversion you can add '@JvmSuppressWildcards' on the associated type"
-                  + " argument, e.g. 'Set<@JvmSuppressWildcards Foo>'.)";
-    }
-
-    List<ComponentPath> alternativeComponents =
-        wildcardAlternatives.isEmpty()
-            ? fullGraph.bindings(missingBinding.key()).stream()
-                .map(Binding::componentPath)
-                .distinct()
-                .collect(toImmutableList())
-            : ImmutableList.of();
-    // Print component name for each binding along the dependency path if the missing binding
-    // exists in a different component than expected
-    if (alternativeComponents.isEmpty()) {
-      // TODO(b/266993189): the passed in diagnostic reporter is constructed with full graph, so it
-      // doesn't print out full dependency path for a binding when invoking reportBinding on it.
-      // Therefore, we manually constructed the binding dependency path and passed into
-      // reportComponent.
-      diagnosticReporter.reportComponent(
-          ERROR,
-          fullGraph.componentNode(missingBinding.componentPath()).get(),
-          missingBindingErrorMessage(missingBinding, fullGraph)
-              + wildcardTypeErrorMessage
-              + "\n\nMissing binding usage:"
-              + diagnosticMessageGeneratorFactory.create(prunedGraph).getMessage(missingBinding));
-    } else {
-      diagnosticReporter.reportComponent(
-          ERROR,
-          fullGraph.componentNode(missingBinding.componentPath()).get(),
-          missingBindingErrorMessage(missingBinding, fullGraph)
-              + wrongComponentErrorMessage(missingBinding, alternativeComponents, prunedGraph));
-    }
+    diagnosticReporter.reportComponent(
+        ERROR,
+        graph.componentNode(missingBinding.componentPath()).get(),
+        missingBindingErrorMessage(missingBinding, graph)
+            + missingBindingDependencyTraceMessage(missingBinding, graph)
+            + alternativeBindingsMessage(missingBinding, graph)
+            + similarBindingsMessage(missingBinding, graph));
   }
 
   private static ImmutableSet<Binding> getSimilarTypeBindings(
@@ -222,50 +181,24 @@
     return errorMessage.toString();
   }
 
-  private String wrongComponentErrorMessage(
-      MissingBinding missingBinding,
-      List<ComponentPath> alternativeComponentPath,
-      BindingGraph graph) {
+  private String missingBindingDependencyTraceMessage(
+      MissingBinding missingBinding, BindingGraph graph) {
     ImmutableSet<DependencyEdge> entryPoints =
         graph.entryPointEdgesDependingOnBinding(missingBinding);
     DiagnosticMessageGenerator generator = diagnosticMessageGeneratorFactory.create(graph);
     ImmutableList<DependencyEdge> dependencyTrace =
         generator.dependencyTrace(missingBinding, entryPoints);
     StringBuilder message =
-        graph.isFullBindingGraph()
-            ? new StringBuilder()
-            : new StringBuilder(dependencyTrace.size() * 100 /* a guess heuristic */);
-    // Check in which component the missing binding is requested. This can be different from the
-    // component the missing binding is in because we'll try to search up the parent components for
-    // a binding which makes missing bindings end up at the root component. This is different from
-    // the place we are logically requesting the binding from. Note that this is related to the
-    // particular dependency trace being shown and so is not necessarily stable.
-    String missingComponentName =
-        getComponentFromDependencyEdge(dependencyTrace.get(0), graph, false);
-    boolean hasSameComponentName = false;
-    for (ComponentPath component : alternativeComponentPath) {
-      message.append("\nNote: A binding for ").append(missingBinding.key()).append(" exists in ");
-      String currentComponentName = component.currentComponent().className().canonicalName();
-      if (currentComponentName.contentEquals(missingComponentName)) {
-        hasSameComponentName = true;
-        message.append("[").append(component).append("]");
-      } else {
-        message.append(currentComponentName);
-      }
-      message.append(":");
-    }
+        new StringBuilder(dependencyTrace.size() * 100 /* a guess heuristic */).append("\n");
     for (DependencyEdge edge : dependencyTrace) {
       String line = dependencyRequestFormatter.format(edge.dependencyRequest());
       if (line.isEmpty()) {
         continue;
       }
-      // If we ran into a rare case where the component names collide and we need to show the full
-      // path, only show the full path for the first dependency request. This is guaranteed to be
-      // the component in question since the logic for checking for a collision uses the first
-      // edge in the trace. Do not expand subsequent component paths to reduce spam.
-      String componentName =
-          String.format("[%s] ", getComponentFromDependencyEdge(edge, graph, hasSameComponentName));
-      hasSameComponentName = false;
+      // We don't have to check for cases where component names collide since
+      //  1. We always show the full classname of the component, and
+      //  2. We always show the full component path at the end of the dependency trace (below).
+      String componentName = String.format("[%s] ", getComponentFromDependencyEdge(edge, graph));
       message.append("\n").append(line.replace(DOUBLE_INDENT, DOUBLE_INDENT + componentName));
     }
     if (!dependencyTrace.isEmpty()) {
@@ -277,6 +210,71 @@
     return message.toString();
   }
 
+  private String alternativeBindingsMessage(
+      MissingBinding missingBinding, BindingGraph graph) {
+    ImmutableSet<Binding> alternativeBindings = graph.bindings(missingBinding.key());
+    if (alternativeBindings.isEmpty()) {
+      return "";
+    }
+    StringBuilder message = new StringBuilder();
+    message.append("\n\nNote: ")
+        .append(missingBinding.key())
+        .append(" is provided in the following other components:");
+    for (Binding alternativeBinding : alternativeBindings) {
+      // Some alternative bindings appear multiple times because they were re-resolved in multiple
+      // components (e.g. due to multibinding contributions). To avoid the noise, we only report
+      // the binding where the module is contributed.
+      if (alternativeBinding.contributingModule().isPresent()
+          && !((ComponentNodeImpl) graph.componentNode(alternativeBinding.componentPath()).get())
+              .componentDescriptor()
+              .moduleTypes()
+              .contains(alternativeBinding.contributingModule().get().xprocessing())) {
+        continue;
+      }
+      message.append("\n").append(INDENT).append(asString(alternativeBinding));
+    }
+    return message.toString();
+  }
+
+  private String similarBindingsMessage(
+      MissingBinding missingBinding, BindingGraph graph) {
+    ImmutableSet<Binding> similarBindings =
+        getSimilarTypeBindings(graph, missingBinding.key());
+    if (similarBindings.isEmpty()) {
+      return "";
+    }
+    StringBuilder message =
+        new StringBuilder(
+            "\n\nNote: A similar binding is provided in the following other components:");
+    for (Binding similarBinding : similarBindings) {
+      message
+          .append("\n")
+          .append(INDENT)
+          .append(similarBinding.key())
+          .append(" is provided at:")
+          .append("\n")
+          .append(DOUBLE_INDENT)
+          .append(asString(similarBinding));
+    }
+    message.append("\n")
+        .append(
+            "(For Kotlin sources, you may need to use '@JvmSuppressWildcards' or '@JvmWildcard' if "
+                + "you need to explicitly control the wildcards at a particular usage site.)");
+    return message.toString();
+  }
+
+  private String asString(Binding binding) {
+    return String.format(
+        "[%s] %s",
+        binding.componentPath().currentComponent().xprocessing().getQualifiedName(),
+        binding.bindingElement().isPresent()
+            ? elementToString(
+                binding.bindingElement().get().xprocessing(),
+                /* elideMethodParameterTypes= */ true)
+            // For synthetic bindings just print the Binding#toString()
+            : binding);
+  }
+
   private boolean allIncomingDependenciesCanUseProduction(
       MissingBinding missingBinding, BindingGraph graph) {
     return graph.network().inEdges(missingBinding).stream()
@@ -305,15 +303,11 @@
         .orElse(false);
   }
 
-  private static String getComponentFromDependencyEdge(
-      DependencyEdge edge, BindingGraph graph, boolean completePath) {
-    ComponentPath componentPath = graph.network().incidentNodes(edge).source().componentPath();
-    return completePath
-        ? componentPath.toString()
-        : componentPath.currentComponent().className().canonicalName();
+  private static String getComponentFromDependencyEdge(DependencyEdge edge, BindingGraph graph) {
+    return source(edge, graph).componentPath().currentComponent().className().canonicalName();
   }
 
-  private Node source(Edge edge, BindingGraph graph) {
+  private static Node source(Edge edge, BindingGraph graph) {
     return graph.network().incidentNodes(edge).source();
   }
 
diff --git a/java/dagger/internal/codegen/bindinggraphvalidation/SetMultibindingValidator.java b/java/dagger/internal/codegen/bindinggraphvalidation/SetMultibindingValidator.java
index f767da8..30ebf09 100644
--- a/java/dagger/internal/codegen/bindinggraphvalidation/SetMultibindingValidator.java
+++ b/java/dagger/internal/codegen/bindinggraphvalidation/SetMultibindingValidator.java
@@ -30,6 +30,7 @@
 import dagger.internal.codegen.model.DiagnosticReporter;
 import dagger.internal.codegen.model.Key;
 import dagger.internal.codegen.validation.ValidationBindingGraphPlugin;
+import java.util.Optional;
 import javax.inject.Inject;
 
 /** Validates that there are not multiple set binding contributions to the same binding. */
@@ -59,7 +60,8 @@
     Multimap<Key, Binding> dereferencedBindsTargets = HashMultimap.create();
     for (Binding dep : bindingGraph.requestedBindings(binding)) {
       if (dep.kind().equals(DELEGATE)) {
-        dereferencedBindsTargets.put(dereferenceDelegateBinding(dep, bindingGraph), dep);
+        dereferenceDelegateBinding(dep, bindingGraph)
+            .ifPresent(dereferencedKey -> dereferencedBindsTargets.put(dereferencedKey, dep));
       }
     }
 
@@ -80,13 +82,19 @@
             });
   }
 
-  /** Returns the delegate target of a delegate binding (going through other delegates as well). */
-  private Key dereferenceDelegateBinding(Binding binding, BindingGraph bindingGraph) {
+  /**
+   * Returns the dereferenced key of a delegate binding (going through other delegates as well).
+   *
+   * <p>If the binding cannot be dereferenced (because it leads to a missing binding or duplicate
+   * bindings) then {@link Optional#empty()} is returned.
+   */
+  private Optional<Key> dereferenceDelegateBinding(Binding binding, BindingGraph bindingGraph) {
     ImmutableSet<Binding> delegateSet = bindingGraph.requestedBindings(binding);
-    if (delegateSet.isEmpty()) {
-      // There may not be a delegate if the delegate is missing. In this case, we just take the
-      // requested key and return that.
-      return Iterables.getOnlyElement(binding.dependencies()).key();
+    if (delegateSet.size() != 1) {
+      // If there isn't exactly 1 delegate then it means either a MissingBinding or DuplicateBinding
+      // error will be reported. Just return nothing rather than trying to dereference further, as
+      // anything we report here will just be noise on top of the other error anyway.
+      return Optional.empty();
     }
     // If there is a binding, first we check if that is a delegate binding so we can dereference
     // that binding if needed.
@@ -94,6 +102,6 @@
     if (delegate.kind().equals(DELEGATE)) {
       return dereferenceDelegateBinding(delegate, bindingGraph);
     }
-    return delegate.key();
+    return Optional.of(delegate.key());
   }
 }
diff --git a/java/dagger/internal/codegen/bootstrap/bootstrap_compiler_deploy.jar b/java/dagger/internal/codegen/bootstrap/bootstrap_compiler_deploy.jar
index 69e859d..6e4b0a9 100644
--- a/java/dagger/internal/codegen/bootstrap/bootstrap_compiler_deploy.jar
+++ b/java/dagger/internal/codegen/bootstrap/bootstrap_compiler_deploy.jar
Binary files differ
diff --git a/java/dagger/internal/codegen/compileroption/CompilerOptions.java b/java/dagger/internal/codegen/compileroption/CompilerOptions.java
index 42599e0..73f7736 100644
--- a/java/dagger/internal/codegen/compileroption/CompilerOptions.java
+++ b/java/dagger/internal/codegen/compileroption/CompilerOptions.java
@@ -24,16 +24,6 @@
   public abstract boolean usesProducers();
 
   /**
-   * Returns true if the experimental Android mode is enabled.
-   *
-   * <p><b>Warning: Do Not use! This flag is for internal, experimental use only!</b>
-   *
-   * <p>Issues related to this flag will not be supported. This flag could break your build, cause
-   * memory leaks in your app, or cause other unknown issues at runtime.
-   */
-  public abstract boolean experimentalMergedMode(XTypeElement element);
-
-  /**
    * Returns true if the fast initialization flag, {@code fastInit}, is enabled.
    *
    * <p>If enabled, the generated code will attempt to optimize for fast component initialization.
diff --git a/java/dagger/internal/codegen/compileroption/ProcessingEnvironmentCompilerOptions.java b/java/dagger/internal/codegen/compileroption/ProcessingEnvironmentCompilerOptions.java
index 356d55b..8138005 100644
--- a/java/dagger/internal/codegen/compileroption/ProcessingEnvironmentCompilerOptions.java
+++ b/java/dagger/internal/codegen/compileroption/ProcessingEnvironmentCompilerOptions.java
@@ -19,7 +19,6 @@
 import static com.google.common.base.CaseFormat.LOWER_CAMEL;
 import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE;
 import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkState;
 import static com.google.common.collect.Sets.immutableEnumSet;
 import static dagger.internal.codegen.compileroption.FeatureStatus.DISABLED;
 import static dagger.internal.codegen.compileroption.FeatureStatus.ENABLED;
@@ -107,37 +106,14 @@
   }
 
   @Override
-  public boolean experimentalMergedMode(XTypeElement component) {
-    boolean isExperimental = experimentalMergedModeInternal();
-    if (isExperimental) {
-      checkState(
-          !fastInitInternal(component),
-          "Both fast init and experimental merged mode were turned on, please specify exactly one"
-              + " compilation mode.");
-    }
-    return isExperimental;
-  }
-
-  @Override
   public boolean fastInit(XTypeElement component) {
-    boolean isFastInit = fastInitInternal(component);
-    if (isFastInit) {
-      checkState(
-          !experimentalMergedModeInternal(),
-          "Both fast init and experimental merged mode were turned on, please specify exactly one"
-              + " compilation mode.");
-    }
-    return isFastInit;
+    return fastInitInternal(component);
   }
 
   private boolean fastInitInternal(XTypeElement component) {
     return isEnabled(FAST_INIT);
   }
 
-  private boolean experimentalMergedModeInternal() {
-    return false;
-  }
-
   @Override
   public boolean formatGeneratedSource() {
     return isEnabled(FORMAT_GENERATED_SOURCE);
@@ -268,6 +244,16 @@
     noLongerRecognized(FLOATING_BINDS_METHODS);
     noLongerRecognized(EXPERIMENTAL_AHEAD_OF_TIME_SUBCOMPONENTS);
     noLongerRecognized(USE_GRADLE_INCREMENTAL_PROCESSING);
+    if (!isEnabled(IGNORE_PROVISION_KEY_WILDCARDS)) {
+      if (processingEnv.getBackend() == XProcessingEnv.Backend.KSP) {
+        processingEnv.getMessager().printMessage(
+            Diagnostic.Kind.ERROR,
+            String.format(
+                "When using KSP, you must also enable the '%s' compiler option (see %s).",
+                "dagger.ignoreProvisionKeyWildcards",
+                "https://dagger.dev/dev-guide/compiler-options#ignore-provision-key-wildcards"));
+      }
+    }
     return this;
   }
 
@@ -359,7 +345,7 @@
 
     GENERATED_CLASS_EXTENDS_COMPONENT,
 
-    IGNORE_PROVISION_KEY_WILDCARDS,
+    IGNORE_PROVISION_KEY_WILDCARDS(ENABLED),
 
     VALIDATE_TRANSITIVE_COMPONENT_DEPENDENCIES(ENABLED)
     ;
@@ -418,7 +404,7 @@
      * How to report that an explicit binding in a subcomponent conflicts with an {@code @Inject}
      * constructor used in an ancestor component.
      */
-    EXPLICIT_BINDING_CONFLICTS_WITH_INJECT(WARNING, ERROR, NONE),
+    EXPLICIT_BINDING_CONFLICTS_WITH_INJECT(ERROR, WARNING, NONE),
     ;
 
     final ValidationType defaultType;
diff --git a/java/dagger/internal/codegen/componentgenerator/ComponentGeneratorModule.java b/java/dagger/internal/codegen/componentgenerator/ComponentGeneratorModule.java
index 179c411..a071eae 100644
--- a/java/dagger/internal/codegen/componentgenerator/ComponentGeneratorModule.java
+++ b/java/dagger/internal/codegen/componentgenerator/ComponentGeneratorModule.java
@@ -16,9 +16,12 @@
 
 package dagger.internal.codegen.componentgenerator;
 
+import androidx.room.compiler.processing.XProcessingEnv;
 import dagger.Binds;
 import dagger.Module;
+import dagger.Provides;
 import dagger.internal.codegen.base.SourceFileGenerator;
+import dagger.internal.codegen.base.SourceFileHjarGenerator;
 import dagger.internal.codegen.binding.BindingGraph;
 import dagger.internal.codegen.binding.ComponentDescriptor;
 
@@ -29,14 +32,23 @@
   @Binds
   abstract SourceFileGenerator<BindingGraph> componentGenerator(ComponentGenerator generator);
 
-  // The HjarSourceFileGenerator wrapper first generates the entire TypeSpec before stripping out
+  // The SourceFileHjarGenerator wrapper first generates the entire TypeSpec before stripping out
   // things that aren't needed for the hjar. However, this can be really expensive for the component
   // because it is usually the most expensive file to generate, and most of its content is not
-  // needed in the hjar. Thus, instead of wrapping the ComponentGenerator in HjarSourceFileGenerator
-  // we provide a completely separate processing step, ComponentHjarProcessingStep, and generator,
-  // ComponentHjarGenerator, for when generating hjars for components, which can avoid generating
-  // the parts of the component that would have been stripped out by the HjarSourceFileGenerator.
-  @Binds
-  abstract SourceFileGenerator<ComponentDescriptor> componentHjarGenerator(
-      ComponentHjarGenerator hjarGenerator);
+  // needed in the hjar. Thus, we provide a completely separate processing step,
+  // ComponentHjarProcessingStep and ComponentHjarGenerator, for when generating hjars for
+  // components, which can avoid generating the parts of the component that would have been stripped
+  // out by the HjarSourceFileGenerator anyway. Note that we still wrap ComponentHjarGenerator in
+  // SourceFileHjarGenerator because it adds in constructor and method bodies that are needed for
+  // Javac to compile correctly, e.g. super(...) calls in the constructor and return statements in
+  // methods.
+  @Provides
+  static SourceFileGenerator<ComponentDescriptor> componentHjarGenerator(
+      XProcessingEnv processingEnv,
+      ComponentHjarGenerator hjarGenerator) {
+    // Note: technically the ComponentHjarGenerator is already in hjar form, but the
+    // SourceFileHjarGenerator wrapper adds in proper method bodies, e.g. constructors that require
+    // super() calls or methods that require return statements.
+    return SourceFileHjarGenerator.wrap(hjarGenerator, processingEnv);
+  }
 }
diff --git a/java/dagger/internal/codegen/componentgenerator/ComponentHjarGenerator.java b/java/dagger/internal/codegen/componentgenerator/ComponentHjarGenerator.java
index 62f1163..4214cbc 100644
--- a/java/dagger/internal/codegen/componentgenerator/ComponentHjarGenerator.java
+++ b/java/dagger/internal/codegen/componentgenerator/ComponentHjarGenerator.java
@@ -192,7 +192,14 @@
                         && isElementAccessibleFrom(
                             module.moduleElement(),
                             component.typeElement().getClassName().packageName()))
-            .map(module -> ComponentRequirement.forModule(module.moduleElement().getType())));
+            .map(module -> ComponentRequirement.forModule(module.moduleElement().getType()))
+            // If the user hasn't defined an explicit creator/builder then we need to prune out the
+            // module requirements that don't require a module instance to match the non-hjar
+            // implementation.
+            .filter(
+                requirement ->
+                    component.creatorDescriptor().isPresent()
+                        || requirement.requiresModuleInstance()));
   }
 
   private boolean hasBindsInstanceMethods(ComponentDescriptor componentDescriptor) {
diff --git a/java/dagger/internal/codegen/javac/BUILD b/java/dagger/internal/codegen/javac/BUILD
index ad2f91b..325dc99 100644
--- a/java/dagger/internal/codegen/javac/BUILD
+++ b/java/dagger/internal/codegen/javac/BUILD
@@ -23,24 +23,10 @@
     name = "javac",
     srcs = glob(["*.java"]),
     plugins = ["//java/dagger/internal/codegen:component-codegen"],
-    exports = [
-        ":javac-import",
-    ],
     deps = [
-        ":javac-import",
         "//java/dagger:core",
-        "//java/dagger/internal/codegen/binding",
         "//java/dagger/internal/codegen/compileroption",
-        "//java/dagger/internal/codegen/langmodel",
         "//java/dagger/internal/codegen/xprocessing",
         "//third_party/java/guava/collect",
     ],
 )
-
-load("@rules_java//java:defs.bzl", "java_import")
-
-# Replacement for @bazel_tools//third_party/java/jdk/langtools:javac, which seems to have gone away?
-java_import(
-    name = "javac-import",
-    jars = ["@bazel_tools//third_party/java/jdk/langtools:javac_jar"],
-)
diff --git a/java/dagger/internal/codegen/javac/JavacPluginCompilerOptions.java b/java/dagger/internal/codegen/javac/JavacPluginCompilerOptions.java
index 6e77835..e7c5a44 100644
--- a/java/dagger/internal/codegen/javac/JavacPluginCompilerOptions.java
+++ b/java/dagger/internal/codegen/javac/JavacPluginCompilerOptions.java
@@ -37,11 +37,6 @@
   }
 
   @Override
-  public boolean experimentalMergedMode(XTypeElement element) {
-    return false;
-  }
-
-  @Override
   public boolean fastInit(XTypeElement element) {
     return false;
   }
diff --git a/java/dagger/internal/codegen/javac/JavacPluginModule.java b/java/dagger/internal/codegen/javac/JavacPluginModule.java
index 5198164..f9e6da9 100644
--- a/java/dagger/internal/codegen/javac/JavacPluginModule.java
+++ b/java/dagger/internal/codegen/javac/JavacPluginModule.java
@@ -24,15 +24,13 @@
 import dagger.Binds;
 import dagger.Module;
 import dagger.Provides;
-import dagger.internal.codegen.binding.BindingGraphFactory;
-import dagger.internal.codegen.binding.ComponentDescriptorFactory;
 import dagger.internal.codegen.compileroption.CompilerOptions;
 import javax.lang.model.util.Elements; // ALLOW_TYPES_ELEMENTS
 import javax.lang.model.util.Types; // ALLOW_TYPES_ELEMENTS
 
 /**
- * A module that provides a {@link BindingGraphFactory} and {@link ComponentDescriptorFactory} for
- * use in {@code javac} plugins. Requires a binding for the {@code javac} {@link Context}.
+ * A module that provides a {@link XMessager}, {@link XProcessingEnv}, and {@link CompilerOptions}
+ * for use in {@code javac} plugins. Requires a binding for the {@code javac} {@link Context}.
  */
 @Module(includes = JavacPluginModule.BindsModule.class)
 public final class JavacPluginModule {
diff --git a/java/dagger/internal/codegen/javapoet/AnnotationSpecs.java b/java/dagger/internal/codegen/javapoet/AnnotationSpecs.java
index 4628802..50ec8b1 100644
--- a/java/dagger/internal/codegen/javapoet/AnnotationSpecs.java
+++ b/java/dagger/internal/codegen/javapoet/AnnotationSpecs.java
@@ -30,7 +30,8 @@
     RAWTYPES("rawtypes"),
     UNCHECKED("unchecked"),
     FUTURE_RETURN_VALUE_IGNORED("FutureReturnValueIgnored"),
-    KOTLIN_INTERNAL("KotlinInternal", "KotlinInternalInJava")
+    KOTLIN_INTERNAL("KotlinInternal", "KotlinInternalInJava"),
+    CAST("cast")
     ;
 
     private final ImmutableList<String> values;
diff --git a/java/dagger/internal/codegen/javapoet/CodeBlocks.java b/java/dagger/internal/codegen/javapoet/CodeBlocks.java
index 912dc71..877a0a5 100644
--- a/java/dagger/internal/codegen/javapoet/CodeBlocks.java
+++ b/java/dagger/internal/codegen/javapoet/CodeBlocks.java
@@ -18,7 +18,8 @@
 
 import static com.squareup.javapoet.MethodSpec.methodBuilder;
 import static com.squareup.javapoet.TypeSpec.anonymousClassBuilder;
-import static dagger.internal.codegen.javapoet.TypeNames.providerOf;
+import static dagger.internal.codegen.javapoet.TypeNames.daggerProviderOf;
+import static dagger.internal.codegen.javapoet.TypeNames.lazyOf;
 import static java.util.stream.StreamSupport.stream;
 import static javax.lang.model.element.Modifier.PUBLIC;
 
@@ -87,7 +88,22 @@
     return CodeBlock.of(
         "$L",
         anonymousClassBuilder("")
-            .superclass(providerOf(providedType))
+            .superclass(daggerProviderOf(providedType))
+            .addMethod(
+                methodBuilder("get")
+                    .addAnnotation(Override.class)
+                    .addModifiers(PUBLIC)
+                    .returns(providedType)
+                    .addCode(body)
+                    .build())
+            .build());
+  }
+
+  public static CodeBlock anonymousLazy(TypeName providedType, CodeBlock body) {
+    return CodeBlock.of(
+        "$L",
+        anonymousClassBuilder("")
+            .superclass(lazyOf(providedType))
             .addMethod(
                 methodBuilder("get")
                     .addAnnotation(Override.class)
diff --git a/java/dagger/internal/codegen/javapoet/TypeNames.java b/java/dagger/internal/codegen/javapoet/TypeNames.java
index 105394d..ea89fc0 100644
--- a/java/dagger/internal/codegen/javapoet/TypeNames.java
+++ b/java/dagger/internal/codegen/javapoet/TypeNames.java
@@ -53,6 +53,16 @@
   public static final ClassName SUBCOMPONENT_FACTORY = SUBCOMPONENT.nestedClass("Factory");
 
   // Dagger Internal classnames
+  public static final ClassName IDENTIFIER_NAME_STRING =
+      ClassName.get("dagger.internal", "IdentifierNameString");
+  public static final ClassName KEEP_FIELD_TYPE = ClassName.get("dagger.internal", "KeepFieldType");
+  public static final ClassName LAZY_CLASS_KEY =
+      ClassName.get("dagger.multibindings", "LazyClassKey");
+  public static final ClassName LAZY_CLASS_KEY_MAP =
+      ClassName.get("dagger.internal", "LazyClassKeyMap");
+  public static final ClassName LAZY_CLASS_KEY_MAP_FACTORY =
+      ClassName.get("dagger.internal", "LazyClassKeyMap", "Factory");
+
   public static final ClassName DELEGATE_FACTORY =
       ClassName.get("dagger.internal", "DelegateFactory");
   public static final ClassName DOUBLE_CHECK = ClassName.get("dagger.internal", "DoubleCheck");
@@ -62,6 +72,7 @@
       ClassName.get("dagger.internal", "InjectedFieldSignature");
   public static final ClassName INSTANCE_FACTORY =
       ClassName.get("dagger.internal", "InstanceFactory");
+  public static final ClassName MAP_BUILDER = ClassName.get("dagger.internal", "MapBuilder");
   public static final ClassName MAP_FACTORY = ClassName.get("dagger.internal", "MapFactory");
   public static final ClassName MAP_PROVIDER_FACTORY =
       ClassName.get("dagger.internal", "MapProviderFactory");
@@ -69,6 +80,8 @@
   public static final ClassName MEMBERS_INJECTORS =
       ClassName.get("dagger.internal", "MembersInjectors");
   public static final ClassName PROVIDER = ClassName.get("javax.inject", "Provider");
+  public static final ClassName DAGGER_PROVIDER = ClassName.get("dagger.internal", "Provider");
+  public static final ClassName DAGGER_PROVIDERS = ClassName.get("dagger.internal", "Providers");
   public static final ClassName PROVIDER_OF_LAZY =
       ClassName.get("dagger.internal", "ProviderOfLazy");
   public static final ClassName SCOPE_METADATA = ClassName.get("dagger.internal", "ScopeMetadata");
@@ -81,6 +94,8 @@
   // Dagger Producers classnames
   public static final ClassName ABSTRACT_PRODUCER =
       ClassName.get("dagger.producers.internal", "AbstractProducer");
+  public static final ClassName ABSTRACT_PRODUCES_METHOD_PRODUCER =
+      ClassName.get("dagger.producers.internal", "AbstractProducesMethodProducer");
   public static final ClassName CANCELLATION_LISTENER =
       ClassName.get("dagger.producers.internal", "CancellationListener");
   public static final ClassName CANCELLATION_POLICY =
@@ -138,6 +153,8 @@
   public static final ClassName ERROR = ClassName.get("java.lang", "Error");
   public static final ClassName EXCEPTION = ClassName.get("java.lang", "Exception");
   public static final ClassName RUNTIME_EXCEPTION = ClassName.get("java.lang", "RuntimeException");
+  public static final ClassName STRING = ClassName.get("java.lang", "String");
+
   public static final ClassName MAP = ClassName.get("java.util", "Map");
   public static final ClassName KOTLIN_METADATA = ClassName.get("kotlin", "Metadata");
   public static final ClassName IMMUTABLE_MAP =
@@ -215,6 +232,10 @@
     return ParameterizedTypeName.get(PROVIDER, typeName);
   }
 
+  public static ParameterizedTypeName daggerProviderOf(TypeName typeName) {
+    return ParameterizedTypeName.get(DAGGER_PROVIDER, typeName);
+  }
+
   public static ParameterizedTypeName setOf(TypeName elementType) {
     return ParameterizedTypeName.get(SET, elementType);
   }
diff --git a/java/dagger/internal/codegen/kythe/BUILD b/java/dagger/internal/codegen/kythe/BUILD
index 9b2e63b..217627d 100644
--- a/java/dagger/internal/codegen/kythe/BUILD
+++ b/java/dagger/internal/codegen/kythe/BUILD
@@ -31,13 +31,13 @@
         "//java/dagger/internal/codegen/javac",
         "//java/dagger/internal/codegen/javapoet",
         "//java/dagger/internal/codegen/kotlin",
-        "//java/dagger/internal/codegen/langmodel",
         "//java/dagger/internal/codegen/model",
         "//java/dagger/internal/codegen/validation",
         "//java/dagger/internal/codegen/xprocessing",
         "//third_party/java/auto:service",
         "//third_party/java/error_prone:annotations",
         "//third_party/java/guava/collect",
+        "//third_party/java/jsr330_inject",
     ],
 )
 
diff --git a/java/dagger/internal/codegen/kythe/DaggerKythePlugin.java b/java/dagger/internal/codegen/kythe/DaggerKythePlugin.java
index 3280b4f..0b8a502 100644
--- a/java/dagger/internal/codegen/kythe/DaggerKythePlugin.java
+++ b/java/dagger/internal/codegen/kythe/DaggerKythePlugin.java
@@ -40,7 +40,7 @@
 import dagger.internal.codegen.binding.BindingDeclaration;
 import dagger.internal.codegen.binding.BindingGraphFactory;
 import dagger.internal.codegen.binding.BindingNode;
-import dagger.internal.codegen.binding.ComponentDescriptorFactory;
+import dagger.internal.codegen.binding.ComponentDescriptor;
 import dagger.internal.codegen.binding.ModuleDescriptor;
 import dagger.internal.codegen.javac.JavacPluginModule;
 import dagger.internal.codegen.javapoet.TypeNames;
@@ -64,7 +64,7 @@
   // TODO(ronshapiro): use flogger
   private static final Logger logger = Logger.getLogger(DaggerKythePlugin.class.getCanonicalName());
   private FactEmitter emitter;
-  @Inject ComponentDescriptorFactory componentDescriptorFactory;
+  @Inject ComponentDescriptor.Factory componentDescriptorFactory;
   @Inject BindingGraphFactory bindingGraphFactory;
   @Inject XProcessingEnv xProcessingEnv;
 
diff --git a/java/dagger/internal/codegen/model/BUILD b/java/dagger/internal/codegen/model/BUILD
index e6c944b..f497f13 100644
--- a/java/dagger/internal/codegen/model/BUILD
+++ b/java/dagger/internal/codegen/model/BUILD
@@ -27,8 +27,6 @@
         "//java/dagger:core",
         "//java/dagger/internal/codegen/extension",
         "//java/dagger/internal/codegen/xprocessing",
-        "//java/dagger/producers",
-        "//java/dagger/spi",
         "//third_party/java/auto:common",
         "//third_party/java/auto:value",
         "//third_party/java/guava/base",
diff --git a/java/dagger/internal/codegen/model/DaggerAnnotation.java b/java/dagger/internal/codegen/model/DaggerAnnotation.java
index 4a59871..23b18e4 100644
--- a/java/dagger/internal/codegen/model/DaggerAnnotation.java
+++ b/java/dagger/internal/codegen/model/DaggerAnnotation.java
@@ -49,7 +49,7 @@
     return equivalenceWrapper().get();
   }
 
-  public AnnotationMirror java() {
+  public AnnotationMirror javac() {
     return toJavac(xprocessing());
   }
 
diff --git a/java/dagger/internal/codegen/model/DaggerElement.java b/java/dagger/internal/codegen/model/DaggerElement.java
index cf2ac52..2de01a1 100644
--- a/java/dagger/internal/codegen/model/DaggerElement.java
+++ b/java/dagger/internal/codegen/model/DaggerElement.java
@@ -31,7 +31,7 @@
 
   public abstract XElement xprocessing();
 
-  public Element java() {
+  public Element javac() {
     return toJavac(xprocessing());
   }
 
diff --git a/java/dagger/internal/codegen/model/DaggerExecutableElement.java b/java/dagger/internal/codegen/model/DaggerExecutableElement.java
index 484e446..42ce1fc 100644
--- a/java/dagger/internal/codegen/model/DaggerExecutableElement.java
+++ b/java/dagger/internal/codegen/model/DaggerExecutableElement.java
@@ -32,7 +32,7 @@
 
   public abstract XExecutableElement xprocessing();
 
-  public ExecutableElement java() {
+  public ExecutableElement javac() {
     return toJavac(xprocessing());
   }
 
diff --git a/java/dagger/internal/codegen/model/DaggerProcessingEnv.java b/java/dagger/internal/codegen/model/DaggerProcessingEnv.java
index 6645b90..4430829 100644
--- a/java/dagger/internal/codegen/model/DaggerProcessingEnv.java
+++ b/java/dagger/internal/codegen/model/DaggerProcessingEnv.java
@@ -39,7 +39,7 @@
     return Backend.valueOf(xprocessing().getBackend().name());
   }
 
-  public ProcessingEnvironment java() {
+  public ProcessingEnvironment javac() {
     return toJavac(xprocessing());
   }
 }
diff --git a/java/dagger/internal/codegen/model/DaggerType.java b/java/dagger/internal/codegen/model/DaggerType.java
index c606f15..b6f0beb 100644
--- a/java/dagger/internal/codegen/model/DaggerType.java
+++ b/java/dagger/internal/codegen/model/DaggerType.java
@@ -39,7 +39,7 @@
     return equivalenceWrapper().get();
   }
 
-  public TypeMirror java() {
+  public TypeMirror javac() {
     return toJavac(xprocessing());
   }
 
diff --git a/java/dagger/internal/codegen/model/DaggerTypeElement.java b/java/dagger/internal/codegen/model/DaggerTypeElement.java
index 77e0c4f..1bfab06 100644
--- a/java/dagger/internal/codegen/model/DaggerTypeElement.java
+++ b/java/dagger/internal/codegen/model/DaggerTypeElement.java
@@ -32,7 +32,7 @@
 
   public abstract XTypeElement xprocessing();
 
-  public TypeElement java() {
+  public TypeElement javac() {
     return toJavac(xprocessing());
   }
 
diff --git a/java/dagger/internal/codegen/model/MoreAnnotationMirrors.java b/java/dagger/internal/codegen/model/MoreAnnotationMirrors.java
index 9b45b89..ade1f28 100644
--- a/java/dagger/internal/codegen/model/MoreAnnotationMirrors.java
+++ b/java/dagger/internal/codegen/model/MoreAnnotationMirrors.java
@@ -35,7 +35,7 @@
    * defined in the annotation type.
    */
   public static String toStableString(DaggerAnnotation qualifier) {
-    return stableAnnotationMirrorToString(qualifier.java());
+    return stableAnnotationMirrorToString(qualifier.javac());
   }
 
   /**
diff --git a/java/dagger/internal/codegen/model/RequestKind.java b/java/dagger/internal/codegen/model/RequestKind.java
index 581a829..d21a04a 100644
--- a/java/dagger/internal/codegen/model/RequestKind.java
+++ b/java/dagger/internal/codegen/model/RequestKind.java
@@ -19,11 +19,6 @@
 import static com.google.common.base.CaseFormat.UPPER_CAMEL;
 import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE;
 
-import dagger.Lazy;
-import dagger.producers.Produced;
-import dagger.producers.Producer;
-import javax.inject.Provider;
-
 /**
  * Represents the different kinds of {@link javax.lang.model.type.TypeMirror types} that may be
  * requested as dependencies for the same key. For example, {@code String}, {@code
@@ -35,13 +30,13 @@
   /** A default request for an instance. E.g.: {@code FooType} */
   INSTANCE,
 
-  /** A request for a {@link Provider}. E.g.: {@code Provider<FooType>} */
+  /** A request for a {@code Provider}. E.g.: {@code Provider<FooType>} */
   PROVIDER,
 
-  /** A request for a {@link Lazy}. E.g.: {@code Lazy<FooType>} */
+  /** A request for a {@code Lazy}. E.g.: {@code Lazy<FooType>} */
   LAZY,
 
-  /** A request for a {@link Provider} of a {@link Lazy}. E.g.: {@code Provider<Lazy<FooType>>} */
+  /** A request for a {@code Provider} of a {@code Lazy}. E.g.: {@code Provider<Lazy<FooType>>}. */
   PROVIDER_OF_LAZY,
 
   /**
@@ -50,10 +45,10 @@
    */
   MEMBERS_INJECTION,
 
-  /** A request for a {@link Producer}. E.g.: {@code Producer<FooType>} */
+  /** A request for a {@code Producer}. E.g.: {@code Producer<FooType>} */
   PRODUCER,
 
-  /** A request for a {@link Produced}. E.g.: {@code Produced<FooType>} */
+  /** A request for a {@code Produced}. E.g.: {@code Produced<FooType>} */
   PRODUCED,
 
   /**
diff --git a/java/dagger/internal/codegen/processingstep/AssistedFactoryProcessingStep.java b/java/dagger/internal/codegen/processingstep/AssistedFactoryProcessingStep.java
index e95bdf9..ebd5d10 100644
--- a/java/dagger/internal/codegen/processingstep/AssistedFactoryProcessingStep.java
+++ b/java/dagger/internal/codegen/processingstep/AssistedFactoryProcessingStep.java
@@ -23,6 +23,7 @@
 import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
 import static dagger.internal.codegen.javapoet.CodeBlocks.toParametersCodeBlock;
 import static dagger.internal.codegen.javapoet.TypeNames.INSTANCE_FACTORY;
+import static dagger.internal.codegen.javapoet.TypeNames.daggerProviderOf;
 import static dagger.internal.codegen.javapoet.TypeNames.providerOf;
 import static dagger.internal.codegen.langmodel.Accessibility.accessibleTypeName;
 import static dagger.internal.codegen.xprocessing.MethodSpecs.overriding;
@@ -311,9 +312,13 @@
                       // use the parameter names of the @AssistedFactory method.
                       metadata.assistedInjectAssistedParameters().stream()
                           .map(metadata.assistedFactoryAssistedParametersMap()::get)
-                          .map(param -> CodeBlock.of("$L", getSimpleName(param)))
+                          .map(param -> CodeBlock.of("$L", param.getJvmName()))
                           .collect(toParametersCodeBlock()))
                   .build())
+          // In a future release, we should delete this javax method. This will still be a breaking
+          // change, but keeping compatibility for a while should reduce the likelihood of breakages
+          // as it would require components built at much older versions using factories built at
+          // newer versions to break.
           .addMethod(
               MethodSpec.methodBuilder("create")
                   .addModifiers(PUBLIC, STATIC)
@@ -331,6 +336,27 @@
                           : CodeBlock.of(""),
                       name,
                       delegateFactoryParam)
+                  .build())
+          // Normally we would have called this just "create", but because of backwards
+          // compatibility we can't have two methods with the same name/arguments returning
+          // different Provider types.
+          .addMethod(
+              MethodSpec.methodBuilder("createFactoryProvider")
+                  .addModifiers(PUBLIC, STATIC)
+                  .addParameter(delegateFactoryParam)
+                  .addTypeVariables(typeVariableNames(metadata.assistedInjectElement()))
+                  .returns(daggerProviderOf(factory.getType().getTypeName()))
+                  .addStatement(
+                      "return $T.$Lcreate(new $T($N))",
+                      INSTANCE_FACTORY,
+                      // Java 7 type inference requires the method call provide the exact type here.
+                      isPreJava8SourceVersion(processingEnv)
+                          ? CodeBlock.of(
+                              "<$T>",
+                              accessibleTypeName(metadata.factoryType(), name, processingEnv))
+                          : CodeBlock.of(""),
+                      name,
+                      delegateFactoryParam)
                   .build());
       return ImmutableList.of(builder);
     }
diff --git a/java/dagger/internal/codegen/processingstep/AssistedInjectProcessingStep.java b/java/dagger/internal/codegen/processingstep/AssistedInjectProcessingStep.java
index 8d73f47..cfd0bec 100644
--- a/java/dagger/internal/codegen/processingstep/AssistedInjectProcessingStep.java
+++ b/java/dagger/internal/codegen/processingstep/AssistedInjectProcessingStep.java
@@ -26,6 +26,7 @@
 import com.squareup.javapoet.ClassName;
 import dagger.internal.codegen.binding.AssistedInjectionAnnotations.AssistedParameter;
 import dagger.internal.codegen.javapoet.TypeNames;
+import dagger.internal.codegen.validation.InjectValidator;
 import dagger.internal.codegen.validation.ValidationReport;
 import java.util.HashSet;
 import java.util.Set;
@@ -34,10 +35,12 @@
 /** An annotation processor for {@link dagger.assisted.AssistedInject}-annotated elements. */
 final class AssistedInjectProcessingStep extends TypeCheckingProcessingStep<XConstructorElement> {
   private final XMessager messager;
+  private final InjectValidator injectValidator;
 
   @Inject
-  AssistedInjectProcessingStep(XMessager messager) {
+  AssistedInjectProcessingStep(XMessager messager, InjectValidator injectValidator) {
     this.messager = messager;
+    this.injectValidator = injectValidator;
   }
 
   @Override
@@ -48,7 +51,13 @@
   @Override
   protected void process(
       XConstructorElement assistedInjectElement, ImmutableSet<ClassName> annotations) {
-    new AssistedInjectValidator().validate(assistedInjectElement).printMessagesTo(messager);
+    // The InjectValidator has already run and reported its errors in InjectProcessingStep, so no
+    // need to report its errors. However, the AssistedInjectValidator relies on the InjectValidator
+    // returning a clean report, so we check that first before running AssistedInjectValidator. This
+    // shouldn't be expensive since InjectValidator caches its results after validating.
+    if (injectValidator.validate(assistedInjectElement.getEnclosingElement()).isClean()) {
+      new AssistedInjectValidator().validate(assistedInjectElement).printMessagesTo(messager);
+    }
   }
 
   private final class AssistedInjectValidator {
diff --git a/java/dagger/internal/codegen/processingstep/ComponentHjarProcessingStep.java b/java/dagger/internal/codegen/processingstep/ComponentHjarProcessingStep.java
index 7a7e180..864bd76 100644
--- a/java/dagger/internal/codegen/processingstep/ComponentHjarProcessingStep.java
+++ b/java/dagger/internal/codegen/processingstep/ComponentHjarProcessingStep.java
@@ -28,7 +28,6 @@
 import dagger.internal.codegen.base.SourceFileGenerator;
 import dagger.internal.codegen.binding.BindingGraph;
 import dagger.internal.codegen.binding.ComponentDescriptor;
-import dagger.internal.codegen.binding.ComponentDescriptorFactory;
 import dagger.internal.codegen.validation.ComponentCreatorValidator;
 import dagger.internal.codegen.validation.ComponentValidator;
 import dagger.internal.codegen.validation.ValidationReport;
@@ -52,7 +51,7 @@
   private final XMessager messager;
   private final ComponentValidator componentValidator;
   private final ComponentCreatorValidator creatorValidator;
-  private final ComponentDescriptorFactory componentDescriptorFactory;
+  private final ComponentDescriptor.Factory componentDescriptorFactory;
   private final SourceFileGenerator<ComponentDescriptor> componentGenerator;
 
   @Inject
@@ -60,7 +59,7 @@
       XMessager messager,
       ComponentValidator componentValidator,
       ComponentCreatorValidator creatorValidator,
-      ComponentDescriptorFactory componentDescriptorFactory,
+      ComponentDescriptor.Factory componentDescriptorFactory,
       SourceFileGenerator<ComponentDescriptor> componentGenerator) {
     this.messager = messager;
     this.componentValidator = componentValidator;
diff --git a/java/dagger/internal/codegen/processingstep/ComponentProcessingStep.java b/java/dagger/internal/codegen/processingstep/ComponentProcessingStep.java
index 5b17c00..168e894 100644
--- a/java/dagger/internal/codegen/processingstep/ComponentProcessingStep.java
+++ b/java/dagger/internal/codegen/processingstep/ComponentProcessingStep.java
@@ -34,7 +34,6 @@
 import dagger.internal.codegen.binding.BindingGraph;
 import dagger.internal.codegen.binding.BindingGraphFactory;
 import dagger.internal.codegen.binding.ComponentDescriptor;
-import dagger.internal.codegen.binding.ComponentDescriptorFactory;
 import dagger.internal.codegen.validation.BindingGraphValidator;
 import dagger.internal.codegen.validation.ComponentCreatorValidator;
 import dagger.internal.codegen.validation.ComponentDescriptorValidator;
@@ -52,7 +51,7 @@
   private final ComponentValidator componentValidator;
   private final ComponentCreatorValidator creatorValidator;
   private final ComponentDescriptorValidator componentDescriptorValidator;
-  private final ComponentDescriptorFactory componentDescriptorFactory;
+  private final ComponentDescriptor.Factory componentDescriptorFactory;
   private final BindingGraphFactory bindingGraphFactory;
   private final SourceFileGenerator<BindingGraph> componentGenerator;
   private final BindingGraphValidator bindingGraphValidator;
@@ -63,7 +62,7 @@
       ComponentValidator componentValidator,
       ComponentCreatorValidator creatorValidator,
       ComponentDescriptorValidator componentDescriptorValidator,
-      ComponentDescriptorFactory componentDescriptorFactory,
+      ComponentDescriptor.Factory componentDescriptorFactory,
       BindingGraphFactory bindingGraphFactory,
       SourceFileGenerator<BindingGraph> componentGenerator,
       BindingGraphValidator bindingGraphValidator) {
@@ -132,7 +131,10 @@
       return;
     }
     BindingGraph fullBindingGraph = bindingGraphFactory.create(subcomponentDescriptor, true);
-    boolean isValid = bindingGraphValidator.isValid(fullBindingGraph.topLevelBindingGraph());
+    // In this case, we don't actually care about the return value. The important part here is that
+    // BindingGraphValidator#isValid() runs all of the SPI plugins and reports any errors.
+    // TODO(bcorso): Add a separate API with no return value for this particular case.
+    boolean unusedIsValid = bindingGraphValidator.isValid(fullBindingGraph.topLevelBindingGraph());
   }
 
   private void generateComponent(BindingGraph bindingGraph) {
diff --git a/java/dagger/internal/codegen/processingstep/MonitoringModuleGenerator.java b/java/dagger/internal/codegen/processingstep/MonitoringModuleGenerator.java
index 00b033d..3692144 100644
--- a/java/dagger/internal/codegen/processingstep/MonitoringModuleGenerator.java
+++ b/java/dagger/internal/codegen/processingstep/MonitoringModuleGenerator.java
@@ -35,6 +35,7 @@
 import com.squareup.javapoet.TypeSpec;
 import dagger.Module;
 import dagger.internal.codegen.base.SourceFileGenerator;
+import dagger.internal.codegen.binding.MonitoringModules;
 import dagger.internal.codegen.binding.SourceFiles;
 import dagger.internal.codegen.javapoet.TypeNames;
 import dagger.multibindings.Multibinds;
@@ -42,10 +43,15 @@
 
 /** Generates a monitoring module for use with production components. */
 final class MonitoringModuleGenerator extends SourceFileGenerator<XTypeElement> {
+  private final MonitoringModules monitoringModules;
 
   @Inject
-  MonitoringModuleGenerator(XFiler filer, XProcessingEnv processingEnv) {
+  MonitoringModuleGenerator(
+      XFiler filer,
+      XProcessingEnv processingEnv,
+      MonitoringModules monitoringModules) {
     super(filer, processingEnv);
+    this.monitoringModules = monitoringModules;
   }
 
   @Override
@@ -55,6 +61,7 @@
 
   @Override
   public ImmutableList<TypeSpec.Builder> topLevelTypes(XTypeElement componentElement) {
+    monitoringModules.add(SourceFiles.generatedMonitoringModuleName(componentElement));
     return ImmutableList.of(
         classBuilder(SourceFiles.generatedMonitoringModuleName(componentElement))
             .addAnnotation(Module.class)
diff --git a/java/dagger/internal/codegen/processingstep/TypeCheckingProcessingStep.java b/java/dagger/internal/codegen/processingstep/TypeCheckingProcessingStep.java
index 5d6a64f..7ff4753 100644
--- a/java/dagger/internal/codegen/processingstep/TypeCheckingProcessingStep.java
+++ b/java/dagger/internal/codegen/processingstep/TypeCheckingProcessingStep.java
@@ -33,6 +33,7 @@
 import com.google.common.collect.Maps;
 import com.squareup.javapoet.ClassName;
 import dagger.internal.codegen.base.DaggerSuperficialValidation.ValidationException;
+import dagger.internal.codegen.binding.MonitoringModules;
 import dagger.internal.codegen.compileroption.CompilerOptions;
 import dagger.internal.codegen.xprocessing.XElements;
 import java.util.ArrayList;
@@ -51,6 +52,7 @@
   @Inject XMessager messager;
   @Inject CompilerOptions compilerOptions;
   @Inject SuperficialValidator superficialValidator;
+  @Inject MonitoringModules monitoringModules;
 
   @Override
   public final ImmutableSet<String> annotations() {
@@ -70,6 +72,16 @@
         .forEach(
             (element, annotations) -> {
               try {
+                if (this instanceof ComponentProcessingStep && !monitoringModules.isEmpty()) {
+                  // If there were any monitoring modules generated by Dagger in this round then we
+                  // should just defer processing the components until the next round. This is an
+                  // optimization to avoid unnecessary processing of components that will likely
+                  // need to be reprocessed next round anyway due to the missing module. We should
+                  // be guaranteed that there will be a next round since the monitoring modules were
+                  // generated in this round.
+                  deferredElements.add(element);
+                  return;
+                }
                 // The XBasicAnnotationProcessor only validates the element itself. However, we
                 // validate the enclosing type here to keep the previous behavior of
                 // BasicAnnotationProcessor, since Dagger still relies on this behavior.
diff --git a/java/dagger/internal/codegen/validation/BUILD b/java/dagger/internal/codegen/validation/BUILD
index cc36708..a24b7e0 100644
--- a/java/dagger/internal/codegen/validation/BUILD
+++ b/java/dagger/internal/codegen/validation/BUILD
@@ -36,7 +36,6 @@
         "//java/dagger/internal/codegen/model",
         "//java/dagger/internal/codegen/xprocessing",
         "//java/dagger/spi",
-        "//third_party/java/auto:common",
         "//third_party/java/auto:value",
         "//third_party/java/checker_framework_annotations",
         "//third_party/java/error_prone:annotations",
diff --git a/java/dagger/internal/codegen/validation/BindingMethodValidator.java b/java/dagger/internal/codegen/validation/BindingMethodValidator.java
index 9598a7c..7310506 100644
--- a/java/dagger/internal/codegen/validation/BindingMethodValidator.java
+++ b/java/dagger/internal/codegen/validation/BindingMethodValidator.java
@@ -140,6 +140,7 @@
 
     @Override
     protected final void checkAdditionalProperties() {
+      checkNotExtensionFunction();
       checkEnclosingElement();
       checkTypeParameters();
       checkNotPrivate();
@@ -152,6 +153,12 @@
     /** Checks additional properties of the binding method. */
     protected void checkAdditionalMethodProperties() {}
 
+    private void checkNotExtensionFunction() {
+      if (method.isExtensionFunction()) {
+        report.addError(bindingMethods("can not be an extension function"));
+      }
+    }
+
     /**
      * Adds an error if the method is not declared in a class or interface annotated with one of the
      * {@link #enclosingElementAnnotations}.
diff --git a/java/dagger/internal/codegen/validation/ComponentValidator.java b/java/dagger/internal/codegen/validation/ComponentValidator.java
index b503448..b3469a1 100644
--- a/java/dagger/internal/codegen/validation/ComponentValidator.java
+++ b/java/dagger/internal/codegen/validation/ComponentValidator.java
@@ -168,6 +168,7 @@
         // the remaining checks will likely just output unhelpful noise in such cases.
         return report.addError(invalidTypeError(), component).build();
       }
+      validateFields();
       validateUseOfCancellationPolicy();
       validateIsAbstractType();
       validateCreators();
@@ -208,6 +209,18 @@
           componentKind().annotation().simpleName());
     }
 
+    private void validateFields() {
+      component.getDeclaredMethods().stream()
+          .filter(method -> method.isKotlinPropertySetter() && method.isAbstract())
+          .forEach(
+              method ->
+                  report.addError(
+                      String.format(
+                          "Cannot use 'abstract var' property in a component declaration to get a"
+                              + " binding. Use 'val' or 'fun' instead: %s",
+                          method.getPropertyName())));
+    }
+
     private void validateCreators() {
       ImmutableSet<XTypeElement> creators =
           enclosedAnnotatedTypes(component, creatorAnnotationsFor(componentAnnotation()));
diff --git a/java/dagger/internal/codegen/validation/DiagnosticMessageGenerator.java b/java/dagger/internal/codegen/validation/DiagnosticMessageGenerator.java
index fc83e31..24ad676 100644
--- a/java/dagger/internal/codegen/validation/DiagnosticMessageGenerator.java
+++ b/java/dagger/internal/codegen/validation/DiagnosticMessageGenerator.java
@@ -164,18 +164,11 @@
       ImmutableList<DependencyEdge> dependencyTrace,
       ImmutableSet<DependencyEdge> requests,
       ImmutableSet<DependencyEdge> entryPoints) {
-    StringBuilder message =
-        graph.isFullBindingGraph()
-            ? new StringBuilder()
-            : new StringBuilder(dependencyTrace.size() * 100 /* a guess heuristic */);
-
-    // Print the dependency trace unless it's a full binding graph
-    if (!graph.isFullBindingGraph()) {
-      dependencyTrace.forEach(
-          edge -> dependencyRequestFormatter.appendFormatLine(message, edge.dependencyRequest()));
-      if (!dependencyTrace.isEmpty()) {
-        appendComponentPathUnlessAtRoot(message, source(getLast(dependencyTrace)));
-      }
+    StringBuilder message = new StringBuilder(dependencyTrace.size() * 100 /* a guess heuristic */);
+    dependencyTrace.forEach(
+        edge -> dependencyRequestFormatter.appendFormatLine(message, edge.dependencyRequest()));
+    if (!dependencyTrace.isEmpty()) {
+      appendComponentPathUnlessAtRoot(message, source(getLast(dependencyTrace)));
     }
     message.append(getRequestsNotInTrace(dependencyTrace, requests, entryPoints));
     return message.toString();
@@ -190,25 +183,19 @@
     ImmutableSet<XElement> requestsToPrint =
         requests.stream()
             // if printing entry points, skip entry points and the traced request
-            .filter(
-                request ->
-                    graph.isFullBindingGraph()
-                        || (!request.isEntryPoint() && !isTracedRequest(dependencyTrace, request)))
+            .filter(request -> !request.isEntryPoint())
+            .filter(request -> !isTracedRequest(dependencyTrace, request))
             .map(request -> request.dependencyRequest().requestElement())
             .flatMap(presentValues())
             .map(DaggerElement::xprocessing)
             .collect(toImmutableSet());
     if (!requestsToPrint.isEmpty()) {
-      message
-          .append("\nIt is")
-          .append(graph.isFullBindingGraph() ? " " : " also ")
-          .append("requested at:");
+      message.append("\nIt is also requested at:");
       elementFormatter.formatIndentedList(message, requestsToPrint, 1);
     }
 
-    // Print the remaining entry points, showing which component they're in, unless it's a full
-    // binding graph
-    if (!graph.isFullBindingGraph() && entryPoints.size() > 1) {
+    // Print the remaining entry points, showing which component they're in
+    if (entryPoints.size() > 1) {
       message.append("\nThe following other entry points also depend on it:");
       entryPointFormatter.formatIndentedList(
           message,
@@ -253,9 +240,14 @@
         }
       };
 
-  private static boolean isTracedRequest(
+  private boolean isTracedRequest(
       ImmutableList<DependencyEdge> dependencyTrace, DependencyEdge request) {
-    return !dependencyTrace.isEmpty() && request.equals(dependencyTrace.get(0));
+    return !dependencyTrace.isEmpty()
+        && request.dependencyRequest().equals(dependencyTrace.get(0).dependencyRequest())
+        // Comparing the dependency request is not enough since the request is just the key.
+        // Instead, we check that the target incident node is the same.
+        && graph.network().incidentNodes(request).target()
+            .equals(graph.network().incidentNodes(dependencyTrace.get(0)).target());
   }
 
   /**
diff --git a/java/dagger/internal/codegen/validation/InjectBindingRegistryImpl.java b/java/dagger/internal/codegen/validation/InjectBindingRegistryImpl.java
index cc2d6e9..16344d3 100644
--- a/java/dagger/internal/codegen/validation/InjectBindingRegistryImpl.java
+++ b/java/dagger/internal/codegen/validation/InjectBindingRegistryImpl.java
@@ -17,6 +17,7 @@
 package dagger.internal.codegen.validation;
 
 import static androidx.room.compiler.processing.XElementKt.isTypeElement;
+import static androidx.room.compiler.processing.compat.XConverters.toKS;
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Preconditions.checkState;
@@ -27,6 +28,7 @@
 import static dagger.internal.codegen.binding.SourceFiles.generatedClassNameForBinding;
 import static dagger.internal.codegen.extension.DaggerCollectors.toOptional;
 import static dagger.internal.codegen.xprocessing.XElements.asTypeElement;
+import static dagger.internal.codegen.xprocessing.XElements.closestEnclosingTypeElement;
 import static dagger.internal.codegen.xprocessing.XTypes.erasedTypeName;
 import static dagger.internal.codegen.xprocessing.XTypes.isDeclared;
 import static dagger.internal.codegen.xprocessing.XTypes.nonObjectSuperclass;
@@ -41,6 +43,7 @@
 import androidx.room.compiler.processing.XTypeElement;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
+import com.google.devtools.ksp.symbol.Origin;
 import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import com.squareup.javapoet.ClassName;
 import dagger.Component;
@@ -82,7 +85,7 @@
   private final BindingFactory bindingFactory;
   private final CompilerOptions compilerOptions;
 
-  final class BindingsCollection<B extends Binding> {
+  private final class BindingsCollection<B extends Binding> {
     private final ClassName factoryClass;
     private final Map<Key, B> bindingsByKey = Maps.newLinkedHashMap();
     private final Deque<B> bindingsRequiringGeneration = new ArrayDeque<>();
@@ -115,24 +118,40 @@
     }
 
     /** Caches the binding and generates it if it needs generation. */
-    void tryRegisterBinding(B binding, boolean warnIfNotAlreadyGenerated) {
+    void tryRegisterBinding(B binding, boolean isCalledFromInjectProcessor) {
+      if (processingEnv.getBackend() == XProcessingEnv.Backend.KSP) {
+        Origin origin =
+            toKS(closestEnclosingTypeElement(binding.bindingElement().get())).getOrigin();
+        // If the origin of the element is from a source file in the current compilation unit then
+        // we're guaranteed that the InjectProcessor should run over the element so only generate
+        // the Factory/MembersInjector if we're being called from the InjectProcessor.
+        //
+        // TODO(bcorso): generally, this isn't something we would need to keep track of manually.
+        // However, KSP incremental processing has a bug that will overwrite the cache for the
+        // element if we generate files for it, which can lead to missing generated files from
+        // other processors. See https://github.com/google/dagger/issues/4063 and
+        // https://github.com/google/dagger/issues/4054. Remove this once that bug is fixed.
+        if (!isCalledFromInjectProcessor && (origin == Origin.JAVA || origin == Origin.KOTLIN)) {
+          return;
+        }
+      }
       tryToCacheBinding(binding);
 
       @SuppressWarnings("unchecked")
       B maybeUnresolved =
           binding.unresolved().isPresent() ? (B) binding.unresolved().get() : binding;
-      tryToGenerateBinding(maybeUnresolved, warnIfNotAlreadyGenerated);
+      tryToGenerateBinding(maybeUnresolved, isCalledFromInjectProcessor);
     }
 
     /**
      * Tries to generate a binding, not generating if it already is generated. For resolved
      * bindings, this will try to generate the unresolved version of the binding.
      */
-    void tryToGenerateBinding(B binding, boolean warnIfNotAlreadyGenerated) {
+    void tryToGenerateBinding(B binding, boolean isCalledFromInjectProcessor) {
       if (shouldGenerateBinding(binding)) {
         bindingsRequiringGeneration.offer(binding);
         if (compilerOptions.warnIfInjectionFactoryNotGeneratedUpstream()
-            && warnIfNotAlreadyGenerated) {
+                && !isCalledFromInjectProcessor) {
           messager.printMessage(
               Kind.NOTE,
               String.format(
@@ -147,6 +166,22 @@
 
     /** Returns true if the binding needs to be generated. */
     private boolean shouldGenerateBinding(B binding) {
+      if (binding instanceof MembersInjectionBinding) {
+        MembersInjectionBinding membersInjectionBinding = (MembersInjectionBinding) binding;
+        // Empty members injection bindings are special and don't need source files.
+        if (membersInjectionBinding.injectionSites().isEmpty()) {
+          return false;
+        }
+        // Members injectors for classes with no local injection sites and no @Inject
+        // constructor are unused.
+        boolean hasInjectConstructor =
+            !(injectedConstructors(membersInjectionBinding.membersInjectedType()).isEmpty()
+                && assistedInjectedConstructors(
+                    membersInjectionBinding.membersInjectedType()).isEmpty());
+        if (!membersInjectionBinding.hasLocalInjectionSites() && !hasInjectConstructor) {
+          return false;
+        }
+      }
       return !binding.unresolved().isPresent()
           && !materializedBindingKeys.contains(binding.key())
           && !bindingsRequiringGeneration.contains(binding)
@@ -200,52 +235,20 @@
     membersInjectionBindings.generateBindings(membersInjectorGenerator);
   }
 
-  /**
-   * Registers the binding for generation and later lookup. If the binding is resolved, we also
-   * attempt to register an unresolved version of it.
-   */
-  private void registerBinding(ProvisionBinding binding, boolean warnIfNotAlreadyGenerated) {
-    provisionBindings.tryRegisterBinding(binding, warnIfNotAlreadyGenerated);
-  }
-
-  /**
-   * Registers the binding for generation and later lookup. If the binding is resolved, we also
-   * attempt to register an unresolved version of it.
-   */
-  private void registerBinding(MembersInjectionBinding binding, boolean warnIfNotAlreadyGenerated) {
-    /*
-     * We generate MembersInjector classes for types with @Inject constructors only if they have any
-     * injection sites.
-     *
-     * We generate MembersInjector classes for types without @Inject constructors only if they have
-     * local (non-inherited) injection sites.
-     *
-     * Warn only when registering bindings post-hoc for those types.
-     */
-    if (warnIfNotAlreadyGenerated) {
-      boolean hasInjectConstructor =
-          !(injectedConstructors(binding.membersInjectedType()).isEmpty()
-              && assistedInjectedConstructors(binding.membersInjectedType()).isEmpty());
-      warnIfNotAlreadyGenerated =
-          hasInjectConstructor
-              ? !binding.injectionSites().isEmpty()
-              : binding.hasLocalInjectionSites();
-    }
-
-    membersInjectionBindings.tryRegisterBinding(binding, warnIfNotAlreadyGenerated);
-  }
-
   @Override
   public Optional<ProvisionBinding> tryRegisterInjectConstructor(
       XConstructorElement constructorElement) {
-    return tryRegisterConstructor(constructorElement, Optional.empty(), false);
+    return tryRegisterConstructor(
+        constructorElement,
+        Optional.empty(),
+        /* isCalledFromInjectProcessor= */ true);
   }
 
   @CanIgnoreReturnValue
   private Optional<ProvisionBinding> tryRegisterConstructor(
       XConstructorElement constructorElement,
       Optional<XType> resolvedType,
-      boolean warnIfNotAlreadyGenerated) {
+      boolean isCalledFromInjectProcessor) {
     XTypeElement typeElement = constructorElement.getEnclosingElement();
 
     // Validating here shouldn't have a performance penalty because the validator caches its reports
@@ -263,9 +266,9 @@
     }
 
     ProvisionBinding binding = bindingFactory.injectionBinding(constructorElement, resolvedType);
-    registerBinding(binding, warnIfNotAlreadyGenerated);
+    provisionBindings.tryRegisterBinding(binding, isCalledFromInjectProcessor);
     if (!binding.injectionSites().isEmpty()) {
-      tryRegisterMembersInjectedType(typeElement, resolvedType, warnIfNotAlreadyGenerated);
+      tryRegisterMembersInjectedType(typeElement, resolvedType, isCalledFromInjectProcessor);
     }
     return Optional.of(binding);
   }
@@ -281,7 +284,9 @@
           fieldElement);
     }
     return tryRegisterMembersInjectedType(
-        asTypeElement(fieldElement.getEnclosingElement()), Optional.empty(), false);
+        asTypeElement(fieldElement.getEnclosingElement()),
+        Optional.empty(),
+        /* isCalledFromInjectProcessor= */ true);
   }
 
   @Override
@@ -295,12 +300,16 @@
           methodElement);
     }
     return tryRegisterMembersInjectedType(
-        asTypeElement(methodElement.getEnclosingElement()), Optional.empty(), false);
+        asTypeElement(methodElement.getEnclosingElement()),
+        Optional.empty(),
+        /* isCalledFromInjectProcessor= */ true);
   }
 
   @CanIgnoreReturnValue
   private Optional<MembersInjectionBinding> tryRegisterMembersInjectedType(
-      XTypeElement typeElement, Optional<XType> resolvedType, boolean warnIfNotAlreadyGenerated) {
+      XTypeElement typeElement,
+      Optional<XType> resolvedType,
+      boolean isCalledFromInjectProcessor) {
     // Validating here shouldn't have a performance penalty because the validator caches its reports
     ValidationReport report = injectValidator.validateForMembersInjection(typeElement);
     report.printMessagesTo(messager);
@@ -316,7 +325,7 @@
     }
 
     MembersInjectionBinding binding = bindingFactory.membersInjectionBinding(type, resolvedType);
-    registerBinding(binding, warnIfNotAlreadyGenerated);
+    membersInjectionBindings.tryRegisterBinding(binding, isCalledFromInjectProcessor);
     for (Optional<XType> supertype = nonObjectSuperclass(type);
         supertype.isPresent();
         supertype = nonObjectSuperclass(supertype.get())) {
@@ -351,7 +360,12 @@
             assistedInjectedConstructors(element).stream())
         // We're guaranteed that there's at most 1 @Inject constructors from above validation.
         .collect(toOptional())
-        .flatMap(constructor -> tryRegisterConstructor(constructor, Optional.of(type), true));
+        .flatMap(
+            constructor ->
+                tryRegisterConstructor(
+                    constructor,
+                    Optional.of(type),
+                    /* isCalledFromInjectProcessor= */ false));
   }
 
   @CanIgnoreReturnValue
@@ -365,7 +379,9 @@
       return Optional.of(binding);
     }
     return tryRegisterMembersInjectedType(
-        key.type().xprocessing().getTypeElement(), Optional.of(key.type().xprocessing()), true);
+        key.type().xprocessing().getTypeElement(),
+        Optional.of(key.type().xprocessing()),
+        /* isCalledFromInjectProcessor= */ false);
   }
 
   @Override
diff --git a/java/dagger/internal/codegen/validation/InjectValidator.java b/java/dagger/internal/codegen/validation/InjectValidator.java
index f223f6a..ac434d7 100644
--- a/java/dagger/internal/codegen/validation/InjectValidator.java
+++ b/java/dagger/internal/codegen/validation/InjectValidator.java
@@ -64,6 +64,7 @@
  */
 @Singleton
 public final class InjectValidator implements ClearableCache {
+
   private final XProcessingEnv processingEnv;
   private final CompilerOptions compilerOptions;
   private final DependencyRequestValidator dependencyRequestValidator;
@@ -298,6 +299,15 @@
           fieldElement);
     }
 
+    if (fieldElement.isProtected()
+        && fieldElement.getEnclosingElement().isFromKotlin()
+        ) {
+      builder.addItem(
+          "Dagger injector does not have access to kotlin protected fields",
+          staticMemberDiagnosticKind(),
+          fieldElement);
+    }
+
     validateDependencyRequest(builder, fieldElement);
 
     return builder.build();
diff --git a/java/dagger/internal/codegen/validation/ModelBindingGraphConverter.java b/java/dagger/internal/codegen/validation/ModelBindingGraphConverter.java
index 314ed5f..ae53978 100644
--- a/java/dagger/internal/codegen/validation/ModelBindingGraphConverter.java
+++ b/java/dagger/internal/codegen/validation/ModelBindingGraphConverter.java
@@ -134,8 +134,8 @@
   }
 
   private static Key toModel(dagger.internal.codegen.model.Key key) {
-    return Key.builder(key.type().java())
-        .qualifier(key.qualifier().map(DaggerAnnotation::java))
+    return Key.builder(key.type().javac())
+        .qualifier(key.qualifier().map(DaggerAnnotation::javac))
         .multibindingContributionIdentifier(
             key.multibindingContributionIdentifier().isPresent()
                 ? Optional.of(toModel(key.multibindingContributionIdentifier().get()))
@@ -159,17 +159,17 @@
             .key(toModel(request.key()))
             .isNullable(request.isNullable());
 
-    request.requestElement().ifPresent(e -> builder.requestElement(e.java()));
+    request.requestElement().ifPresent(e -> builder.requestElement(e.javac()));
     return builder.build();
   }
 
   private static Scope toModel(dagger.internal.codegen.model.Scope scope) {
-    return Scope.scope(scope.scopeAnnotation().java());
+    return Scope.scope(scope.scopeAnnotation().javac());
   }
 
   private static ComponentPath toModel(dagger.internal.codegen.model.ComponentPath path) {
     return ComponentPath.create(
-        path.components().stream().map(DaggerTypeElement::java).collect(toImmutableList()));
+        path.components().stream().map(DaggerTypeElement::javac).collect(toImmutableList()));
   }
 
   private static dagger.internal.codegen.model.BindingGraph.ComponentNode toInternal(
@@ -232,8 +232,8 @@
           binding.dependencies().stream()
               .map(ModelBindingGraphConverter::toModel)
               .collect(toImmutableSet()),
-          binding.bindingElement().map(DaggerElement::java),
-          binding.contributingModule().map(DaggerTypeElement::java),
+          binding.bindingElement().map(DaggerElement::javac),
+          binding.contributingModule().map(DaggerTypeElement::javac),
           binding.requiresModuleInstance(),
           binding.scope().map(ModelBindingGraphConverter::toModel),
           binding.isNullable(),
@@ -291,7 +291,7 @@
     static ChildFactoryMethodEdge create(
         dagger.internal.codegen.model.BindingGraph.ChildFactoryMethodEdge childFactoryMethodEdge) {
       return new AutoValue_ModelBindingGraphConverter_ChildFactoryMethodEdgeImpl(
-          childFactoryMethodEdge.factoryMethod().java(), childFactoryMethodEdge);
+          childFactoryMethodEdge.factoryMethod().javac(), childFactoryMethodEdge);
     }
 
     abstract dagger.internal.codegen.model.BindingGraph.ChildFactoryMethodEdge delegate();
@@ -310,7 +310,7 @@
             subcomponentCreatorBindingEdge) {
       return new AutoValue_ModelBindingGraphConverter_SubcomponentCreatorBindingEdgeImpl(
           subcomponentCreatorBindingEdge.declaringModules().stream()
-              .map(DaggerTypeElement::java)
+              .map(DaggerTypeElement::javac)
               .collect(toImmutableSet()),
           subcomponentCreatorBindingEdge);
     }
diff --git a/java/dagger/internal/codegen/validation/ModuleValidator.java b/java/dagger/internal/codegen/validation/ModuleValidator.java
index a1d9b0d..38bce2b 100644
--- a/java/dagger/internal/codegen/validation/ModuleValidator.java
+++ b/java/dagger/internal/codegen/validation/ModuleValidator.java
@@ -58,7 +58,7 @@
 import dagger.internal.codegen.base.DaggerSuperficialValidation;
 import dagger.internal.codegen.base.ModuleKind;
 import dagger.internal.codegen.binding.BindingGraphFactory;
-import dagger.internal.codegen.binding.ComponentDescriptorFactory;
+import dagger.internal.codegen.binding.ComponentDescriptor;
 import dagger.internal.codegen.binding.InjectionAnnotations;
 import dagger.internal.codegen.binding.MethodSignatureFormatter;
 import dagger.internal.codegen.javapoet.TypeNames;
@@ -109,7 +109,7 @@
 
   private final AnyBindingMethodValidator anyBindingMethodValidator;
   private final MethodSignatureFormatter methodSignatureFormatter;
-  private final ComponentDescriptorFactory componentDescriptorFactory;
+  private final ComponentDescriptor.Factory componentDescriptorFactory;
   private final BindingGraphFactory bindingGraphFactory;
   private final BindingGraphValidator bindingGraphValidator;
   private final InjectionAnnotations injectionAnnotations;
@@ -122,7 +122,7 @@
   ModuleValidator(
       AnyBindingMethodValidator anyBindingMethodValidator,
       MethodSignatureFormatter methodSignatureFormatter,
-      ComponentDescriptorFactory componentDescriptorFactory,
+      ComponentDescriptor.Factory componentDescriptorFactory,
       BindingGraphFactory bindingGraphFactory,
       BindingGraphValidator bindingGraphValidator,
       InjectionAnnotations injectionAnnotations,
diff --git a/java/dagger/internal/codegen/validation/ProducesMethodValidator.java b/java/dagger/internal/codegen/validation/ProducesMethodValidator.java
index cf78b63..9b4c16c 100644
--- a/java/dagger/internal/codegen/validation/ProducesMethodValidator.java
+++ b/java/dagger/internal/codegen/validation/ProducesMethodValidator.java
@@ -90,7 +90,7 @@
     // TODO(beder): Properly handle nullable with producer methods.
     private void checkNullable() {
       Nullability nullability = Nullability.of(method);
-      if (nullability.nullableAnnotation().isPresent()) {
+      if (!nullability.nullableAnnotations().isEmpty()) {
         report.addWarning("@Nullable on @Produces methods does not do anything");
       }
     }
diff --git a/java/dagger/internal/codegen/validation/SpiModelBindingGraphConverter.java b/java/dagger/internal/codegen/validation/SpiModelBindingGraphConverter.java
index 75d0f7f..42e1adf 100644
--- a/java/dagger/internal/codegen/validation/SpiModelBindingGraphConverter.java
+++ b/java/dagger/internal/codegen/validation/SpiModelBindingGraphConverter.java
@@ -16,9 +16,11 @@
 
 package dagger.internal.codegen.validation;
 
+import static androidx.room.compiler.processing.compat.XConverters.getProcessingEnv;
 import static androidx.room.compiler.processing.compat.XConverters.toJavac;
 import static androidx.room.compiler.processing.compat.XConverters.toKS;
 import static androidx.room.compiler.processing.compat.XConverters.toKSResolver;
+import static com.google.common.base.Preconditions.checkState;
 import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
 import static dagger.internal.codegen.extension.DaggerStreams.toImmutableMap;
 import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
@@ -31,6 +33,7 @@
 import androidx.room.compiler.processing.XTypeElement;
 import com.google.auto.value.AutoValue;
 import com.google.auto.value.extension.memoized.Memoized;
+import com.google.common.base.Equivalence;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSetMultimap;
 import com.google.common.graph.EndpointPair;
@@ -38,7 +41,16 @@
 import com.google.common.graph.MutableNetwork;
 import com.google.common.graph.Network;
 import com.google.common.graph.NetworkBuilder;
+import com.google.devtools.ksp.processing.Resolver;
+import com.google.devtools.ksp.processing.SymbolProcessorEnvironment;
+import com.google.devtools.ksp.symbol.KSAnnotated;
+import com.google.devtools.ksp.symbol.KSAnnotation;
+import com.google.devtools.ksp.symbol.KSClassDeclaration;
+import com.google.devtools.ksp.symbol.KSFunctionDeclaration;
+import com.google.devtools.ksp.symbol.KSType;
+import dagger.internal.codegen.xprocessing.XAnnotations;
 import dagger.internal.codegen.xprocessing.XElements;
+import dagger.internal.codegen.xprocessing.XTypes;
 import dagger.spi.model.Binding;
 import dagger.spi.model.BindingGraph;
 import dagger.spi.model.BindingGraph.ChildFactoryMethodEdge;
@@ -64,6 +76,12 @@
 import dagger.spi.model.RequestKind;
 import dagger.spi.model.Scope;
 import java.util.Optional;
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeMirror;
 import javax.tools.Diagnostic;
 
 /** A Utility class for converting to the {@link BindingGraph} used by external plugins. */
@@ -141,19 +159,20 @@
     }
   }
 
-  private static Key toSpiModel(dagger.internal.codegen.model.Key key, XProcessingEnv env) {
+  private static Key toSpiModel(dagger.internal.codegen.model.Key key) {
     Key.Builder builder =
-        Key.builder(toSpiModel(key.type().xprocessing(), env))
-            .qualifier(key.qualifier().map(qualifier -> toSpiModel(qualifier.xprocessing(), env)));
+        Key.builder(toSpiModel(key.type().xprocessing()))
+            .qualifier(key.qualifier().map(qualifier -> toSpiModel(qualifier.xprocessing())));
     if (key.multibindingContributionIdentifier().isPresent()) {
       return builder
           .multibindingContributionIdentifier(
               toSpiModel(
-                  key.multibindingContributionIdentifier().get().contributingModule().xprocessing(),
-                  env),
+                  key.multibindingContributionIdentifier()
+                      .get()
+                      .contributingModule()
+                      .xprocessing()),
               toSpiModel(
-                  key.multibindingContributionIdentifier().get().bindingMethod().xprocessing(),
-                  env))
+                  key.multibindingContributionIdentifier().get().bindingMethod().xprocessing()))
           .build();
     }
     return builder.build().withoutMultibindingContributionIdentifier();
@@ -169,98 +188,50 @@
 
   @SuppressWarnings("CheckReturnValue")
   private static DependencyRequest toSpiModel(
-      dagger.internal.codegen.model.DependencyRequest request, XProcessingEnv env) {
+      dagger.internal.codegen.model.DependencyRequest request) {
     DependencyRequest.Builder builder =
         DependencyRequest.builder()
             .kind(toSpiModel(request.kind()))
-            .key(toSpiModel(request.key(), env))
+            .key(toSpiModel(request.key()))
             .isNullable(request.isNullable());
 
-    request
-        .requestElement()
-        .ifPresent(e -> builder.requestElement(toSpiModel(e.xprocessing(), env)));
+    request.requestElement().ifPresent(e -> builder.requestElement(toSpiModel(e.xprocessing())));
     return builder.build();
   }
 
-  private static Scope toSpiModel(dagger.internal.codegen.model.Scope scope, XProcessingEnv env) {
-    return Scope.scope(toSpiModel(scope.scopeAnnotation().xprocessing(), env));
+  private static Scope toSpiModel(dagger.internal.codegen.model.Scope scope) {
+    return Scope.scope(toSpiModel(scope.scopeAnnotation().xprocessing()));
   }
 
-  private static ComponentPath toSpiModel(
-      dagger.internal.codegen.model.ComponentPath path, XProcessingEnv env) {
+  private static ComponentPath toSpiModel(dagger.internal.codegen.model.ComponentPath path) {
     return ComponentPath.create(
         path.components().stream()
-            .map(component -> toSpiModel(component.xprocessing(), env))
+            .map(component -> toSpiModel(component.xprocessing()))
             .collect(toImmutableList()));
   }
 
-  private static DaggerTypeElement toSpiModel(XTypeElement typeElement, XProcessingEnv env) {
-    switch (env.getBackend()) {
-      case JAVAC:
-        return DaggerTypeElement.fromJavac(toJavac(typeElement));
-      case KSP:
-        return DaggerTypeElement.fromKsp(toKS(typeElement));
-    }
-    throw new IllegalStateException(
-        String.format("Backend %s is not supported yet.", env.getBackend()));
+  private static DaggerTypeElement toSpiModel(XTypeElement typeElement) {
+    return DaggerTypeElementImpl.from(typeElement);
   }
 
-  private static DaggerType toSpiModel(XType type, XProcessingEnv env) {
-    switch (env.getBackend()) {
-      case JAVAC:
-        return DaggerType.fromJavac(toJavac(type));
-      case KSP:
-        return DaggerType.fromKsp(toKS(type));
-    }
-    throw new IllegalStateException(
-        String.format("Backend %s is not supported yet.", env.getBackend()));
+  private static DaggerType toSpiModel(XType type) {
+    return DaggerTypeImpl.from(type);
   }
 
-  static DaggerAnnotation toSpiModel(XAnnotation annotation, XProcessingEnv env) {
-    DaggerTypeElement typeElement = toSpiModel(annotation.getTypeElement(), env);
-
-    switch (env.getBackend()) {
-      case JAVAC:
-        return DaggerAnnotation.fromJavac(typeElement, toJavac(annotation));
-      case KSP:
-        return DaggerAnnotation.fromKsp(typeElement, toKS(annotation));
-    }
-    throw new IllegalStateException(
-        String.format("Backend %s is not supported yet.", env.getBackend()));
+  static DaggerAnnotation toSpiModel(XAnnotation annotation) {
+    return DaggerAnnotationImpl.from(annotation);
   }
 
-  private static DaggerElement toSpiModel(XElement element, XProcessingEnv env) {
-    switch (env.getBackend()) {
-      case JAVAC:
-        return DaggerElement.fromJavac(toJavac(element));
-      case KSP:
-        return DaggerElement.fromKsp(XElements.toKSAnnotated(element));
-    }
-    throw new IllegalStateException(
-        String.format("Backend %s is not supported yet.", env.getBackend()));
+  private static DaggerElement toSpiModel(XElement element) {
+    return DaggerElementImpl.from(element);
   }
 
-  private static DaggerExecutableElement toSpiModel(
-      XExecutableElement executableElement, XProcessingEnv env) {
-    switch (env.getBackend()) {
-      case JAVAC:
-        return DaggerExecutableElement.fromJava(toJavac(executableElement));
-      case KSP:
-        return DaggerExecutableElement.fromKsp(toKS(executableElement));
-    }
-    throw new IllegalStateException(
-        String.format("Backend %s is not supported yet.", env.getBackend()));
+  private static DaggerExecutableElement toSpiModel(XExecutableElement executableElement) {
+    return DaggerExecutableElementImpl.from(executableElement);
   }
 
   static DaggerProcessingEnv toSpiModel(XProcessingEnv env) {
-    switch (env.getBackend()) {
-      case JAVAC:
-        return DaggerProcessingEnv.fromJavac(toJavac(env));
-      case KSP:
-        return DaggerProcessingEnv.fromKsp(toKS(env), toKSResolver(env));
-    }
-    throw new IllegalStateException(
-        String.format("Backend %s is not supported yet.", env.getBackend()));
+    return DaggerProcessingEnvImpl.from(env);
   }
 
   private static dagger.internal.codegen.model.BindingGraph.ComponentNode toInternal(
@@ -295,14 +266,14 @@
         dagger.internal.codegen.model.BindingGraph.ComponentNode componentNode,
         XProcessingEnv env) {
       return new AutoValue_SpiModelBindingGraphConverter_ComponentNodeImpl(
-          toSpiModel(componentNode.componentPath(), env),
+          toSpiModel(componentNode.componentPath()),
           componentNode.isSubcomponent(),
           componentNode.isRealComponent(),
           componentNode.entryPoints().stream()
-              .map(request -> SpiModelBindingGraphConverter.toSpiModel(request, env))
+              .map(SpiModelBindingGraphConverter::toSpiModel)
               .collect(toImmutableSet()),
           componentNode.scopes().stream()
-              .map(request -> SpiModelBindingGraphConverter.toSpiModel(request, env))
+              .map(SpiModelBindingGraphConverter::toSpiModel)
               .collect(toImmutableSet()),
           componentNode);
     }
@@ -319,15 +290,15 @@
   abstract static class BindingNodeImpl implements Binding {
     static Binding create(dagger.internal.codegen.model.Binding binding, XProcessingEnv env) {
       return new AutoValue_SpiModelBindingGraphConverter_BindingNodeImpl(
-          toSpiModel(binding.key(), env),
-          toSpiModel(binding.componentPath(), env),
+          toSpiModel(binding.key()),
+          toSpiModel(binding.componentPath()),
           binding.dependencies().stream()
-              .map(request -> SpiModelBindingGraphConverter.toSpiModel(request, env))
+              .map(SpiModelBindingGraphConverter::toSpiModel)
               .collect(toImmutableSet()),
-          binding.bindingElement().map(element -> toSpiModel(element.xprocessing(), env)),
-          binding.contributingModule().map(module -> toSpiModel(module.xprocessing(), env)),
+          binding.bindingElement().map(element -> toSpiModel(element.xprocessing())),
+          binding.contributingModule().map(module -> toSpiModel(module.xprocessing())),
           binding.requiresModuleInstance(),
-          binding.scope().map(scope -> SpiModelBindingGraphConverter.toSpiModel(scope, env)),
+          binding.scope().map(SpiModelBindingGraphConverter::toSpiModel),
           binding.isNullable(),
           binding.isProduction(),
           toSpiModel(binding.kind()),
@@ -348,8 +319,8 @@
         dagger.internal.codegen.model.BindingGraph.MissingBinding missingBinding,
         XProcessingEnv env) {
       return new AutoValue_SpiModelBindingGraphConverter_MissingBindingImpl(
-          toSpiModel(missingBinding.componentPath(), env),
-          toSpiModel(missingBinding.key(), env),
+          toSpiModel(missingBinding.componentPath()),
+          toSpiModel(missingBinding.key()),
           missingBinding);
     }
 
@@ -369,7 +340,7 @@
         dagger.internal.codegen.model.BindingGraph.DependencyEdge dependencyEdge,
         XProcessingEnv env) {
       return new AutoValue_SpiModelBindingGraphConverter_DependencyEdgeImpl(
-          toSpiModel(dependencyEdge.dependencyRequest(), env),
+          toSpiModel(dependencyEdge.dependencyRequest()),
           dependencyEdge.isEntryPoint(),
           dependencyEdge);
     }
@@ -388,8 +359,7 @@
         dagger.internal.codegen.model.BindingGraph.ChildFactoryMethodEdge childFactoryMethodEdge,
         XProcessingEnv env) {
       return new AutoValue_SpiModelBindingGraphConverter_ChildFactoryMethodEdgeImpl(
-          toSpiModel(childFactoryMethodEdge.factoryMethod().xprocessing(), env),
-          childFactoryMethodEdge);
+          toSpiModel(childFactoryMethodEdge.factoryMethod().xprocessing()), childFactoryMethodEdge);
     }
 
     abstract dagger.internal.codegen.model.BindingGraph.ChildFactoryMethodEdge internalDelegate();
@@ -409,7 +379,7 @@
         XProcessingEnv env) {
       return new AutoValue_SpiModelBindingGraphConverter_SubcomponentCreatorBindingEdgeImpl(
           subcomponentCreatorBindingEdge.declaringModules().stream()
-              .map(module -> toSpiModel(module.xprocessing(), env))
+              .map(module -> toSpiModel(module.xprocessing()))
               .collect(toImmutableSet()),
           subcomponentCreatorBindingEdge);
     }
@@ -458,6 +428,225 @@
     }
   }
 
+  @AutoValue
+  abstract static class DaggerElementImpl extends DaggerElement {
+    public static DaggerElement from(XElement element) {
+      return new AutoValue_SpiModelBindingGraphConverter_DaggerElementImpl(element);
+    }
+
+    abstract XElement element();
+
+    @Override
+    public Element javac() {
+      checkIsJavac(backend());
+      return toJavac(element());
+    }
+
+    @Override
+    public KSAnnotated ksp() {
+      checkIsKsp(backend());
+      return toKS(element());
+    }
+
+    @Override
+    public DaggerProcessingEnv.Backend backend() {
+      return getBackend(getProcessingEnv(element()));
+    }
+
+    @Override
+    public final String toString() {
+      return XElements.toStableString(element());
+    }
+  }
+
+  @AutoValue
+  abstract static class DaggerTypeElementImpl extends DaggerTypeElement {
+    public static DaggerTypeElement from(XTypeElement element) {
+      return new AutoValue_SpiModelBindingGraphConverter_DaggerTypeElementImpl(element);
+    }
+
+    abstract XTypeElement element();
+
+    @Override
+    public TypeElement javac() {
+      checkIsJavac(backend());
+      return toJavac(element());
+    }
+
+    @Override
+    public KSClassDeclaration ksp() {
+      checkIsKsp(backend());
+      return toKS(element());
+    }
+
+    @Override
+    public DaggerProcessingEnv.Backend backend() {
+      return getBackend(getProcessingEnv(element()));
+    }
+
+    @Override
+    public final String toString() {
+      return XElements.toStableString(element());
+    }
+  }
+
+  @AutoValue
+  abstract static class DaggerTypeImpl extends DaggerType {
+    public static DaggerType from(XType type) {
+      return new AutoValue_SpiModelBindingGraphConverter_DaggerTypeImpl(
+          XTypes.equivalence().wrap(type));
+    }
+
+    abstract Equivalence.Wrapper<XType> type();
+
+    @Override
+    public TypeMirror javac() {
+      checkIsJavac(backend());
+      return toJavac(type().get());
+    }
+
+    @Override
+    public KSType ksp() {
+      checkIsKsp(backend());
+      return toKS(type().get());
+    }
+
+    @Override
+    public DaggerProcessingEnv.Backend backend() {
+      return getBackend(getProcessingEnv(type().get()));
+    }
+
+    @Override
+    public final String toString() {
+      return XTypes.toStableString(type().get());
+    }
+  }
+
+  @AutoValue
+  abstract static class DaggerAnnotationImpl extends DaggerAnnotation {
+    public static DaggerAnnotation from(XAnnotation annotation) {
+      return new AutoValue_SpiModelBindingGraphConverter_DaggerAnnotationImpl(
+          XAnnotations.equivalence().wrap(annotation));
+    }
+
+    abstract Equivalence.Wrapper<XAnnotation> annotation();
+
+    @Override
+    public DaggerTypeElement annotationTypeElement() {
+      return DaggerTypeElementImpl.from(annotation().get().getTypeElement());
+    }
+
+    @Override
+    public AnnotationMirror javac() {
+      checkIsJavac(backend());
+      return toJavac(annotation().get());
+    }
+
+    @Override
+    public KSAnnotation ksp() {
+      checkIsKsp(backend());
+      return toKS(annotation().get());
+    }
+
+    @Override
+    public DaggerProcessingEnv.Backend backend() {
+      return getBackend(getProcessingEnv(annotation().get()));
+    }
+
+    @Override
+    public final String toString() {
+      return XAnnotations.toStableString(annotation().get());
+    }
+  }
+
+  @AutoValue
+  abstract static class DaggerExecutableElementImpl extends DaggerExecutableElement {
+    public static DaggerExecutableElement from(XExecutableElement executableElement) {
+      return new AutoValue_SpiModelBindingGraphConverter_DaggerExecutableElementImpl(
+          executableElement);
+    }
+
+    abstract XExecutableElement executableElement();
+
+    @Override
+    public ExecutableElement javac() {
+      checkIsJavac(backend());
+      return toJavac(executableElement());
+    }
+
+    @Override
+    public KSFunctionDeclaration ksp() {
+      checkIsKsp(backend());
+      return toKS(executableElement());
+    }
+
+    @Override
+    public DaggerProcessingEnv.Backend backend() {
+      return getBackend(getProcessingEnv(executableElement()));
+    }
+
+    @Override
+    public final String toString() {
+      return XElements.toStableString(executableElement());
+    }
+  }
+
+  private static class DaggerProcessingEnvImpl extends DaggerProcessingEnv {
+    private final XProcessingEnv env;
+
+    public static DaggerProcessingEnv from(XProcessingEnv env) {
+      return new DaggerProcessingEnvImpl(env);
+    }
+
+    DaggerProcessingEnvImpl(XProcessingEnv env) {
+      this.env = env;
+    }
+
+    @Override
+    public ProcessingEnvironment javac() {
+      checkIsJavac(backend());
+      return toJavac(env);
+    }
+
+    @Override
+    public SymbolProcessorEnvironment ksp() {
+      checkIsKsp(backend());
+      return toKS(env);
+    }
+
+    @Override
+    public Resolver resolver() {
+      return toKSResolver(env);
+    }
+
+    @Override
+    public DaggerProcessingEnv.Backend backend() {
+      return getBackend(env);
+    }
+  }
+
+  private static void checkIsJavac(DaggerProcessingEnv.Backend backend) {
+    checkState(
+        backend == DaggerProcessingEnv.Backend.JAVAC,
+        "Expected JAVAC backend but was: %s", backend);
+  }
+
+  private static void checkIsKsp(DaggerProcessingEnv.Backend backend) {
+    checkState(
+        backend == DaggerProcessingEnv.Backend.KSP,
+        "Expected KSP backend but was: %s", backend);
+  }
+
+  private static DaggerProcessingEnv.Backend getBackend(XProcessingEnv env) {
+    switch (env.getBackend()) {
+      case JAVAC:
+        return DaggerProcessingEnv.Backend.JAVAC;
+      case KSP:
+        return DaggerProcessingEnv.Backend.KSP;
+    }
+    throw new AssertionError(String.format("Unexpected backend %s", env.getBackend()));
+  }
+
   private static final class DiagnosticReporterImpl extends DiagnosticReporter {
     static DiagnosticReporterImpl create(
         dagger.internal.codegen.model.DiagnosticReporter reporter) {
diff --git a/java/dagger/internal/codegen/writing/AssistedInjectionParameters.java b/java/dagger/internal/codegen/writing/AssistedInjectionParameters.java
index 42551a0..87ac24a 100644
--- a/java/dagger/internal/codegen/writing/AssistedInjectionParameters.java
+++ b/java/dagger/internal/codegen/writing/AssistedInjectionParameters.java
@@ -23,10 +23,10 @@
 
 import androidx.room.compiler.processing.XConstructorElement;
 import androidx.room.compiler.processing.XConstructorType;
+import androidx.room.compiler.processing.XExecutableParameterElement;
 import androidx.room.compiler.processing.XMethodType;
 import androidx.room.compiler.processing.XType;
 import androidx.room.compiler.processing.XTypeElement;
-import androidx.room.compiler.processing.XVariableElement;
 import com.google.common.collect.ImmutableList;
 import com.squareup.javapoet.ParameterSpec;
 import dagger.internal.codegen.binding.AssistedInjectionAnnotations;
@@ -79,12 +79,12 @@
   }
 
   private static ImmutableList<ParameterSpec> assistedParameterSpecs(
-      List<? extends XVariableElement> paramElements,
+      List<XExecutableParameterElement> paramElements,
       List<XType> paramTypes,
       ShardImplementation shardImplementation) {
     ImmutableList.Builder<ParameterSpec> assistedParameterSpecs = ImmutableList.builder();
     for (int i = 0; i < paramElements.size(); i++) {
-      XVariableElement paramElement = paramElements.get(i);
+      XExecutableParameterElement paramElement = paramElements.get(i);
       XType paramType = paramTypes.get(i);
       if (AssistedInjectionAnnotations.isAssistedParameter(paramElement)) {
         assistedParameterSpecs.add(
diff --git a/java/dagger/internal/codegen/writing/BUILD b/java/dagger/internal/codegen/writing/BUILD
index c8f9b61..3adeb66 100644
--- a/java/dagger/internal/codegen/writing/BUILD
+++ b/java/dagger/internal/codegen/writing/BUILD
@@ -31,11 +31,9 @@
         "//java/dagger/internal/codegen/compileroption",
         "//java/dagger/internal/codegen/extension",
         "//java/dagger/internal/codegen/javapoet",
-        "//java/dagger/internal/codegen/kotlin",
         "//java/dagger/internal/codegen/langmodel",
         "//java/dagger/internal/codegen/model",
         "//java/dagger/internal/codegen/xprocessing",
-        "//java/dagger/producers",
         "//third_party/java/auto:common",
         "//third_party/java/auto:value",
         "//third_party/java/error_prone:annotations",
diff --git a/java/dagger/internal/codegen/writing/ComponentCreatorImplementationFactory.java b/java/dagger/internal/codegen/writing/ComponentCreatorImplementationFactory.java
index 88d4d41..f74b50a 100644
--- a/java/dagger/internal/codegen/writing/ComponentCreatorImplementationFactory.java
+++ b/java/dagger/internal/codegen/writing/ComponentCreatorImplementationFactory.java
@@ -202,6 +202,12 @@
         case NEEDED:
           return Optional.of(normalSetterMethod(requirement));
         case UNNEEDED:
+          // If this is a generated Builder, then remove the setter methods for modules that don't
+          // require an instance.
+          if (!componentDescriptor().creatorDescriptor().isPresent()
+                  && !requirement.requiresModuleInstance()) {
+            return Optional.empty();
+          }
           // TODO(bcorso): Don't generate noop setters for any unneeded requirements.
           // However, since this is a breaking change we can at least avoid trying
           // to generate noop setters for impossible cases like when the requirement type
diff --git a/java/dagger/internal/codegen/writing/ComponentImplementation.java b/java/dagger/internal/codegen/writing/ComponentImplementation.java
index 204d6fa..a41b1c7 100644
--- a/java/dagger/internal/codegen/writing/ComponentImplementation.java
+++ b/java/dagger/internal/codegen/writing/ComponentImplementation.java
@@ -42,6 +42,7 @@
 import static javax.lang.model.element.Modifier.STATIC;
 import static javax.tools.Diagnostic.Kind.ERROR;
 
+import androidx.room.compiler.processing.XExecutableParameterElement;
 import androidx.room.compiler.processing.XMessager;
 import androidx.room.compiler.processing.XMethodElement;
 import androidx.room.compiler.processing.XProcessingEnv;
@@ -72,9 +73,9 @@
 import dagger.internal.codegen.binding.BindingGraph;
 import dagger.internal.codegen.binding.BindingNode;
 import dagger.internal.codegen.binding.BindingRequest;
+import dagger.internal.codegen.binding.CancellationPolicy;
 import dagger.internal.codegen.binding.ComponentCreatorDescriptor;
 import dagger.internal.codegen.binding.ComponentDescriptor;
-import dagger.internal.codegen.binding.ComponentDescriptor.CancellationPolicy;
 import dagger.internal.codegen.binding.ComponentDescriptor.ComponentMethodDescriptor;
 import dagger.internal.codegen.binding.ComponentRequirement;
 import dagger.internal.codegen.binding.KeyVariableNamer;
@@ -111,16 +112,11 @@
   /** Compiler Modes. */
   public enum CompilerMode {
     DEFAULT,
-    FAST_INIT,
-    EXPERIMENTAL_MERGED_MODE;
+    FAST_INIT;
 
     public boolean isFastInit() {
       return this == CompilerMode.FAST_INIT;
     }
-
-    public boolean isExperimentalMergedMode() {
-      return this == CompilerMode.EXPERIMENTAL_MERGED_MODE;
-    }
   }
 
   /** A type of field that this component can contain. */
@@ -311,11 +307,7 @@
     this.messager = messager;
     XTypeElement typeElement = rootComponentImplementation().componentDescriptor().typeElement();
     this.compilerMode =
-        compilerOptions.fastInit(typeElement)
-            ? CompilerMode.FAST_INIT
-            : (compilerOptions.experimentalMergedMode(typeElement)
-                ? CompilerMode.EXPERIMENTAL_MERGED_MODE
-                : CompilerMode.DEFAULT);
+        compilerOptions.fastInit(typeElement) ? CompilerMode.FAST_INIT : CompilerMode.DEFAULT;
   }
 
   /**
@@ -464,7 +456,7 @@
     private final UniqueNameSet assistedParamNames = new UniqueNameSet();
     private final List<CodeBlock> initializations = new ArrayList<>();
     private final SwitchingProviders switchingProviders;
-    private final ExperimentalSwitchingProviders experimentalSwitchingProviders;
+    private final LazyClassKeyProviders lazyClassKeyProviders;
     private final Map<Key, CodeBlock> cancellations = new LinkedHashMap<>();
     private final Map<XVariableElement, String> uniqueAssistedName = new LinkedHashMap<>();
     private final List<CodeBlock> componentRequirementInitializations = new ArrayList<>();
@@ -481,9 +473,7 @@
     private ShardImplementation(ClassName name) {
       this.name = name;
       this.switchingProviders = new SwitchingProviders(this, processingEnv);
-      this.experimentalSwitchingProviders =
-          new ExperimentalSwitchingProviders(this, componentRequestRepresentationsProvider);
-
+      this.lazyClassKeyProviders = new LazyClassKeyProviders(this);
       if (graph.componentDescriptor().isProduction()) {
         claimMethodName(CANCELLATION_LISTENER_METHOD_NAME);
       }
@@ -517,9 +507,8 @@
       return switchingProviders;
     }
 
-    /** Returns the {@link ExperimentalSwitchingProviders} class for this shard. */
-    public ExperimentalSwitchingProviders getExperimentalSwitchingProviders() {
-      return experimentalSwitchingProviders;
+    public LazyClassKeyProviders getLazyClassKeyProviders() {
+      return lazyClassKeyProviders;
     }
 
     /** Returns the {@link ComponentImplementation} that owns this shard. */
@@ -665,12 +654,12 @@
       return assistedParamNames.getUniqueName(name);
     }
 
-    public String getUniqueFieldNameForAssistedParam(XVariableElement element) {
-      if (uniqueAssistedName.containsKey(element)) {
-        return uniqueAssistedName.get(element);
+    public String getUniqueFieldNameForAssistedParam(XExecutableParameterElement parameter) {
+      if (uniqueAssistedName.containsKey(parameter)) {
+        return uniqueAssistedName.get(parameter);
       }
-      String name = getUniqueAssistedParamName(getSimpleName(element));
-      uniqueAssistedName.put(element, name);
+      String name = getUniqueAssistedParamName(parameter.getJvmName());
+      uniqueAssistedName.put(parameter, name);
       return name;
     }
 
diff --git a/java/dagger/internal/codegen/writing/ComponentProvisionRequestRepresentation.java b/java/dagger/internal/codegen/writing/ComponentProvisionRequestRepresentation.java
index d7594cb..41c3c46 100644
--- a/java/dagger/internal/codegen/writing/ComponentProvisionRequestRepresentation.java
+++ b/java/dagger/internal/codegen/writing/ComponentProvisionRequestRepresentation.java
@@ -36,7 +36,6 @@
   private final BindingGraph bindingGraph;
   private final ComponentRequirementExpressions componentRequirementExpressions;
   private final CompilerOptions compilerOptions;
-  private final boolean isExperimentalMergedMode;
 
   @AssistedInject
   ComponentProvisionRequestRepresentation(
@@ -49,16 +48,11 @@
     this.bindingGraph = bindingGraph;
     this.componentRequirementExpressions = componentRequirementExpressions;
     this.compilerOptions = compilerOptions;
-    this.isExperimentalMergedMode =
-        componentImplementation.compilerMode().isExperimentalMergedMode();
   }
 
   @Override
   Expression getDependencyExpression(ClassName requestingClass) {
-    CodeBlock componentDependency =
-        isExperimentalMergedMode
-            ? CodeBlock.of("(($T) dependencies[0])", componentRequirement().type().getTypeName())
-            : getComponentRequirementExpression(requestingClass);
+    CodeBlock componentDependency = getComponentRequirementExpression(requestingClass);
     CodeBlock invocation =
         CodeBlock.of(
             "$L.$L()", componentDependency, asMethod(binding.bindingElement().get()).getJvmName());
diff --git a/java/dagger/internal/codegen/writing/ComponentRequestRepresentations.java b/java/dagger/internal/codegen/writing/ComponentRequestRepresentations.java
index 124eba1..dd34316 100644
--- a/java/dagger/internal/codegen/writing/ComponentRequestRepresentations.java
+++ b/java/dagger/internal/codegen/writing/ComponentRequestRepresentations.java
@@ -19,7 +19,6 @@
 import static androidx.room.compiler.processing.XTypeKt.isVoid;
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
 import static com.google.common.collect.Iterables.getOnlyElement;
 import static dagger.internal.codegen.base.Util.reentrantComputeIfAbsent;
 import static dagger.internal.codegen.binding.BindingRequest.bindingRequest;
@@ -28,13 +27,17 @@
 import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
 import static dagger.internal.codegen.xprocessing.MethodSpecs.overriding;
 import static dagger.internal.codegen.xprocessing.XElements.getSimpleName;
+import static dagger.internal.codegen.xprocessing.XProcessingEnvs.isPreJava8SourceVersion;
 
 import androidx.room.compiler.processing.XMethodElement;
+import androidx.room.compiler.processing.XProcessingEnv;
 import androidx.room.compiler.processing.XType;
 import com.google.common.collect.ImmutableList;
 import com.squareup.javapoet.ClassName;
 import com.squareup.javapoet.CodeBlock;
 import com.squareup.javapoet.MethodSpec;
+import dagger.internal.codegen.base.MapType;
+import dagger.internal.codegen.base.OptionalType;
 import dagger.internal.codegen.binding.Binding;
 import dagger.internal.codegen.binding.BindingGraph;
 import dagger.internal.codegen.binding.BindingRequest;
@@ -69,11 +72,8 @@
       membersInjectionBindingRepresentationFactory;
   private final ProvisionBindingRepresentation.Factory provisionBindingRepresentationFactory;
   private final ProductionBindingRepresentation.Factory productionBindingRepresentationFactory;
-  private final ExperimentalSwitchingProviderDependencyRepresentation.Factory
-      experimentalSwitchingProviderDependencyRepresentationFactory;
   private final Map<Binding, BindingRepresentation> representations = new HashMap<>();
-  private final Map<Binding, ExperimentalSwitchingProviderDependencyRepresentation>
-      experimentalSwitchingProviderDependencyRepresentations = new HashMap<>();
+  private final XProcessingEnv processingEnv;
 
   @Inject
   ComponentRequestRepresentations(
@@ -84,8 +84,7 @@
       MembersInjectionBindingRepresentation.Factory membersInjectionBindingRepresentationFactory,
       ProvisionBindingRepresentation.Factory provisionBindingRepresentationFactory,
       ProductionBindingRepresentation.Factory productionBindingRepresentationFactory,
-      ExperimentalSwitchingProviderDependencyRepresentation.Factory
-          experimentalSwitchingProviderDependencyRepresentationFactory) {
+      XProcessingEnv processingEnv) {
     this.parent = parent;
     this.graph = graph;
     this.componentImplementation = componentImplementation;
@@ -93,9 +92,8 @@
         membersInjectionBindingRepresentationFactory;
     this.provisionBindingRepresentationFactory = provisionBindingRepresentationFactory;
     this.productionBindingRepresentationFactory = productionBindingRepresentationFactory;
-    this.experimentalSwitchingProviderDependencyRepresentationFactory =
-        experimentalSwitchingProviderDependencyRepresentationFactory;
     this.componentRequirementExpressions = checkNotNull(componentRequirementExpressions);
+    this.processingEnv = processingEnv;
   }
 
   /**
@@ -241,6 +239,15 @@
         componentMethod.methodElement()
             .asMemberOf(componentImplementation.graph().componentTypeElement().getType())
             .getReturnType();
+
+    // When compiling with -source 7, javac's type inference isn't strong enough to match things
+    // like Optional<javax.inject.Provider<T>> to Optional<dagger.internal.Provider<T>>.
+    if (isPreJava8SourceVersion(processingEnv)
+        && (MapType.isMapOfProvider(returnType)
+            || OptionalType.isOptionalProviderType(returnType))) {
+      return expression.castTo(returnType.getRawType());
+    }
+
     return !isVoid(returnType) && !expression.type().isAssignableTo(returnType)
         ? expression.castTo(returnType)
         : expression;
@@ -278,29 +285,4 @@
     }
     throw new AssertionError();
   }
-
-  /**
-   * Returns an {@link ExperimentalSwitchingProviderDependencyRepresentation} for the requested
-   * binding to satisfy dependency requests on it from experimental switching providers. Cannot be
-   * used for Members Injection requests.
-   */
-  ExperimentalSwitchingProviderDependencyRepresentation
-      getExperimentalSwitchingProviderDependencyRepresentation(BindingRequest request) {
-    checkState(
-        componentImplementation.compilerMode().isExperimentalMergedMode(),
-        "Compiler mode should be experimentalMergedMode!");
-    Optional<Binding> localBinding = graph.localContributionBinding(request.key());
-
-    if (localBinding.isPresent()) {
-      return reentrantComputeIfAbsent(
-          experimentalSwitchingProviderDependencyRepresentations,
-          localBinding.get(),
-          binding ->
-              experimentalSwitchingProviderDependencyRepresentationFactory.create(
-                  (ProvisionBinding) binding));
-    }
-
-    checkArgument(parent.isPresent(), "no expression found for %s", request);
-    return parent.get().getExperimentalSwitchingProviderDependencyRepresentation(request);
-  }
 }
diff --git a/java/dagger/internal/codegen/writing/DelegateRequestRepresentation.java b/java/dagger/internal/codegen/writing/DelegateRequestRepresentation.java
index 673a659..82c01cf 100644
--- a/java/dagger/internal/codegen/writing/DelegateRequestRepresentation.java
+++ b/java/dagger/internal/codegen/writing/DelegateRequestRepresentation.java
@@ -36,7 +36,9 @@
 import dagger.internal.codegen.binding.BindsTypeChecker;
 import dagger.internal.codegen.binding.ContributionBinding;
 import dagger.internal.codegen.javapoet.Expression;
+import dagger.internal.codegen.javapoet.TypeNames;
 import dagger.internal.codegen.model.RequestKind;
+import dagger.internal.codegen.xprocessing.XTypes;
 
 /** A {@link dagger.internal.codegen.writing.RequestRepresentation} for {@code @Binds} methods. */
 final class DelegateRequestRepresentation extends RequestRepresentation {
@@ -88,8 +90,14 @@
             ? delegateExpression.castTo(contributedType)
             : delegateExpression;
       default:
-        return castToRawTypeIfNecessary(
-            delegateExpression, requestType(requestKind, contributedType, processingEnv));
+        XType requestedType = requestType(requestKind, contributedType, processingEnv);
+        if (XTypes.isTypeOf(requestedType, TypeNames.PROVIDER)) {
+          // Even though the user may have requested a javax Provider, our generated code and
+          // factories only work in the Dagger Provider type, so swap to that one before doing
+          // a cast.
+          requestedType = XTypes.rewrapType(requestedType, TypeNames.DAGGER_PROVIDER);
+        }
+        return castToRawTypeIfNecessary(delegateExpression, requestedType);
     }
   }
 
diff --git a/java/dagger/internal/codegen/writing/DependencyMethodProviderCreationExpression.java b/java/dagger/internal/codegen/writing/DependencyMethodProviderCreationExpression.java
index 49cc024..c54b03c 100644
--- a/java/dagger/internal/codegen/writing/DependencyMethodProviderCreationExpression.java
+++ b/java/dagger/internal/codegen/writing/DependencyMethodProviderCreationExpression.java
@@ -24,7 +24,7 @@
 import static com.squareup.javapoet.MethodSpec.constructorBuilder;
 import static com.squareup.javapoet.MethodSpec.methodBuilder;
 import static com.squareup.javapoet.TypeSpec.classBuilder;
-import static dagger.internal.codegen.javapoet.TypeNames.providerOf;
+import static dagger.internal.codegen.javapoet.TypeNames.daggerProviderOf;
 import static dagger.internal.codegen.writing.ComponentImplementation.TypeSpecKind.COMPONENT_PROVISION_FACTORY;
 import static dagger.internal.codegen.xprocessing.XElements.asMethod;
 import static dagger.internal.codegen.xprocessing.XElements.getSimpleName;
@@ -47,7 +47,6 @@
 import dagger.internal.codegen.compileroption.CompilerOptions;
 import dagger.internal.codegen.writing.ComponentImplementation.ShardImplementation;
 import dagger.internal.codegen.writing.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
-import dagger.internal.codegen.xprocessing.XAnnotations;
 
 /**
  * A {@link javax.inject.Provider} creation expression for a provision method on a component's
@@ -106,9 +105,8 @@
 
     binding
         .nullability()
-        .nullableAnnotation()
-        .map(XAnnotations::getClassName)
-        .ifPresent(getMethod::addAnnotation);
+        .nullableAnnotations()
+        .forEach(getMethod::addAnnotation);
 
     // We need to use the componentShard here since the generated type is static and shards are
     // not static classes so it can't be nested inside the shard.
@@ -123,7 +121,7 @@
     componentShard.addType(
         COMPONENT_PROVISION_FACTORY,
         classBuilder(factoryClassName)
-            .addSuperinterface(providerOf(keyType))
+            .addSuperinterface(daggerProviderOf(keyType))
             .addModifiers(PRIVATE, STATIC, FINAL)
             .addField(dependencyClassName, dependency().variableName(), PRIVATE, FINAL)
             .addMethod(
diff --git a/java/dagger/internal/codegen/writing/DerivedFromFrameworkInstanceRequestRepresentation.java b/java/dagger/internal/codegen/writing/DerivedFromFrameworkInstanceRequestRepresentation.java
index 4095a60..f054e6a 100644
--- a/java/dagger/internal/codegen/writing/DerivedFromFrameworkInstanceRequestRepresentation.java
+++ b/java/dagger/internal/codegen/writing/DerivedFromFrameworkInstanceRequestRepresentation.java
@@ -24,11 +24,13 @@
 import dagger.assisted.Assisted;
 import dagger.assisted.AssistedFactory;
 import dagger.assisted.AssistedInject;
+import dagger.internal.codegen.base.MapType;
 import dagger.internal.codegen.binding.BindsTypeChecker;
 import dagger.internal.codegen.binding.ComponentDescriptor.ComponentMethodDescriptor;
 import dagger.internal.codegen.binding.ContributionBinding;
 import dagger.internal.codegen.binding.FrameworkType;
 import dagger.internal.codegen.javapoet.Expression;
+import dagger.internal.codegen.javapoet.TypeNames;
 import dagger.internal.codegen.model.BindingKind;
 import dagger.internal.codegen.model.RequestKind;
 
@@ -59,30 +61,61 @@
 
   @Override
   Expression getDependencyExpression(ClassName requestingClass) {
-    Expression expression =
-        frameworkType.to(
-            requestKind,
-            frameworkRequestRepresentation.getDependencyExpression(requestingClass),
-            processingEnv);
-    return requiresTypeCast(expression, requestingClass)
-        ? expression.castTo(binding.contributedType())
-        : expression;
+    return getDependencyExpressionFromFrameworkExpression(
+        frameworkRequestRepresentation.getDependencyExpression(requestingClass),
+        requestingClass);
   }
 
   @Override
   Expression getDependencyExpressionForComponentMethod(
       ComponentMethodDescriptor componentMethod, ComponentImplementation component) {
+    return getDependencyExpressionFromFrameworkExpression(
+        frameworkRequestRepresentation
+            .getDependencyExpressionForComponentMethod(componentMethod, component),
+        component.name());
+  }
+
+  private Expression getDependencyExpressionFromFrameworkExpression(
+      Expression frameworkExpression, ClassName requestingClass) {
     Expression expression =
         frameworkType.to(
             requestKind,
-            frameworkRequestRepresentation.getDependencyExpressionForComponentMethod(
-                componentMethod, component),
+            frameworkExpression,
             processingEnv);
-    return requiresTypeCast(expression, component.name())
+
+    // If it is a map type we need to do a raw type cast. This is because a user requested field
+    // type like dagger.internal.Provider<Map<K, javax.inject.Provider<V>>> isn't always assignable
+    // from something like dagger.internal.Provider<Map<K, dagger.internal.Provider<V>>> just due
+    // to variance issues.
+    if (MapType.isMapOfProvider(binding.contributedType())) {
+      return castMapOfProvider(expression, binding);
+    }
+
+    return requiresTypeCast(expression, requestingClass)
         ? expression.castTo(binding.contributedType())
         : expression;
   }
 
+  private Expression castMapOfProvider(Expression expression, ContributionBinding binding) {
+    switch (requestKind) {
+      case INSTANCE:
+        return expression.castTo(binding.contributedType());
+      case PROVIDER:
+      case PROVIDER_OF_LAZY:
+        return expression.castTo(processingEnv.requireType(TypeNames.DAGGER_PROVIDER).getRawType());
+      case LAZY:
+        return expression.castTo(processingEnv.requireType(TypeNames.LAZY).getRawType());
+      case PRODUCER:
+      case FUTURE:
+        return expression.castTo(processingEnv.requireType(TypeNames.PRODUCER).getRawType());
+      case PRODUCED:
+        return expression.castTo(processingEnv.requireType(TypeNames.PRODUCED).getRawType());
+
+      case MEMBERS_INJECTION: // fall through
+    }
+    throw new IllegalStateException("Unexpected request kind: " + requestKind);
+  }
+
   private boolean requiresTypeCast(Expression expression, ClassName requestingClass) {
     return binding.kind().equals(BindingKind.DELEGATE)
         && requestKind.equals(RequestKind.INSTANCE)
diff --git a/java/dagger/internal/codegen/writing/ExperimentalSwitchingProviderDependencyRepresentation.java b/java/dagger/internal/codegen/writing/ExperimentalSwitchingProviderDependencyRepresentation.java
deleted file mode 100644
index 1ebbb24..0000000
--- a/java/dagger/internal/codegen/writing/ExperimentalSwitchingProviderDependencyRepresentation.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (C) 2021 The Dagger Authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package dagger.internal.codegen.writing;
-
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
-import static dagger.internal.codegen.langmodel.Accessibility.isRawTypeAccessible;
-import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
-import static dagger.internal.codegen.xprocessing.XTypes.rewrapType;
-
-import androidx.room.compiler.processing.XProcessingEnv;
-import androidx.room.compiler.processing.XType;
-import com.squareup.javapoet.CodeBlock;
-import dagger.assisted.Assisted;
-import dagger.assisted.AssistedFactory;
-import dagger.assisted.AssistedInject;
-import dagger.internal.codegen.base.ContributionType;
-import dagger.internal.codegen.binding.BindsTypeChecker;
-import dagger.internal.codegen.binding.FrameworkType;
-import dagger.internal.codegen.binding.ProvisionBinding;
-import dagger.internal.codegen.javapoet.Expression;
-import dagger.internal.codegen.javapoet.TypeNames;
-import dagger.internal.codegen.model.BindingKind;
-import dagger.internal.codegen.model.DependencyRequest;
-import dagger.internal.codegen.model.RequestKind;
-import dagger.internal.codegen.writing.ComponentImplementation.ShardImplementation;
-
-/**
- * Returns type casted expressions to satisfy dependency requests from experimental switching
- * providers.
- */
-final class ExperimentalSwitchingProviderDependencyRepresentation {
-  private final ProvisionBinding binding;
-  private final ShardImplementation shardImplementation;
-  private final BindsTypeChecker bindsTypeChecker;
-  private final XProcessingEnv processingEnv;
-  private final XType type;
-
-  @AssistedInject
-  ExperimentalSwitchingProviderDependencyRepresentation(
-      @Assisted ProvisionBinding binding,
-      ComponentImplementation componentImplementation,
-      BindsTypeChecker bindsTypeChecker,
-      XProcessingEnv processingEnv) {
-    this.binding = binding;
-    this.shardImplementation = componentImplementation.shardImplementation(binding);
-    this.processingEnv = processingEnv;
-    this.bindsTypeChecker = bindsTypeChecker;
-    this.type =
-        isDelegateSetValuesBinding()
-            // For convience we allow @Binds @ElementsIntoSet from Collection => Set so that List
-            // can be contributed without converting to a Set first. Thus, here we rewrap the
-            // contributed type from Set<T> => Collection<T> to reflect this.
-            ? rewrapType(binding.contributedType(), TypeNames.COLLECTION)
-            : binding.contributedType();
-  }
-
-  Expression getDependencyExpression(RequestKind requestKind, ProvisionBinding requestingBinding) {
-    int index = findIndexOfDependency(requestingBinding);
-    XType frameworkType =
-        processingEnv.getDeclaredType(
-            processingEnv.requireTypeElement(FrameworkType.PROVIDER.frameworkClassName()));
-    Expression expression =
-        FrameworkType.PROVIDER.to(
-            requestKind,
-            Expression.create(
-                frameworkType,
-                CodeBlock.of(
-                    "(($T) dependencies[$L])", frameworkType.getRawType().getTypeName(), index)),
-            processingEnv);
-    if (usesExplicitTypeCast(expression, requestKind)) {
-      return expression.castTo(type);
-    }
-    if (usesRawTypeCast(requestKind)) {
-      return expression.castTo(type.getRawType());
-    }
-    return expression;
-  }
-
-  private int findIndexOfDependency(ProvisionBinding requestingBinding) {
-    return requestingBinding.dependencies().stream()
-            .map(DependencyRequest::key)
-            .collect(toImmutableList())
-            .indexOf(binding.key())
-        + (requestingBinding.requiresModuleInstance()
-                && requestingBinding.contributingModule().isPresent()
-            ? 1
-            : 0);
-  }
-
-  private boolean isDelegateSetValuesBinding() {
-    return binding.kind().equals(BindingKind.DELEGATE)
-        && binding.contributionType().equals(ContributionType.SET_VALUES);
-  }
-
-  private boolean usesExplicitTypeCast(Expression expression, RequestKind requestKind) {
-    // If the type is accessible, we can directly cast the expression use the type.
-    return requestKind.equals(RequestKind.INSTANCE)
-        && !bindsTypeChecker.isAssignable(expression.type(), type, binding.contributionType())
-        && isTypeAccessibleFrom(type, shardImplementation.name().packageName());
-  }
-
-  private boolean usesRawTypeCast(RequestKind requestKind) {
-    // If a type has inaccessible type arguments, then cast to raw type.
-    return requestKind.equals(RequestKind.INSTANCE)
-        && !isTypeAccessibleFrom(type, shardImplementation.name().packageName())
-        && isRawTypeAccessible(type, shardImplementation.name().packageName());
-  }
-
-  @AssistedFactory
-  static interface Factory {
-    ExperimentalSwitchingProviderDependencyRepresentation create(ProvisionBinding binding);
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/ExperimentalSwitchingProviders.java b/java/dagger/internal/codegen/writing/ExperimentalSwitchingProviders.java
deleted file mode 100644
index 586b5f5..0000000
--- a/java/dagger/internal/codegen/writing/ExperimentalSwitchingProviders.java
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * Copyright (C) 2022 The Dagger Authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package dagger.internal.codegen.writing;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.collect.Iterables.getLast;
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static com.squareup.javapoet.MethodSpec.methodBuilder;
-import static com.squareup.javapoet.TypeSpec.classBuilder;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
-import static dagger.internal.codegen.javapoet.AnnotationSpecs.Suppression.UNCHECKED;
-import static dagger.internal.codegen.javapoet.AnnotationSpecs.suppressWarnings;
-import static dagger.internal.codegen.javapoet.TypeNames.providerOf;
-import static javax.lang.model.element.Modifier.FINAL;
-import static javax.lang.model.element.Modifier.PRIVATE;
-import static javax.lang.model.element.Modifier.PUBLIC;
-import static javax.lang.model.element.Modifier.STATIC;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.CodeBlock;
-import com.squareup.javapoet.MethodSpec;
-import com.squareup.javapoet.TypeName;
-import com.squareup.javapoet.TypeSpec;
-import com.squareup.javapoet.TypeVariableName;
-import dagger.internal.codegen.binding.ProvisionBinding;
-import dagger.internal.codegen.javapoet.CodeBlocks;
-import dagger.internal.codegen.model.Key;
-import dagger.internal.codegen.writing.ComponentImplementation.ShardImplementation;
-import dagger.internal.codegen.writing.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.TreeMap;
-import javax.inject.Provider;
-
-/**
- * Keeps track of all provider expression requests for a component.
- *
- * <p>The provider expression request will be satisfied by a single generated {@code Provider} class
- * that can provide instances for all types by switching on an id.
- */
-final class ExperimentalSwitchingProviders {
-  /**
-   * Each switch size is fixed at 100 cases each and put in its own method. This is to limit the
-   * size of the methods so that we don't reach the "huge" method size limit for Android that will
-   * prevent it from being AOT compiled in some versions of Android (b/77652521). This generally
-   * starts to happen around 1500 cases, but we are choosing 100 to be safe.
-   */
-  // TODO(bcorso): Include a proguard_spec in the Dagger library to prevent inlining these methods?
-  // TODO(ronshapiro): Consider making this configurable via a flag.
-  private static final int MAX_CASES_PER_SWITCH = 100;
-
-  private static final long MAX_CASES_PER_CLASS = MAX_CASES_PER_SWITCH * MAX_CASES_PER_SWITCH;
-  private static final TypeVariableName T = TypeVariableName.get("T");
-
-  /**
-   * Maps a {@link Key} to an instance of a {@link SwitchingProviderBuilder}. Each group of {@code
-   * MAX_CASES_PER_CLASS} keys will share the same instance.
-   */
-  private final Map<Key, SwitchingProviderBuilder> switchingProviderBuilders =
-      new LinkedHashMap<>();
-
-  private final ShardImplementation shardImplementation;
-  private final Provider<ComponentRequestRepresentations> componentRequestRepresentationsProvider;
-
-  ExperimentalSwitchingProviders(
-      ShardImplementation shardImplementation,
-      Provider<ComponentRequestRepresentations> componentRequestRepresentationsProvider) {
-    this.shardImplementation = checkNotNull(shardImplementation);
-    this.componentRequestRepresentationsProvider =
-        checkNotNull(componentRequestRepresentationsProvider);
-  }
-
-  /** Returns the framework instance creation expression for an inner switching provider class. */
-  FrameworkInstanceCreationExpression newFrameworkInstanceCreationExpression(
-      ProvisionBinding binding, RequestRepresentation unscopedInstanceRequestRepresentation) {
-    return new FrameworkInstanceCreationExpression() {
-      @Override
-      public CodeBlock creationExpression() {
-        return switchingProviderBuilders
-            .computeIfAbsent(binding.key(), key -> getSwitchingProviderBuilder())
-            .getNewInstanceCodeBlock(binding, unscopedInstanceRequestRepresentation);
-      }
-    };
-  }
-
-  private SwitchingProviderBuilder getSwitchingProviderBuilder() {
-    if (switchingProviderBuilders.size() % MAX_CASES_PER_CLASS == 0) {
-      String name = shardImplementation.getUniqueClassName("SwitchingProvider");
-      // TODO(wanyingd): move Switching Providers and injection methods to Shard classes to avoid
-      // exceeding component class constant pool limit.
-      SwitchingProviderBuilder switchingProviderBuilder =
-          new SwitchingProviderBuilder(shardImplementation.name().nestedClass(name));
-      shardImplementation.addTypeSupplier(switchingProviderBuilder::build);
-      return switchingProviderBuilder;
-    }
-    return getLast(switchingProviderBuilders.values());
-  }
-
-  // TODO(bcorso): Consider just merging this class with ExperimentalSwitchingProviders.
-  private final class SwitchingProviderBuilder {
-    // Keep the switch cases ordered by switch id. The switch Ids are assigned in pre-order
-    // traversal, but the switch cases are assigned in post-order traversal of the binding graph.
-    private final Map<Integer, CodeBlock> switchCases = new TreeMap<>();
-    private final Map<Key, Integer> switchIds = new HashMap<>();
-    private final ClassName switchingProviderType;
-
-    SwitchingProviderBuilder(ClassName switchingProviderType) {
-      this.switchingProviderType = checkNotNull(switchingProviderType);
-    }
-
-    private CodeBlock getNewInstanceCodeBlock(
-        ProvisionBinding binding, RequestRepresentation unscopedInstanceRequestRepresentation) {
-      Key key = binding.key();
-      if (!switchIds.containsKey(key)) {
-        int switchId = switchIds.size();
-        switchIds.put(key, switchId);
-        switchCases.put(
-            switchId, createSwitchCaseCodeBlock(key, unscopedInstanceRequestRepresentation));
-      }
-
-      CodeBlock switchingProviderDependencies;
-      switch (binding.kind()) {
-          // TODO(wanyingd): there might be a better way to get component requirement information
-          // without using unscopedInstanceRequestRepresentation.
-        case COMPONENT_PROVISION:
-          switchingProviderDependencies =
-              ((ComponentProvisionRequestRepresentation) unscopedInstanceRequestRepresentation)
-                  .getComponentRequirementExpression(shardImplementation.name());
-          break;
-        case SUBCOMPONENT_CREATOR:
-          switchingProviderDependencies =
-              ((SubcomponentCreatorRequestRepresentation) unscopedInstanceRequestRepresentation)
-                  .getDependencyExpressionArguments();
-          break;
-        case MULTIBOUND_SET:
-        case MULTIBOUND_MAP:
-        case OPTIONAL:
-        case INJECTION:
-        case PROVISION:
-        case ASSISTED_FACTORY:
-          // Arguments built in the order of module reference, provision dependencies and members
-          // injection dependencies
-          switchingProviderDependencies =
-              componentRequestRepresentationsProvider.get().getCreateMethodArgumentsCodeBlock(
-                  binding, shardImplementation.name());
-          break;
-        default:
-          throw new IllegalArgumentException("Unexpected binding kind: " + binding.kind());
-      }
-
-      return CodeBlock.of(
-          "new $T<$L>($L)",
-          switchingProviderType,
-          // Add the type parameter explicitly when the binding is scoped because Java can't resolve
-          // the type when wrapped. For example, the following will error:
-          //   fooProvider = DoubleCheck.provider(new SwitchingProvider<>(1));
-          CodeBlock.of("$T", shardImplementation.accessibleTypeName(binding.contributedType())),
-          switchingProviderDependencies.isEmpty()
-              ? CodeBlock.of("$L", switchIds.get(key))
-              : CodeBlock.of("$L, $L", switchIds.get(key), switchingProviderDependencies));
-    }
-
-    private CodeBlock createSwitchCaseCodeBlock(
-        Key key, RequestRepresentation unscopedInstanceRequestRepresentation) {
-      // TODO(bcorso): Try to delay calling getDependencyExpression() until we are writing out the
-      // SwitchingProvider because calling it here makes FrameworkFieldInitializer think there's a
-      // cycle when initializing ExperimentalSwitchingProviders which adds an unnecessary
-      // DelegateFactory.
-      CodeBlock instanceCodeBlock =
-          unscopedInstanceRequestRepresentation
-              .getDependencyExpression(switchingProviderType)
-              .box()
-              .codeBlock();
-
-      return CodeBlock.builder()
-          // TODO(bcorso): Is there something else more useful than the key?
-          .add("case $L: // $L \n", switchIds.get(key), key)
-          .addStatement("return ($T) $L", T, instanceCodeBlock)
-          .build();
-    }
-
-    private TypeSpec build() {
-      TypeSpec.Builder builder =
-          classBuilder(switchingProviderType)
-              .addModifiers(PRIVATE, FINAL, STATIC)
-              .addTypeVariable(T)
-              .addSuperinterface(providerOf(T))
-              .addMethods(getMethods());
-
-      // The SwitchingProvider constructor lists switch id first and then the dependency array.
-      MethodSpec.Builder constructor = MethodSpec.constructorBuilder();
-      builder.addField(TypeName.INT, "id", PRIVATE, FINAL);
-      constructor.addParameter(TypeName.INT, "id").addStatement("this.id = id");
-      // Pass in provision dependencies and members injection dependencies.
-      builder.addField(Object[].class, "dependencies", FINAL, PRIVATE);
-      constructor
-          .addParameter(Object[].class, "dependencies")
-          .addStatement("this.dependencies = dependencies")
-          .varargs(true);
-
-      return builder.addMethod(constructor.build()).build();
-    }
-
-    private ImmutableList<MethodSpec> getMethods() {
-      ImmutableList<CodeBlock> switchCodeBlockPartitions = switchCodeBlockPartitions();
-      if (switchCodeBlockPartitions.size() == 1) {
-        // There are less than MAX_CASES_PER_SWITCH cases, so no need for extra get methods.
-        return ImmutableList.of(
-            methodBuilder("get")
-                .addModifiers(PUBLIC)
-                .addAnnotation(suppressWarnings(UNCHECKED))
-                .addAnnotation(Override.class)
-                .returns(T)
-                .addCode(getOnlyElement(switchCodeBlockPartitions))
-                .build());
-      }
-
-      // This is the main public "get" method that will route to private getter methods.
-      MethodSpec.Builder routerMethod =
-          methodBuilder("get")
-              .addModifiers(PUBLIC)
-              .addAnnotation(Override.class)
-              .returns(T)
-              .beginControlFlow("switch (id / $L)", MAX_CASES_PER_SWITCH);
-
-      ImmutableList.Builder<MethodSpec> getMethods = ImmutableList.builder();
-      for (int i = 0; i < switchCodeBlockPartitions.size(); i++) {
-        MethodSpec method =
-            methodBuilder("get" + i)
-                .addModifiers(PRIVATE)
-                .addAnnotation(suppressWarnings(UNCHECKED))
-                .returns(T)
-                .addCode(switchCodeBlockPartitions.get(i))
-                .build();
-        getMethods.add(method);
-        routerMethod.addStatement("case $L: return $N()", i, method);
-      }
-
-      routerMethod.addStatement("default: throw new $T(id)", AssertionError.class).endControlFlow();
-
-      return getMethods.add(routerMethod.build()).build();
-    }
-
-    private ImmutableList<CodeBlock> switchCodeBlockPartitions() {
-      return Lists.partition(ImmutableList.copyOf(switchCases.values()), MAX_CASES_PER_SWITCH)
-          .stream()
-          .map(
-              partitionCases ->
-                  CodeBlock.builder()
-                      .beginControlFlow("switch (id)")
-                      .add(CodeBlocks.concat(partitionCases))
-                      .addStatement("default: throw new $T(id)", AssertionError.class)
-                      .endControlFlow()
-                      .build())
-          .collect(toImmutableList());
-    }
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/FactoryGenerator.java b/java/dagger/internal/codegen/writing/FactoryGenerator.java
index 9ec1314..32195ba 100644
--- a/java/dagger/internal/codegen/writing/FactoryGenerator.java
+++ b/java/dagger/internal/codegen/writing/FactoryGenerator.java
@@ -35,16 +35,15 @@
 import static dagger.internal.codegen.model.BindingKind.INJECTION;
 import static dagger.internal.codegen.model.BindingKind.PROVISION;
 import static dagger.internal.codegen.writing.GwtCompatibility.gwtIncompatibleAnnotation;
-import static dagger.internal.codegen.xprocessing.XElements.getSimpleName;
 import static javax.lang.model.element.Modifier.FINAL;
 import static javax.lang.model.element.Modifier.PRIVATE;
 import static javax.lang.model.element.Modifier.PUBLIC;
 import static javax.lang.model.element.Modifier.STATIC;
 
 import androidx.room.compiler.processing.XElement;
+import androidx.room.compiler.processing.XExecutableParameterElement;
 import androidx.room.compiler.processing.XFiler;
 import androidx.room.compiler.processing.XProcessingEnv;
-import androidx.room.compiler.processing.XVariableElement;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Lists;
@@ -71,7 +70,6 @@
 import dagger.internal.codegen.model.Scope;
 import dagger.internal.codegen.writing.InjectionMethods.InjectionSiteMethod;
 import dagger.internal.codegen.writing.InjectionMethods.ProvisionMethod;
-import dagger.internal.codegen.xprocessing.XAnnotations;
 import java.util.List;
 import java.util.Optional;
 import java.util.stream.Stream;
@@ -236,7 +234,7 @@
     UniqueNameSet uniqueFieldNames = new UniqueNameSet();
     ImmutableMap<DependencyRequest, FieldSpec> frameworkFields = frameworkFields(binding);
     frameworkFields.values().forEach(field -> uniqueFieldNames.claim(field.name));
-    ImmutableMap<XVariableElement, ParameterSpec> assistedParameters =
+    ImmutableMap<XExecutableParameterElement, ParameterSpec> assistedParameters =
         assistedParameters(binding).stream()
             .collect(
                 toImmutableMap(
@@ -244,13 +242,12 @@
                     parameter ->
                         ParameterSpec.builder(
                                 parameter.getType().getTypeName(),
-                                uniqueFieldNames.getUniqueName(getSimpleName(parameter)))
+                                uniqueFieldNames.getUniqueName(parameter.getJvmName()))
                             .build()));
     TypeName providedTypeName = providedTypeName(binding);
     MethodSpec.Builder getMethod =
         methodBuilder("get")
             .addModifiers(PUBLIC)
-            .returns(providedTypeName)
             .addParameters(assistedParameters.values());
 
     if (factoryTypeName(binding).isPresent()) {
@@ -270,13 +267,14 @@
     if (binding.kind().equals(PROVISION)) {
       binding
           .nullability()
-          .nullableAnnotation()
-          .map(XAnnotations::getClassName)
-          .ifPresent(getMethod::addAnnotation);
+          .nullableAnnotations()
+          .forEach(getMethod::addAnnotation);
+      getMethod.returns(providedTypeName);
       getMethod.addStatement("return $L", invokeNewInstance);
     } else if (!binding.injectionSites().isEmpty()) {
       CodeBlock instance = CodeBlock.of("instance");
       getMethod
+          .returns(providedTypeName)
           .addStatement("$T $L = $L", providedTypeName, instance, invokeNewInstance)
           .addCode(
               InjectionSiteMethod.invokeAll(
@@ -286,8 +284,11 @@
                   binding.key().type().xprocessing(),
                   sourceFiles.frameworkFieldUsages(binding.dependencies(), frameworkFields)::get))
           .addStatement("return $L", instance);
+
     } else {
-      getMethod.addStatement("return $L", invokeNewInstance);
+      getMethod
+          .returns(providedTypeName)
+          .addStatement("return $L", invokeNewInstance);
     }
     return getMethod.build();
   }
diff --git a/java/dagger/internal/codegen/writing/FrameworkFieldInitializer.java b/java/dagger/internal/codegen/writing/FrameworkFieldInitializer.java
index 5a98177..32f0dde 100644
--- a/java/dagger/internal/codegen/writing/FrameworkFieldInitializer.java
+++ b/java/dagger/internal/codegen/writing/FrameworkFieldInitializer.java
@@ -142,8 +142,9 @@
         FrameworkField.forBinding(
             binding, frameworkInstanceCreationExpression.alternativeFrameworkClass());
 
-    TypeName fieldType =
-        useRawType ? contributionBindingField.type().rawType : contributionBindingField.type();
+    TypeName fieldType = useRawType
+        ? TypeNames.rawTypeName(contributionBindingField.type())
+        : contributionBindingField.type();
 
     if (binding.kind() == BindingKind.ASSISTED_INJECTION) {
       // An assisted injection factory doesn't extend Provider, so we reference the generated
diff --git a/java/dagger/internal/codegen/writing/FrameworkInstanceBindingRepresentation.java b/java/dagger/internal/codegen/writing/FrameworkInstanceBindingRepresentation.java
index bb62d52..037df56 100644
--- a/java/dagger/internal/codegen/writing/FrameworkInstanceBindingRepresentation.java
+++ b/java/dagger/internal/codegen/writing/FrameworkInstanceBindingRepresentation.java
@@ -47,7 +47,6 @@
   FrameworkInstanceBindingRepresentation(
       @Assisted ProvisionBinding binding,
       BindingGraph graph,
-      @Assisted FrameworkInstanceSupplier providerField,
       ComponentImplementation componentImplementation,
       DelegateRequestRepresentation.Factory delegateRequestRepresentationFactory,
       DerivedFromFrameworkInstanceRequestRepresentation.Factory
@@ -65,7 +64,7 @@
     this.providerRequestRepresentation =
         binding.kind().equals(DELEGATE) && !needsCaching(binding, graph)
             ? delegateRequestRepresentationFactory.create(binding, RequestKind.PROVIDER)
-            : providerInstanceRequestRepresentationFactory.create(binding, providerField);
+            : providerInstanceRequestRepresentationFactory.create(binding);
     this.producerFromProviderRepresentation =
         producerNodeInstanceRequestRepresentationFactory.create(
             binding,
@@ -108,7 +107,6 @@
 
   @AssistedFactory
   static interface Factory {
-    FrameworkInstanceBindingRepresentation create(
-        ProvisionBinding binding, FrameworkInstanceSupplier providerField);
+    FrameworkInstanceBindingRepresentation create(ProvisionBinding binding);
   }
 }
diff --git a/java/dagger/internal/codegen/writing/FrameworkInstanceKind.java b/java/dagger/internal/codegen/writing/FrameworkInstanceKind.java
index 1353e88..8e9d4c6 100644
--- a/java/dagger/internal/codegen/writing/FrameworkInstanceKind.java
+++ b/java/dagger/internal/codegen/writing/FrameworkInstanceKind.java
@@ -19,21 +19,17 @@
 import static dagger.internal.codegen.model.BindingKind.DELEGATE;
 
 import dagger.internal.codegen.binding.ContributionBinding;
-import dagger.internal.codegen.model.BindingKind;
 import dagger.internal.codegen.writing.ComponentImplementation.CompilerMode;
 
 /** Generation mode for satisfying framework request to Provision Binding. */
 enum FrameworkInstanceKind {
   SWITCHING_PROVIDER,
-  EXPERIMENTAL_SWITCHING_PROVIDER,
   STATIC_FACTORY,
   PROVIDER_FIELD;
 
   public static FrameworkInstanceKind from(ContributionBinding binding, CompilerMode compilerMode) {
     if (usesSwitchingProvider(binding, compilerMode)) {
-      if (compilerMode.isExperimentalMergedMode()) {
-        return EXPERIMENTAL_SWITCHING_PROVIDER;
-      } else if (compilerMode.isFastInit()) {
+      if (compilerMode.isFastInit()) {
         return SWITCHING_PROVIDER;
       } else {
         throw new IllegalStateException(
@@ -48,12 +44,7 @@
 
   private static boolean usesSwitchingProvider(
       ContributionBinding binding, CompilerMode compilerMode) {
-    if (!compilerMode.isFastInit() && !compilerMode.isExperimentalMergedMode()) {
-      return false;
-    }
-    // TODO(wanyingd): remove this check once we allow inaccessible types in merged mode.
-    if (compilerMode.isExperimentalMergedMode()
-        && binding.kind().equals(BindingKind.ASSISTED_FACTORY)) {
+    if (!compilerMode.isFastInit()) {
       return false;
     }
     switch (binding.kind()) {
@@ -100,10 +91,9 @@
         return true;
       case PROVISION:
         return !compilerMode.isFastInit()
-            && !compilerMode.isExperimentalMergedMode()
             && !binding.requiresModuleInstance();
       case INJECTION:
-        return !compilerMode.isFastInit() && !compilerMode.isExperimentalMergedMode();
+        return !compilerMode.isFastInit();
       default:
         return false;
     }
diff --git a/java/dagger/internal/codegen/writing/HjarSourceFileGenerator.java b/java/dagger/internal/codegen/writing/HjarSourceFileGenerator.java
deleted file mode 100644
index 4bafb5a..0000000
--- a/java/dagger/internal/codegen/writing/HjarSourceFileGenerator.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (C) 2017 The Dagger Authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package dagger.internal.codegen.writing;
-
-import static com.squareup.javapoet.MethodSpec.constructorBuilder;
-import static com.squareup.javapoet.MethodSpec.methodBuilder;
-import static com.squareup.javapoet.TypeSpec.classBuilder;
-import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
-import static javax.lang.model.element.Modifier.PRIVATE;
-
-import androidx.room.compiler.processing.XElement;
-import com.google.common.collect.ImmutableList;
-import com.squareup.javapoet.ClassName;
-import com.squareup.javapoet.FieldSpec;
-import com.squareup.javapoet.MethodSpec;
-import com.squareup.javapoet.TypeSpec;
-import dagger.internal.codegen.base.SourceFileGenerator;
-import javax.lang.model.element.Modifier;
-
-/**
- * A source file generator that only writes the relevant code necessary for Bazel to create a
- * correct header (ABI) jar.
- */
-public final class HjarSourceFileGenerator<T> extends SourceFileGenerator<T> {
-  private final SourceFileGenerator<T> delegate;
-
-  private HjarSourceFileGenerator(SourceFileGenerator<T> delegate) {
-    super(delegate);
-    this.delegate = delegate;
-  }
-
-  public static <T> SourceFileGenerator<T> wrap(SourceFileGenerator<T> delegate) {
-    return new HjarSourceFileGenerator<>(delegate);
-  }
-
-  @Override
-  public XElement originatingElement(T input) {
-    return delegate.originatingElement(input);
-  }
-
-  @Override
-  public ImmutableList<TypeSpec.Builder> topLevelTypes(T input) {
-    return delegate.topLevelTypes(input).stream()
-        .map(completeType -> skeletonType(completeType.build()))
-        .collect(toImmutableList());
-  }
-
-  private TypeSpec.Builder skeletonType(TypeSpec completeType) {
-    TypeSpec.Builder skeleton =
-        classBuilder(completeType.name)
-            .addSuperinterfaces(completeType.superinterfaces)
-            .addTypeVariables(completeType.typeVariables)
-            .addModifiers(completeType.modifiers.toArray(new Modifier[0]))
-            .addAnnotations(completeType.annotations);
-
-    if (!completeType.superclass.equals(ClassName.OBJECT)) {
-      skeleton.superclass(completeType.superclass);
-    }
-
-    completeType.methodSpecs.stream()
-        .filter(method -> !method.modifiers.contains(PRIVATE) || method.isConstructor())
-        .map(this::skeletonMethod)
-        .forEach(skeleton::addMethod);
-
-    completeType.fieldSpecs.stream()
-        .filter(field -> !field.modifiers.contains(PRIVATE))
-        .map(this::skeletonField)
-        .forEach(skeleton::addField);
-
-    completeType.typeSpecs.stream()
-        .map(type -> skeletonType(type).build())
-        .forEach(skeleton::addType);
-
-    return skeleton;
-  }
-
-  private MethodSpec skeletonMethod(MethodSpec completeMethod) {
-    MethodSpec.Builder skeleton =
-        completeMethod.isConstructor()
-            ? constructorBuilder()
-            : methodBuilder(completeMethod.name).returns(completeMethod.returnType);
-
-    if (completeMethod.isConstructor()) {
-      // Code in Turbine must (for technical reasons in javac) have a valid super() call for
-      // constructors, otherwise javac will bark, and Turbine has no way to avoid this. So we retain
-      // constructor method bodies if they do exist
-      skeleton.addCode(completeMethod.code);
-    }
-
-    return skeleton
-        .addModifiers(completeMethod.modifiers)
-        .addTypeVariables(completeMethod.typeVariables)
-        .addParameters(completeMethod.parameters)
-        .addExceptions(completeMethod.exceptions)
-        .varargs(completeMethod.varargs)
-        .addAnnotations(completeMethod.annotations)
-        .build();
-  }
-
-  private FieldSpec skeletonField(FieldSpec completeField) {
-    return FieldSpec.builder(
-            completeField.type,
-            completeField.name,
-            completeField.modifiers.toArray(new Modifier[0]))
-        .addAnnotations(completeField.annotations)
-        .build();
-  }
-}
diff --git a/java/dagger/internal/codegen/writing/InaccessibleMapKeyProxyGenerator.java b/java/dagger/internal/codegen/writing/InaccessibleMapKeyProxyGenerator.java
index e43d844..3eaf92d 100644
--- a/java/dagger/internal/codegen/writing/InaccessibleMapKeyProxyGenerator.java
+++ b/java/dagger/internal/codegen/writing/InaccessibleMapKeyProxyGenerator.java
@@ -26,10 +26,13 @@
 import androidx.room.compiler.processing.XFiler;
 import androidx.room.compiler.processing.XProcessingEnv;
 import com.google.common.collect.ImmutableList;
+import com.squareup.javapoet.FieldSpec;
 import com.squareup.javapoet.TypeSpec;
 import dagger.internal.codegen.base.SourceFileGenerator;
 import dagger.internal.codegen.binding.ContributionBinding;
 import dagger.internal.codegen.binding.MapKeys;
+import dagger.internal.codegen.javapoet.TypeNames;
+import dagger.internal.codegen.model.DaggerAnnotation;
 import javax.inject.Inject;
 
 /**
@@ -56,11 +59,31 @@
   public ImmutableList<TypeSpec.Builder> topLevelTypes(ContributionBinding binding) {
     return MapKeys.mapKeyFactoryMethod(binding, processingEnv)
         .map(
-            method ->
-                classBuilder(MapKeys.mapKeyProxyClassName(binding))
-                    .addModifiers(PUBLIC, FINAL)
-                    .addMethod(constructorBuilder().addModifiers(PRIVATE).build())
-                    .addMethod(method))
+            method -> {
+              TypeSpec.Builder builder =
+                  classBuilder(MapKeys.mapKeyProxyClassName(binding))
+                      .addModifiers(PUBLIC, FINAL)
+                      .addMethod(constructorBuilder().addModifiers(PRIVATE).build())
+                      .addMethod(method);
+              // In proguard, we need to keep the classes referenced by @LazyClassKey, we do that by
+              // generating a field referencing the type, and then applying @KeepFieldType to the
+              // field. Here, we generate the field in the proxy class. For classes that are
+              // accessible from the dagger component, we generate fields in LazyClassKeyProvider.
+              // Note: the generated field should not be initialized to avoid class loading.
+              binding
+                  .mapKey()
+                  .map(DaggerAnnotation::xprocessing)
+                  .filter(
+                      mapKey ->
+                          mapKey.getTypeElement().getClassName().equals(TypeNames.LAZY_CLASS_KEY))
+                  .map(
+                      mapKey ->
+                          FieldSpec.builder(mapKey.getAsType("value").getTypeName(), "className")
+                              .addAnnotation(TypeNames.KEEP_FIELD_TYPE)
+                              .build())
+                  .ifPresent(builder::addField);
+              return builder;
+            })
         .map(ImmutableList::of)
         .orElse(ImmutableList.of());
   }
diff --git a/java/dagger/internal/codegen/writing/InjectionMethods.java b/java/dagger/internal/codegen/writing/InjectionMethods.java
index 75b950a..39c03dd 100644
--- a/java/dagger/internal/codegen/writing/InjectionMethods.java
+++ b/java/dagger/internal/codegen/writing/InjectionMethods.java
@@ -18,6 +18,7 @@
 
 import static androidx.room.compiler.processing.XElementKt.isConstructor;
 import static androidx.room.compiler.processing.XElementKt.isMethod;
+import static androidx.room.compiler.processing.XElementKt.isMethodParameter;
 import static androidx.room.compiler.processing.XTypeKt.isVoid;
 import static com.google.common.base.CaseFormat.LOWER_CAMEL;
 import static com.google.common.base.CaseFormat.UPPER_CAMEL;
@@ -27,7 +28,6 @@
 import static dagger.internal.codegen.binding.SourceFiles.generatedClassNameForBinding;
 import static dagger.internal.codegen.binding.SourceFiles.memberInjectedFieldSignatureForVariable;
 import static dagger.internal.codegen.binding.SourceFiles.membersInjectorNameForType;
-import static dagger.internal.codegen.binding.SourceFiles.protectAgainstKeywords;
 import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
 import static dagger.internal.codegen.extension.DaggerStreams.toImmutableMap;
 import static dagger.internal.codegen.javapoet.CodeBlocks.makeParametersCodeBlock;
@@ -81,7 +81,6 @@
 import java.util.List;
 import java.util.Optional;
 import java.util.function.Function;
-import javax.lang.model.SourceVersion;
 
 /** Convenience methods for creating and invoking {@link InjectionMethod}s. */
 final class InjectionMethods {
@@ -145,7 +144,7 @@
     static CodeBlock invoke(
         ProvisionBinding binding,
         Function<DependencyRequest, CodeBlock> dependencyUsage,
-        Function<XVariableElement, String> uniqueAssistedParameterName,
+        Function<XExecutableParameterElement, String> uniqueAssistedParameterName,
         ClassName requestingClass,
         Optional<CodeBlock> moduleReference,
         CompilerOptions compilerOptions) {
@@ -162,7 +161,7 @@
     static ImmutableList<CodeBlock> invokeArguments(
         ProvisionBinding binding,
         Function<DependencyRequest, CodeBlock> dependencyUsage,
-        Function<XVariableElement, String> uniqueAssistedParameterName) {
+        Function<XExecutableParameterElement, String> uniqueAssistedParameterName) {
       ImmutableMap<XExecutableParameterElement, DependencyRequest> dependencyRequestMap =
           binding.provisionDependencies().stream()
               .collect(
@@ -406,10 +405,10 @@
     if (isVoid(method.getReturnType())) {
       return builder.addStatement("$L", invocation).build();
     } else {
-      Nullability.of(method)
-          .nullableAnnotation()
-          .map(XAnnotations::getClassName)
-          .ifPresent(builder::addAnnotation);
+      Nullability nullability = Nullability.of(method);
+      nullability
+          .nullableAnnotations()
+          .forEach(builder::addAnnotation);
       return builder
           .returns(method.getReturnType().getTypeName())
           .addStatement("return $L", invocation)
@@ -463,7 +462,11 @@
     return parameters.stream()
         .map(
             parameter -> {
-              String name = parameterNameSet.getUniqueName(validJavaName(getSimpleName(parameter)));
+              String name =
+                  parameterNameSet.getUniqueName(
+                      isMethodParameter(parameter)
+                          ? asMethodParameter(parameter).getJvmName()
+                          : getSimpleName(parameter));
               boolean useObject = !isRawTypePubliclyAccessible(parameter.getType());
               return copyParameter(methodBuilder, parameter.getType(), name, useObject);
             })
@@ -487,19 +490,4 @@
     // If we had to cast the instance add an extra parenthesis incase we're calling a method on it.
     return useObject ? CodeBlock.of("($L)", instance) : instance;
   }
-
-  private static String validJavaName(CharSequence name) {
-    if (SourceVersion.isIdentifier(name)) {
-      return protectAgainstKeywords(name.toString());
-    }
-
-    StringBuilder newName = new StringBuilder(name.length());
-    char firstChar = name.charAt(0);
-    if (!Character.isJavaIdentifierStart(firstChar)) {
-      newName.append('_');
-    }
-
-    name.chars().forEach(c -> newName.append(Character.isJavaIdentifierPart(c) ? c : '_'));
-    return newName.toString();
-  }
 }
diff --git a/java/dagger/internal/codegen/writing/InjectionOrProvisionProviderCreationExpression.java b/java/dagger/internal/codegen/writing/InjectionOrProvisionProviderCreationExpression.java
index d32531b..27e017d 100644
--- a/java/dagger/internal/codegen/writing/InjectionOrProvisionProviderCreationExpression.java
+++ b/java/dagger/internal/codegen/writing/InjectionOrProvisionProviderCreationExpression.java
@@ -18,8 +18,15 @@
 
 import static com.google.common.base.Preconditions.checkNotNull;
 import static dagger.internal.codegen.binding.SourceFiles.generatedClassNameForBinding;
+import static dagger.internal.codegen.extension.DaggerCollectors.toOptional;
+import static dagger.internal.codegen.model.BindingKind.ASSISTED_FACTORY;
 import static dagger.internal.codegen.model.BindingKind.INJECTION;
+import static dagger.internal.codegen.xprocessing.XElements.getSimpleName;
 
+import androidx.room.compiler.processing.XMethodElement;
+import androidx.room.compiler.processing.XProcessingEnv;
+import androidx.room.compiler.processing.XTypeElement;
+import com.squareup.javapoet.ClassName;
 import com.squareup.javapoet.CodeBlock;
 import dagger.assisted.Assisted;
 import dagger.assisted.AssistedFactory;
@@ -29,6 +36,7 @@
 import dagger.internal.codegen.javapoet.TypeNames;
 import dagger.internal.codegen.writing.ComponentImplementation.ShardImplementation;
 import dagger.internal.codegen.writing.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
+import java.util.Optional;
 import javax.inject.Provider;
 
 /**
@@ -42,32 +50,64 @@
   private final ContributionBinding binding;
   private final ShardImplementation shardImplementation;
   private final ComponentRequestRepresentations componentRequestRepresentations;
+  private final XProcessingEnv processingEnv;
 
   @AssistedInject
   InjectionOrProvisionProviderCreationExpression(
       @Assisted ContributionBinding binding,
       ComponentImplementation componentImplementation,
-      ComponentRequestRepresentations componentRequestRepresentations) {
+      ComponentRequestRepresentations componentRequestRepresentations,
+      XProcessingEnv processingEnv) {
     this.binding = checkNotNull(binding);
     this.shardImplementation = componentImplementation.shardImplementation(binding);
     this.componentRequestRepresentations = componentRequestRepresentations;
+    this.processingEnv = processingEnv;
   }
 
   @Override
   public CodeBlock creationExpression() {
+    ClassName factoryImpl = generatedClassNameForBinding(binding);
     CodeBlock createFactory =
         CodeBlock.of(
-            "$T.create($L)",
-            generatedClassNameForBinding(binding),
+            "$T.$L($L)",
+            factoryImpl,
+            // A different name is used for assisted factories due to backwards compatibility
+            // issues when migrating from the javax Provider.
+            binding.kind().equals(ASSISTED_FACTORY) ? "createFactoryProvider" : "create",
             componentRequestRepresentations.getCreateMethodArgumentsCodeBlock(
                 binding, shardImplementation.name()));
 
+    // If this is for an AssistedFactory, then we may need to change the call in case we're building
+    // against a library built at an older version of Dagger before the changes to make factories
+    // return a Dagger Provider instead of a javax.inject.Provider.
+    if (binding.kind().equals(ASSISTED_FACTORY)) {
+      XTypeElement factoryType = processingEnv.findTypeElement(factoryImpl);
+      // If we can't find the factory, then assume it is being generated this run, which means
+      // it should be the newer version and not need wrapping. If it is missing for some other
+      // reason, then that likely means there will just be some other compilation failure.
+      if (factoryType != null) {
+        Optional<XMethodElement> createMethod = factoryType.getDeclaredMethods().stream()
+            .filter(method -> method.isStatic()
+                && getSimpleName(method).equals("createFactoryProvider"))
+            .collect(toOptional());
+        // Only convert it if the newer method doesn't exist.
+        if (createMethod.isEmpty()) {
+          createFactory = CodeBlock.of(
+            "$T.asDaggerProvider($T.create($L))",
+            TypeNames.DAGGER_PROVIDERS,
+            factoryImpl,
+            componentRequestRepresentations.getCreateMethodArgumentsCodeBlock(
+                binding, shardImplementation.name()));
+        }
+      }
+    }
+
     // When scoping a parameterized factory for an @Inject class, Java 7 cannot always infer the
     // type properly, so cast to a raw framework type before scoping.
     if (binding.kind().equals(INJECTION)
         && binding.unresolved().isPresent()
         && binding.scope().isPresent()) {
-      return CodeBlocks.cast(createFactory, TypeNames.PROVIDER);
+      return CodeBlocks.cast(createFactory, TypeNames.DAGGER_PROVIDER);
     } else {
       return createFactory;
     }
diff --git a/java/dagger/internal/codegen/writing/LazyClassKeyProviders.java b/java/dagger/internal/codegen/writing/LazyClassKeyProviders.java
new file mode 100644
index 0000000..2c25811
--- /dev/null
+++ b/java/dagger/internal/codegen/writing/LazyClassKeyProviders.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2024 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.internal.codegen.writing;
+
+import static dagger.internal.codegen.base.MapKeyAccessibility.isMapKeyAccessibleFrom;
+import static javax.lang.model.element.Modifier.FINAL;
+import static javax.lang.model.element.Modifier.PRIVATE;
+import static javax.lang.model.element.Modifier.STATIC;
+
+import androidx.room.compiler.processing.XAnnotation;
+import com.google.common.base.Preconditions;
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.FieldSpec;
+import com.squareup.javapoet.TypeSpec;
+import dagger.internal.codegen.base.UniqueNameSet;
+import dagger.internal.codegen.javapoet.TypeNames;
+import dagger.internal.codegen.model.Key;
+import dagger.internal.codegen.writing.ComponentImplementation.ShardImplementation;
+import java.util.HashMap;
+import java.util.Map;
+
+/** Keeps track of all providers for DaggerMap keys. */
+public final class LazyClassKeyProviders {
+  public static final String MAP_KEY_PROVIDER_NAME = "LazyClassKeyProvider";
+  private final ClassName mapKeyProviderType;
+  private final Map<Key, FieldSpec> entries = new HashMap<>();
+  private final Map<Key, FieldSpec> keepClassNamesFields = new HashMap<>();
+  private final UniqueNameSet uniqueFieldNames = new UniqueNameSet();
+  private final ShardImplementation shardImplementation;
+  private boolean providerAdded = false;
+
+  LazyClassKeyProviders(ShardImplementation shardImplementation) {
+    String name = shardImplementation.getUniqueClassName(MAP_KEY_PROVIDER_NAME);
+    mapKeyProviderType = shardImplementation.name().nestedClass(name);
+    this.shardImplementation = shardImplementation;
+  }
+
+  /** Returns a reference to a field in LazyClassKeyProvider that corresponds to this binding. */
+  CodeBlock getMapKeyExpression(Key key) {
+    // This is for avoid generating empty LazyClassKeyProvider in codegen tests
+    if (!providerAdded) {
+      shardImplementation.addTypeSupplier(this::build);
+      providerAdded = true;
+    }
+    if (!entries.containsKey(key)) {
+      addField(key);
+    }
+    return CodeBlock.of("$T.$N", mapKeyProviderType, entries.get(key));
+  }
+
+  private void addField(Key key) {
+    Preconditions.checkArgument(
+        key.multibindingContributionIdentifier().isPresent()
+            && key.multibindingContributionIdentifier()
+                .get()
+                .bindingMethod()
+                .xprocessing()
+                .hasAnnotation(TypeNames.LAZY_CLASS_KEY));
+    XAnnotation lazyClassKeyAnnotation =
+        key.multibindingContributionIdentifier()
+            .get()
+            .bindingMethod()
+            .xprocessing()
+            .getAnnotation(TypeNames.LAZY_CLASS_KEY);
+    ClassName lazyClassKey =
+        lazyClassKeyAnnotation.getAsType("value").getTypeElement().getClassName();
+    entries.put(
+        key,
+        FieldSpec.builder(
+                TypeNames.STRING,
+                uniqueFieldNames.getUniqueName(lazyClassKey.canonicalName().replace('.', '_')))
+            // TODO(b/217435141): Leave the field as non-final. We will apply @IdentifierNameString
+            // on the field, which doesn't work well with static final fields.
+            .addModifiers(STATIC)
+            .initializer("$S", lazyClassKey.reflectionName())
+            .build());
+    // To be able to apply -includedescriptorclasses rule to keep the class names referenced by
+    // LazyClassKey, we need to generate fields that uses those classes as type in
+    // LazyClassKeyProvider. For types that are not accessible from the generated component, we
+    // generate fields in the proxy class.
+    // Note: the generated field should not be initialized to avoid class loading.
+    if (isMapKeyAccessibleFrom(lazyClassKeyAnnotation, shardImplementation.name().packageName())) {
+      keepClassNamesFields.put(
+          key,
+          FieldSpec.builder(
+                  lazyClassKey,
+                  uniqueFieldNames.getUniqueName(lazyClassKey.canonicalName().replace('.', '_')))
+              .addAnnotation(TypeNames.KEEP_FIELD_TYPE)
+              .build());
+    }
+  }
+
+  private TypeSpec build() {
+    TypeSpec.Builder builder =
+        TypeSpec.classBuilder(mapKeyProviderType)
+            .addAnnotation(TypeNames.IDENTIFIER_NAME_STRING)
+            .addModifiers(PRIVATE, STATIC, FINAL)
+            .addFields(entries.values())
+            .addFields(keepClassNamesFields.values());
+    return builder.build();
+  }
+}
diff --git a/java/dagger/internal/codegen/writing/MapFactoryCreationExpression.java b/java/dagger/internal/codegen/writing/MapFactoryCreationExpression.java
index 1f857db..0ea382d 100644
--- a/java/dagger/internal/codegen/writing/MapFactoryCreationExpression.java
+++ b/java/dagger/internal/codegen/writing/MapFactoryCreationExpression.java
@@ -22,14 +22,16 @@
 import static dagger.internal.codegen.extension.DaggerCollectors.toOptional;
 
 import androidx.room.compiler.processing.XProcessingEnv;
-import androidx.room.compiler.processing.XType;
+import com.squareup.javapoet.ClassName;
 import com.squareup.javapoet.CodeBlock;
+import com.squareup.javapoet.TypeName;
 import dagger.assisted.Assisted;
 import dagger.assisted.AssistedFactory;
 import dagger.assisted.AssistedInject;
 import dagger.internal.codegen.base.MapType;
 import dagger.internal.codegen.binding.BindingGraph;
 import dagger.internal.codegen.binding.ContributionBinding;
+import dagger.internal.codegen.binding.MapKeys;
 import dagger.internal.codegen.javapoet.TypeNames;
 import dagger.internal.codegen.model.DependencyRequest;
 import java.util.stream.Stream;
@@ -41,6 +43,8 @@
   private final ComponentImplementation componentImplementation;
   private final BindingGraph graph;
   private final ContributionBinding binding;
+  private final boolean useLazyClassKey;
+  private final LazyClassKeyProviders lazyClassKeyProviders;
 
   @AssistedInject
   MapFactoryCreationExpression(
@@ -54,22 +58,31 @@
     this.binding = checkNotNull(binding);
     this.componentImplementation = componentImplementation;
     this.graph = graph;
+    this.useLazyClassKey = MapKeys.useLazyClassKey(binding, graph);
+    this.lazyClassKeyProviders =
+        componentImplementation.shardImplementation(binding).getLazyClassKeyProviders();
   }
 
   @Override
   public CodeBlock creationExpression() {
-    CodeBlock.Builder builder = CodeBlock.builder().add("$T.", mapFactoryClassName(binding));
+    ClassName mapFactoryClassName = mapFactoryClassName(binding);
+    CodeBlock.Builder builder = CodeBlock.builder().add("$T.", mapFactoryClassName);
+    TypeName valueTypeName = TypeName.OBJECT;
     if (!useRawType()) {
       MapType mapType = MapType.from(binding.key());
       // TODO(ronshapiro): either inline this into mapFactoryClassName, or add a
       // mapType.unwrappedValueType() method that doesn't require a framework type
-      XType valueType =
+      valueTypeName =
           Stream.of(TypeNames.PROVIDER, TypeNames.PRODUCER, TypeNames.PRODUCED)
               .filter(mapType::valuesAreTypeOf)
               .map(mapType::unwrappedValueType)
               .collect(toOptional())
-              .orElseGet(mapType::valueType);
-      builder.add("<$T, $T>", mapType.keyType().getTypeName(), valueType.getTypeName());
+              .orElseGet(mapType::valueType)
+              .getTypeName();
+      builder.add(
+          "<$T, $T>",
+          useLazyClassKey ? TypeNames.STRING : mapType.keyType().getTypeName(),
+          valueTypeName);
     }
 
     builder.add("builder($L)", binding.dependencies().size());
@@ -78,12 +91,20 @@
       ContributionBinding contributionBinding = graph.contributionBinding(dependency.key());
       builder.add(
           ".put($L, $L)",
-          getMapKeyExpression(contributionBinding, componentImplementation.name(), processingEnv),
+          useLazyClassKey
+              ? lazyClassKeyProviders.getMapKeyExpression(dependency.key())
+              : getMapKeyExpression(
+                  contributionBinding, componentImplementation.name(), processingEnv),
           multibindingDependencyExpression(dependency));
     }
-    builder.add(".build()");
 
-    return builder.build();
+    return useLazyClassKey
+        ? CodeBlock.of(
+            "$T.<$T>of($L)",
+            TypeNames.LAZY_CLASS_KEY_MAP_FACTORY,
+            valueTypeName,
+            builder.add(".build()").build())
+        : builder.add(".build()").build();
   }
 
   @AssistedFactory
diff --git a/java/dagger/internal/codegen/writing/MapRequestRepresentation.java b/java/dagger/internal/codegen/writing/MapRequestRepresentation.java
index bb49ebe..f631d34 100644
--- a/java/dagger/internal/codegen/writing/MapRequestRepresentation.java
+++ b/java/dagger/internal/codegen/writing/MapRequestRepresentation.java
@@ -38,6 +38,7 @@
 import dagger.internal.codegen.base.MapType;
 import dagger.internal.codegen.binding.BindingGraph;
 import dagger.internal.codegen.binding.ContributionBinding;
+import dagger.internal.codegen.binding.MapKeys;
 import dagger.internal.codegen.binding.ProvisionBinding;
 import dagger.internal.codegen.javapoet.Expression;
 import dagger.internal.codegen.javapoet.TypeNames;
@@ -54,7 +55,8 @@
   private final ProvisionBinding binding;
   private final ImmutableMap<DependencyRequest, ContributionBinding> dependencies;
   private final ComponentRequestRepresentations componentRequestRepresentations;
-  private final boolean isExperimentalMergedMode;
+  private final boolean useLazyClassKey;
+  private final LazyClassKeyProviders lazyClassKeyProviders;
 
   @AssistedInject
   MapRequestRepresentation(
@@ -70,12 +72,29 @@
     this.componentRequestRepresentations = componentRequestRepresentations;
     this.dependencies =
         Maps.toMap(binding.dependencies(), dep -> graph.contributionBinding(dep.key()));
-    this.isExperimentalMergedMode =
-        componentImplementation.compilerMode().isExperimentalMergedMode();
+    this.useLazyClassKey = MapKeys.useLazyClassKey(binding, graph);
+    this.lazyClassKeyProviders =
+        componentImplementation.shardImplementation(binding).getLazyClassKeyProviders();
   }
 
   @Override
   Expression getDependencyExpression(ClassName requestingClass) {
+    MapType mapType = MapType.from(binding.key());
+    Expression dependencyExpression = getUnderlyingMapExpression(requestingClass);
+    // LazyClassKey is backed with a string map, therefore needs to be wrapped.
+    if (useLazyClassKey) {
+      return Expression.create(
+          dependencyExpression.type(),
+          CodeBlock.of(
+              "$T.<$T>of($L)",
+              TypeNames.LAZY_CLASS_KEY_MAP,
+              mapType.valueType().getTypeName(),
+              dependencyExpression.codeBlock()));
+    }
+    return dependencyExpression;
+  }
+
+  private Expression getUnderlyingMapExpression(ClassName requestingClass) {
     // TODO(ronshapiro): We should also make an ImmutableMap version of MapFactory
     boolean isImmutableMapAvailable = isImmutableMapAvailable();
     // TODO(ronshapiro, gak): Use Maps.immutableEnumMap() if it's available?
@@ -87,9 +106,7 @@
               .add(maybeTypeParameters(requestingClass))
               .add(
                   "of($L)",
-                  dependencies
-                      .keySet()
-                      .stream()
+                  dependencies.keySet().stream()
                       .map(dependency -> keyAndValueExpression(dependency, requestingClass))
                       .collect(toParametersCodeBlock()))
               .build());
@@ -104,10 +121,10 @@
                 "singletonMap($L)",
                 keyAndValueExpression(getOnlyElement(dependencies.keySet()), requestingClass)));
       default:
-        CodeBlock.Builder instantiation = CodeBlock.builder();
-        instantiation
-            .add("$T.", isImmutableMapAvailable ? ImmutableMap.class : MapBuilder.class)
-            .add(maybeTypeParameters(requestingClass));
+        CodeBlock.Builder instantiation =
+            CodeBlock.builder()
+                .add("$T.", isImmutableMapAvailable ? ImmutableMap.class : MapBuilder.class)
+                .add(maybeTypeParameters(requestingClass));
         if (isImmutableMapBuilderWithExpectedSizeAvailable()) {
           instantiation.add("builderWithExpectedSize($L)", dependencies.size());
         } else if (isImmutableMapAvailable) {
@@ -135,16 +152,12 @@
   private CodeBlock keyAndValueExpression(DependencyRequest dependency, ClassName requestingClass) {
     return CodeBlock.of(
         "$L, $L",
-        getMapKeyExpression(dependencies.get(dependency), requestingClass, processingEnv),
-        isExperimentalMergedMode
-            ? componentRequestRepresentations
-                .getExperimentalSwitchingProviderDependencyRepresentation(
-                    bindingRequest(dependency))
-                .getDependencyExpression(dependency.kind(), binding)
-                .codeBlock()
-            : componentRequestRepresentations
-                .getDependencyExpression(bindingRequest(dependency), requestingClass)
-                .codeBlock());
+        useLazyClassKey
+            ? lazyClassKeyProviders.getMapKeyExpression(dependency.key())
+            : getMapKeyExpression(dependencies.get(dependency), requestingClass, processingEnv),
+        componentRequestRepresentations
+            .getDependencyExpression(bindingRequest(dependency), requestingClass)
+            .codeBlock());
   }
 
   private Expression collectionsStaticFactoryInvocation(
@@ -163,7 +176,9 @@
     MapType mapType = MapType.from(binding.key());
     return isTypeAccessibleFrom(bindingKeyType, requestingClass.packageName())
         ? CodeBlock.of(
-            "<$T, $T>", mapType.keyType().getTypeName(), mapType.valueType().getTypeName())
+            "<$T, $T>",
+            useLazyClassKey ? TypeNames.STRING : mapType.keyType().getTypeName(),
+            mapType.valueType().getTypeName())
         : CodeBlock.of("");
   }
 
diff --git a/java/dagger/internal/codegen/writing/MembersInjectionMethods.java b/java/dagger/internal/codegen/writing/MembersInjectionMethods.java
index bac7490..a00e367 100644
--- a/java/dagger/internal/codegen/writing/MembersInjectionMethods.java
+++ b/java/dagger/internal/codegen/writing/MembersInjectionMethods.java
@@ -16,15 +16,12 @@
 
 package dagger.internal.codegen.writing;
 
-import static com.google.common.base.Preconditions.checkState;
 import static com.squareup.javapoet.MethodSpec.methodBuilder;
 import static dagger.internal.codegen.base.Util.reentrantComputeIfAbsent;
-import static dagger.internal.codegen.binding.BindingRequest.bindingRequest;
 import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
 import static dagger.internal.codegen.writing.ComponentImplementation.MethodSpecKind.MEMBERS_INJECTION_METHOD;
 import static dagger.internal.codegen.xprocessing.XElements.getSimpleName;
 import static javax.lang.model.element.Modifier.PRIVATE;
-import static javax.lang.model.element.Modifier.STATIC;
 
 import androidx.room.compiler.processing.XProcessingEnv;
 import androidx.room.compiler.processing.XType;
@@ -52,7 +49,6 @@
 @PerComponentImplementation
 final class MembersInjectionMethods {
   private final Map<Key, Expression> injectMethodExpressions = new LinkedHashMap<>();
-  private final Map<Key, Expression> experimentalInjectMethodExpressions = new LinkedHashMap<>();
   private final ComponentImplementation componentImplementation;
   private final ComponentRequestRepresentations bindingExpressions;
   private final BindingGraph graph;
@@ -81,7 +77,7 @@
             : graph.localContributionBinding(key).get();
     Expression expression =
         reentrantComputeIfAbsent(
-            injectMethodExpressions, key, k -> injectMethodExpression(binding, false));
+            injectMethodExpressions, key, k -> injectMethodExpression(binding));
     ShardImplementation shardImplementation = componentImplementation.shardImplementation(binding);
     return Expression.create(
         expression.type(),
@@ -94,32 +90,11 @@
                 instance));
   }
 
-  /**
-   * Returns the members injection {@link Expression} for the given {@link Key}, creating it if
-   * necessary.
-   */
-  Expression getInjectExpressionExperimental(
-      ProvisionBinding provisionBinding, CodeBlock instance, ClassName requestingClass) {
-    checkState(
-        componentImplementation.compilerMode().isExperimentalMergedMode(),
-        "Compiler mode should be experimentalMergedMode!");
-    Expression expression =
-        reentrantComputeIfAbsent(
-            experimentalInjectMethodExpressions,
-            provisionBinding.key(),
-            k -> injectMethodExpression(provisionBinding, true));
-    return Expression.create(
-        expression.type(), CodeBlock.of("$L($L, dependencies)", expression.codeBlock(), instance));
-  }
-
-  private Expression injectMethodExpression(Binding binding, boolean useStaticInjectionMethod) {
+  private Expression injectMethodExpression(Binding binding) {
     // TODO(wanyingd): move Switching Providers and injection methods to Shard classes to avoid
     // exceeding component class constant pool limit.
     // Add to Component Shard so that is can be accessible from Switching Providers.
-    ShardImplementation shardImplementation =
-        useStaticInjectionMethod
-            ? componentImplementation.getComponentShard()
-            : componentImplementation.shardImplementation(binding);
+    ShardImplementation shardImplementation = componentImplementation.shardImplementation(binding);
     XType keyType = binding.key().type().xprocessing();
     XType membersInjectedType =
         isTypeAccessibleFrom(keyType, shardImplementation.name().packageName())
@@ -132,16 +107,10 @@
     ParameterSpec parameter =
         ParameterSpec.builder(membersInjectedType.getTypeName(), "instance").build();
     MethodSpec.Builder methodBuilder =
-        useStaticInjectionMethod
-            ? methodBuilder(methodName)
-                .addModifiers(PRIVATE, STATIC)
-                .returns(membersInjectedType.getTypeName())
-                .addParameter(parameter)
-                .addParameter(Object[].class, "dependencies")
-            : methodBuilder(methodName)
-                .addModifiers(PRIVATE)
-                .returns(membersInjectedType.getTypeName())
-                .addParameter(parameter);
+        methodBuilder(methodName)
+            .addModifiers(PRIVATE)
+            .returns(membersInjectedType.getTypeName())
+            .addParameter(parameter);
     XTypeElement canIgnoreReturnValue =
         processingEnv.findTypeElement("com.google.errorprone.annotations.CanIgnoreReturnValue");
     if (canIgnoreReturnValue != null) {
@@ -155,23 +124,14 @@
             instance,
             membersInjectedType,
             request ->
-                (useStaticInjectionMethod
-                        ? bindingExpressions
-                            .getExperimentalSwitchingProviderDependencyRepresentation(
-                                bindingRequest(request))
-                            .getDependencyExpression(request.kind(), (ProvisionBinding) binding)
-                        : bindingExpressions.getDependencyArgumentExpression(
-                            request, shardImplementation.name()))
+                bindingExpressions
+                    .getDependencyArgumentExpression(request, shardImplementation.name())
                     .codeBlock()));
     methodBuilder.addStatement("return $L", instance);
 
     MethodSpec method = methodBuilder.build();
     shardImplementation.addMethod(MEMBERS_INJECTION_METHOD, method);
-    return Expression.create(
-        membersInjectedType,
-        useStaticInjectionMethod
-            ? CodeBlock.of("$T.$N", shardImplementation.name(), method)
-            : CodeBlock.of("$N", method));
+    return Expression.create(membersInjectedType, CodeBlock.of("$N", method));
   }
 
   private static ImmutableSet<InjectionSite> injectionSites(Binding binding) {
diff --git a/java/dagger/internal/codegen/writing/MembersInjectionRequestRepresentation.java b/java/dagger/internal/codegen/writing/MembersInjectionRequestRepresentation.java
index 79b8802..f8f31a3 100644
--- a/java/dagger/internal/codegen/writing/MembersInjectionRequestRepresentation.java
+++ b/java/dagger/internal/codegen/writing/MembersInjectionRequestRepresentation.java
@@ -17,7 +17,6 @@
 package dagger.internal.codegen.writing;
 
 import static com.google.common.collect.Iterables.getOnlyElement;
-import static dagger.internal.codegen.xprocessing.XElements.getSimpleName;
 
 import androidx.room.compiler.processing.XExecutableParameterElement;
 import androidx.room.compiler.processing.XMethodElement;
@@ -56,7 +55,7 @@
     XMethodElement methodElement = componentMethod.methodElement();
     XExecutableParameterElement parameter = getOnlyElement(methodElement.getParameters());
     return membersInjectionMethods.getInjectExpression(
-        binding.key(), CodeBlock.of("$L", getSimpleName(parameter)), component.name());
+        binding.key(), CodeBlock.of("$L", parameter.getJvmName()), component.name());
   }
 
   // TODO(bcorso): Consider making this a method on all RequestRepresentations.
diff --git a/java/dagger/internal/codegen/writing/MembersInjectorGenerator.java b/java/dagger/internal/codegen/writing/MembersInjectorGenerator.java
index 82d12dd..36a9915 100644
--- a/java/dagger/internal/codegen/writing/MembersInjectorGenerator.java
+++ b/java/dagger/internal/codegen/writing/MembersInjectorGenerator.java
@@ -20,8 +20,6 @@
 import static com.squareup.javapoet.MethodSpec.constructorBuilder;
 import static com.squareup.javapoet.MethodSpec.methodBuilder;
 import static com.squareup.javapoet.TypeSpec.classBuilder;
-import static dagger.internal.codegen.binding.AssistedInjectionAnnotations.assistedInjectedConstructors;
-import static dagger.internal.codegen.binding.InjectionAnnotations.injectedConstructors;
 import static dagger.internal.codegen.binding.SourceFiles.bindingTypeElementTypeVariableNames;
 import static dagger.internal.codegen.binding.SourceFiles.generateBindingFieldsForDependencies;
 import static dagger.internal.codegen.binding.SourceFiles.membersInjectorNameForType;
@@ -90,19 +88,6 @@
 
   @Override
   public ImmutableList<TypeSpec.Builder> topLevelTypes(MembersInjectionBinding binding) {
-    // Empty members injection bindings are special and don't need source files.
-    if (binding.injectionSites().isEmpty()) {
-      return ImmutableList.of();
-    }
-
-    // Members injectors for classes with no local injection sites and no @Inject
-    // constructor are unused.
-    if (!binding.hasLocalInjectionSites()
-        && injectedConstructors(binding.membersInjectedType()).isEmpty()
-        && assistedInjectedConstructors(binding.membersInjectedType()).isEmpty()) {
-      return ImmutableList.of();
-    }
-
 
     // We don't want to write out resolved bindings -- we want to write out the generic version.
     checkState(
@@ -162,7 +147,9 @@
               dependency.key().type().xprocessing(), generatedTypeName.packageName());
 
       String fieldName = fieldNames.getUniqueName(bindingField.name());
-      TypeName fieldType = useRawFrameworkType ? bindingField.type().rawType : bindingField.type();
+      TypeName fieldType = useRawFrameworkType
+          ? TypeNames.rawTypeName(bindingField.type())
+          : bindingField.type();
       FieldSpec.Builder fieldBuilder = FieldSpec.builder(fieldType, fieldName, PRIVATE, FINAL);
       ParameterSpec.Builder parameterBuilder = ParameterSpec.builder(fieldType, fieldName);
 
diff --git a/java/dagger/internal/codegen/writing/OptionalFactories.java b/java/dagger/internal/codegen/writing/OptionalFactories.java
index deb9dbf..3c327e8 100644
--- a/java/dagger/internal/codegen/writing/OptionalFactories.java
+++ b/java/dagger/internal/codegen/writing/OptionalFactories.java
@@ -28,8 +28,8 @@
 import static dagger.internal.codegen.javapoet.AnnotationSpecs.Suppression.RAWTYPES;
 import static dagger.internal.codegen.javapoet.AnnotationSpecs.Suppression.UNCHECKED;
 import static dagger.internal.codegen.javapoet.TypeNames.abstractProducerOf;
+import static dagger.internal.codegen.javapoet.TypeNames.daggerProviderOf;
 import static dagger.internal.codegen.javapoet.TypeNames.listenableFutureOf;
-import static dagger.internal.codegen.javapoet.TypeNames.providerOf;
 import static dagger.internal.codegen.writing.ComponentImplementation.FieldSpecKind.ABSENT_OPTIONAL_FIELD;
 import static dagger.internal.codegen.writing.ComponentImplementation.MethodSpecKind.ABSENT_OPTIONAL_METHOD;
 import static dagger.internal.codegen.writing.ComponentImplementation.TypeSpecKind.PRESENT_FACTORY;
@@ -62,15 +62,12 @@
 import dagger.internal.codegen.javapoet.AnnotationSpecs;
 import dagger.internal.codegen.javapoet.TypeNames;
 import dagger.internal.codegen.model.RequestKind;
-import dagger.producers.Producer;
-import dagger.producers.internal.Producers;
 import java.util.Comparator;
 import java.util.Map;
 import java.util.Optional;
 import java.util.TreeMap;
 import java.util.concurrent.Executor;
 import javax.inject.Inject;
-import javax.inject.Provider;
 
 /** The nested class and static methods required by the component to implement optional bindings. */
 // TODO(dpb): Name members simply if a component uses only one of Guava or JDK Optional.
@@ -150,15 +147,15 @@
                 "absent%sProvider", UPPER_UNDERSCORE.to(UPPER_CAMEL, optionalKind.name())))
         .addModifiers(PRIVATE, STATIC)
         .addTypeVariable(typeVariable)
-        .returns(providerOf(optionalKind.of(typeVariable)))
+        .returns(daggerProviderOf(optionalKind.of(typeVariable)))
         .addJavadoc(
             "Returns a {@link $T} that returns {@code $L}.",
-            TypeNames.PROVIDER,
+            TypeNames.DAGGER_PROVIDER,
             optionalKind.absentValueExpression())
         .addCode("$L // safe covariant cast\n", AnnotationSpecs.suppressWarnings(UNCHECKED))
         .addStatement(
             "$1T provider = ($1T) $2N",
-            providerOf(optionalKind.of(typeVariable)),
+            daggerProviderOf(optionalKind.of(typeVariable)),
             perGeneratedFileCache.absentOptionalProviderFields.computeIfAbsent(
                 optionalKind,
                 kind -> {
@@ -176,7 +173,7 @@
    */
   private FieldSpec absentOptionalProviderField(OptionalKind optionalKind) {
     return FieldSpec.builder(
-            TypeNames.PROVIDER,
+            TypeNames.DAGGER_PROVIDER,
             String.format("ABSENT_%s_PROVIDER", optionalKind.name()),
             PRIVATE,
             STATIC,
@@ -185,7 +182,7 @@
         .initializer("$T.create($L)", InstanceFactory.class, optionalKind.absentValueExpression())
         .addJavadoc(
             "A {@link $T} that returns {@code $L}.",
-            TypeNames.PROVIDER,
+            TypeNames.DAGGER_PROVIDER,
             optionalKind.absentValueExpression())
         .build();
   }
@@ -193,7 +190,7 @@
   /** Information about the type of a factory for present bindings. */
   @AutoValue
   abstract static class PresentFactorySpec {
-    /** Whether the factory is a {@link Provider} or a {@link Producer}. */
+    /** Whether the factory is a {@code Provider} or a {@code Producer}. */
     abstract FrameworkType frameworkType();
 
     /** What kind of {@code Optional} is returned. */
@@ -302,7 +299,7 @@
    *       {@code Producer<Optional<Produced<T>>>}.
    * </ul>
    *
-   * @param delegateFactory an expression for a {@link Provider} or {@link Producer} of the
+   * @param delegateFactory an expression for a {@code Provider} or {@code Producer} of the
    *     underlying type
    */
   CodeBlock presentOptionalFactory(ContributionBinding binding, CodeBlock delegateFactory) {
@@ -415,7 +412,9 @@
                         spec.optionalKind(),
                         spec.valueType(),
                         CodeBlock.of(
-                            "$T.createFutureProduced($N.get())", Producers.class, delegateField)))
+                            "$T.createFutureProduced($N.get())",
+                            TypeNames.PRODUCERS,
+                            delegateField)))
                 .build();
 
           default:
diff --git a/java/dagger/internal/codegen/writing/OptionalRequestRepresentation.java b/java/dagger/internal/codegen/writing/OptionalRequestRepresentation.java
index b775314..8c92191 100644
--- a/java/dagger/internal/codegen/writing/OptionalRequestRepresentation.java
+++ b/java/dagger/internal/codegen/writing/OptionalRequestRepresentation.java
@@ -33,13 +33,13 @@
 import dagger.internal.codegen.binding.ProvisionBinding;
 import dagger.internal.codegen.javapoet.Expression;
 import dagger.internal.codegen.model.DependencyRequest;
+import dagger.internal.codegen.model.RequestKind;
 
 /** A binding expression for optional bindings. */
 final class OptionalRequestRepresentation extends RequestRepresentation {
   private final ProvisionBinding binding;
   private final ComponentRequestRepresentations componentRequestRepresentations;
   private final XProcessingEnv processingEnv;
-  private final boolean isExperimentalMergedMode;
 
   @AssistedInject
   OptionalRequestRepresentation(
@@ -50,8 +50,6 @@
     this.binding = binding;
     this.componentRequestRepresentations = componentRequestRepresentations;
     this.processingEnv = processingEnv;
-    this.isExperimentalMergedMode =
-        componentImplementation.compilerMode().isExperimentalMergedMode();
   }
 
   @Override
@@ -78,18 +76,15 @@
     DependencyRequest dependency = getOnlyElement(binding.dependencies());
 
     CodeBlock dependencyExpression =
-        isExperimentalMergedMode
-            ? componentRequestRepresentations
-                .getExperimentalSwitchingProviderDependencyRepresentation(
-                    bindingRequest(dependency))
-                .getDependencyExpression(dependency.kind(), binding)
-                .codeBlock()
-            : componentRequestRepresentations
-                .getDependencyExpression(bindingRequest(dependency), requestingClass)
-                .codeBlock();
+        componentRequestRepresentations
+            .getDependencyExpression(bindingRequest(dependency), requestingClass)
+            .codeBlock();
 
-    return isTypeAccessibleFrom(
-            dependency.key().type().xprocessing(), requestingClass.packageName())
+    boolean needsObjectExpression = !isTypeAccessibleFrom(
+        dependency.key().type().xprocessing(), requestingClass.packageName())
+        || (isPreJava8SourceVersion(processingEnv) && dependency.kind() == RequestKind.PROVIDER);
+
+    return !needsObjectExpression
         ? Expression.create(
             binding.key().type().xprocessing(),
             optionalKind.presentExpression(dependencyExpression))
diff --git a/java/dagger/internal/codegen/writing/ProducerEntryPointView.java b/java/dagger/internal/codegen/writing/ProducerEntryPointView.java
index 648e253..34d5458 100644
--- a/java/dagger/internal/codegen/writing/ProducerEntryPointView.java
+++ b/java/dagger/internal/codegen/writing/ProducerEntryPointView.java
@@ -31,14 +31,11 @@
 import dagger.internal.codegen.javapoet.TypeNames;
 import dagger.internal.codegen.model.RequestKind;
 import dagger.internal.codegen.writing.ComponentImplementation.ShardImplementation;
-import dagger.producers.Producer;
-import dagger.producers.internal.CancellationListener;
-import dagger.producers.internal.Producers;
 import java.util.Optional;
 
 /**
- * A factory of {@linkplain Producers#entryPointViewOf(Producer, CancellationListener) entry point
- * views} of {@link Producer}s.
+ * A factory of {@code Producers#entryPointViewOf(Producer, CancellationListener)} of
+ * {@code Producer}s.
  */
 final class ProducerEntryPointView {
   private final ShardImplementation shardImplementation;
@@ -50,9 +47,8 @@
   }
 
   /**
-   * Returns an expression for an {@linkplain Producers#entryPointViewOf(Producer,
-   * CancellationListener) entry point view} of a producer if the component method returns a {@link
-   * Producer} or {@link com.google.common.util.concurrent.ListenableFuture}.
+   * Returns an expression for an {@code Producers#entryPointViewOf(Producer, CancellationListener)}
+   * of a producer if the component method returns a {@code Producer} or {@code ListenableFuture}.
    *
    * <p>This is intended to be a replacement implementation for {@link
    * dagger.internal.codegen.writing.RequestRepresentation#getDependencyExpressionForComponentMethod(ComponentMethodDescriptor,
@@ -97,7 +93,7 @@
         CodeBlock.of(
             "this.$N = $T.entryPointViewOf($L, $L);",
             field,
-            Producers.class,
+            TypeNames.PRODUCERS,
             producerExpression.getDependencyExpression(shardImplementation.name()).codeBlock(),
             // Always pass in the componentShard reference here rather than the owning shard for
             // this key because this needs to be the root CancellationListener.
diff --git a/java/dagger/internal/codegen/writing/ProducerFactoryGenerator.java b/java/dagger/internal/codegen/writing/ProducerFactoryGenerator.java
index e6c88a9..1d8ab02 100644
--- a/java/dagger/internal/codegen/writing/ProducerFactoryGenerator.java
+++ b/java/dagger/internal/codegen/writing/ProducerFactoryGenerator.java
@@ -77,16 +77,13 @@
 import dagger.internal.codegen.model.DependencyRequest;
 import dagger.internal.codegen.model.Key;
 import dagger.internal.codegen.model.RequestKind;
-import dagger.producers.Producer;
-import dagger.producers.internal.AbstractProducesMethodProducer;
-import dagger.producers.internal.Producers;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map.Entry;
 import java.util.Optional;
 import javax.inject.Inject;
 
-/** Generates {@link Producer} implementations from {@link ProductionBinding} instances. */
+/** Generates {@code Producer} implementations from {@link ProductionBinding} instances. */
 public final class ProducerFactoryGenerator extends SourceFileGenerator<ProductionBinding> {
   private final CompilerOptions compilerOptions;
   private final KeyFactory keyFactory;
@@ -163,7 +160,7 @@
             addFieldAndConstructorParameter(
                 factoryBuilder, constructorBuilder, fieldName, bindingField.type());
         fieldsBuilder.put(dependency, field);
-        frameworkFieldAssignments.add(fieldAssignment(field, bindingField.type()));
+        frameworkFieldAssignments.add(fieldAssignment(field, bindingField));
       }
     }
     ImmutableMap<DependencyRequest, FieldSpec> fields = fieldsBuilder.build();
@@ -219,7 +216,7 @@
     factoryBuilder
         .superclass(
             ParameterizedTypeName.get(
-                ClassName.get(AbstractProducesMethodProducer.class),
+                TypeNames.ABSTRACT_PRODUCES_METHOD_PRODUCER,
                 futureTransform.applyArgType(),
                 providedTypeName))
         .addMethod(constructor)
@@ -260,11 +257,12 @@
     return field;
   }
 
-  private static CodeBlock fieldAssignment(FieldSpec field, ParameterizedTypeName type) {
+  private static CodeBlock fieldAssignment(FieldSpec field, FrameworkField frameworkField) {
     CodeBlock.Builder statement = CodeBlock.builder();
-    if (type != null && type.rawType.equals(TypeNames.PRODUCER)) {
+    if (frameworkField.type() != null
+        && TypeNames.rawTypeName(frameworkField.type()).equals(TypeNames.PRODUCER)) {
       statement.addStatement(
-          "this.$1N = $2T.nonCancellationPropagatingViewOf($1N)", field, Producers.class);
+          "this.$1N = $2T.nonCancellationPropagatingViewOf($1N)", field, TypeNames.PRODUCERS);
     } else {
       statement.addStatement("this.$1N = $1N", field);
     }
@@ -275,7 +273,7 @@
       MethodSpec.Builder constructorBuilder, FieldSpec field, ParameterizedTypeName type) {
     if (type != null && type.rawType.equals(TypeNames.PRODUCER)) {
       constructorBuilder.addStatement(
-          "this.$1N = $2T.nonCancellationPropagatingViewOf($1N)", field, Producers.class);
+          "this.$1N = $2T.nonCancellationPropagatingViewOf($1N)", field, TypeNames.PRODUCERS);
     } else {
       constructorBuilder.addStatement("this.$1N = $1N", field);
     }
diff --git a/java/dagger/internal/codegen/writing/ProducerFromProviderCreationExpression.java b/java/dagger/internal/codegen/writing/ProducerFromProviderCreationExpression.java
index 05dd50b..9d08956 100644
--- a/java/dagger/internal/codegen/writing/ProducerFromProviderCreationExpression.java
+++ b/java/dagger/internal/codegen/writing/ProducerFromProviderCreationExpression.java
@@ -26,10 +26,9 @@
 import dagger.internal.codegen.javapoet.TypeNames;
 import dagger.internal.codegen.model.RequestKind;
 import dagger.internal.codegen.writing.FrameworkFieldInitializer.FrameworkInstanceCreationExpression;
-import dagger.producers.Producer;
 import java.util.Optional;
 
-/** An {@link Producer} creation expression for provision bindings. */
+/** An {@code Producer} creation expression for provision bindings. */
 final class ProducerFromProviderCreationExpression implements FrameworkInstanceCreationExpression {
   private final RequestRepresentation providerRequestRepresentation;
   private final ClassName requestingClass;
diff --git a/java/dagger/internal/codegen/writing/ProducerNodeInstanceRequestRepresentation.java b/java/dagger/internal/codegen/writing/ProducerNodeInstanceRequestRepresentation.java
index 813010c..cdcc389 100644
--- a/java/dagger/internal/codegen/writing/ProducerNodeInstanceRequestRepresentation.java
+++ b/java/dagger/internal/codegen/writing/ProducerNodeInstanceRequestRepresentation.java
@@ -26,9 +26,9 @@
 import dagger.internal.codegen.binding.ContributionBinding;
 import dagger.internal.codegen.binding.FrameworkType;
 import dagger.internal.codegen.javapoet.Expression;
+import dagger.internal.codegen.javapoet.TypeNames;
 import dagger.internal.codegen.model.Key;
 import dagger.internal.codegen.writing.ComponentImplementation.ShardImplementation;
-import dagger.producers.internal.Producers;
 
 /** Binding expression for producer node instances. */
 final class ProducerNodeInstanceRequestRepresentation
@@ -61,7 +61,7 @@
         key,
         CodeBlock.of(
             "$T.cancel($L, $N);",
-            Producers.class,
+            TypeNames.PRODUCERS,
             result.codeBlock(),
             ComponentImplementation.MAY_INTERRUPT_IF_RUNNING_PARAM));
     return result;
diff --git a/java/dagger/internal/codegen/writing/ProviderInstanceRequestRepresentation.java b/java/dagger/internal/codegen/writing/ProviderInstanceRequestRepresentation.java
index 9bd8f3d..f031a72 100644
--- a/java/dagger/internal/codegen/writing/ProviderInstanceRequestRepresentation.java
+++ b/java/dagger/internal/codegen/writing/ProviderInstanceRequestRepresentation.java
@@ -20,18 +20,29 @@
 import dagger.assisted.Assisted;
 import dagger.assisted.AssistedFactory;
 import dagger.assisted.AssistedInject;
-import dagger.internal.codegen.binding.ContributionBinding;
 import dagger.internal.codegen.binding.FrameworkType;
+import dagger.internal.codegen.binding.ProvisionBinding;
 
 /** Binding expression for provider instances. */
 final class ProviderInstanceRequestRepresentation extends FrameworkInstanceRequestRepresentation {
 
   @AssistedInject
   ProviderInstanceRequestRepresentation(
-      @Assisted ContributionBinding binding,
-      @Assisted FrameworkInstanceSupplier frameworkInstanceSupplier,
+      @Assisted ProvisionBinding binding,
+      SwitchingProviderInstanceSupplier.Factory switchingProviderInstanceSupplierFactory,
+      StaticFactoryInstanceSupplier.Factory staticFactoryInstanceSupplierFactory,
+      ProviderInstanceSupplier.Factory providerInstanceSupplierFactory,
+      ComponentImplementation componentImplementation,
       XProcessingEnv processingEnv) {
-    super(binding, frameworkInstanceSupplier, processingEnv);
+    super(
+        binding,
+        frameworkInstanceSupplier(
+            binding,
+            switchingProviderInstanceSupplierFactory,
+            staticFactoryInstanceSupplierFactory,
+            providerInstanceSupplierFactory,
+            componentImplementation),
+        processingEnv);
   }
 
   @Override
@@ -39,9 +50,27 @@
     return FrameworkType.PROVIDER;
   }
 
+  private static FrameworkInstanceSupplier frameworkInstanceSupplier(
+      ProvisionBinding binding,
+      SwitchingProviderInstanceSupplier.Factory switchingProviderInstanceSupplierFactory,
+      StaticFactoryInstanceSupplier.Factory staticFactoryInstanceSupplierFactory,
+      ProviderInstanceSupplier.Factory providerInstanceSupplierFactory,
+      ComponentImplementation componentImplementation) {
+    FrameworkInstanceKind frameworkInstanceKind =
+        FrameworkInstanceKind.from(binding, componentImplementation.compilerMode());
+    switch (frameworkInstanceKind) {
+      case SWITCHING_PROVIDER:
+        return switchingProviderInstanceSupplierFactory.create(binding);
+      case STATIC_FACTORY:
+        return staticFactoryInstanceSupplierFactory.create(binding);
+      case PROVIDER_FIELD:
+        return providerInstanceSupplierFactory.create(binding);
+    }
+    throw new AssertionError("Unexpected FrameworkInstanceKind: " + frameworkInstanceKind);
+  }
+
   @AssistedFactory
   static interface Factory {
-    ProviderInstanceRequestRepresentation create(
-        ContributionBinding binding, FrameworkInstanceSupplier frameworkInstanceSupplier);
+    ProviderInstanceRequestRepresentation create(ProvisionBinding binding);
   }
 }
diff --git a/java/dagger/internal/codegen/writing/ProvisionBindingRepresentation.java b/java/dagger/internal/codegen/writing/ProvisionBindingRepresentation.java
index 4ae7f37..0f9b6f3 100644
--- a/java/dagger/internal/codegen/writing/ProvisionBindingRepresentation.java
+++ b/java/dagger/internal/codegen/writing/ProvisionBindingRepresentation.java
@@ -25,7 +25,6 @@
 import dagger.internal.codegen.binding.BindingGraph;
 import dagger.internal.codegen.binding.BindingRequest;
 import dagger.internal.codegen.binding.ProvisionBinding;
-import dagger.internal.codegen.compileroption.CompilerOptions;
 import dagger.internal.codegen.model.RequestKind;
 import dagger.internal.codegen.writing.ComponentImplementation.CompilerMode;
 
@@ -43,34 +42,17 @@
   @AssistedInject
   ProvisionBindingRepresentation(
       @Assisted ProvisionBinding binding,
-      BindingGraph graph,
-      ComponentImplementation componentImplementation,
       DirectInstanceBindingRepresentation.Factory directInstanceBindingRepresentationFactory,
       FrameworkInstanceBindingRepresentation.Factory frameworkInstanceBindingRepresentationFactory,
-      SwitchingProviderInstanceSupplier.Factory switchingProviderInstanceSupplierFactory,
-      ProviderInstanceSupplier.Factory providerInstanceSupplierFactory,
-      StaticFactoryInstanceSupplier.Factory staticFactoryInstanceSupplierFactory,
-      CompilerOptions compilerOptions) {
+      BindingGraph graph,
+      ComponentImplementation componentImplementation) {
     this.binding = binding;
     this.graph = graph;
     this.compilerMode = componentImplementation.compilerMode();
     this.directInstanceBindingRepresentation =
         directInstanceBindingRepresentationFactory.create(binding);
-    FrameworkInstanceSupplier frameworkInstanceSupplier = null;
-    switch (FrameworkInstanceKind.from(binding, compilerMode)) {
-      case SWITCHING_PROVIDER:
-      case EXPERIMENTAL_SWITCHING_PROVIDER:
-        frameworkInstanceSupplier = switchingProviderInstanceSupplierFactory.create(binding);
-        break;
-      case STATIC_FACTORY:
-        frameworkInstanceSupplier = staticFactoryInstanceSupplierFactory.create(binding);
-        break;
-      case PROVIDER_FIELD:
-        frameworkInstanceSupplier = providerInstanceSupplierFactory.create(binding);
-        break;
-    }
     this.frameworkInstanceBindingRepresentation =
-        frameworkInstanceBindingRepresentationFactory.create(binding, frameworkInstanceSupplier);
+        frameworkInstanceBindingRepresentationFactory.create(binding);
   }
 
   @Override
@@ -81,9 +63,6 @@
   }
 
   private boolean usesDirectInstanceExpression(RequestKind requestKind) {
-    if (compilerMode.isExperimentalMergedMode()) {
-      return false;
-    }
     if (requestKind != RequestKind.INSTANCE && requestKind != RequestKind.FUTURE) {
       return false;
     }
diff --git a/java/dagger/internal/codegen/writing/SetRequestRepresentation.java b/java/dagger/internal/codegen/writing/SetRequestRepresentation.java
index f5d77ad..68a340a 100644
--- a/java/dagger/internal/codegen/writing/SetRequestRepresentation.java
+++ b/java/dagger/internal/codegen/writing/SetRequestRepresentation.java
@@ -47,7 +47,6 @@
   private final BindingGraph graph;
   private final ComponentRequestRepresentations componentRequestRepresentations;
   private final XProcessingEnv processingEnv;
-  private final boolean isExperimentalMergedMode;
 
   @AssistedInject
   SetRequestRepresentation(
@@ -60,8 +59,6 @@
     this.graph = graph;
     this.componentRequestRepresentations = componentRequestRepresentations;
     this.processingEnv = processingEnv;
-    this.isExperimentalMergedMode =
-        componentImplementation.compilerMode().isExperimentalMergedMode();
   }
 
   @Override
@@ -139,14 +136,7 @@
       DependencyRequest dependency, ClassName requestingClass) {
     RequestRepresentation bindingExpression =
         componentRequestRepresentations.getRequestRepresentation(bindingRequest(dependency));
-    CodeBlock expression =
-        isExperimentalMergedMode
-            ? componentRequestRepresentations
-                .getExperimentalSwitchingProviderDependencyRepresentation(
-                    bindingRequest(dependency))
-                .getDependencyExpression(dependency.kind(), binding)
-                .codeBlock()
-            : bindingExpression.getDependencyExpression(requestingClass).codeBlock();
+    CodeBlock expression = bindingExpression.getDependencyExpression(requestingClass).codeBlock();
 
     // TODO(b/211774331): Type casting should be Set after contributions to Set multibinding are
     // limited to be Set.
diff --git a/java/dagger/internal/codegen/writing/SimpleMethodRequestRepresentation.java b/java/dagger/internal/codegen/writing/SimpleMethodRequestRepresentation.java
index 4026f16..79613fd 100644
--- a/java/dagger/internal/codegen/writing/SimpleMethodRequestRepresentation.java
+++ b/java/dagger/internal/codegen/writing/SimpleMethodRequestRepresentation.java
@@ -19,7 +19,6 @@
 import static androidx.room.compiler.processing.XElementKt.isConstructor;
 import static androidx.room.compiler.processing.XElementKt.isMethod;
 import static com.google.common.base.Preconditions.checkArgument;
-import static dagger.internal.codegen.binding.BindingRequest.bindingRequest;
 import static dagger.internal.codegen.javapoet.CodeBlocks.makeParametersCodeBlock;
 import static dagger.internal.codegen.javapoet.TypeNames.rawTypeName;
 import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
@@ -58,7 +57,6 @@
   private final MembersInjectionMethods membersInjectionMethods;
   private final ComponentRequirementExpressions componentRequirementExpressions;
   private final ShardImplementation shardImplementation;
-  private final boolean isExperimentalMergedMode;
 
   @AssistedInject
   SimpleMethodRequestRepresentation(
@@ -80,8 +78,6 @@
     this.membersInjectionMethods = membersInjectionMethods;
     this.componentRequirementExpressions = componentRequirementExpressions;
     this.shardImplementation = componentImplementation.shardImplementation(binding);
-    this.isExperimentalMergedMode =
-        componentImplementation.compilerMode().isExperimentalMergedMode();
   }
 
   @Override
@@ -146,12 +142,8 @@
   }
 
   private Expression dependencyArgument(DependencyRequest dependency, ClassName requestingClass) {
-    return isExperimentalMergedMode
-        ? componentRequestRepresentations
-            .getExperimentalSwitchingProviderDependencyRepresentation(bindingRequest(dependency))
-            .getDependencyExpression(dependency.kind(), provisionBinding)
-        : componentRequestRepresentations.getDependencyArgumentExpression(
-            dependency, requestingClass);
+    return componentRequestRepresentations.getDependencyArgumentExpression(
+        dependency, requestingClass);
   }
 
   private Expression injectMembers(CodeBlock instance, ClassName requestingClass) {
@@ -167,11 +159,8 @@
         instance = CodeBlock.of("($T) ($T) $L", keyType, rawTypeName(keyType), instance);
       }
     }
-    return isExperimentalMergedMode
-        ? membersInjectionMethods.getInjectExpressionExperimental(
-            provisionBinding, instance, requestingClass)
-        : membersInjectionMethods.getInjectExpression(
-            provisionBinding.key(), instance, requestingClass);
+    return membersInjectionMethods.getInjectExpression(
+        provisionBinding.key(), instance, requestingClass);
   }
 
   private Optional<CodeBlock> moduleReference(ClassName requestingClass) {
@@ -180,11 +169,7 @@
             .contributingModule()
             .map(XTypeElement::getType)
             .map(ComponentRequirement::forModule)
-            .map(
-                module ->
-                    isExperimentalMergedMode
-                        ? CodeBlock.of("(($T) dependencies[0])", module.type().getTypeName())
-                        : componentRequirementExpressions.getExpression(module, requestingClass))
+            .map(module -> componentRequirementExpressions.getExpression(module, requestingClass))
         : Optional.empty();
   }
 
diff --git a/java/dagger/internal/codegen/writing/StaticMemberSelects.java b/java/dagger/internal/codegen/writing/StaticMemberSelects.java
index 3fea617..a1ea63c 100644
--- a/java/dagger/internal/codegen/writing/StaticMemberSelects.java
+++ b/java/dagger/internal/codegen/writing/StaticMemberSelects.java
@@ -22,11 +22,11 @@
 import static dagger.internal.codegen.binding.SourceFiles.generatedClassNameForBinding;
 import static dagger.internal.codegen.binding.SourceFiles.setFactoryClassName;
 import static dagger.internal.codegen.javapoet.CodeBlocks.toParametersCodeBlock;
+import static dagger.internal.codegen.javapoet.TypeNames.DAGGER_PROVIDER;
 import static dagger.internal.codegen.javapoet.TypeNames.FACTORY;
 import static dagger.internal.codegen.javapoet.TypeNames.MAP_FACTORY;
 import static dagger.internal.codegen.javapoet.TypeNames.PRODUCER;
 import static dagger.internal.codegen.javapoet.TypeNames.PRODUCERS;
-import static dagger.internal.codegen.javapoet.TypeNames.PROVIDER;
 import static dagger.internal.codegen.langmodel.Accessibility.isTypeAccessibleFrom;
 import static dagger.internal.codegen.xprocessing.XTypes.isDeclared;
 
@@ -52,7 +52,7 @@
         ? new ParameterizedStaticMethod(
             PRODUCERS, typeParameters, CodeBlock.of("emptyMapProducer()"), PRODUCER)
         : new ParameterizedStaticMethod(
-            MAP_FACTORY, typeParameters, CodeBlock.of("emptyMapProvider()"), PROVIDER);
+            MAP_FACTORY, typeParameters, CodeBlock.of("emptyMapProvider()"), DAGGER_PROVIDER);
   }
 
   /**
diff --git a/java/dagger/internal/codegen/writing/SubcomponentCreatorRequestRepresentation.java b/java/dagger/internal/codegen/writing/SubcomponentCreatorRequestRepresentation.java
index eeadabe..c71c70a 100644
--- a/java/dagger/internal/codegen/writing/SubcomponentCreatorRequestRepresentation.java
+++ b/java/dagger/internal/codegen/writing/SubcomponentCreatorRequestRepresentation.java
@@ -20,29 +20,23 @@
 
 import com.squareup.javapoet.ClassName;
 import com.squareup.javapoet.CodeBlock;
-import com.squareup.javapoet.FieldSpec;
 import dagger.assisted.Assisted;
 import dagger.assisted.AssistedFactory;
 import dagger.assisted.AssistedInject;
 import dagger.internal.codegen.binding.ContributionBinding;
 import dagger.internal.codegen.javapoet.Expression;
 import dagger.internal.codegen.writing.ComponentImplementation.ShardImplementation;
-import java.util.ArrayList;
-import java.util.List;
 
 /** A binding expression for a subcomponent creator that just invokes the constructor. */
 final class SubcomponentCreatorRequestRepresentation extends RequestRepresentation {
   private final ShardImplementation shardImplementation;
   private final ContributionBinding binding;
-  private final boolean isExperimentalMergedMode;
 
   @AssistedInject
   SubcomponentCreatorRequestRepresentation(
       @Assisted ContributionBinding binding, ComponentImplementation componentImplementation) {
     this.binding = binding;
     this.shardImplementation = componentImplementation.shardImplementation(binding);
-    this.isExperimentalMergedMode =
-        componentImplementation.compilerMode().isExperimentalMergedMode();
   }
 
   @Override
@@ -51,20 +45,9 @@
         binding.key().type().xprocessing(),
         "new $T($L)",
         shardImplementation.getSubcomponentCreatorSimpleName(binding.key()),
-        isExperimentalMergedMode
-            ? getDependenciesExperimental()
-            : shardImplementation.componentFieldsByImplementation().values().stream()
-                .map(field -> CodeBlock.of("$N", field))
-                .collect(toParametersCodeBlock()));
-  }
-
-  private CodeBlock getDependenciesExperimental() {
-    List<CodeBlock> expressions = new ArrayList<>();
-    int index = 0;
-    for (FieldSpec field : shardImplementation.componentFieldsByImplementation().values()) {
-      expressions.add(CodeBlock.of("($T) dependencies[$L]", field.type, index++));
-    }
-    return expressions.stream().collect(toParametersCodeBlock());
+        shardImplementation.componentFieldsByImplementation().values().stream()
+            .map(field -> CodeBlock.of("$N", field))
+            .collect(toParametersCodeBlock()));
   }
 
   CodeBlock getDependencyExpressionArguments() {
diff --git a/java/dagger/internal/codegen/writing/SwitchingProviderInstanceSupplier.java b/java/dagger/internal/codegen/writing/SwitchingProviderInstanceSupplier.java
index 7bea206..6f8ca7b 100644
--- a/java/dagger/internal/codegen/writing/SwitchingProviderInstanceSupplier.java
+++ b/java/dagger/internal/codegen/writing/SwitchingProviderInstanceSupplier.java
@@ -46,11 +46,9 @@
           unscopedDirectInstanceRequestRepresentationFactory) {
     ShardImplementation shardImplementation = componentImplementation.shardImplementation(binding);
     FrameworkInstanceCreationExpression frameworkInstanceCreationExpression =
-        componentImplementation.compilerMode().isExperimentalMergedMode()
-            ? shardImplementation.getExperimentalSwitchingProviders()
-                .newFrameworkInstanceCreationExpression(
-                    binding, unscopedDirectInstanceRequestRepresentationFactory.create(binding))
-            : shardImplementation.getSwitchingProviders().newFrameworkInstanceCreationExpression(
+        shardImplementation
+            .getSwitchingProviders()
+            .newFrameworkInstanceCreationExpression(
                 binding, unscopedDirectInstanceRequestRepresentationFactory.create(binding));
     this.frameworkInstanceSupplier =
         new FrameworkFieldInitializer(
diff --git a/java/dagger/internal/codegen/writing/SwitchingProviders.java b/java/dagger/internal/codegen/writing/SwitchingProviders.java
index e6c3bbf..736f515 100644
--- a/java/dagger/internal/codegen/writing/SwitchingProviders.java
+++ b/java/dagger/internal/codegen/writing/SwitchingProviders.java
@@ -24,7 +24,7 @@
 import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
 import static dagger.internal.codegen.javapoet.AnnotationSpecs.Suppression.UNCHECKED;
 import static dagger.internal.codegen.javapoet.AnnotationSpecs.suppressWarnings;
-import static dagger.internal.codegen.javapoet.TypeNames.providerOf;
+import static dagger.internal.codegen.javapoet.TypeNames.daggerProviderOf;
 import static javax.lang.model.element.Modifier.FINAL;
 import static javax.lang.model.element.Modifier.PRIVATE;
 import static javax.lang.model.element.Modifier.PUBLIC;
@@ -172,7 +172,7 @@
           classBuilder(switchingProviderType)
               .addModifiers(PRIVATE, FINAL, STATIC)
               .addTypeVariable(T)
-              .addSuperinterface(providerOf(T))
+              .addSuperinterface(daggerProviderOf(T))
               .addMethods(getMethods());
 
       // The SwitchingProvider constructor lists all component parameters first and switch id last.
diff --git a/java/dagger/internal/codegen/xprocessing/BUILD b/java/dagger/internal/codegen/xprocessing/BUILD
index 262be17..da465e1 100644
--- a/java/dagger/internal/codegen/xprocessing/BUILD
+++ b/java/dagger/internal/codegen/xprocessing/BUILD
@@ -30,6 +30,7 @@
     deps = [
         ":xprocessing-lib",
         "//java/dagger/internal/codegen/extension",
+        "//java/dagger/spi",
         "//third_party/java/auto:common",
         "//third_party/java/guava/base",
         "//third_party/java/guava/collect",
diff --git a/java/dagger/internal/codegen/xprocessing/DaggerElements.java b/java/dagger/internal/codegen/xprocessing/DaggerElements.java
new file mode 100644
index 0000000..84daeb0
--- /dev/null
+++ b/java/dagger/internal/codegen/xprocessing/DaggerElements.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.internal.codegen.xprocessing;
+
+import androidx.room.compiler.processing.XElement;
+import androidx.room.compiler.processing.XProcessingEnv;
+import androidx.room.compiler.processing.XType;
+import androidx.room.compiler.processing.compat.XConverters;
+import com.google.devtools.ksp.symbol.KSClassDeclaration;
+import com.google.devtools.ksp.symbol.KSFunctionDeclaration;
+import com.google.devtools.ksp.symbol.KSPropertyDeclaration;
+import com.google.devtools.ksp.symbol.KSValueParameter;
+import dagger.spi.model.DaggerElement;
+import dagger.spi.model.DaggerProcessingEnv;
+import dagger.spi.model.DaggerType;
+
+/** Convert Dagger model types to XProcessing types. */
+public final class DaggerElements {
+  public static XElement toXProcessing(
+      DaggerElement element, DaggerProcessingEnv daggerProcessingEnv) {
+    XProcessingEnv processingEnv = toXProcessing(daggerProcessingEnv);
+    switch (element.backend()) {
+      case JAVAC:
+        return XConverters.toXProcessing(element.javac(), processingEnv);
+      case KSP:
+        if (element.ksp() instanceof KSFunctionDeclaration) {
+          return XConverters.toXProcessing((KSFunctionDeclaration) element.ksp(), processingEnv);
+        } else if (element.ksp() instanceof KSClassDeclaration) {
+          return XConverters.toXProcessing((KSClassDeclaration) element.ksp(), processingEnv);
+        } else if (element.ksp() instanceof KSValueParameter) {
+          return XConverters.toXProcessing((KSValueParameter) element.ksp(), processingEnv);
+        } else if (element.ksp() instanceof KSPropertyDeclaration) {
+          return XConverters.toXProcessing((KSPropertyDeclaration) element.ksp(), processingEnv);
+        }
+        throw new IllegalStateException(
+            String.format("Unsupported ksp declaration %s.", element.ksp()));
+    }
+    throw new IllegalStateException(
+        String.format("Backend %s not supported yet.", element.backend()));
+  }
+
+  public static XType toXProcessing(DaggerType type, DaggerProcessingEnv daggerProcessingEnv) {
+    XProcessingEnv processingEnv = toXProcessing(daggerProcessingEnv);
+    switch (type.backend()) {
+      case JAVAC:
+        return XConverters.toXProcessing(type.javac(), processingEnv);
+      case KSP:
+        return XConverters.toXProcessing(type.ksp(), processingEnv);
+    }
+    throw new IllegalStateException(String.format("Backend %s not supported yet.", type.backend()));
+  }
+
+  public static XProcessingEnv toXProcessing(DaggerProcessingEnv processingEnv) {
+    switch (processingEnv.backend()) {
+      case JAVAC:
+        return XProcessingEnv.create(processingEnv.javac());
+      case KSP:
+        return XProcessingEnv.create(processingEnv.ksp(), processingEnv.resolver());
+    }
+    throw new IllegalStateException(
+        String.format("Backend %s not supported yet.", processingEnv.backend()));
+  }
+
+  private DaggerElements() {}
+}
diff --git a/java/dagger/internal/codegen/xprocessing/JavaPoetExt.java b/java/dagger/internal/codegen/xprocessing/JavaPoetExt.java
index b28d9c0..bf8e94f 100644
--- a/java/dagger/internal/codegen/xprocessing/JavaPoetExt.java
+++ b/java/dagger/internal/codegen/xprocessing/JavaPoetExt.java
@@ -50,8 +50,7 @@
   }
 
   public static ParameterSpec toParameterSpec(XExecutableParameterElement param) {
-    return ParameterSpec.builder(param.getType().getTypeName(), XElements.getSimpleName(param))
-        .build();
+    return ParameterSpec.builder(param.getType().getTypeName(), param.getJvmName()).build();
   }
 
   private JavaPoetExt() {}
diff --git a/java/dagger/internal/codegen/xprocessing/MethodSpecs.java b/java/dagger/internal/codegen/xprocessing/MethodSpecs.java
index fa1f265..cc8c2f4 100644
--- a/java/dagger/internal/codegen/xprocessing/MethodSpecs.java
+++ b/java/dagger/internal/codegen/xprocessing/MethodSpecs.java
@@ -16,7 +16,6 @@
 
 package dagger.internal.codegen.xprocessing;
 
-import static dagger.internal.codegen.xprocessing.XElements.getSimpleName;
 import static javax.lang.model.element.Modifier.PROTECTED;
 import static javax.lang.model.element.Modifier.PUBLIC;
 
@@ -47,7 +46,7 @@
       builder.addModifiers(PROTECTED);
     }
     for (int i = 0; i < methodType.getParameterTypes().size(); i++) {
-      String parameterName = getSimpleName(method.getParameters().get(i));
+      String parameterName = method.getParameters().get(i).getJvmName();
       TypeName parameterType = methodType.getParameterTypes().get(i).getTypeName();
       builder.addParameter(ParameterSpec.builder(parameterType, parameterName).build());
     }
diff --git a/java/dagger/internal/codegen/xprocessing/XElements.java b/java/dagger/internal/codegen/xprocessing/XElements.java
index 552be65..b63d4d9 100644
--- a/java/dagger/internal/codegen/xprocessing/XElements.java
+++ b/java/dagger/internal/codegen/xprocessing/XElements.java
@@ -47,6 +47,7 @@
 import androidx.room.compiler.processing.XTypeElement;
 import androidx.room.compiler.processing.XTypeParameterElement;
 import androidx.room.compiler.processing.XVariableElement;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import com.google.devtools.ksp.symbol.KSAnnotated;
 import com.squareup.javapoet.ClassName;
@@ -54,6 +55,7 @@
 import java.util.Optional;
 import javax.annotation.Nullable;
 import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.Modifier;
 
 // TODO(bcorso): Consider moving these methods into XProcessing library.
 /** A utility class for {@link XElement} helper methods. */
@@ -383,5 +385,37 @@
     return element.getClosestMemberContainer().asClassName().getPackageName();
   }
 
+  public static boolean isFinal(XExecutableElement element) {
+    if (element.isFinal()) {
+      return true;
+    }
+    if (getProcessingEnv(element).getBackend() == XProcessingEnv.Backend.KSP) {
+      if (toKS(element).getModifiers().contains(com.google.devtools.ksp.symbol.Modifier.FINAL)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  public static ImmutableList<Modifier> getModifiers(XExecutableElement element) {
+    ImmutableList.Builder<Modifier> builder = ImmutableList.builder();
+    if (isFinal(element)) {
+      builder.add(Modifier.FINAL);
+    } else if (element.isAbstract()) {
+      builder.add(Modifier.ABSTRACT);
+    }
+    if (element.isStatic()) {
+      builder.add(Modifier.STATIC);
+    }
+    if (element.isPublic()) {
+      builder.add(Modifier.PUBLIC);
+    } else if (element.isPrivate()) {
+      builder.add(Modifier.PRIVATE);
+    } else if (element.isProtected()) {
+      builder.add(Modifier.PROTECTED);
+    }
+    return builder.build();
+  }
+
   private XElements() {}
 }
diff --git a/java/dagger/internal/codegen/xprocessing/XMethodElements.java b/java/dagger/internal/codegen/xprocessing/XMethodElements.java
index 3066d79..cbff642 100644
--- a/java/dagger/internal/codegen/xprocessing/XMethodElements.java
+++ b/java/dagger/internal/codegen/xprocessing/XMethodElements.java
@@ -16,11 +16,8 @@
 
 package dagger.internal.codegen.xprocessing;
 
-import static androidx.room.compiler.processing.compat.XConverters.getProcessingEnv;
-import static androidx.room.compiler.processing.compat.XConverters.toJavac;
 
 import androidx.room.compiler.processing.XMethodElement;
-import androidx.room.compiler.processing.XProcessingEnv;
 import androidx.room.compiler.processing.XTypeElement;
 
 // TODO(bcorso): Consider moving these methods into XProcessing library.
@@ -40,19 +37,5 @@
     return !method.getExecutableType().getTypeVariableNames().isEmpty();
   }
 
-  // TODO(b/278628663): Replace with XMethodElement#isDefault.
-  public static boolean isDefault(XMethodElement method) {
-    XProcessingEnv processingEnv = getProcessingEnv(method);
-    switch (processingEnv.getBackend()) {
-      case JAVAC:
-        return toJavac(method).isDefault();
-      case KSP:
-        throw new AssertionError(
-            "XMethodElement#isDefault() is not supported on KSP yet: "
-                + XElements.toStableString(method));
-    }
-    throw new AssertionError(String.format("Unsupported backend %s", processingEnv.getBackend()));
-  }
-
   private XMethodElements() {}
 }
diff --git a/java/dagger/internal/codegen/xprocessing/XTypeElements.java b/java/dagger/internal/codegen/xprocessing/XTypeElements.java
index 6d9c564..7330b8f 100644
--- a/java/dagger/internal/codegen/xprocessing/XTypeElements.java
+++ b/java/dagger/internal/codegen/xprocessing/XTypeElements.java
@@ -16,21 +16,16 @@
 
 package dagger.internal.codegen.xprocessing;
 
-import static androidx.room.compiler.processing.compat.XConverters.getProcessingEnv;
 import static com.google.common.base.Preconditions.checkNotNull;
 import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
 import static kotlin.streams.jdk8.StreamsKt.asStream;
 
 import androidx.room.compiler.processing.XHasModifiers;
 import androidx.room.compiler.processing.XMethodElement;
-import androidx.room.compiler.processing.XProcessingEnv;
 import androidx.room.compiler.processing.XTypeElement;
 import androidx.room.compiler.processing.XTypeParameterElement;
-import androidx.room.compiler.processing.compat.XConverters;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
-import com.google.devtools.ksp.symbol.Origin;
-import com.squareup.javapoet.ClassName;
 import com.squareup.javapoet.TypeVariableName;
 
 // TODO(bcorso): Consider moving these methods into XProcessing library.
@@ -142,20 +137,5 @@
     return visibilities.build();
   }
 
-  /** Returns true if the source of the given type element is Kotlin. */
-  public static boolean isKotlinSource(XTypeElement typeElement) {
-    XProcessingEnv processingEnv = getProcessingEnv(typeElement);
-    switch (processingEnv.getBackend()) {
-      case KSP:
-        // If this is KSP, then we should be able to check the origin of the declaration.
-        Origin origin = XConverters.toKS(typeElement).getOrigin();
-        return origin == Origin.KOTLIN || origin == Origin.KOTLIN_LIB;
-      case JAVAC:
-        // If this is KAPT, then the java stubs should have kotlin metadata.
-        return typeElement.hasAnnotation(ClassName.get("kotlin", "Metadata"));
-    }
-    throw new AssertionError("Unhandled backend kind: " + processingEnv.getBackend());
-  }
-
   private XTypeElements() {}
 }
diff --git a/java/dagger/internal/codegen/xprocessing/XTypes.java b/java/dagger/internal/codegen/xprocessing/XTypes.java
index 654ce69..7f4b77a 100644
--- a/java/dagger/internal/codegen/xprocessing/XTypes.java
+++ b/java/dagger/internal/codegen/xprocessing/XTypes.java
@@ -388,12 +388,46 @@
    * {@link Optional} is returned if there is no non-{@link Object} superclass.
    */
   public static Optional<XType> nonObjectSuperclass(XType type) {
-    return isDeclared(type)
-        ? type.getSuperTypes().stream()
-            .filter(supertype -> !supertype.getTypeName().equals(TypeName.OBJECT))
-            .filter(supertype -> isDeclared(supertype) && supertype.getTypeElement().isClass())
-            .collect(toOptional())
-        : Optional.empty();
+    if (!isDeclared(type)) {
+      return Optional.empty();
+    }
+    // We compare elements (rather than TypeName) here because its more efficient on the heap.
+    XTypeElement objectElement = objectElement(getProcessingEnv(type));
+    XTypeElement typeElement = type.getTypeElement();
+    if (!typeElement.isClass() || typeElement.equals(objectElement)) {
+      return Optional.empty();
+    }
+    XType superClass = typeElement.getSuperClass();
+    if (!isDeclared(superClass)) {
+      return Optional.empty();
+    }
+    XTypeElement superClassElement = superClass.getTypeElement();
+    if (!superClassElement.isClass() || superClassElement.equals(objectElement)) {
+      return Optional.empty();
+    }
+    // TODO(b/310954522): XType#getSuperTypes() is less efficient (especially on the heap) as it
+    // requires creating XType for not just superclass but all super interfaces as well, so we go
+    // through a bit of effort here to avoid that call unless its absolutely necessary since
+    // nonObjectSuperclass is called quite a bit via InjectionSiteFactory. However, we should
+    // eventually optimize this on the XProcessing side instead, e.g. maybe separating
+    // XType#getSuperClass() into a separate method.
+    return superClass.getTypeArguments().isEmpty()
+        ? Optional.of(superClass)
+        : type.getSuperTypes().stream()
+            .filter(XTypes::isDeclared)
+            .filter(supertype -> supertype.getTypeElement().isClass())
+            .filter(supertype -> !supertype.getTypeElement().equals(objectElement))
+            .collect(toOptional());
+  }
+
+  private static XTypeElement objectElement(XProcessingEnv processingEnv) {
+    switch (processingEnv.getBackend()) {
+      case JAVAC:
+        return processingEnv.requireTypeElement(TypeName.OBJECT);
+      case KSP:
+        return processingEnv.requireTypeElement("kotlin.Any");
+    }
+    throw new AssertionError("Unexpected backend: " + processingEnv.getBackend());
   }
 
   /**
diff --git a/java/dagger/internal/codegen/xprocessing/xprocessing-testing.jar b/java/dagger/internal/codegen/xprocessing/xprocessing-testing.jar
index 7811751..4d0d7fd 100644
--- a/java/dagger/internal/codegen/xprocessing/xprocessing-testing.jar
+++ b/java/dagger/internal/codegen/xprocessing/xprocessing-testing.jar
Binary files differ
diff --git a/java/dagger/internal/codegen/xprocessing/xprocessing.jar b/java/dagger/internal/codegen/xprocessing/xprocessing.jar
index 1c41e20..24590f8 100644
--- a/java/dagger/internal/codegen/xprocessing/xprocessing.jar
+++ b/java/dagger/internal/codegen/xprocessing/xprocessing.jar
Binary files differ
diff --git a/java/dagger/lint/DaggerKotlinIssueDetector.kt b/java/dagger/lint/DaggerKotlinIssueDetector.kt
index 8ca8623..6a4a33c 100644
--- a/java/dagger/lint/DaggerKotlinIssueDetector.kt
+++ b/java/dagger/lint/DaggerKotlinIssueDetector.kt
@@ -204,7 +204,8 @@
         ) {
           val containingClass = node.containingClass?.toUElement(UClass::class.java) ?: return
           if (containingClass.isObject()) {
-            val annotation = node.findAnnotation(JVM_STATIC_ANNOTATION)!!
+            val annotation = node.findAnnotation(JVM_STATIC_ANNOTATION)
+              ?: node.javaPsi.modifierList.findAnnotation(JVM_STATIC_ANNOTATION)!!
             context.report(
               ISSUE_JVM_STATIC_PROVIDES_IN_OBJECT,
               context.getLocation(annotation),
diff --git a/java/dagger/model/BUILD b/java/dagger/model/BUILD
index aaa8306..1a672dc 100644
--- a/java/dagger/model/BUILD
+++ b/java/dagger/model/BUILD
@@ -44,7 +44,6 @@
     deps = [
         "//java/dagger:core",
         "//java/dagger/internal/codegen/extension",
-        "//java/dagger/producers",
         "//third_party/java/auto:common",
         "//third_party/java/auto:value",
         "//third_party/java/error_prone:annotations",
diff --git a/java/dagger/model/BindingGraph.java b/java/dagger/model/BindingGraph.java
index 1ccba43..d09bf02 100644
--- a/java/dagger/model/BindingGraph.java
+++ b/java/dagger/model/BindingGraph.java
@@ -43,14 +43,13 @@
  * <p>A {@link BindingGraph} represents one of the following:
  *
  * <ul>
- *   <li>an entire component hierarchy rooted at a {@link dagger.Component} or {@link
- *       dagger.producers.ProductionComponent}
- *   <li>a partial component hierarchy rooted at a {@link dagger.Subcomponent} or {@link
- *       dagger.producers.ProductionSubcomponent} (only when the value of {@code
- *       -Adagger.fullBindingGraphValidation} is not {@code NONE})
- *   <li>the bindings installed by a {@link Module} or {@link dagger.producers.ProducerModule},
- *       including all subcomponents generated by {@link Module#subcomponents()} ()} and {@link
- *       dagger.producers.ProducerModule#subcomponents()} ()}
+ *   <li>an entire component hierarchy rooted at a {@code Component} or {@code ProductionComponent}
+ *   <li>a partial component hierarchy rooted at a {@code Subcomponent} or
+ *       {@code ProductionSubcomponent} (only when the value of
+ *       {@code -Adagger.fullBindingGraphValidation} is not {@code NONE})
+ *   <li>the bindings installed by a {@code Module} or {@code ProducerModule},
+ *       including all subcomponents generated by {@code Module#subcomponents()} and
+ *       {@code ProducerModule#subcomponents()}
  * </ul>
  *
  * In the case of a {@link BindingGraph} representing a module, the root {@link ComponentNode} will
diff --git a/java/dagger/model/BindingKind.java b/java/dagger/model/BindingKind.java
index 1bfb080..46d1130 100644
--- a/java/dagger/model/BindingKind.java
+++ b/java/dagger/model/BindingKind.java
@@ -34,8 +34,7 @@
   ASSISTED_FACTORY,
 
   /**
-   * An implicit binding for a {@link dagger.Component}- or {@link
-   * dagger.producers.ProductionComponent}-annotated type.
+   * An implicit binding for a {@code Component}- or {@code ProductionComponent}-annotated type.
    */
   COMPONENT,
 
@@ -65,14 +64,13 @@
   /** A binding for a {@link dagger.BindsInstance}-annotated builder method. */
   BOUND_INSTANCE,
 
-  /** A binding for a {@link dagger.producers.Produces}-annotated method. */
+  /** A binding for a {@code Produces}-annotated method. */
   PRODUCTION,
 
   /**
-   * A binding for a production method on a production component's {@linkplain
-   * dagger.producers.ProductionComponent#dependencies()} dependency} that returns a {@link
-   * com.google.common.util.concurrent.ListenableFuture} or {@link
-   * com.google.common.util.concurrent.FluentFuture}. Methods on production component dependencies
+   * A binding for a production method on a production component's
+   * {@code ProductionComponent#dependencies()} that returns a {@code ListenableFuture} or
+   * {@code FluentFuture}. Methods on production component dependencies
    * that don't return a future are considered {@linkplain #COMPONENT_PROVISION component provision
    * bindings}.
    */
diff --git a/java/dagger/model/ComponentPath.java b/java/dagger/model/ComponentPath.java
index 5a74c7a..9dfdbf9 100644
--- a/java/dagger/model/ComponentPath.java
+++ b/java/dagger/model/ComponentPath.java
@@ -40,8 +40,7 @@
   public abstract ImmutableList<TypeElement> components();
 
   /**
-   * Returns the root {@link dagger.Component}- or {@link
-   * dagger.producers.ProductionComponent}-annotated type
+   * Returns the root {@code Component}- or {@code ProductionComponent}-annotated type
    */
   public final TypeElement rootComponent() {
     return components().get(0);
diff --git a/java/dagger/model/RequestKind.java b/java/dagger/model/RequestKind.java
index 74a4346..6a19b0a 100644
--- a/java/dagger/model/RequestKind.java
+++ b/java/dagger/model/RequestKind.java
@@ -19,11 +19,6 @@
 import static com.google.common.base.CaseFormat.UPPER_CAMEL;
 import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE;
 
-import dagger.Lazy;
-import dagger.producers.Produced;
-import dagger.producers.Producer;
-import javax.inject.Provider;
-
 /**
  * Represents the different kinds of {@link javax.lang.model.type.TypeMirror types} that may be
  * requested as dependencies for the same key. For example, {@code String}, {@code
@@ -35,13 +30,13 @@
   /** A default request for an instance. E.g.: {@code FooType} */
   INSTANCE,
 
-  /** A request for a {@link Provider}. E.g.: {@code Provider<FooType>} */
+  /** A request for a {@code Provider}. E.g.: {@code Provider<FooType>} */
   PROVIDER,
 
-  /** A request for a {@link Lazy}. E.g.: {@code Lazy<FooType>} */
+  /** A request for a {@code Lazy}. E.g.: {@code Lazy<FooType>} */
   LAZY,
 
-  /** A request for a {@link Provider} of a {@link Lazy}. E.g.: {@code Provider<Lazy<FooType>>} */
+  /** A request for a {@code Provider} of a {@code Lazy}. E.g.: {@code Provider<Lazy<FooType>>} */
   PROVIDER_OF_LAZY,
 
   /**
@@ -50,15 +45,15 @@
    */
   MEMBERS_INJECTION,
 
-  /** A request for a {@link Producer}. E.g.: {@code Producer<FooType>} */
+  /** A request for a {@code Producer}. E.g.: {@code Producer<FooType>} */
   PRODUCER,
 
-  /** A request for a {@link Produced}. E.g.: {@code Produced<FooType>} */
+  /** A request for a {@code Produced}. E.g.: {@code Produced<FooType>} */
   PRODUCED,
 
   /**
-   * A request for a {@link com.google.common.util.concurrent.ListenableFuture}. E.g.: {@code
-   * ListenableFuture<FooType>}. These can only be requested by component interfaces.
+   * A request for a {@code ListenableFuture}. E.g.: {@code ListenableFuture<FooType>}. These can
+   * only be requested by component interfaces.
    */
   FUTURE,
   ;
diff --git a/java/dagger/model/Scope.java b/java/dagger/model/Scope.java
index c7ebfa8..fe64c86 100644
--- a/java/dagger/model/Scope.java
+++ b/java/dagger/model/Scope.java
@@ -26,7 +26,6 @@
 import com.google.common.base.Equivalence;
 import com.squareup.javapoet.ClassName;
 import dagger.Reusable;
-import dagger.producers.ProductionScope;
 import javax.inject.Singleton;
 import javax.lang.model.element.AnnotationMirror;
 import javax.lang.model.element.TypeElement;
@@ -88,7 +87,7 @@
     return isScope(REUSABLE);
   }
 
-  /** Returns {@code true} if this scope is the {@link ProductionScope @ProductionScope} scope. */
+  /** Returns {@code true} if this scope is the {@code @ProductionScope} scope. */
   public final boolean isProductionScope() {
     return isScope(PRODUCTION_SCOPE);
   }
diff --git a/java/dagger/multibindings/LazyClassKey.java b/java/dagger/multibindings/LazyClassKey.java
new file mode 100644
index 0000000..da46984
--- /dev/null
+++ b/java/dagger/multibindings/LazyClassKey.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2024 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.multibindings;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import dagger.MapKey;
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * A {@link MapKey} annotation for maps with {@code Class<?>} keys.
+ *
+ * <p>The difference from {@link ClassKey} is that dagger generates a string representation for the
+ * class to use under the hood, which prevents loading unused classes at runtime.
+ */
+@Target({ElementType.METHOD, ElementType.FIELD, ElementType.TYPE})
+@Retention(RUNTIME)
+@Documented
+@MapKey
+public @interface LazyClassKey {
+  Class<?> value();
+}
diff --git a/java/dagger/producers/internal/AbstractMapProducer.java b/java/dagger/producers/internal/AbstractMapProducer.java
index c60f0cb..360f1eb 100644
--- a/java/dagger/producers/internal/AbstractMapProducer.java
+++ b/java/dagger/producers/internal/AbstractMapProducer.java
@@ -17,12 +17,13 @@
 package dagger.producers.internal;
 
 import static com.google.common.base.Preconditions.checkNotNull;
+import static dagger.internal.Providers.asDaggerProvider;
 import static dagger.producers.internal.Producers.producerFromProvider;
 
 import com.google.common.collect.ImmutableMap;
+import dagger.internal.Provider;
 import dagger.producers.Producer;
 import java.util.Map;
-import javax.inject.Provider;
 
 /**
  * An {@code abstract} {@link Producer} implementation used to implement {@link Map} bindings.
@@ -76,6 +77,15 @@
       return this;
     }
 
+    /**
+     * Legacy javax version of the method to support libraries compiled with an older version of
+     * Dagger. Do not use directly.
+     */
+    @Deprecated
+    Builder<K, V, V2> put(K key, javax.inject.Provider<V> providerOfValue) {
+      return put(key, asDaggerProvider(providerOfValue));
+    }
+
     /** Adds contributions from a super-implementation of a component into this builder. */
     Builder<K, V, V2> putAll(Producer<Map<K, V2>> mapOfProducers) {
       if (mapOfProducers instanceof DelegateProducer) {
diff --git a/java/dagger/producers/internal/AbstractProducesMethodProducer.java b/java/dagger/producers/internal/AbstractProducesMethodProducer.java
index 0cf36ca..95b8f83 100644
--- a/java/dagger/producers/internal/AbstractProducesMethodProducer.java
+++ b/java/dagger/producers/internal/AbstractProducesMethodProducer.java
@@ -17,15 +17,16 @@
 package dagger.producers.internal;
 
 import static dagger.internal.Preconditions.checkNotNull;
+import static dagger.internal.Providers.asDaggerProvider;
 
 import com.google.common.util.concurrent.AsyncFunction;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
+import dagger.internal.Provider;
 import dagger.producers.monitoring.ProducerMonitor;
 import dagger.producers.monitoring.ProducerToken;
 import dagger.producers.monitoring.ProductionComponentMonitor;
 import java.util.concurrent.Executor;
-import javax.inject.Provider;
 import org.checkerframework.checker.nullness.compatqual.NullableDecl;
 
 /**
@@ -54,6 +55,18 @@
     this.executorProvider = checkNotNull(executorProvider);
   }
 
+  /**
+   * Legacy javax version of the method to support libraries compiled with an older version of
+   * Dagger. Do not use directly.
+   */
+  @Deprecated
+  protected AbstractProducesMethodProducer(
+      javax.inject.Provider<ProductionComponentMonitor> monitorProvider,
+      @NullableDecl ProducerToken token,
+      javax.inject.Provider<Executor> executorProvider) {
+    this(asDaggerProvider(monitorProvider), token, asDaggerProvider(executorProvider));
+  }
+
   @Override
   protected final ListenableFuture<T> compute() {
     monitor = monitorProvider.get().producerMonitorFor(token);
diff --git a/java/dagger/producers/internal/DelegateProducer.java b/java/dagger/producers/internal/DelegateProducer.java
index 6cc7547..de29234 100644
--- a/java/dagger/producers/internal/DelegateProducer.java
+++ b/java/dagger/producers/internal/DelegateProducer.java
@@ -20,8 +20,8 @@
 
 import com.google.common.util.concurrent.ListenableFuture;
 import dagger.internal.DoubleCheck;
+import dagger.internal.Provider;
 import dagger.producers.Producer;
-import javax.inject.Provider;
 
 /**
  * A DelegateProducer that is used to stitch Producer indirection during initialization across
diff --git a/java/dagger/producers/internal/MapOfProducedProducer.java b/java/dagger/producers/internal/MapOfProducedProducer.java
index bd9f1bf..3db7740 100644
--- a/java/dagger/producers/internal/MapOfProducedProducer.java
+++ b/java/dagger/producers/internal/MapOfProducedProducer.java
@@ -18,6 +18,7 @@
 
 import static com.google.common.util.concurrent.Futures.transform;
 import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
+import static dagger.internal.Providers.asDaggerProvider;
 
 import com.google.common.base.Function;
 import com.google.common.collect.ImmutableMap;
@@ -25,11 +26,11 @@
 import com.google.common.collect.Maps;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
+import dagger.internal.Provider;
 import dagger.producers.Produced;
 import dagger.producers.Producer;
 import java.util.List;
 import java.util.Map;
-import javax.inject.Provider;
 
 /**
  * A {@link Producer} implementation used to implement {@link Map} bindings. This producer returns a
@@ -108,6 +109,15 @@
       return this;
     }
 
+    /**
+     * Legacy javax version of the method to support libraries compiled with an older version of
+     * Dagger. Do not use directly.
+     */
+    @Deprecated
+    public Builder<K, V> put(K key, javax.inject.Provider<V> providerOfValue) {
+      return put(key, asDaggerProvider(providerOfValue));
+    }
+
     @Override
     public Builder<K, V> putAll(Producer<Map<K, Produced<V>>> mapOfProducedProducer) {
       super.putAll(mapOfProducedProducer);
diff --git a/java/dagger/producers/internal/MapOfProducerProducer.java b/java/dagger/producers/internal/MapOfProducerProducer.java
index 064cf74..145ea6d 100644
--- a/java/dagger/producers/internal/MapOfProducerProducer.java
+++ b/java/dagger/producers/internal/MapOfProducerProducer.java
@@ -16,6 +16,7 @@
 
 package dagger.producers.internal;
 
+import static dagger.internal.Providers.asDaggerProvider;
 import static dagger.producers.internal.Producers.entryPointViewOf;
 import static dagger.producers.internal.Producers.nonCancellationPropagatingViewOf;
 
@@ -24,9 +25,9 @@
 import com.google.common.collect.Maps;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
+import dagger.internal.Provider;
 import dagger.producers.Producer;
 import java.util.Map;
-import javax.inject.Provider;
 
 /**
  * A {@link Producer} implementation used to implement {@link Map} bindings. This factory returns an
@@ -65,6 +66,15 @@
       return this;
     }
 
+    /**
+     * Legacy javax version of the method to support libraries compiled with an older version of
+     * Dagger. Do not use directly.
+     */
+    @Deprecated
+    public Builder<K, V> put(K key, javax.inject.Provider<V> providerOfValue) {
+      return put(key, asDaggerProvider(providerOfValue));
+    }
+
     @Override
     public Builder<K, V> putAll(Producer<Map<K, Producer<V>>> mapOfProducerProducer) {
       super.putAll(mapOfProducerProducer);
diff --git a/java/dagger/producers/internal/MapProducer.java b/java/dagger/producers/internal/MapProducer.java
index 8caeb45..c832ef4 100644
--- a/java/dagger/producers/internal/MapProducer.java
+++ b/java/dagger/producers/internal/MapProducer.java
@@ -17,18 +17,19 @@
 package dagger.producers.internal;
 
 import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
+import static dagger.internal.Providers.asDaggerProvider;
 
 import com.google.common.base.Function;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Maps;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
+import dagger.internal.Provider;
 import dagger.producers.Producer;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
-import javax.inject.Provider;
 
 /**
  * A {@link Producer} implementation used to implement {@link Map} bindings. This producer returns a
@@ -62,6 +63,15 @@
       return this;
     }
 
+    /**
+     * Legacy javax version of the method to support libraries compiled with an older version of
+     * Dagger. Do not use directly.
+     */
+    @Deprecated
+    public Builder<K, V> put(K key, javax.inject.Provider<V> providerOfValue) {
+      return put(key, asDaggerProvider(providerOfValue));
+    }
+
     @Override
     public Builder<K, V> putAll(Producer<Map<K, V>> mapProducer) {
       super.putAll(mapProducer);
diff --git a/java/dagger/producers/internal/Producers.java b/java/dagger/producers/internal/Producers.java
index 54e4d5e..9385ee3 100644
--- a/java/dagger/producers/internal/Producers.java
+++ b/java/dagger/producers/internal/Producers.java
@@ -20,6 +20,7 @@
 import static com.google.common.util.concurrent.Futures.catchingAsync;
 import static com.google.common.util.concurrent.Futures.transform;
 import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
+import static dagger.internal.Providers.asDaggerProvider;
 
 import com.google.common.base.Function;
 import com.google.common.collect.ImmutableMap;
@@ -27,12 +28,12 @@
 import com.google.common.util.concurrent.AsyncFunction;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
+import dagger.internal.Provider;
 import dagger.producers.Produced;
 import dagger.producers.Producer;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import javax.inject.Provider;
 
 /**
  * Utility methods for use in generated producer code.
@@ -135,6 +136,15 @@
   }
 
   /**
+   * Legacy javax version of the method to support libraries compiled with an older version of
+   * Dagger. Do not use directly.
+   */
+  @Deprecated
+  public static <T> Producer<T> producerFromProvider(final javax.inject.Provider<T> provider) {
+    return producerFromProvider(asDaggerProvider(provider));
+  }
+
+  /**
    * Returns a producer that succeeds with the given value.
    *
    * @deprecated Prefer the non-internal version of this method: {@link
diff --git a/java/dagger/proguard.pro b/java/dagger/proguard.pro
new file mode 100644
index 0000000..1bfc947
--- /dev/null
+++ b/java/dagger/proguard.pro
@@ -0,0 +1,3 @@
+-keepclasseswithmembers,includedescriptorclasses class * {
+   @dagger.internal.KeepFieldType <fields>;
+}
\ No newline at end of file
diff --git a/java/dagger/r8.pro b/java/dagger/r8.pro
new file mode 100644
index 0000000..17e0ffe
--- /dev/null
+++ b/java/dagger/r8.pro
@@ -0,0 +1,3 @@
+-identifiernamestring @dagger.internal.IdentifierNameString class ** {
+    static java.lang.String *;
+}
\ No newline at end of file
diff --git a/java/dagger/spi/BUILD b/java/dagger/spi/BUILD
index 13428c1..8084e63 100644
--- a/java/dagger/spi/BUILD
+++ b/java/dagger/spi/BUILD
@@ -63,7 +63,6 @@
     ],
     artifact_target_maven_deps = [
         "com.google.code.findbugs:jsr305",
-        "com.google.dagger:dagger-producers",
         "com.google.dagger:dagger",
         "com.google.devtools.ksp:symbol-processing-api",
         "com.google.guava:failureaccess",
diff --git a/java/dagger/spi/model/BUILD b/java/dagger/spi/model/BUILD
index e9346dd..e5af4e5 100644
--- a/java/dagger/spi/model/BUILD
+++ b/java/dagger/spi/model/BUILD
@@ -40,7 +40,6 @@
     deps = [
         "//java/dagger:core",
         "//java/dagger/internal/codegen/extension",
-        "//java/dagger/producers",
         "//third_party/java/auto:common",
         "//third_party/java/auto:value",
         "//third_party/java/error_prone:annotations",
@@ -48,7 +47,6 @@
         "//third_party/java/guava/collect",
         "//third_party/java/guava/graph",
         "//third_party/java/javapoet",
-        "//third_party/java/jsr305_annotations",
         "//third_party/java/jsr330_inject",
         "@maven//:com_google_devtools_ksp_symbol_processing_api",
     ],
diff --git a/java/dagger/spi/model/BindingGraph.java b/java/dagger/spi/model/BindingGraph.java
index aab7c2a..7f433a1 100644
--- a/java/dagger/spi/model/BindingGraph.java
+++ b/java/dagger/spi/model/BindingGraph.java
@@ -41,14 +41,14 @@
  * <p>A {@link BindingGraph} represents one of the following:
  *
  * <ul>
- *   <li>an entire component hierarchy rooted at a {@link dagger.Component} or {@link
- *       dagger.producers.ProductionComponent}
- *   <li>a partial component hierarchy rooted at a {@link dagger.Subcomponent} or {@link
- *       dagger.producers.ProductionSubcomponent} (only when the value of {@code
- *       -Adagger.fullBindingGraphValidation} is not {@code NONE})
- *   <li>the bindings installed by a {@link Module} or {@link dagger.producers.ProducerModule},
- *       including all subcomponents generated by {@link Module#subcomponents()} ()} and {@link
- *       dagger.producers.ProducerModule#subcomponents()} ()}
+ *   <li>an entire component hierarchy rooted at a {@link dagger.Component} or
+ *       {@code ProductionComponent}
+ *   <li>a partial component hierarchy rooted at a {@link dagger.Subcomponent} or
+ *       {@code ProductionSubcomponent} (only when the value of
+ *       {@code -Adagger.fullBindingGraphValidation} is not {@code NONE})
+ *   <li>the bindings installed by a {@link Module} or {@code ProducerModule},
+ *       including all subcomponents generated by {@link Module#subcomponents()} ()} and
+ *       {@code ProducerModule#subcomponents()} ()}
  * </ul>
  *
  * In the case of a {@link BindingGraph} representing a module, the root {@link ComponentNode} will
diff --git a/java/dagger/spi/model/BindingKind.java b/java/dagger/spi/model/BindingKind.java
index b854b53..eb1e835 100644
--- a/java/dagger/spi/model/BindingKind.java
+++ b/java/dagger/spi/model/BindingKind.java
@@ -34,8 +34,8 @@
   ASSISTED_FACTORY,
 
   /**
-   * An implicit binding for a {@link dagger.Component}- or {@link
-   * dagger.producers.ProductionComponent}-annotated type.
+   * An implicit binding for a {@link dagger.Component}- or {@code ProductionComponent}-annotated
+   * type.
    */
   COMPONENT,
 
@@ -65,16 +65,14 @@
   /** A binding for a {@link dagger.BindsInstance}-annotated builder method. */
   BOUND_INSTANCE,
 
-  /** A binding for a {@link dagger.producers.Produces}-annotated method. */
+  /** A binding for a {@code Produces}-annotated method. */
   PRODUCTION,
 
   /**
-   * A binding for a production method on a production component's {@linkplain
-   * dagger.producers.ProductionComponent#dependencies()} dependency} that returns a {@link
-   * com.google.common.util.concurrent.ListenableFuture} or {@link
-   * com.google.common.util.concurrent.FluentFuture}. Methods on production component dependencies
-   * that don't return a future are considered {@linkplain #COMPONENT_PROVISION component provision
-   * bindings}.
+   * A binding for a production method on a production component's
+   * {@code ProductionComponent#dependencies()} that returns a {@code ListenableFuture} or
+   * {@code FluentFuture}. Methods on production component dependencies
+   * that don't return a future are considered component provision bindings.
    */
   COMPONENT_PRODUCTION,
 
diff --git a/java/dagger/spi/model/ComponentPath.java b/java/dagger/spi/model/ComponentPath.java
index 63a5f6b..11c811e 100644
--- a/java/dagger/spi/model/ComponentPath.java
+++ b/java/dagger/spi/model/ComponentPath.java
@@ -39,8 +39,7 @@
   public abstract ImmutableList<DaggerTypeElement> components();
 
   /**
-   * Returns the root {@link dagger.Component}- or {@link
-   * dagger.producers.ProductionComponent}-annotated type
+   * Returns the root {@code Component}- or {@code ProductionComponent}-annotated type
    */
   public final DaggerTypeElement rootComponent() {
     return components().get(0);
@@ -89,7 +88,7 @@
 
   @Override
   public final String toString() {
-    return components().stream().map(DaggerTypeElement::qualifiedName).collect(joining(" → "));
+    return components().stream().map(Key::qualifiedName).collect(joining(" → "));
   }
 
   @Memoized
diff --git a/java/dagger/spi/model/DaggerAnnotation.java b/java/dagger/spi/model/DaggerAnnotation.java
index 2ec66c0..5b59003 100644
--- a/java/dagger/spi/model/DaggerAnnotation.java
+++ b/java/dagger/spi/model/DaggerAnnotation.java
@@ -16,55 +16,29 @@
 
 package dagger.spi.model;
 
-import com.google.auto.common.AnnotationMirrors;
-import com.google.auto.value.AutoValue;
 import com.google.devtools.ksp.symbol.KSAnnotation;
-import javax.annotation.Nullable;
+import com.google.errorprone.annotations.DoNotMock;
 import javax.lang.model.element.AnnotationMirror;
 
 /** Wrapper type for an annotation. */
-@AutoValue
+@DoNotMock("Only use real implementations created by Dagger")
 public abstract class DaggerAnnotation {
-  public static DaggerAnnotation fromJavac(
-      DaggerTypeElement annotationTypeElement, AnnotationMirror annotation) {
-    return new AutoValue_DaggerAnnotation(annotationTypeElement, annotation, null);
-  }
-
-  public static DaggerAnnotation fromKsp(
-      DaggerTypeElement annotationTypeElement, KSAnnotation ksp) {
-    return new AutoValue_DaggerAnnotation(annotationTypeElement, null, ksp);
-  }
-
   public abstract DaggerTypeElement annotationTypeElement();
 
   /**
-   * java representation for the annotation, returns {@code null} if the annotation isn't a java
-   * element.
+   * Returns the Javac representation for the annotation.
+   *
+   * @throws IllegalStateException if the current backend isn't Javac.
    */
-  @Nullable
-  public abstract AnnotationMirror java();
+  public abstract AnnotationMirror javac();
 
-  /** KSP declaration for the annotation, returns {@code null} not using KSP. */
-  @Nullable
+  /**
+   * Returns the KSP representation for the annotation.
+   *
+   * @throws IllegalStateException if the current backend isn't KSP.
+   */
   public abstract KSAnnotation ksp();
 
-  public DaggerProcessingEnv.Backend backend() {
-    if (java() != null) {
-      return DaggerProcessingEnv.Backend.JAVAC;
-    } else if (ksp() != null) {
-      return DaggerProcessingEnv.Backend.KSP;
-    }
-    throw new AssertionError("Unexpected backend");
-  }
-
-  @Override
-  public final String toString() {
-    switch (backend()) {
-      case JAVAC:
-        return AnnotationMirrors.toString(java());
-      case KSP:
-        return ksp().toString();
-    }
-    throw new IllegalStateException(String.format("Backend %s not supported yet.", backend()));
-  }
+  /** Returns the backend used in this compilation. */
+  public abstract DaggerProcessingEnv.Backend backend();
 }
diff --git a/java/dagger/spi/model/DaggerElement.java b/java/dagger/spi/model/DaggerElement.java
index 0f6a2cf..0c0c53e 100644
--- a/java/dagger/spi/model/DaggerElement.java
+++ b/java/dagger/spi/model/DaggerElement.java
@@ -16,49 +16,27 @@
 
 package dagger.spi.model;
 
-import com.google.auto.value.AutoValue;
 import com.google.devtools.ksp.symbol.KSAnnotated;
-import javax.annotation.Nullable;
+import com.google.errorprone.annotations.DoNotMock;
 import javax.lang.model.element.Element;
 
 /** Wrapper type for an element. */
-@AutoValue
+@DoNotMock("Only use real implementations created by Dagger")
 public abstract class DaggerElement {
-  public static DaggerElement fromJavac(Element element) {
-    return new AutoValue_DaggerElement(element, null);
-  }
-
-  public static DaggerElement fromKsp(KSAnnotated ksp) {
-    return new AutoValue_DaggerElement(null, ksp);
-  }
+  /**
+   * Returns the Javac representation for the element.
+   *
+   * @throws IllegalStateException if the current backend isn't Javac.
+   */
+  public abstract Element javac();
 
   /**
-   * Java representation for the element, returns {@code null} not using java annotation processor.
+   * Returns the KSP representation for the element.
+   *
+   * @throws IllegalStateException if the current backend isn't KSP.
    */
-  @Nullable
-  public abstract Element java();
-
-  /** KSP declaration for the element, returns {@code null} not using KSP. */
-  @Nullable
   public abstract KSAnnotated ksp();
 
-  public DaggerProcessingEnv.Backend backend() {
-    if (java() != null) {
-      return DaggerProcessingEnv.Backend.JAVAC;
-    } else if (ksp() != null) {
-      return DaggerProcessingEnv.Backend.KSP;
-    }
-    throw new AssertionError("Unexpected backend");
-  }
-
-  @Override
-  public final String toString() {
-    switch (backend()) {
-      case JAVAC:
-        return java().toString();
-      case KSP:
-        return ksp().toString();
-    }
-    throw new IllegalStateException(String.format("Backend %s not supported yet.", backend()));
-  }
+  /** Returns the backend used in this compilation. */
+  public abstract DaggerProcessingEnv.Backend backend();
 }
diff --git a/java/dagger/spi/model/DaggerExecutableElement.java b/java/dagger/spi/model/DaggerExecutableElement.java
index 7df6a1e..afbd8e0 100644
--- a/java/dagger/spi/model/DaggerExecutableElement.java
+++ b/java/dagger/spi/model/DaggerExecutableElement.java
@@ -16,59 +16,27 @@
 
 package dagger.spi.model;
 
-import com.google.auto.value.AutoValue;
 import com.google.devtools.ksp.symbol.KSFunctionDeclaration;
-import javax.annotation.Nullable;
+import com.google.errorprone.annotations.DoNotMock;
 import javax.lang.model.element.ExecutableElement;
 
 /** Wrapper type for an executable element. */
-@AutoValue
+@DoNotMock("Only use real implementations created by Dagger")
 public abstract class DaggerExecutableElement {
-  public static DaggerExecutableElement fromJava(ExecutableElement executableElement) {
-    return new AutoValue_DaggerExecutableElement(executableElement, null);
-  }
-
-  public static DaggerExecutableElement fromKsp(KSFunctionDeclaration declaration) {
-    return new AutoValue_DaggerExecutableElement(null, declaration);
-  }
+  /**
+   * Returns the Javac representation for the executable element.
+   *
+   * @throws IllegalStateException if the current backend isn't Javac.
+   */
+  public abstract ExecutableElement javac();
 
   /**
-   * Java representation for the element, returns {@code null} not using java annotation processor.
+   * Returns the KSP representation for the executable element.
+   *
+   * @throws IllegalStateException if the current backend isn't KSP.
    */
-  @Nullable
-  public abstract ExecutableElement java();
-
-  /** KSP declaration for the element, returns {@code null} not using KSP. */
-  @Nullable
   public abstract KSFunctionDeclaration ksp();
 
-  public DaggerProcessingEnv.Backend backend() {
-    if (java() != null) {
-      return DaggerProcessingEnv.Backend.JAVAC;
-    } else if (ksp() != null) {
-      return DaggerProcessingEnv.Backend.KSP;
-    }
-    throw new AssertionError("Unexpected backend");
-  }
-
-  @Override
-  public final String toString() {
-    switch (backend()) {
-      case JAVAC:
-        return java().toString();
-      case KSP:
-        return ksp().toString();
-    }
-    throw new IllegalStateException(String.format("Backend %s not supported yet.", backend()));
-  }
-
-  String simpleName() {
-    switch (backend()) {
-      case JAVAC:
-        return java().getSimpleName().toString();
-      case KSP:
-        return ksp().getSimpleName().toString();
-    }
-    throw new IllegalStateException(String.format("Backend %s not supported yet.", backend()));
-  }
+  /** Returns the backend used in this compilation. */
+  public abstract DaggerProcessingEnv.Backend backend();
 }
diff --git a/java/dagger/spi/model/DaggerProcessingEnv.java b/java/dagger/spi/model/DaggerProcessingEnv.java
index 8c652c8..ab2e33e 100644
--- a/java/dagger/spi/model/DaggerProcessingEnv.java
+++ b/java/dagger/spi/model/DaggerProcessingEnv.java
@@ -16,50 +16,41 @@
 
 package dagger.spi.model;
 
-import com.google.auto.value.AutoValue;
 import com.google.devtools.ksp.processing.Resolver;
 import com.google.devtools.ksp.processing.SymbolProcessorEnvironment;
-import javax.annotation.Nullable;
+import com.google.errorprone.annotations.DoNotMock;
 import javax.annotation.processing.ProcessingEnvironment;
 
 /** Wrapper type for an element. */
-@AutoValue
+@DoNotMock("Only use real implementations created by Dagger")
 public abstract class DaggerProcessingEnv {
   /** Represents a type of backend used for compilation. */
-  public enum Backend { JAVAC, KSP }
-
-  public static boolean isJavac(Backend backend) {
-    return backend.equals(Backend.JAVAC);
-  }
-
-  public static DaggerProcessingEnv fromJavac(ProcessingEnvironment env) {
-    return new AutoValue_DaggerProcessingEnv(env, null, null);
-  }
-
-  public static DaggerProcessingEnv fromKsp(SymbolProcessorEnvironment env, Resolver resolver) {
-    return new AutoValue_DaggerProcessingEnv(null, env, resolver);
+  public enum Backend {
+    JAVAC,
+    KSP
   }
 
   /**
-   * Java representation for the processing environment, returns {@code null} not using java
-   * annotation processor.
+   * Returns the Javac representation for the processing environment.
+   *
+   * @throws IllegalStateException if the current backend isn't Javac.
    */
-  @Nullable
-  public abstract ProcessingEnvironment java();
+  public abstract ProcessingEnvironment javac();
 
-  @Nullable
+  /**
+   * Returns the KSP representation for the processing environment.
+   *
+   * @throws IllegalStateException if the current backend isn't KSP.
+   */
   public abstract SymbolProcessorEnvironment ksp();
 
-  @Nullable
+  /**
+   * Returns the KSP representation for the resolver.
+   *
+   * @throws IllegalStateException if the current backend isn't KSP.
+   */
   public abstract Resolver resolver();
 
   /** Returns the backend used in this compilation. */
-  public DaggerProcessingEnv.Backend backend() {
-    if (java() != null) {
-      return DaggerProcessingEnv.Backend.JAVAC;
-    } else if (ksp() != null) {
-      return DaggerProcessingEnv.Backend.KSP;
-    }
-    throw new AssertionError("Unexpected backend");
-  }
+  public abstract DaggerProcessingEnv.Backend backend();
 }
diff --git a/java/dagger/spi/model/DaggerType.java b/java/dagger/spi/model/DaggerType.java
index 249d494..4633506 100644
--- a/java/dagger/spi/model/DaggerType.java
+++ b/java/dagger/spi/model/DaggerType.java
@@ -16,47 +16,27 @@
 
 package dagger.spi.model;
 
-import com.google.auto.value.AutoValue;
 import com.google.devtools.ksp.symbol.KSType;
-import javax.annotation.Nullable;
+import com.google.errorprone.annotations.DoNotMock;
 import javax.lang.model.type.TypeMirror;
 
 /** Wrapper type for a type. */
-@AutoValue
+@DoNotMock("Only use real implementations created by Dagger")
 public abstract class DaggerType {
-  public static DaggerType fromJavac(TypeMirror type) {
-    return new AutoValue_DaggerType(type, null);
-  }
+  /**
+   * Returns the Javac representation for the type.
+   *
+   * @throws IllegalStateException if the current backend isn't Javac.
+   */
+  public abstract TypeMirror javac();
 
-  public static DaggerType fromKsp(KSType type) {
-    return new AutoValue_DaggerType(null, type);
-  }
-
-  /** Java representation for the type, returns {@code null} not using java annotation processor. */
-  @Nullable
-  public abstract TypeMirror java();
-
-  /** KSP declaration for the type, returns {@code null} not using KSP. */
-  @Nullable
+  /**
+   * Returns the KSP representation for the type.
+   *
+   * @throws IllegalStateException if the current backend isn't KSP.
+   */
   public abstract KSType ksp();
 
-  public DaggerProcessingEnv.Backend backend() {
-    if (java() != null) {
-      return DaggerProcessingEnv.Backend.JAVAC;
-    } else if (ksp() != null) {
-      return DaggerProcessingEnv.Backend.KSP;
-    }
-    throw new AssertionError("Unexpected backend");
-  }
-
-  @Override
-  public final String toString() {
-    switch (backend()) {
-      case JAVAC:
-        return java().toString();
-      case KSP:
-        return ksp().toString();
-    }
-    throw new IllegalStateException(String.format("Backend %s not supported yet.", backend()));
-  }
+  /** Returns the backend used in this compilation. */
+  public abstract DaggerProcessingEnv.Backend backend();
 }
diff --git a/java/dagger/spi/model/DaggerTypeElement.java b/java/dagger/spi/model/DaggerTypeElement.java
index 2f70a54..935770d 100644
--- a/java/dagger/spi/model/DaggerTypeElement.java
+++ b/java/dagger/spi/model/DaggerTypeElement.java
@@ -16,78 +16,27 @@
 
 package dagger.spi.model;
 
-import com.google.auto.common.MoreElements;
-import com.google.auto.value.AutoValue;
 import com.google.devtools.ksp.symbol.KSClassDeclaration;
-import javax.annotation.Nullable;
+import com.google.errorprone.annotations.DoNotMock;
 import javax.lang.model.element.TypeElement;
 
 /** Wrapper type for a type element. */
-@AutoValue
+@DoNotMock("Only use real implementations created by Dagger")
 public abstract class DaggerTypeElement {
-  public static DaggerTypeElement fromJavac(@Nullable TypeElement element) {
-    return new AutoValue_DaggerTypeElement(element, null);
-  }
+  /**
+   * Returns the Javac representation for the type element.
+   *
+   * @throws IllegalStateException if the current backend isn't Javac.
+   */
+  public abstract TypeElement javac();
 
-  public static DaggerTypeElement fromKsp(@Nullable KSClassDeclaration declaration) {
-    return new AutoValue_DaggerTypeElement(null, declaration);
-  }
-
-  /** Java representation for the type, returns {@code null} not using java annotation processor. */
-  @Nullable
-  public abstract TypeElement java();
-
-  /** KSP declaration for the element, returns {@code null} not using KSP. */
-  @Nullable
+  /**
+   * Returns the KSP representation for the type element.
+   *
+   * @throws IllegalStateException if the current backend isn't KSP.
+   */
   public abstract KSClassDeclaration ksp();
 
-  public final boolean hasAnnotation(String annotationName) {
-    switch (backend()) {
-      case JAVAC:
-        return MoreElements.isAnnotationPresent(java(), annotationName);
-      case KSP:
-        return KspUtilsKt.hasAnnotation(ksp(), annotationName);
-    }
-    throw new IllegalStateException(String.format("Backend %s not supported yet.", backend()));
-  }
-
-  public String packageName() {
-    switch (backend()) {
-      case JAVAC:
-        return MoreElements.getPackage(java()).getQualifiedName().toString();
-      case KSP:
-        return KspUtilsKt.getNormalizedPackageName(ksp());
-    }
-    throw new IllegalStateException(String.format("Backend %s not supported yet.", backend()));
-  }
-
-  public String qualifiedName() {
-    switch (backend()) {
-      case JAVAC:
-        return java().getQualifiedName().toString();
-      case KSP:
-        return ksp().getQualifiedName().asString();
-    }
-    throw new IllegalStateException(String.format("Backend %s not supported yet.", backend()));
-  }
-
-  public DaggerProcessingEnv.Backend backend() {
-    if (java() != null) {
-      return DaggerProcessingEnv.Backend.JAVAC;
-    } else if (ksp() != null) {
-      return DaggerProcessingEnv.Backend.KSP;
-    }
-    throw new AssertionError("Unexpected backend");
-  }
-
-  @Override
-  public final String toString() {
-    switch (backend()) {
-      case JAVAC:
-        return java().toString();
-      case KSP:
-        return ksp().toString();
-    }
-    throw new IllegalStateException(String.format("Backend %s not supported yet.", backend()));
-  }
+  /** Returns the backend used in this compilation. */
+  public abstract DaggerProcessingEnv.Backend backend();
 }
diff --git a/java/dagger/spi/model/Key.java b/java/dagger/spi/model/Key.java
index d871e6d..d4478f6 100644
--- a/java/dagger/spi/model/Key.java
+++ b/java/dagger/spi/model/Key.java
@@ -130,7 +130,7 @@
     private static MultibindingContributionIdentifier create(
         DaggerTypeElement contributingModule, DaggerExecutableElement bindingMethod) {
       return new AutoValue_Key_MultibindingContributionIdentifier(
-          contributingModule.qualifiedName(), bindingMethod.simpleName());
+          qualifiedName(contributingModule), simpleName(bindingMethod));
     }
 
     /** Returns the module containing the multibinding method. */
@@ -150,4 +150,24 @@
       return String.format("%s#%s", contributingModule(), bindingMethod());
     }
   }
+
+  static String qualifiedName(DaggerTypeElement element) {
+    switch (element.backend()) {
+      case JAVAC:
+        return element.javac().getQualifiedName().toString();
+      case KSP:
+        return element.ksp().getQualifiedName().asString();
+    }
+    throw new IllegalStateException("Unknown backend: " + element.backend());
+  }
+
+  private static String simpleName(DaggerExecutableElement element) {
+    switch (element.backend()) {
+      case JAVAC:
+        return element.javac().getSimpleName().toString();
+      case KSP:
+        return element.ksp().getSimpleName().asString();
+    }
+    throw new IllegalStateException("Unknown backend: " + element.backend());
+  }
 }
diff --git a/java/dagger/spi/model/MoreAnnotationMirrors.java b/java/dagger/spi/model/MoreAnnotationMirrors.java
index 44c0363..a5c04c6 100644
--- a/java/dagger/spi/model/MoreAnnotationMirrors.java
+++ b/java/dagger/spi/model/MoreAnnotationMirrors.java
@@ -35,7 +35,7 @@
    * defined in the annotation type.
    */
   public static String toStableString(DaggerAnnotation qualifier) {
-    return stableAnnotationMirrorToString(qualifier.java());
+    return stableAnnotationMirrorToString(qualifier.javac());
   }
 
   /**
diff --git a/java/dagger/spi/model/RequestKind.java b/java/dagger/spi/model/RequestKind.java
index 62f46cd..bcbe26d 100644
--- a/java/dagger/spi/model/RequestKind.java
+++ b/java/dagger/spi/model/RequestKind.java
@@ -19,11 +19,6 @@
 import static com.google.common.base.CaseFormat.UPPER_CAMEL;
 import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE;
 
-import dagger.Lazy;
-import dagger.producers.Produced;
-import dagger.producers.Producer;
-import javax.inject.Provider;
-
 /**
  * Represents the different kinds of {@link javax.lang.model.type.TypeMirror types} that may be
  * requested as dependencies for the same key. For example, {@code String}, {@code
@@ -35,13 +30,13 @@
   /** A default request for an instance. E.g.: {@code FooType} */
   INSTANCE,
 
-  /** A request for a {@link Provider}. E.g.: {@code Provider<FooType>} */
+  /** A request for a {@code Provider}. E.g.: {@code Provider<FooType>} */
   PROVIDER,
 
-  /** A request for a {@link Lazy}. E.g.: {@code Lazy<FooType>} */
+  /** A request for a {@code Lazy}. E.g.: {@code Lazy<FooType>} */
   LAZY,
 
-  /** A request for a {@link Provider} of a {@link Lazy}. E.g.: {@code Provider<Lazy<FooType>>} */
+  /** A request for a {@code Provider} of a {@code Lazy}. E.g.: {@code Provider<Lazy<FooType>>}. */
   PROVIDER_OF_LAZY,
 
   /**
@@ -50,15 +45,15 @@
    */
   MEMBERS_INJECTION,
 
-  /** A request for a {@link Producer}. E.g.: {@code Producer<FooType>} */
+  /** A request for a {@code Producer}. E.g.: {@code Producer<FooType>} */
   PRODUCER,
 
-  /** A request for a {@link Produced}. E.g.: {@code Produced<FooType>} */
+  /** A request for a {@code Produced}. E.g.: {@code Produced<FooType>} */
   PRODUCED,
 
   /**
-   * A request for a {@link com.google.common.util.concurrent.ListenableFuture}. E.g.: {@code
-   * ListenableFuture<FooType>}. These can only be requested by component interfaces.
+   * A request for a {@code ListenableFuture}. E.g.: {@code ListenableFuture<FooType>}. These can
+   * only be requested by component interfaces.
    */
   FUTURE,
   ;
diff --git a/java/dagger/spi/model/Scope.java b/java/dagger/spi/model/Scope.java
index d1505b9..2d86101 100644
--- a/java/dagger/spi/model/Scope.java
+++ b/java/dagger/spi/model/Scope.java
@@ -18,6 +18,7 @@
 
 import static com.google.common.base.Preconditions.checkArgument;
 
+import com.google.auto.common.MoreElements;
 import com.google.auto.value.AutoValue;
 
 /** A representation of a {@link javax.inject.Scope}. */
@@ -42,8 +43,16 @@
    * Returns {@code true} if {@code scopeAnnotationType} is a {@link javax.inject.Scope} annotation.
    */
   public static boolean isScope(DaggerTypeElement scopeAnnotationType) {
-    return scopeAnnotationType.hasAnnotation(SCOPE)
-        || scopeAnnotationType.hasAnnotation(SCOPE_JAVAX);
+    switch (scopeAnnotationType.backend()) {
+      case JAVAC:
+        return MoreElements.isAnnotationPresent(scopeAnnotationType.javac(), SCOPE)
+            || MoreElements.isAnnotationPresent(scopeAnnotationType.javac(), SCOPE_JAVAX);
+      case KSP:
+        return KspUtilsKt.hasAnnotation(scopeAnnotationType.ksp(), SCOPE)
+            || KspUtilsKt.hasAnnotation(scopeAnnotationType.ksp(), SCOPE_JAVAX);
+    }
+    throw new IllegalStateException(
+        String.format("Backend %s not supported yet.", scopeAnnotationType.backend()));
   }
 
   private boolean isScope(String annotationName) {
@@ -71,8 +80,7 @@
   }
 
   /**
-   * Returns {@code true} if this scope is the {@link
-   * dagger.producers.ProductionScope @ProductionScope} scope.
+   * Returns {@code true} if this scope is the {@code @ProductionScope} scope.
    */
   public final boolean isProductionScope() {
     return isScope(PRODUCTION_SCOPE);
diff --git a/java/dagger/spi/model/testing/BindingGraphSubject.java b/java/dagger/spi/model/testing/BindingGraphSubject.java
index e206731..4d53d93 100644
--- a/java/dagger/spi/model/testing/BindingGraphSubject.java
+++ b/java/dagger/spi/model/testing/BindingGraphSubject.java
@@ -112,7 +112,7 @@
   private static String formattedType(DaggerType type) {
     switch (type.backend()) {
       case JAVAC:
-        return type.java().toString();
+        return type.javac().toString();
       case KSP:
         return type.ksp().getDeclaration().getQualifiedName().asString();
     }
diff --git a/java/dagger/testing/compile/BUILD b/java/dagger/testing/compile/BUILD
index 5859398..a0e09a8 100644
--- a/java/dagger/testing/compile/BUILD
+++ b/java/dagger/testing/compile/BUILD
@@ -26,6 +26,9 @@
         "CompilerProcessors.java",
         "CompilerTests.java",
     ],
+    exports = [
+        "//java/dagger/internal/codegen/xprocessing:xprocessing-testing",
+    ],
     deps = [
         "//java/dagger/internal/codegen:processor",
         "//java/dagger/internal/codegen/extension",
diff --git a/java/dagger/testing/compile/CompilerTests.java b/java/dagger/testing/compile/CompilerTests.java
index 5557420..ac74a61 100644
--- a/java/dagger/testing/compile/CompilerTests.java
+++ b/java/dagger/testing/compile/CompilerTests.java
@@ -21,6 +21,7 @@
 import static com.google.common.collect.Streams.stream;
 import static com.google.testing.compile.Compiler.javac;
 import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
+import static java.util.stream.Collectors.toMap;
 
 import androidx.room.compiler.processing.XProcessingEnv;
 import androidx.room.compiler.processing.XProcessingEnvConfig;
@@ -39,6 +40,7 @@
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.io.Files;
+import com.google.devtools.ksp.processing.SymbolProcessorProvider;
 import com.google.testing.compile.Compiler;
 import dagger.internal.codegen.ComponentProcessor;
 import dagger.internal.codegen.KspComponentProcessor;
@@ -46,11 +48,13 @@
 import java.io.File;
 import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.NoSuchElementException;
 import java.util.function.Consumer;
+import javax.annotation.processing.Processor;
 import org.junit.rules.TemporaryFolder;
 
 /** A helper class for working with java compiler tests. */
@@ -150,6 +154,8 @@
       // Set default values
       return builder
           .processorOptions(DEFAULT_PROCESSOR_OPTIONS)
+          .additionalJavacProcessors(ImmutableList.of())
+          .additionalKspProcessors(ImmutableList.of())
           .processingStepSuppliers(ImmutableSet.of())
           .bindingGraphPluginSuppliers(ImmutableSet.of());
     }
@@ -160,6 +166,12 @@
     /** Returns the annotation processor options */
     abstract ImmutableMap<String, String> processorOptions();
 
+    /** Returns the extra Javac processors. */
+    abstract ImmutableCollection<Processor> additionalJavacProcessors();
+
+    /** Returns the extra KSP processors. */
+    abstract ImmutableCollection<SymbolProcessorProvider> additionalKspProcessors();
+
     /** Returns the processing steps suppliers. */
     abstract ImmutableCollection<Supplier<XProcessingStep>> processingStepSuppliers();
 
@@ -192,6 +204,16 @@
       return toBuilder().processorOptions(newProcessorOptions).build();
     }
 
+    /** Returns a new {@link HiltCompiler} instance with the additional Javac processors. */
+    public DaggerCompiler withAdditionalJavacProcessors(Processor... processors) {
+      return toBuilder().additionalJavacProcessors(ImmutableList.copyOf(processors)).build();
+    }
+
+    /** Returns a new {@link HiltCompiler} instance with the additional KSP processors. */
+    public DaggerCompiler withAdditionalKspProcessors(SymbolProcessorProvider... processors) {
+      return toBuilder().additionalKspProcessors(ImmutableList.copyOf(processors)).build();
+    }
+
     /** Returns a new {@link Compiler} instance with the given processing steps. */
     public DaggerCompiler withProcessingSteps(Supplier<XProcessingStep>... suppliers) {
       return toBuilder().processingStepSuppliers(ImmutableList.copyOf(suppliers)).build();
@@ -210,23 +232,43 @@
           /* kotlincArguments= */ ImmutableList.of(
               "-P", "plugin:org.jetbrains.kotlin.kapt3:correctErrorTypes=true"),
           /* config= */ PROCESSING_ENV_CONFIG,
-          /* javacProcessors= */ ImmutableList.of(
-              ComponentProcessor.withTestPlugins(bindingGraphPlugins()),
-              new CompilerProcessors.JavacProcessor(processingSteps())),
-          /* symbolProcessorProviders= */ ImmutableList.of(
-              KspComponentProcessor.Provider.withTestPlugins(bindingGraphPlugins()),
-              new CompilerProcessors.KspProcessor.Provider(processingSteps())),
+          /* javacProcessors= */ mergeProcessors(
+              ImmutableList.of(
+                  ComponentProcessor.withTestPlugins(bindingGraphPlugins()),
+                  new CompilerProcessors.JavacProcessor(processingSteps())),
+              additionalJavacProcessors()),
+          /* symbolProcessorProviders= */ mergeProcessors(
+              ImmutableList.of(
+                  KspComponentProcessor.Provider.withTestPlugins(bindingGraphPlugins()),
+                  new CompilerProcessors.KspProcessor.Provider(processingSteps())),
+              additionalKspProcessors()),
           result -> {
             onCompilationResult.accept(result);
             return null;
           });
     }
 
+    private static <T> ImmutableList<T> mergeProcessors(
+        Collection<T> defaultProcessors, Collection<T> extraProcessors) {
+      Map<Class<?>, T> processors =
+          defaultProcessors.stream()
+              .collect(toMap(Object::getClass, (T e) -> e, (p1, p2) -> p2, HashMap::new));
+      // Adds extra processors, and allows overriding any processors of the same class.
+      extraProcessors.forEach(processor -> processors.put(processor.getClass(), processor));
+      return ImmutableList.copyOf(processors.values());
+    }
+
     /** Used to build a {@link DaggerCompiler}. */
     @AutoValue.Builder
     public abstract static class Builder {
       abstract Builder sources(ImmutableCollection<Source> sources);
       abstract Builder processorOptions(Map<String, String> processorOptions);
+
+      abstract Builder additionalJavacProcessors(ImmutableCollection<Processor> processors);
+
+      abstract Builder additionalKspProcessors(
+          ImmutableCollection<SymbolProcessorProvider> processors);
+
       abstract Builder processingStepSuppliers(
           ImmutableCollection<Supplier<XProcessingStep>> processingStepSuppliers);
       abstract Builder bindingGraphPluginSuppliers(
diff --git a/javatests/artifacts/dagger-android-ksp/app/build.gradle b/javatests/artifacts/dagger-android-ksp/app/build.gradle
new file mode 100644
index 0000000..434590a
--- /dev/null
+++ b/javatests/artifacts/dagger-android-ksp/app/build.gradle
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+plugins {
+    id 'com.android.application'
+    id 'org.jetbrains.kotlin.android'
+    id 'com.google.devtools.ksp'
+}
+
+android {
+    namespace 'dagger.android.ksp'
+    compileSdkVersion 33
+    defaultConfig {
+        applicationId 'dagger.android.ksp'
+        minSdk 16
+        targetSdk 33
+        versionCode 1
+        versionName "1.0"
+    }
+
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_17
+        targetCompatibility JavaVersion.VERSION_17
+    }
+    testOptions {
+        unitTests.includeAndroidResources = true
+    }
+    sourceSets {
+        String sharedTestDir = 'src/sharedTest/java'
+        test {
+            java.srcDirs += sharedTestDir
+        }
+        androidTest {
+            java.srcDirs += sharedTestDir
+        }
+    }
+}
+
+dependencies {
+    implementation 'androidx.appcompat:appcompat:1.2.0'
+    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
+
+    testImplementation 'com.google.truth:truth:1.0.1'
+    testImplementation 'org.robolectric:robolectric:4.11.1'
+    testImplementation 'androidx.core:core:1.3.2'
+    testImplementation 'androidx.test.ext:junit:1.1.5'
+    testImplementation 'androidx.test:runner:1.5.2'
+    testImplementation 'androidx.test.espresso:espresso-core:3.5.1'
+
+    androidTestImplementation 'com.google.truth:truth:1.0.1'
+    androidTestImplementation 'androidx.test.ext:junit:1.1.5'
+    androidTestImplementation 'androidx.test:runner:1.5.2'
+    androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
+
+    // Dagger Android dependencies
+    implementation 'com.google.dagger:dagger:LOCAL-SNAPSHOT'
+    implementation 'com.google.dagger:dagger-android-support:LOCAL-SNAPSHOT'
+    implementation 'com.google.dagger:dagger-android:LOCAL-SNAPSHOT'
+    ksp 'com.google.dagger:dagger-android-processor:LOCAL-SNAPSHOT'
+    ksp "com.google.dagger:dagger-compiler:LOCAL-SNAPSHOT"
+}
\ No newline at end of file
diff --git a/javatests/artifacts/dagger-android-ksp/app/src/main/AndroidManifest.xml b/javatests/artifacts/dagger-android-ksp/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..89b0dbf
--- /dev/null
+++ b/javatests/artifacts/dagger-android-ksp/app/src/main/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<!--
+  ~ Copyright (C) 2023 The Dagger Authors.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~ http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+  package="dagger.android.ksp">
+
+  <application
+    android:name=".SimpleApplication"
+    android:label="@string/appName"
+    android:theme="@style/Theme.AppCompat.Light">
+    <activity android:name=".SimpleActivity" android:exported="true">
+      <intent-filter>
+        <action android:name="android.intent.action.MAIN" />
+        <category android:name="android.intent.category.LAUNCHER" />
+      </intent-filter>
+    </activity>
+  </application>
+</manifest>
\ No newline at end of file
diff --git a/java/dagger/spi/model/CompilerEnvironment.java b/javatests/artifacts/dagger-android-ksp/app/src/main/kotlin/dagger/android/ksp/Model .kt
similarity index 68%
copy from java/dagger/spi/model/CompilerEnvironment.java
copy to javatests/artifacts/dagger-android-ksp/app/src/main/kotlin/dagger/android/ksp/Model .kt
index 28553e4..8dd333d 100644
--- a/java/dagger/spi/model/CompilerEnvironment.java
+++ b/javatests/artifacts/dagger-android-ksp/app/src/main/kotlin/dagger/android/ksp/Model .kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Dagger Authors.
+ * Copyright (C) 2023 The Dagger Authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,10 +14,9 @@
  * limitations under the License.
  */
 
-package dagger.spi.model;
+package dagger.android.ksp
 
-/** Types for the compiler in use for annotation processing. */
-public enum CompilerEnvironment {
-  JAVA,
-  KSP
-}
+import javax.inject.Qualifier
+
+/** Qualifies bindings relating to [android.os.Build.MODEL]. */
+@Qualifier @Retention(AnnotationRetention.RUNTIME) internal annotation class Model
diff --git a/java/dagger/spi/model/CompilerEnvironment.java b/javatests/artifacts/dagger-android-ksp/app/src/main/kotlin/dagger/android/ksp/ModelModule.kt
similarity index 70%
copy from java/dagger/spi/model/CompilerEnvironment.java
copy to javatests/artifacts/dagger-android-ksp/app/src/main/kotlin/dagger/android/ksp/ModelModule.kt
index 28553e4..25c0f72 100644
--- a/java/dagger/spi/model/CompilerEnvironment.java
+++ b/javatests/artifacts/dagger-android-ksp/app/src/main/kotlin/dagger/android/ksp/ModelModule.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Dagger Authors.
+ * Copyright (C) 2023 The Dagger Authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,10 +14,13 @@
  * limitations under the License.
  */
 
-package dagger.spi.model;
+package dagger.android.ksp
 
-/** Types for the compiler in use for annotation processing. */
-public enum CompilerEnvironment {
-  JAVA,
-  KSP
+import android.os.Build.MODEL
+import dagger.Module
+import dagger.Provides
+
+@Module
+object ModelModule {
+  @Provides @Model fun provideModel(): String = MODEL
 }
diff --git a/javatests/artifacts/dagger-android-ksp/app/src/main/kotlin/dagger/android/ksp/SimpleActivity.kt b/javatests/artifacts/dagger-android-ksp/app/src/main/kotlin/dagger/android/ksp/SimpleActivity.kt
new file mode 100644
index 0000000..5b9b84b
--- /dev/null
+++ b/javatests/artifacts/dagger-android-ksp/app/src/main/kotlin/dagger/android/ksp/SimpleActivity.kt
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.android.ksp
+
+import android.os.Bundle
+import android.util.Log
+import android.widget.TextView
+import dagger.Binds
+import dagger.Module
+import dagger.Subcomponent
+import dagger.android.AndroidInjector
+import dagger.android.support.DaggerAppCompatActivity
+import dagger.multibindings.ClassKey
+import dagger.multibindings.IntoMap
+import javax.inject.Inject
+
+/**
+ * The main activity of the application.
+ *
+ * <p>It can be injected with any binding from both {@link SimpleActivityComponent} and {@link
+ * SimpleApplication.SimpleComponent}.
+ */
+class SimpleActivity : DaggerAppCompatActivity() {
+  private val TAG: String = SimpleActivity::class.java.getSimpleName()
+
+  @Inject @UserName lateinit var userName: String
+  @Inject @Model lateinit var model: String
+
+  override protected fun onCreate(savedInstanceState: Bundle?) {
+    super.onCreate(savedInstanceState)
+    Log.i(TAG, "Injected with userName and model: " + userName + ", " + model)
+
+    setContentView(R.layout.activity_main)
+
+    val greeting = findViewById(R.id.greeting) as TextView
+    val text = getResources().getString(R.string.welcome, userName, model)
+    greeting.setText(text)
+  }
+}
+
+@Subcomponent
+interface SimpleActivityComponent : AndroidInjector<SimpleActivity> {
+
+  @Subcomponent.Factory interface Factory : AndroidInjector.Factory<SimpleActivity> {}
+}
+
+@Module(subcomponents = [SimpleActivityComponent::class], includes = [UserNameModule::class])
+interface InjectorModule {
+  @Binds
+  @IntoMap
+  @ClassKey(SimpleActivity::class)
+  fun bind(factory: SimpleActivityComponent.Factory): AndroidInjector.Factory<*>
+}
+
diff --git a/javatests/artifacts/dagger-android-ksp/app/src/main/kotlin/dagger/android/ksp/SimpleApplication.kt b/javatests/artifacts/dagger-android-ksp/app/src/main/kotlin/dagger/android/ksp/SimpleApplication.kt
new file mode 100644
index 0000000..37dfd05
--- /dev/null
+++ b/javatests/artifacts/dagger-android-ksp/app/src/main/kotlin/dagger/android/ksp/SimpleApplication.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.android.ksp
+
+import android.util.Log
+import dagger.Component
+import dagger.android.AndroidInjectionModule
+import dagger.android.AndroidInjector
+import dagger.android.DaggerApplication
+import javax.inject.Inject
+import javax.inject.Singleton
+
+/**
+ * A simple, skeletal application that demonstrates a dependency-injected application using the
+ * utilities in {@code dagger.android}.
+ */
+class SimpleApplication : DaggerApplication() {
+  private val TAG = SimpleApplication::class.java.getSimpleName()
+
+  @Inject @Model lateinit var model: String
+
+  override public fun onCreate() {
+    super.onCreate()
+    Log.i(TAG, "Injected with model: " + model)
+  }
+
+  override protected fun applicationInjector(): AndroidInjector<SimpleApplication> {
+    return DaggerSimpleComponent.factory().create(this)
+  }
+}
+
+@Singleton
+@Component(
+  modules =
+    [AndroidInjectionModule::class, InjectorModule::class, ModelModule::class]
+)
+interface SimpleComponent : AndroidInjector<SimpleApplication> {
+  @Component.Factory interface Factory : AndroidInjector.Factory<SimpleApplication> {}
+}
diff --git a/java/dagger/spi/model/CompilerEnvironment.java b/javatests/artifacts/dagger-android-ksp/app/src/main/kotlin/dagger/android/ksp/UserName.kt
similarity index 69%
copy from java/dagger/spi/model/CompilerEnvironment.java
copy to javatests/artifacts/dagger-android-ksp/app/src/main/kotlin/dagger/android/ksp/UserName.kt
index 28553e4..3388c09 100644
--- a/java/dagger/spi/model/CompilerEnvironment.java
+++ b/javatests/artifacts/dagger-android-ksp/app/src/main/kotlin/dagger/android/ksp/UserName.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Dagger Authors.
+ * Copyright (C) 2023 The Dagger Authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,10 +14,9 @@
  * limitations under the License.
  */
 
-package dagger.spi.model;
+package dagger.android.ksp
 
-/** Types for the compiler in use for annotation processing. */
-public enum CompilerEnvironment {
-  JAVA,
-  KSP
-}
+import javax.inject.Qualifier
+
+/** Qualifies bindings relating to the user name. */
+@Qualifier @Retention(AnnotationRetention.RUNTIME) internal annotation class UserName
diff --git a/java/dagger/spi/model/CompilerEnvironment.java b/javatests/artifacts/dagger-android-ksp/app/src/main/kotlin/dagger/android/ksp/UserNameModule.kt
similarity index 72%
copy from java/dagger/spi/model/CompilerEnvironment.java
copy to javatests/artifacts/dagger-android-ksp/app/src/main/kotlin/dagger/android/ksp/UserNameModule.kt
index 28553e4..2628398 100644
--- a/java/dagger/spi/model/CompilerEnvironment.java
+++ b/javatests/artifacts/dagger-android-ksp/app/src/main/kotlin/dagger/android/ksp/UserNameModule.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Dagger Authors.
+ * Copyright (C) 2023 The Dagger Authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,10 +14,12 @@
  * limitations under the License.
  */
 
-package dagger.spi.model;
+package dagger.android.ksp
 
-/** Types for the compiler in use for annotation processing. */
-public enum CompilerEnvironment {
-  JAVA,
-  KSP
+import dagger.Module
+import dagger.Provides
+
+@Module
+object UserNameModule {
+  @UserName @Provides fun provideUserName(): String = "ProdUser"
 }
diff --git a/javatests/artifacts/dagger-android-ksp/app/src/main/res/layout/activity_main.xml b/javatests/artifacts/dagger-android-ksp/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..4693e55
--- /dev/null
+++ b/javatests/artifacts/dagger-android-ksp/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2023 The Dagger Authors.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~ http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+  android:layout_width="match_parent"
+  android:layout_height="match_parent"
+  android:background="@android:color/background_light">
+
+  <TextView
+    android:id="@+id/greeting"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:layout_alignParentTop="true"
+    android:textColor="@android:color/primary_text_light"
+    />
+</RelativeLayout>
\ No newline at end of file
diff --git a/javatests/artifacts/dagger-android-ksp/app/src/main/res/values/strings.xml b/javatests/artifacts/dagger-android-ksp/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..4bf0e39
--- /dev/null
+++ b/javatests/artifacts/dagger-android-ksp/app/src/main/res/values/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2023 The Dagger Authors.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~ http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<resources>
+  <!--The app name [CHAR_LIMIT=25]-->
+  <string name="appName">Simple Dagger Android</string>
+
+  <!--The greeting message [CHAR_LIMIT=100]-->
+  <string name="welcome">Hello, %1$s! You are on build %2$s.</string>
+</resources>
\ No newline at end of file
diff --git a/javatests/artifacts/dagger-android-ksp/app/src/sharedTest/kotlin/dagger/android/ksp/SimpleActivityTest.kt b/javatests/artifacts/dagger-android-ksp/app/src/sharedTest/kotlin/dagger/android/ksp/SimpleActivityTest.kt
new file mode 100644
index 0000000..22a2efb
--- /dev/null
+++ b/javatests/artifacts/dagger-android-ksp/app/src/sharedTest/kotlin/dagger/android/ksp/SimpleActivityTest.kt
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.android.ksp
+
+import android.content.Context
+import androidx.test.core.app.ActivityScenario
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.espresso.Espresso.onView
+import androidx.test.espresso.assertion.ViewAssertions.matches
+import androidx.test.espresso.matcher.ViewMatchers.withId
+import androidx.test.espresso.matcher.ViewMatchers.withText
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class SimpleActivityTest {
+  @Test
+  fun testActivityInject() {
+    ActivityScenario.launch(SimpleActivity::class.java).onActivity { activity ->
+      onView(withId(R.id.greeting))
+        .check(matches(withText("Hello, ProdUser! You are on build robolectric.")))
+    }
+  }
+
+  @Test
+  fun verifyApplicationInstance() {
+    assertThat((ApplicationProvider.getApplicationContext() as Context) is SimpleApplication)
+      .isTrue()
+  }
+}
diff --git a/javatests/artifacts/dagger-android-ksp/build.gradle b/javatests/artifacts/dagger-android-ksp/build.gradle
new file mode 100644
index 0000000..2aa0605
--- /dev/null
+++ b/javatests/artifacts/dagger-android-ksp/build.gradle
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+buildscript {
+    ext {
+        agp_version = "8.1.0"
+        kotlin_version = "1.9.20"
+        ksp_version = "$kotlin_version-1.0.14"
+    }
+    repositories {
+        google()
+        mavenCentral()
+        mavenLocal()
+    }
+    dependencies {
+        classpath "com.android.tools.build:gradle:$agp_version"
+        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+        classpath "com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin:$ksp_version"
+    }
+}
+
+allprojects {
+    repositories {
+        google()
+        mavenCentral()
+        mavenLocal()
+    }
+}
+
+task clean(type: Delete) {
+    delete rootProject.buildDir
+}
\ No newline at end of file
diff --git a/javatests/artifacts/dagger-android-ksp/gradle.properties b/javatests/artifacts/dagger-android-ksp/gradle.properties
new file mode 100644
index 0000000..0bdf325
--- /dev/null
+++ b/javatests/artifacts/dagger-android-ksp/gradle.properties
@@ -0,0 +1,4 @@
+android.useAndroidX=true
+org.gradle.caching=true
+org.gradle.parallel=true
+org.gradle.jvmargs=-Xmx2048m
\ No newline at end of file
diff --git a/javatests/artifacts/dagger-android-ksp/gradle/wrapper/gradle-wrapper.jar b/javatests/artifacts/dagger-android-ksp/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..7f93135
--- /dev/null
+++ b/javatests/artifacts/dagger-android-ksp/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/javatests/artifacts/dagger-android-ksp/gradle/wrapper/gradle-wrapper.properties b/javatests/artifacts/dagger-android-ksp/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..3fa8f86
--- /dev/null
+++ b/javatests/artifacts/dagger-android-ksp/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,7 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
+networkTimeout=10000
+validateDistributionUrl=true
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/javatests/artifacts/dagger-android-ksp/gradlew b/javatests/artifacts/dagger-android-ksp/gradlew
new file mode 100755
index 0000000..1aa94a4
--- /dev/null
+++ b/javatests/artifacts/dagger-android-ksp/gradlew
@@ -0,0 +1,249 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+#
+#   Gradle start up script for POSIX generated by Gradle.
+#
+#   Important for running:
+#
+#   (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+#       noncompliant, but you have some other compliant shell such as ksh or
+#       bash, then to run this script, type that shell name before the whole
+#       command line, like:
+#
+#           ksh Gradle
+#
+#       Busybox and similar reduced shells will NOT work, because this script
+#       requires all of these POSIX shell features:
+#         * functions;
+#         * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+#           «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+#         * compound commands having a testable exit status, especially «case»;
+#         * various built-in commands including «command», «set», and «ulimit».
+#
+#   Important for patching:
+#
+#   (2) This script targets any POSIX shell, so it avoids extensions provided
+#       by Bash, Ksh, etc; in particular arrays are avoided.
+#
+#       The "traditional" practice of packing multiple parameters into a
+#       space-separated string is a well documented source of bugs and security
+#       problems, so this is (mostly) avoided, by progressively accumulating
+#       options in "$@", and eventually passing that to Java.
+#
+#       Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+#       and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+#       see the in-line comments for details.
+#
+#       There are tweaks for specific operating systems such as AIX, CygWin,
+#       Darwin, MinGW, and NonStop.
+#
+#   (3) This script is generated from the Groovy template
+#       https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+#       within the Gradle project.
+#
+#       You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+    APP_HOME=${app_path%"${app_path##*/}"}  # leaves a trailing /; empty if no leading path
+    [ -h "$app_path" ]
+do
+    ls=$( ls -ld "$app_path" )
+    link=${ls#*' -> '}
+    case $link in             #(
+      /*)   app_path=$link ;; #(
+      *)    app_path=$APP_HOME$link ;;
+    esac
+done
+
+# This is normally unused
+# shellcheck disable=SC2034
+APP_BASE_NAME=${0##*/}
+# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
+APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+    echo "$*"
+} >&2
+
+die () {
+    echo
+    echo "$*"
+    echo
+    exit 1
+} >&2
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "$( uname )" in                #(
+  CYGWIN* )         cygwin=true  ;; #(
+  Darwin* )         darwin=true  ;; #(
+  MSYS* | MINGW* )  msys=true    ;; #(
+  NONSTOP* )        nonstop=true ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD=$JAVA_HOME/jre/sh/java
+    else
+        JAVACMD=$JAVA_HOME/bin/java
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD=java
+    if ! command -v java >/dev/null 2>&1
+    then
+        die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+    case $MAX_FD in #(
+      max*)
+        # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
+        # shellcheck disable=SC2039,SC3045
+        MAX_FD=$( ulimit -H -n ) ||
+            warn "Could not query maximum file descriptor limit"
+    esac
+    case $MAX_FD in  #(
+      '' | soft) :;; #(
+      *)
+        # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
+        # shellcheck disable=SC2039,SC3045
+        ulimit -n "$MAX_FD" ||
+            warn "Could not set maximum file descriptor limit to $MAX_FD"
+    esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+#   * args from the command line
+#   * the main class name
+#   * -classpath
+#   * -D...appname settings
+#   * --module-path (only if needed)
+#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+    APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+    CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+    JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    for arg do
+        if
+            case $arg in                                #(
+              -*)   false ;;                            # don't mess with options #(
+              /?*)  t=${arg#/} t=/${t%%/*}              # looks like a POSIX filepath
+                    [ -e "$t" ] ;;                      #(
+              *)    false ;;
+            esac
+        then
+            arg=$( cygpath --path --ignore --mixed "$arg" )
+        fi
+        # Roll the args list around exactly as many times as the number of
+        # args, so each arg winds up back in the position where it started, but
+        # possibly modified.
+        #
+        # NB: a `for` loop captures its iteration list before it begins, so
+        # changing the positional parameters here affects neither the number of
+        # iterations, nor the values presented in `arg`.
+        shift                   # remove old arg
+        set -- "$@" "$arg"      # push replacement arg
+    done
+fi
+
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Collect all arguments for the java command:
+#   * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
+#     and any embedded shellness will be escaped.
+#   * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
+#     treated as '${Hostname}' itself on the command line.
+
+set -- \
+        "-Dorg.gradle.appname=$APP_BASE_NAME" \
+        -classpath "$CLASSPATH" \
+        org.gradle.wrapper.GradleWrapperMain \
+        "$@"
+
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+    die "xargs is not available"
+fi
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+#   readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+#   set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+        printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+        xargs -n1 |
+        sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+        tr '\n' ' '
+    )" '"$@"'
+
+exec "$JAVACMD" "$@"
diff --git a/javatests/artifacts/dagger-android-ksp/gradlew.bat b/javatests/artifacts/dagger-android-ksp/gradlew.bat
new file mode 100644
index 0000000..93e3f59
--- /dev/null
+++ b/javatests/artifacts/dagger-android-ksp/gradlew.bat
@@ -0,0 +1,92 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem      https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%"=="" @echo off
+@rem ##########################################################################
+@rem
+@rem  Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%"=="" set DIRNAME=.
+@rem This is normally unused
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if %ERRORLEVEL% equ 0 goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if %ERRORLEVEL% equ 0 goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+set EXIT_CODE=%ERRORLEVEL%
+if %EXIT_CODE% equ 0 set EXIT_CODE=1
+if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
+exit /b %EXIT_CODE%
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/javatests/artifacts/dagger-android-ksp/settings.gradle b/javatests/artifacts/dagger-android-ksp/settings.gradle
new file mode 100644
index 0000000..ae4079c
--- /dev/null
+++ b/javatests/artifacts/dagger-android-ksp/settings.gradle
@@ -0,0 +1,9 @@
+/*
+ * This file was generated by the Gradle 'init' task.
+ *
+ * The settings file is used to specify which projects to include in your build.
+ * For more detailed information on multi-project builds, please refer to https://docs.gradle.org/8.4/userguide/building_swift_projects.html in the Gradle documentation.
+ */
+
+rootProject.name = 'dagger-android-ksp'
+include('app')
diff --git a/javatests/artifacts/dagger-android/simple/app/build.gradle b/javatests/artifacts/dagger-android/simple/app/build.gradle
index be30b3b..881a304 100644
--- a/javatests/artifacts/dagger-android/simple/app/build.gradle
+++ b/javatests/artifacts/dagger-android/simple/app/build.gradle
@@ -17,13 +17,13 @@
 apply plugin: 'com.android.application'
 
 android {
-    compileSdkVersion 32
-    buildToolsVersion "32.0.0"
+    compileSdkVersion 33
+    buildToolsVersion "33.0.0"
 
     defaultConfig {
         applicationId "dagger.android.simple"
-        minSdkVersion 15
-        targetSdkVersion 32
+        minSdkVersion 16
+        targetSdkVersion 33
         versionCode 1
         versionName "1.0"
     }
diff --git a/javatests/artifacts/dagger-android/simple/gradle.properties b/javatests/artifacts/dagger-android/simple/gradle.properties
index 6cde789..0bdf325 100644
--- a/javatests/artifacts/dagger-android/simple/gradle.properties
+++ b/javatests/artifacts/dagger-android/simple/gradle.properties
@@ -1,3 +1,4 @@
 android.useAndroidX=true
 org.gradle.caching=true
-org.gradle.parallel=true
\ No newline at end of file
+org.gradle.parallel=true
+org.gradle.jvmargs=-Xmx2048m
\ No newline at end of file
diff --git a/javatests/artifacts/dagger-android/simple/gradle/wrapper/gradle-wrapper.properties b/javatests/artifacts/dagger-android/simple/gradle/wrapper/gradle-wrapper.properties
index 00e33ed..98debb8 100644
--- a/javatests/artifacts/dagger-android/simple/gradle/wrapper/gradle-wrapper.properties
+++ b/javatests/artifacts/dagger-android/simple/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.1-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.2-bin.zip
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
diff --git a/javatests/artifacts/dagger-ksp/build.gradle b/javatests/artifacts/dagger-ksp/build.gradle
index 9e92640..35aea20 100644
--- a/javatests/artifacts/dagger-ksp/build.gradle
+++ b/javatests/artifacts/dagger-ksp/build.gradle
@@ -17,8 +17,8 @@
 buildscript {
   ext {
     dagger_version = "LOCAL-SNAPSHOT"
-    kotlin_version = "1.8.0"
-    ksp_version = "1.8.0-1.0.9"
+    kotlin_version = "1.9.20"
+    ksp_version = "$kotlin_version-1.0.14"
     junit_version = "4.13"
     truth_version = "1.0.1"
   }
@@ -27,6 +27,7 @@
     mavenLocal()
   }
   dependencies {
+    classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version")
     classpath("com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin:$ksp_version")
   }
 }
diff --git a/javatests/artifacts/dagger-ksp/gradle.properties b/javatests/artifacts/dagger-ksp/gradle.properties
index e68633c..a516e45 100644
--- a/javatests/artifacts/dagger-ksp/gradle.properties
+++ b/javatests/artifacts/dagger-ksp/gradle.properties
@@ -1,2 +1,3 @@
 org.gradle.caching=true
-org.gradle.parallel=true
\ No newline at end of file
+org.gradle.parallel=true
+org.gradle.jvmargs=-Xmx2048m
\ No newline at end of file
diff --git a/javatests/artifacts/dagger-ksp/gradle/wrapper/gradle-wrapper.properties b/javatests/artifacts/dagger-ksp/gradle/wrapper/gradle-wrapper.properties
index 0f80bbf..98debb8 100644
--- a/javatests/artifacts/dagger-ksp/gradle/wrapper/gradle-wrapper.properties
+++ b/javatests/artifacts/dagger-ksp/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.2-bin.zip
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
diff --git a/javatests/artifacts/dagger-ksp/transitive-annotation-app/library1/src/main/java/library1/MySubcomponentWithBuilder.java b/javatests/artifacts/dagger-ksp/transitive-annotation-app/library1/src/main/java/library1/MySubcomponentWithBuilder.java
index 27045ea..1aa04f1 100644
--- a/javatests/artifacts/dagger-ksp/transitive-annotation-app/library1/src/main/java/library1/MySubcomponentWithBuilder.java
+++ b/javatests/artifacts/dagger-ksp/transitive-annotation-app/library1/src/main/java/library1/MySubcomponentWithBuilder.java
@@ -29,9 +29,9 @@
  * the classpath. In most cases, Dagger shouldn't care that the annotation isn't on the classpath
  */
 // TODO(b/219587431): Support @MyTransitiveAnnotation (Requires generating metadata).
-@MySubcomponentScope // TODO(b/269172737): Fix issue that requires reordering to build successfully.
 @MyAnnotation(MyTransitiveType.VALUE)
 @MyOtherAnnotation(MyTransitiveType.class)
+@MySubcomponentScope
 @Subcomponent(modules = MySubcomponentModule.class)
 public abstract class MySubcomponentWithBuilder {
   @MyQualifier
diff --git a/javatests/artifacts/dagger-ksp/transitive-annotation-app/library1/src/main/java/library1/MySubcomponentWithFactory.java b/javatests/artifacts/dagger-ksp/transitive-annotation-app/library1/src/main/java/library1/MySubcomponentWithFactory.java
index 9005193..baac297 100644
--- a/javatests/artifacts/dagger-ksp/transitive-annotation-app/library1/src/main/java/library1/MySubcomponentWithFactory.java
+++ b/javatests/artifacts/dagger-ksp/transitive-annotation-app/library1/src/main/java/library1/MySubcomponentWithFactory.java
@@ -29,9 +29,9 @@
  * the classpath. In most cases, Dagger shouldn't care that the annotation isn't on the classpath
  */
 // TODO(b/219587431): Support @MyTransitiveAnnotation (Requires generating metadata).
-@MySubcomponentScope // TODO(b/269172737): Fix issue that requires reordering to build successfully.
 @MyAnnotation(MyTransitiveType.VALUE)
 @MyOtherAnnotation(MyTransitiveType.class)
+@MySubcomponentScope
 @Subcomponent(modules = MySubcomponentModule.class)
 public abstract class MySubcomponentWithFactory {
   // TODO(b/219587431): Support @MyTransitiveAnnotation (Requires generating metadata).
diff --git a/javatests/artifacts/dagger/build-tests/build.gradle b/javatests/artifacts/dagger/build-tests/build.gradle
index 2d2696d..7418b9f 100644
--- a/javatests/artifacts/dagger/build-tests/build.gradle
+++ b/javatests/artifacts/dagger/build-tests/build.gradle
@@ -23,6 +23,7 @@
 test {
     systemProperty 'dagger_version', "$dagger_version"
     systemProperty 'kotlin_version', "$kotlin_version"
+    systemProperty 'ksp_version', "$ksp_version"
 }
 
 dependencies {
diff --git a/javatests/artifacts/dagger/build-tests/src/main/java/buildtests/GradleModule.java b/javatests/artifacts/dagger/build-tests/src/main/java/buildtests/GradleModule.java
index d02dd91..c4d53d6 100644
--- a/javatests/artifacts/dagger/build-tests/src/main/java/buildtests/GradleModule.java
+++ b/javatests/artifacts/dagger/build-tests/src/main/java/buildtests/GradleModule.java
@@ -20,6 +20,7 @@
 import java.io.File;
 import java.io.FileWriter;
 import java.io.IOException;
+import java.nio.file.Path;
 
 /** Used to create files for a Gradle module in a particular directory. */
 public final class GradleModule {
@@ -39,6 +40,10 @@
     this.moduleSrcDir = new File(moduleDir, "src/main/java/");
   }
 
+  public Path getDir() {
+    return moduleDir.toPath();
+  }
+
   public GradleModule addBuildFile(String... content) throws IOException {
     writeFile(createFile(moduleDir, "build.gradle"), content);
     return this;
diff --git a/javatests/artifacts/dagger/build-tests/src/test/java/buildtests/IncrementalProcessingTest.java b/javatests/artifacts/dagger/build-tests/src/test/java/buildtests/IncrementalProcessingTest.java
new file mode 100644
index 0000000..bb84b83
--- /dev/null
+++ b/javatests/artifacts/dagger/build-tests/src/test/java/buildtests/IncrementalProcessingTest.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package buildtests;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.gradle.testkit.runner.BuildResult;
+import org.gradle.testkit.runner.GradleRunner;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+// This is a regression test for https://github.com/google/dagger/issues/4054
+@RunWith(JUnit4.class)
+public class IncrementalProcessingTest {
+  @Rule public TemporaryFolder tmpFolder = new TemporaryFolder();
+
+  @Test
+  public void testIncrementalProcessing() throws IOException {
+    File projectDir = tmpFolder.getRoot();
+    GradleModule.create(projectDir)
+        .addSettingsFile("include 'app'")
+        .addBuildFile(
+            "buildscript {",
+            "  ext {",
+            String.format("dagger_version = \"%s\"", System.getProperty("dagger_version")),
+            String.format("kotlin_version = \"%s\"", System.getProperty("kotlin_version")),
+            String.format("ksp_version = \"%s\"", System.getProperty("ksp_version")),
+            "  }",
+            "}",
+            "",
+            "allprojects {",
+            "  repositories {",
+            "    mavenCentral()",
+            "    mavenLocal()",
+            "  }",
+            "}");
+
+    GradleModule appModule =
+        GradleModule.create(projectDir, "app")
+            .addBuildFile(
+                "plugins {",
+                "  id 'application'",
+                "  id 'org.jetbrains.kotlin.jvm' version \"$kotlin_version\"",
+                "  id 'com.google.devtools.ksp' version \"$ksp_version\"",
+                "}",
+                "dependencies {",
+                "  implementation \"org.jetbrains.kotlin:kotlin-stdlib\"",
+                "  implementation \"com.google.dagger:dagger:$dagger_version\"",
+                "  ksp \"com.google.dagger:dagger-compiler:$dagger_version\"",
+                "}")
+            // Note: both A and AFactory need to be in the same source file for this to test the
+            // regression in https://github.com/google/dagger/issues/4054.
+            .addSrcFile(
+                "A.kt",
+                "package app",
+                "",
+                "import dagger.assisted.AssistedFactory",
+                "import dagger.assisted.AssistedInject",
+                "",
+                "class A @AssistedInject constructor()",
+                "",
+                "@AssistedFactory",
+                "interface AFactory {",
+                "    fun create(): A",
+                "}");
+
+    // We'll be changing the contents of MyComponent between builds, so store it in a variable.
+    String myComponentContent =
+        String.join(
+            "\n",
+            "package app",
+            "",
+            "import dagger.Component",
+            "",
+            "@Component",
+            "interface MyComponent {",
+            "  fun factory(): AFactory",
+            "}");
+    appModule.addSrcFile("MyComponent.kt",  myComponentContent);
+
+    // Build #1
+    build(projectDir);
+    assertThat(getAllKspGeneratedFileNames(appModule.getDir()))
+        .containsExactly(
+            "A_Factory.java",
+            "AFactory_Impl.java",
+            "DaggerMyComponent.java");
+
+    // Change method name in MyComponent.kt to trigger incremental processing of only MyComponent.
+    appModule.addSrcFile("MyComponent.kt",  myComponentContent.replace("factory()", "factory2()"));
+
+    // Build #2
+    build(projectDir);
+    assertThat(getAllKspGeneratedFileNames(appModule.getDir()))
+        .containsExactly(
+            "A_Factory.java",
+            "AFactory_Impl.java",
+            "DaggerMyComponent.java");
+  }
+
+  private static BuildResult build(File projectDir) {
+    return GradleRunner.create()
+        .withArguments("--stacktrace", "build")
+        .withProjectDir(projectDir)
+        .build();
+  }
+
+  private static Set<String> getAllKspGeneratedFileNames(Path moduleDir) throws IOException {
+    return getAllFileNames(moduleDir.resolve("build/generated/ksp/main/java/"));
+  }
+
+  private static Set<String> getAllFileNames(Path dir) throws IOException {
+    if (!Files.isDirectory(dir)) {
+      throw new IllegalArgumentException("Expected directory: " + dir);
+    }
+    return Files.walk(dir)
+        .filter(Files::isRegularFile)
+        .map(file -> file.getFileName().toString())
+        .collect(Collectors.toSet());
+  }
+}
diff --git a/javatests/artifacts/dagger/build.gradle b/javatests/artifacts/dagger/build.gradle
index 314ee46..499b1ee 100644
--- a/javatests/artifacts/dagger/build.gradle
+++ b/javatests/artifacts/dagger/build.gradle
@@ -17,7 +17,8 @@
 buildscript {
   ext {
     dagger_version = "LOCAL-SNAPSHOT"
-    kotlin_version = "1.8.0"
+    kotlin_version = "1.9.20"
+    ksp_version = "$kotlin_version-1.0.14"
     junit_version = "4.13"
     truth_version = "1.0.1"
   }
diff --git a/javatests/artifacts/dagger/gradle.properties b/javatests/artifacts/dagger/gradle.properties
index e68633c..a516e45 100644
--- a/javatests/artifacts/dagger/gradle.properties
+++ b/javatests/artifacts/dagger/gradle.properties
@@ -1,2 +1,3 @@
 org.gradle.caching=true
-org.gradle.parallel=true
\ No newline at end of file
+org.gradle.parallel=true
+org.gradle.jvmargs=-Xmx2048m
\ No newline at end of file
diff --git a/javatests/artifacts/dagger/gradle/wrapper/gradle-wrapper.properties b/javatests/artifacts/dagger/gradle/wrapper/gradle-wrapper.properties
index 0f80bbf..98debb8 100644
--- a/javatests/artifacts/dagger/gradle/wrapper/gradle-wrapper.properties
+++ b/javatests/artifacts/dagger/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.2-bin.zip
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
diff --git a/javatests/artifacts/dagger/lazyclasskey/app/build.gradle b/javatests/artifacts/dagger/lazyclasskey/app/build.gradle
new file mode 100644
index 0000000..b44309a
--- /dev/null
+++ b/javatests/artifacts/dagger/lazyclasskey/app/build.gradle
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2024 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+plugins {
+    id 'com.android.application'
+}
+
+android {
+
+    namespace 'dagger.lazyclasskey'
+    compileSdkVersion 33
+    defaultConfig {
+        applicationId 'dagger.lazyclasskey'
+        minSdk 16
+        targetSdk 33
+        versionCode 1
+        versionName "1.0"
+        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+    }
+
+    buildTypes {
+        debug {
+            minifyEnabled true
+            shrinkResources true
+            proguardFiles getDefaultProguardFile(
+                    'proguard-android-optimize.txt'),
+                    'proguard-rules.pro'
+
+        }
+    }
+
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_11
+        targetCompatibility JavaVersion.VERSION_11
+    }
+}
+
+dependencies {
+    implementation 'androidx.appcompat:appcompat:1.2.0'
+    implementation 'com.google.errorprone:error_prone_annotations:2.15.0'
+
+    androidTestImplementation 'androidx.test:core:1.5.0-alpha02'
+    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
+    androidTestImplementation "androidx.test:runner:1.5.2"
+    androidTestImplementation "androidx.test:rules:1.5.0"
+    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
+
+    // Dagger dependencies
+    implementation "com.google.dagger:dagger:$dagger_version"
+    annotationProcessor "com.google.dagger:dagger-compiler:$dagger_version"
+}
diff --git a/javatests/artifacts/dagger/lazyclasskey/app/proguard-rules.pro b/javatests/artifacts/dagger/lazyclasskey/app/proguard-rules.pro
new file mode 100644
index 0000000..9598002
--- /dev/null
+++ b/javatests/artifacts/dagger/lazyclasskey/app/proguard-rules.pro
@@ -0,0 +1,5 @@
+
+-dontwarn com.google.errorprone.annotations.MustBeClosed
+ # TODO(b/324097623) Remove the keep rules once test won't be affected by obfuscation
+-keep class kotlin.**
+-keep class javax.** { *; }
diff --git a/javatests/artifacts/dagger/lazyclasskey/app/src/androidTest/java/dagger/lazyclasskey/FlowerAppTest.java b/javatests/artifacts/dagger/lazyclasskey/app/src/androidTest/java/dagger/lazyclasskey/FlowerAppTest.java
new file mode 100644
index 0000000..86e1401
--- /dev/null
+++ b/javatests/artifacts/dagger/lazyclasskey/app/src/androidTest/java/dagger/lazyclasskey/FlowerAppTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2024 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.lazyclasskey;
+
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.matcher.ViewMatchers.withResourceName;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
+import static org.hamcrest.Matchers.startsWith;
+
+import android.content.Intent;
+import androidx.test.core.app.ActivityScenario;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class FlowerAppTest {
+  @Test
+  public void testFlowerAppWithR8DoesNotCrash() {
+    Intent mainIntent =
+        new Intent(ApplicationProvider.getApplicationContext(), FlowerActivity.class);
+    try (ActivityScenario<FlowerActivity> scenario = ActivityScenario.launch(mainIntent)) {
+      onView(withResourceName("flower_info"))
+          .check(matches(withText(startsWith(Lily.class.getSimpleName()))));
+    }
+  }
+}
diff --git a/javatests/artifacts/dagger/lazyclasskey/app/src/main/AndroidManifest.xml b/javatests/artifacts/dagger/lazyclasskey/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..cec4061
--- /dev/null
+++ b/javatests/artifacts/dagger/lazyclasskey/app/src/main/AndroidManifest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2024 The Dagger Authors.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~ http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+  package="dagger.lazyclasskey">
+  <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="34"/>
+  <application
+      android:theme="@style/Theme.AppCompat.Light.NoActionBar"
+      android:taskAffinity=""
+      android:label="@string/app_name">
+      <activity
+          android:name=".FlowerActivity"
+          android:exported="true">
+        <intent-filter>
+          <action android:name="android.intent.action.MAIN"/>
+          <category android:name="android.intent.category.LAUNCHER"/>
+        </intent-filter>
+      </activity>
+  </application>
+</manifest>
+
diff --git a/java/dagger/spi/model/CompilerEnvironment.java b/javatests/artifacts/dagger/lazyclasskey/app/src/main/java/dagger/lazyclasskey/Flower.java
similarity index 74%
rename from java/dagger/spi/model/CompilerEnvironment.java
rename to javatests/artifacts/dagger/lazyclasskey/app/src/main/java/dagger/lazyclasskey/Flower.java
index 28553e4..34161a1 100644
--- a/java/dagger/spi/model/CompilerEnvironment.java
+++ b/javatests/artifacts/dagger/lazyclasskey/app/src/main/java/dagger/lazyclasskey/Flower.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Dagger Authors.
+ * Copyright (C) 2024 The Dagger Authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,10 +14,7 @@
  * limitations under the License.
  */
 
-package dagger.spi.model;
+package dagger.lazyclasskey;
 
-/** Types for the compiler in use for annotation processing. */
-public enum CompilerEnvironment {
-  JAVA,
-  KSP
-}
+/** Base class for flowers. */
+interface Flower {}
diff --git a/javatests/artifacts/dagger/lazyclasskey/app/src/main/java/dagger/lazyclasskey/FlowerActivity.java b/javatests/artifacts/dagger/lazyclasskey/app/src/main/java/dagger/lazyclasskey/FlowerActivity.java
new file mode 100644
index 0000000..0050127
--- /dev/null
+++ b/javatests/artifacts/dagger/lazyclasskey/app/src/main/java/dagger/lazyclasskey/FlowerActivity.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2024 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.lazyclasskey;
+
+import android.os.Bundle;
+import android.widget.TextView;
+import androidx.activity.ComponentActivity;
+import java.util.Locale;
+import java.util.Map;
+
+/** Displays flower price information. */
+public final class FlowerActivity extends ComponentActivity {
+  public void onCreate(Bundle savedInstanceState) {
+    super.onCreate(savedInstanceState);
+    Map<Class<?>, Integer> flowerPrices = DaggerFlowerComponent.create().getFlowerMap();
+    setContentView(R.layout.flower_activity);
+    if (!flowerPrices.containsKey(Rose.class)) {
+      throw new IllegalStateException("Rose price not found");
+    }
+    if (!flowerPrices.containsKey(Lily.class)) {
+      throw new IllegalStateException("Lily price not found");
+    }
+    ((TextView) findViewById(R.id.flower_info))
+        .setText(
+            String.format(
+                Locale.US,
+                "%s : %d dollar, %s : %d dollar",
+                Lily.class.getSimpleName(),
+                flowerPrices.get(Lily.class),
+                Rose.class.getSimpleName(),
+                flowerPrices.get(Rose.class)));
+  }
+
+  class ProguardClassNames {
+    Rose rose;
+    Lily lily;
+  }
+}
diff --git a/java/dagger/spi/model/CompilerEnvironment.java b/javatests/artifacts/dagger/lazyclasskey/app/src/main/java/dagger/lazyclasskey/FlowerComponent.java
similarity index 66%
copy from java/dagger/spi/model/CompilerEnvironment.java
copy to javatests/artifacts/dagger/lazyclasskey/app/src/main/java/dagger/lazyclasskey/FlowerComponent.java
index 28553e4..1302126 100644
--- a/java/dagger/spi/model/CompilerEnvironment.java
+++ b/javatests/artifacts/dagger/lazyclasskey/app/src/main/java/dagger/lazyclasskey/FlowerComponent.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Dagger Authors.
+ * Copyright (C) 2024 The Dagger Authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,10 +14,13 @@
  * limitations under the License.
  */
 
-package dagger.spi.model;
+package dagger.lazyclasskey;
 
-/** Types for the compiler in use for annotation processing. */
-public enum CompilerEnvironment {
-  JAVA,
-  KSP
+import dagger.Component;
+import java.util.Map;
+
+/** Dagger component for flower bindings. */
+@Component(modules = FlowerModule.class)
+public interface FlowerComponent {
+  Map<Class<?>, Integer> getFlowerMap();
 }
diff --git a/javatests/artifacts/dagger/lazyclasskey/app/src/main/java/dagger/lazyclasskey/FlowerModule.java b/javatests/artifacts/dagger/lazyclasskey/app/src/main/java/dagger/lazyclasskey/FlowerModule.java
new file mode 100644
index 0000000..4f9b61c
--- /dev/null
+++ b/javatests/artifacts/dagger/lazyclasskey/app/src/main/java/dagger/lazyclasskey/FlowerModule.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2024 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.lazyclasskey;
+
+import dagger.Module;
+import dagger.Provides;
+import dagger.multibindings.IntoMap;
+import dagger.multibindings.LazyClassKey;
+
+/** Module for providing flower prices. */
+@Module
+abstract class FlowerModule {
+  @IntoMap
+  @LazyClassKey(Lily.class)
+  @Provides
+  static int lilyPrice() {
+    return 1;
+  }
+
+  @IntoMap
+  @LazyClassKey(Rose.class)
+  @Provides
+  static int rosePrice() {
+    return 2;
+  }
+}
diff --git a/java/dagger/spi/model/CompilerEnvironment.java b/javatests/artifacts/dagger/lazyclasskey/app/src/main/java/dagger/lazyclasskey/Lily.java
similarity index 74%
copy from java/dagger/spi/model/CompilerEnvironment.java
copy to javatests/artifacts/dagger/lazyclasskey/app/src/main/java/dagger/lazyclasskey/Lily.java
index 28553e4..c8c21be 100644
--- a/java/dagger/spi/model/CompilerEnvironment.java
+++ b/javatests/artifacts/dagger/lazyclasskey/app/src/main/java/dagger/lazyclasskey/Lily.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Dagger Authors.
+ * Copyright (C) 2024 The Dagger Authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,10 +14,7 @@
  * limitations under the License.
  */
 
-package dagger.spi.model;
+package dagger.lazyclasskey;
 
-/** Types for the compiler in use for annotation processing. */
-public enum CompilerEnvironment {
-  JAVA,
-  KSP
-}
+/** Stores info for Lily. */
+final class Lily implements Flower {}
diff --git a/java/dagger/spi/model/CompilerEnvironment.java b/javatests/artifacts/dagger/lazyclasskey/app/src/main/java/dagger/lazyclasskey/Rose.java
similarity index 74%
copy from java/dagger/spi/model/CompilerEnvironment.java
copy to javatests/artifacts/dagger/lazyclasskey/app/src/main/java/dagger/lazyclasskey/Rose.java
index 28553e4..abdd87a 100644
--- a/java/dagger/spi/model/CompilerEnvironment.java
+++ b/javatests/artifacts/dagger/lazyclasskey/app/src/main/java/dagger/lazyclasskey/Rose.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Dagger Authors.
+ * Copyright (C) 2024 The Dagger Authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,10 +14,7 @@
  * limitations under the License.
  */
 
-package dagger.spi.model;
+package dagger.lazyclasskey;
 
-/** Types for the compiler in use for annotation processing. */
-public enum CompilerEnvironment {
-  JAVA,
-  KSP
-}
+/** Stores information for Rose. */
+final class Rose implements Flower {}
diff --git a/javatests/artifacts/dagger/lazyclasskey/app/src/main/res/layout/flower_activity.xml b/javatests/artifacts/dagger/lazyclasskey/app/src/main/res/layout/flower_activity.xml
new file mode 100644
index 0000000..400691d
--- /dev/null
+++ b/javatests/artifacts/dagger/lazyclasskey/app/src/main/res/layout/flower_activity.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2024 The Dagger Authors.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~ http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<LinearLayout
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical">
+     <TextView android:id="@+id/flower_info"
+              android:layout_width="wrap_content"
+              android:layout_height="wrap_content" />
+</LinearLayout>
+
diff --git a/javatests/artifacts/dagger/lazyclasskey/app/src/main/res/values/strings.xml b/javatests/artifacts/dagger/lazyclasskey/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..72ad12a
--- /dev/null
+++ b/javatests/artifacts/dagger/lazyclasskey/app/src/main/res/values/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2024 The Dagger Authors.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~ http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<resources>
+  <!-- The name of the application [CHAR LIMIT=25] -->
+  <string name="app_name">Flower Demo</string>
+</resources>
+
diff --git a/javatests/artifacts/dagger/lazyclasskey/build.gradle b/javatests/artifacts/dagger/lazyclasskey/build.gradle
new file mode 100644
index 0000000..a0d4252
--- /dev/null
+++ b/javatests/artifacts/dagger/lazyclasskey/build.gradle
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2024 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+buildscript {
+    ext {
+        dagger_version = 'LOCAL-SNAPSHOT'
+        // AGP is set below 7.2.0 on purpose to be able to obfuscate debug apk.
+        agp_version = "7.1.2"
+        kotlin_version = '1.9.20'
+    }
+    repositories {
+        google()
+        mavenCentral()
+        mavenLocal()
+    }
+    dependencies {
+        classpath "com.android.tools.build:gradle:$agp_version"
+        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+    }
+}
+
+allprojects {
+    repositories {
+        google()
+        mavenCentral()
+        mavenLocal()
+    }
+}
+
+subprojects {
+    afterEvaluate {
+        dependencies {
+            // This is needed to align older versions of kotlin-stdlib.
+            // The main issue is that in v1.8.0 the jdk7 and jdk8 artifacts were
+            // merged into kotlin-stdlib, so without this alignment we end up
+            // getting duplicate classes by pulling in both artifacts.
+            // See: https://kotlinlang.org/docs/whatsnew18.html#usage-of-the-latest-kotlin-stdlib-version-in-transitive-dependencies
+            implementation(platform("org.jetbrains.kotlin:kotlin-bom:$kotlin_version"))
+        }
+    }
+}
+
+task clean(type: Delete) {
+    delete rootProject.buildDir
+}
diff --git a/javatests/artifacts/dagger/lazyclasskey/gradle.properties b/javatests/artifacts/dagger/lazyclasskey/gradle.properties
new file mode 100644
index 0000000..abca46e
--- /dev/null
+++ b/javatests/artifacts/dagger/lazyclasskey/gradle.properties
@@ -0,0 +1,12 @@
+android.useAndroidX=true
+android.enableJetifier=true
+
+# Enable and fail the build if an issue is found that disallows the
+# configuration cache. These options along with this app being built in
+# presubmit helps us cache changes that would cause config cache to be disabled
+# via the HiltGradlePlugin.
+org.gradle.unsafe.configuration-cache-problems=fail
+org.gradle.unsafe.configuration-cache.max-problems=0
+org.gradle.caching=true
+org.gradle.parallel=true
+org.gradle.jvmargs=-Xmx2048m
diff --git a/javatests/artifacts/dagger/lazyclasskey/gradle/wrapper/gradle-wrapper.jar b/javatests/artifacts/dagger/lazyclasskey/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..d64cd49
--- /dev/null
+++ b/javatests/artifacts/dagger/lazyclasskey/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/javatests/artifacts/dagger/lazyclasskey/gradle/wrapper/gradle-wrapper.properties b/javatests/artifacts/dagger/lazyclasskey/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..9623276
--- /dev/null
+++ b/javatests/artifacts/dagger/lazyclasskey/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,7 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
+networkTimeout=10000
+validateDistributionUrl=true
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/javatests/artifacts/dagger/lazyclasskey/gradlew b/javatests/artifacts/dagger/lazyclasskey/gradlew
new file mode 100755
index 0000000..1aa94a4
--- /dev/null
+++ b/javatests/artifacts/dagger/lazyclasskey/gradlew
@@ -0,0 +1,249 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+#
+#   Gradle start up script for POSIX generated by Gradle.
+#
+#   Important for running:
+#
+#   (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+#       noncompliant, but you have some other compliant shell such as ksh or
+#       bash, then to run this script, type that shell name before the whole
+#       command line, like:
+#
+#           ksh Gradle
+#
+#       Busybox and similar reduced shells will NOT work, because this script
+#       requires all of these POSIX shell features:
+#         * functions;
+#         * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+#           «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+#         * compound commands having a testable exit status, especially «case»;
+#         * various built-in commands including «command», «set», and «ulimit».
+#
+#   Important for patching:
+#
+#   (2) This script targets any POSIX shell, so it avoids extensions provided
+#       by Bash, Ksh, etc; in particular arrays are avoided.
+#
+#       The "traditional" practice of packing multiple parameters into a
+#       space-separated string is a well documented source of bugs and security
+#       problems, so this is (mostly) avoided, by progressively accumulating
+#       options in "$@", and eventually passing that to Java.
+#
+#       Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+#       and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+#       see the in-line comments for details.
+#
+#       There are tweaks for specific operating systems such as AIX, CygWin,
+#       Darwin, MinGW, and NonStop.
+#
+#   (3) This script is generated from the Groovy template
+#       https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+#       within the Gradle project.
+#
+#       You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+    APP_HOME=${app_path%"${app_path##*/}"}  # leaves a trailing /; empty if no leading path
+    [ -h "$app_path" ]
+do
+    ls=$( ls -ld "$app_path" )
+    link=${ls#*' -> '}
+    case $link in             #(
+      /*)   app_path=$link ;; #(
+      *)    app_path=$APP_HOME$link ;;
+    esac
+done
+
+# This is normally unused
+# shellcheck disable=SC2034
+APP_BASE_NAME=${0##*/}
+# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
+APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+    echo "$*"
+} >&2
+
+die () {
+    echo
+    echo "$*"
+    echo
+    exit 1
+} >&2
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "$( uname )" in                #(
+  CYGWIN* )         cygwin=true  ;; #(
+  Darwin* )         darwin=true  ;; #(
+  MSYS* | MINGW* )  msys=true    ;; #(
+  NONSTOP* )        nonstop=true ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD=$JAVA_HOME/jre/sh/java
+    else
+        JAVACMD=$JAVA_HOME/bin/java
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD=java
+    if ! command -v java >/dev/null 2>&1
+    then
+        die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+    case $MAX_FD in #(
+      max*)
+        # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
+        # shellcheck disable=SC2039,SC3045
+        MAX_FD=$( ulimit -H -n ) ||
+            warn "Could not query maximum file descriptor limit"
+    esac
+    case $MAX_FD in  #(
+      '' | soft) :;; #(
+      *)
+        # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
+        # shellcheck disable=SC2039,SC3045
+        ulimit -n "$MAX_FD" ||
+            warn "Could not set maximum file descriptor limit to $MAX_FD"
+    esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+#   * args from the command line
+#   * the main class name
+#   * -classpath
+#   * -D...appname settings
+#   * --module-path (only if needed)
+#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+    APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+    CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+    JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    for arg do
+        if
+            case $arg in                                #(
+              -*)   false ;;                            # don't mess with options #(
+              /?*)  t=${arg#/} t=/${t%%/*}              # looks like a POSIX filepath
+                    [ -e "$t" ] ;;                      #(
+              *)    false ;;
+            esac
+        then
+            arg=$( cygpath --path --ignore --mixed "$arg" )
+        fi
+        # Roll the args list around exactly as many times as the number of
+        # args, so each arg winds up back in the position where it started, but
+        # possibly modified.
+        #
+        # NB: a `for` loop captures its iteration list before it begins, so
+        # changing the positional parameters here affects neither the number of
+        # iterations, nor the values presented in `arg`.
+        shift                   # remove old arg
+        set -- "$@" "$arg"      # push replacement arg
+    done
+fi
+
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Collect all arguments for the java command:
+#   * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
+#     and any embedded shellness will be escaped.
+#   * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
+#     treated as '${Hostname}' itself on the command line.
+
+set -- \
+        "-Dorg.gradle.appname=$APP_BASE_NAME" \
+        -classpath "$CLASSPATH" \
+        org.gradle.wrapper.GradleWrapperMain \
+        "$@"
+
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+    die "xargs is not available"
+fi
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+#   readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+#   set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+        printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+        xargs -n1 |
+        sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+        tr '\n' ' '
+    )" '"$@"'
+
+exec "$JAVACMD" "$@"
diff --git a/javatests/artifacts/dagger/lazyclasskey/gradlew.bat b/javatests/artifacts/dagger/lazyclasskey/gradlew.bat
new file mode 100644
index 0000000..93e3f59
--- /dev/null
+++ b/javatests/artifacts/dagger/lazyclasskey/gradlew.bat
@@ -0,0 +1,92 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem      https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%"=="" @echo off
+@rem ##########################################################################
+@rem
+@rem  Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%"=="" set DIRNAME=.
+@rem This is normally unused
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if %ERRORLEVEL% equ 0 goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if %ERRORLEVEL% equ 0 goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+set EXIT_CODE=%ERRORLEVEL%
+if %EXIT_CODE% equ 0 set EXIT_CODE=1
+if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
+exit /b %EXIT_CODE%
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/javatests/artifacts/dagger/lazyclasskey/settings.gradle b/javatests/artifacts/dagger/lazyclasskey/settings.gradle
new file mode 100644
index 0000000..5bb49fa
--- /dev/null
+++ b/javatests/artifacts/dagger/lazyclasskey/settings.gradle
@@ -0,0 +1,2 @@
+rootProject.name = 'lazyclasskey'
+include('app')
diff --git a/javatests/artifacts/hilt-android/lazyclasskey/app/build.gradle b/javatests/artifacts/hilt-android/lazyclasskey/app/build.gradle
new file mode 100644
index 0000000..0f854cb
--- /dev/null
+++ b/javatests/artifacts/hilt-android/lazyclasskey/app/build.gradle
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2024 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+plugins {
+    id 'com.android.application'
+    id 'com.google.dagger.hilt.android'
+}
+
+android {
+
+    namespace 'hilt.lazyclasskey'
+    compileSdkVersion 33
+    defaultConfig {
+        applicationId 'hilt.lazyclasskey'
+        minSdk 16
+        targetSdk 33
+        versionCode 1
+        versionName "1.0"
+        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+    }
+
+    buildTypes {
+        debug {
+            minifyEnabled true
+            shrinkResources true
+            proguardFiles getDefaultProguardFile(
+                    'proguard-android-optimize.txt'),
+                    'proguard-rules.pro'
+
+        }
+    }
+
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_11
+        targetCompatibility JavaVersion.VERSION_11
+    }
+}
+
+dependencies {
+    implementation 'androidx.appcompat:appcompat:1.2.0'
+    implementation 'com.google.errorprone:error_prone_annotations:2.15.0'
+
+    androidTestImplementation 'androidx.test:core:1.5.0-alpha02'
+    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
+    androidTestImplementation "androidx.test:runner:1.5.2"
+    androidTestImplementation "androidx.test:rules:1.5.0"
+    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
+
+    // Hilt dependencies
+    implementation "com.google.dagger:hilt-android:$hilt_version"
+    annotationProcessor "com.google.dagger:hilt-compiler:$hilt_version"
+}
\ No newline at end of file
diff --git a/javatests/artifacts/hilt-android/lazyclasskey/app/proguard-rules.pro b/javatests/artifacts/hilt-android/lazyclasskey/app/proguard-rules.pro
new file mode 100644
index 0000000..d389c43
--- /dev/null
+++ b/javatests/artifacts/hilt-android/lazyclasskey/app/proguard-rules.pro
@@ -0,0 +1,3 @@
+-dontwarn com.google.errorprone.annotations.MustBeClosed
+ # TODO(b/324097623) Remove the keep rules once test won't be affected by obfuscation
+-keep class kotlin.**
\ No newline at end of file
diff --git a/javatests/artifacts/hilt-android/lazyclasskey/app/src/androidTest/java/hilt/lazyclasskey/FlowerAppTest.java b/javatests/artifacts/hilt-android/lazyclasskey/app/src/androidTest/java/hilt/lazyclasskey/FlowerAppTest.java
new file mode 100644
index 0000000..a3cf1c3
--- /dev/null
+++ b/javatests/artifacts/hilt-android/lazyclasskey/app/src/androidTest/java/hilt/lazyclasskey/FlowerAppTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2024 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package hilt.lazyclasskey;
+
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.matcher.ViewMatchers.withResourceName;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
+import static org.hamcrest.Matchers.startsWith;
+
+import android.content.Intent;
+import androidx.test.core.app.ActivityScenario;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class FlowerAppTest {
+  @Test
+  public void testFlowerAppWithR8DoesNotCrash() {
+    Intent mainIntent =
+        new Intent(ApplicationProvider.getApplicationContext(), FlowerActivity.class);
+    try (ActivityScenario<FlowerActivity> scenario = ActivityScenario.launch(mainIntent)) {
+      onView(withResourceName("flower_info"))
+          .check(matches(withText(startsWith(Lily.class.getSimpleName()))));
+    }
+  }
+}
diff --git a/javatests/artifacts/hilt-android/lazyclasskey/app/src/main/AndroidManifest.xml b/javatests/artifacts/hilt-android/lazyclasskey/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..9a6ab88
--- /dev/null
+++ b/javatests/artifacts/hilt-android/lazyclasskey/app/src/main/AndroidManifest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2024 The Dagger Authors.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~ http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+  package="hilt.lazyclasskey">
+  <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="34"/>
+  <application android:name=".FlowerApp"
+      android:taskAffinity=""
+      android:theme="@style/Theme.AppCompat.Light.NoActionBar"
+      android:label="@string/app_name">
+      <activity
+          android:name=".FlowerActivity"
+          android:exported="true">
+        <intent-filter>
+          <action android:name="android.intent.action.MAIN"/>
+          <category android:name="android.intent.category.LAUNCHER"/>
+        </intent-filter>
+      </activity>
+  </application>
+</manifest>
diff --git a/java/dagger/spi/model/CompilerEnvironment.java b/javatests/artifacts/hilt-android/lazyclasskey/app/src/main/java/hilt/lazyclasskey/Flower.java
similarity index 74%
copy from java/dagger/spi/model/CompilerEnvironment.java
copy to javatests/artifacts/hilt-android/lazyclasskey/app/src/main/java/hilt/lazyclasskey/Flower.java
index 28553e4..f7d23fc 100644
--- a/java/dagger/spi/model/CompilerEnvironment.java
+++ b/javatests/artifacts/hilt-android/lazyclasskey/app/src/main/java/hilt/lazyclasskey/Flower.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Dagger Authors.
+ * Copyright (C) 2024 The Dagger Authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,10 +14,7 @@
  * limitations under the License.
  */
 
-package dagger.spi.model;
+package hilt.lazyclasskey;
 
-/** Types for the compiler in use for annotation processing. */
-public enum CompilerEnvironment {
-  JAVA,
-  KSP
-}
+/** Base class for flowers. */
+interface Flower {}
diff --git a/javatests/artifacts/hilt-android/lazyclasskey/app/src/main/java/hilt/lazyclasskey/FlowerActivity.java b/javatests/artifacts/hilt-android/lazyclasskey/app/src/main/java/hilt/lazyclasskey/FlowerActivity.java
new file mode 100644
index 0000000..b85bde0
--- /dev/null
+++ b/javatests/artifacts/hilt-android/lazyclasskey/app/src/main/java/hilt/lazyclasskey/FlowerActivity.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2024 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package hilt.lazyclasskey;
+
+import android.os.Bundle;
+import androidx.appcompat.app.AppCompatActivity;
+import android.widget.TextView;
+import dagger.hilt.android.AndroidEntryPoint;
+import java.util.Locale;
+import java.util.Map;
+import javax.inject.Inject;
+
+/** Displays flower price information. */
+@AndroidEntryPoint
+public final class FlowerActivity extends AppCompatActivity {
+  @Inject Map<Class<?>, Integer> flowerPrices;
+
+  @Override
+  public void onCreate(Bundle savedInstanceState) {
+    super.onCreate(savedInstanceState);
+    setContentView(R.layout.flower_activity);
+    if (!flowerPrices.containsKey(Rose.class)) {
+      throw new IllegalStateException("Rose price not found");
+    }
+    if (!flowerPrices.containsKey(Lily.class)) {
+      throw new IllegalStateException("Lily price not found");
+    }
+    ((TextView) findViewById(R.id.flower_info))
+        .setText(
+            String.format(
+                Locale.US,
+                "%s : %d dollar, %s : %d dollar",
+                Lily.class.getSimpleName(),
+                flowerPrices.get(Lily.class),
+                Rose.class.getSimpleName(),
+                flowerPrices.get(Rose.class)));
+  }
+}
diff --git a/java/dagger/spi/model/CompilerEnvironment.java b/javatests/artifacts/hilt-android/lazyclasskey/app/src/main/java/hilt/lazyclasskey/FlowerApp.java
similarity index 66%
copy from java/dagger/spi/model/CompilerEnvironment.java
copy to javatests/artifacts/hilt-android/lazyclasskey/app/src/main/java/hilt/lazyclasskey/FlowerApp.java
index 28553e4..337ae88 100644
--- a/java/dagger/spi/model/CompilerEnvironment.java
+++ b/javatests/artifacts/hilt-android/lazyclasskey/app/src/main/java/hilt/lazyclasskey/FlowerApp.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Dagger Authors.
+ * Copyright (C) 2024 The Dagger Authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,10 +14,11 @@
  * limitations under the License.
  */
 
-package dagger.spi.model;
+package hilt.lazyclasskey;
 
-/** Types for the compiler in use for annotation processing. */
-public enum CompilerEnvironment {
-  JAVA,
-  KSP
-}
+import android.app.Application;
+import dagger.hilt.android.HiltAndroidApp;
+
+/** The main app responsible for providing flower information. */
+@HiltAndroidApp
+public class FlowerApp extends Application {}
diff --git a/javatests/artifacts/hilt-android/lazyclasskey/app/src/main/java/hilt/lazyclasskey/FlowerModule.java b/javatests/artifacts/hilt-android/lazyclasskey/app/src/main/java/hilt/lazyclasskey/FlowerModule.java
new file mode 100644
index 0000000..3e04eac
--- /dev/null
+++ b/javatests/artifacts/hilt-android/lazyclasskey/app/src/main/java/hilt/lazyclasskey/FlowerModule.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2024 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package hilt.lazyclasskey;
+
+import dagger.Module;
+import dagger.Provides;
+import dagger.hilt.InstallIn;
+import dagger.hilt.components.SingletonComponent;
+import dagger.multibindings.IntoMap;
+import dagger.multibindings.LazyClassKey;
+
+/** Module for providing flower prices. */
+@Module
+@InstallIn(SingletonComponent.class)
+abstract class FlowerModule {
+  @IntoMap
+  @LazyClassKey(Lily.class)
+  @Provides
+  static int lilyPrice() {
+    return 1;
+  }
+
+  @IntoMap
+  @LazyClassKey(Rose.class)
+  @Provides
+  static int rosePrice() {
+    return 2;
+  }
+}
diff --git a/java/dagger/spi/model/CompilerEnvironment.java b/javatests/artifacts/hilt-android/lazyclasskey/app/src/main/java/hilt/lazyclasskey/Lily.java
similarity index 74%
copy from java/dagger/spi/model/CompilerEnvironment.java
copy to javatests/artifacts/hilt-android/lazyclasskey/app/src/main/java/hilt/lazyclasskey/Lily.java
index 28553e4..fc3831a 100644
--- a/java/dagger/spi/model/CompilerEnvironment.java
+++ b/javatests/artifacts/hilt-android/lazyclasskey/app/src/main/java/hilt/lazyclasskey/Lily.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Dagger Authors.
+ * Copyright (C) 2024 The Dagger Authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,10 +14,7 @@
  * limitations under the License.
  */
 
-package dagger.spi.model;
+package hilt.lazyclasskey;
 
-/** Types for the compiler in use for annotation processing. */
-public enum CompilerEnvironment {
-  JAVA,
-  KSP
-}
+/** Stores info for Lily. */
+final class Lily implements Flower {}
diff --git a/java/dagger/spi/model/CompilerEnvironment.java b/javatests/artifacts/hilt-android/lazyclasskey/app/src/main/java/hilt/lazyclasskey/Rose.java
similarity index 74%
copy from java/dagger/spi/model/CompilerEnvironment.java
copy to javatests/artifacts/hilt-android/lazyclasskey/app/src/main/java/hilt/lazyclasskey/Rose.java
index 28553e4..695d8fb 100644
--- a/java/dagger/spi/model/CompilerEnvironment.java
+++ b/javatests/artifacts/hilt-android/lazyclasskey/app/src/main/java/hilt/lazyclasskey/Rose.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Dagger Authors.
+ * Copyright (C) 2024 The Dagger Authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,10 +14,7 @@
  * limitations under the License.
  */
 
-package dagger.spi.model;
+package hilt.lazyclasskey;
 
-/** Types for the compiler in use for annotation processing. */
-public enum CompilerEnvironment {
-  JAVA,
-  KSP
-}
+/** Stores information for Rose. */
+final class Rose implements Flower {}
diff --git a/javatests/artifacts/hilt-android/lazyclasskey/app/src/main/res/layout/flower_activity.xml b/javatests/artifacts/hilt-android/lazyclasskey/app/src/main/res/layout/flower_activity.xml
new file mode 100644
index 0000000..1c6f03f
--- /dev/null
+++ b/javatests/artifacts/hilt-android/lazyclasskey/app/src/main/res/layout/flower_activity.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2024 The Dagger Authors.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~ http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<LinearLayout
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical">
+     <TextView android:id="@+id/flower_info"
+              android:layout_width="wrap_content"
+              android:layout_height="wrap_content" />
+</LinearLayout>
diff --git a/javatests/artifacts/hilt-android/lazyclasskey/app/src/main/res/values/strings.xml b/javatests/artifacts/hilt-android/lazyclasskey/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..55a2258
--- /dev/null
+++ b/javatests/artifacts/hilt-android/lazyclasskey/app/src/main/res/values/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2024 The Dagger Authors.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~ http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<resources>
+  <!-- The name of the application [CHAR LIMIT=25] -->
+  <string name="app_name">Flower Demo</string>
+</resources>
diff --git a/javatests/artifacts/hilt-android/lazyclasskey/build.gradle b/javatests/artifacts/hilt-android/lazyclasskey/build.gradle
new file mode 100644
index 0000000..14bbfbd
--- /dev/null
+++ b/javatests/artifacts/hilt-android/lazyclasskey/build.gradle
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2024 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+buildscript {
+    ext {
+        hilt_version = 'LOCAL-SNAPSHOT'
+        // AGP is set below 7.2.0 on purpose to be able to obfuscate debug apk.
+        agp_version = "7.1.2"
+        kotlin_version = '1.9.20'
+    }
+    repositories {
+        google()
+        mavenCentral()
+        mavenLocal()
+    }
+    dependencies {
+        classpath "com.android.tools.build:gradle:$agp_version"
+        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+	classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version"
+    }
+}
+
+allprojects {
+    repositories {
+        google()
+        mavenCentral()
+        mavenLocal()
+    }
+}
+
+subprojects {
+    afterEvaluate {
+        dependencies {
+            // This is needed to align older versions of kotlin-stdlib.
+            // The main issue is that in v1.8.0 the jdk7 and jdk8 artifacts were
+            // merged into kotlin-stdlib, so without this alignment we end up
+            // getting duplicate classes by pulling in both artifacts.
+            // See: https://kotlinlang.org/docs/whatsnew18.html#usage-of-the-latest-kotlin-stdlib-version-in-transitive-dependencies
+            implementation(platform("org.jetbrains.kotlin:kotlin-bom:$kotlin_version"))
+        }
+    }
+}
+
+task clean(type: Delete) {
+    delete rootProject.buildDir
+}
diff --git a/javatests/artifacts/hilt-android/lazyclasskey/gradle.properties b/javatests/artifacts/hilt-android/lazyclasskey/gradle.properties
new file mode 100644
index 0000000..abca46e
--- /dev/null
+++ b/javatests/artifacts/hilt-android/lazyclasskey/gradle.properties
@@ -0,0 +1,12 @@
+android.useAndroidX=true
+android.enableJetifier=true
+
+# Enable and fail the build if an issue is found that disallows the
+# configuration cache. These options along with this app being built in
+# presubmit helps us cache changes that would cause config cache to be disabled
+# via the HiltGradlePlugin.
+org.gradle.unsafe.configuration-cache-problems=fail
+org.gradle.unsafe.configuration-cache.max-problems=0
+org.gradle.caching=true
+org.gradle.parallel=true
+org.gradle.jvmargs=-Xmx2048m
diff --git a/javatests/artifacts/hilt-android/lazyclasskey/gradle/wrapper/gradle-wrapper.jar b/javatests/artifacts/hilt-android/lazyclasskey/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..7f93135
--- /dev/null
+++ b/javatests/artifacts/hilt-android/lazyclasskey/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/javatests/artifacts/hilt-android/lazyclasskey/gradle/wrapper/gradle-wrapper.properties b/javatests/artifacts/hilt-android/lazyclasskey/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..9623276
--- /dev/null
+++ b/javatests/artifacts/hilt-android/lazyclasskey/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,7 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
+networkTimeout=10000
+validateDistributionUrl=true
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/javatests/artifacts/hilt-android/lazyclasskey/gradlew b/javatests/artifacts/hilt-android/lazyclasskey/gradlew
new file mode 100755
index 0000000..1aa94a4
--- /dev/null
+++ b/javatests/artifacts/hilt-android/lazyclasskey/gradlew
@@ -0,0 +1,249 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+#
+#   Gradle start up script for POSIX generated by Gradle.
+#
+#   Important for running:
+#
+#   (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+#       noncompliant, but you have some other compliant shell such as ksh or
+#       bash, then to run this script, type that shell name before the whole
+#       command line, like:
+#
+#           ksh Gradle
+#
+#       Busybox and similar reduced shells will NOT work, because this script
+#       requires all of these POSIX shell features:
+#         * functions;
+#         * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+#           «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+#         * compound commands having a testable exit status, especially «case»;
+#         * various built-in commands including «command», «set», and «ulimit».
+#
+#   Important for patching:
+#
+#   (2) This script targets any POSIX shell, so it avoids extensions provided
+#       by Bash, Ksh, etc; in particular arrays are avoided.
+#
+#       The "traditional" practice of packing multiple parameters into a
+#       space-separated string is a well documented source of bugs and security
+#       problems, so this is (mostly) avoided, by progressively accumulating
+#       options in "$@", and eventually passing that to Java.
+#
+#       Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+#       and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+#       see the in-line comments for details.
+#
+#       There are tweaks for specific operating systems such as AIX, CygWin,
+#       Darwin, MinGW, and NonStop.
+#
+#   (3) This script is generated from the Groovy template
+#       https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+#       within the Gradle project.
+#
+#       You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+    APP_HOME=${app_path%"${app_path##*/}"}  # leaves a trailing /; empty if no leading path
+    [ -h "$app_path" ]
+do
+    ls=$( ls -ld "$app_path" )
+    link=${ls#*' -> '}
+    case $link in             #(
+      /*)   app_path=$link ;; #(
+      *)    app_path=$APP_HOME$link ;;
+    esac
+done
+
+# This is normally unused
+# shellcheck disable=SC2034
+APP_BASE_NAME=${0##*/}
+# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
+APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+    echo "$*"
+} >&2
+
+die () {
+    echo
+    echo "$*"
+    echo
+    exit 1
+} >&2
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "$( uname )" in                #(
+  CYGWIN* )         cygwin=true  ;; #(
+  Darwin* )         darwin=true  ;; #(
+  MSYS* | MINGW* )  msys=true    ;; #(
+  NONSTOP* )        nonstop=true ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD=$JAVA_HOME/jre/sh/java
+    else
+        JAVACMD=$JAVA_HOME/bin/java
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD=java
+    if ! command -v java >/dev/null 2>&1
+    then
+        die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+    case $MAX_FD in #(
+      max*)
+        # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
+        # shellcheck disable=SC2039,SC3045
+        MAX_FD=$( ulimit -H -n ) ||
+            warn "Could not query maximum file descriptor limit"
+    esac
+    case $MAX_FD in  #(
+      '' | soft) :;; #(
+      *)
+        # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
+        # shellcheck disable=SC2039,SC3045
+        ulimit -n "$MAX_FD" ||
+            warn "Could not set maximum file descriptor limit to $MAX_FD"
+    esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+#   * args from the command line
+#   * the main class name
+#   * -classpath
+#   * -D...appname settings
+#   * --module-path (only if needed)
+#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+    APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+    CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+    JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    for arg do
+        if
+            case $arg in                                #(
+              -*)   false ;;                            # don't mess with options #(
+              /?*)  t=${arg#/} t=/${t%%/*}              # looks like a POSIX filepath
+                    [ -e "$t" ] ;;                      #(
+              *)    false ;;
+            esac
+        then
+            arg=$( cygpath --path --ignore --mixed "$arg" )
+        fi
+        # Roll the args list around exactly as many times as the number of
+        # args, so each arg winds up back in the position where it started, but
+        # possibly modified.
+        #
+        # NB: a `for` loop captures its iteration list before it begins, so
+        # changing the positional parameters here affects neither the number of
+        # iterations, nor the values presented in `arg`.
+        shift                   # remove old arg
+        set -- "$@" "$arg"      # push replacement arg
+    done
+fi
+
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Collect all arguments for the java command:
+#   * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
+#     and any embedded shellness will be escaped.
+#   * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
+#     treated as '${Hostname}' itself on the command line.
+
+set -- \
+        "-Dorg.gradle.appname=$APP_BASE_NAME" \
+        -classpath "$CLASSPATH" \
+        org.gradle.wrapper.GradleWrapperMain \
+        "$@"
+
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+    die "xargs is not available"
+fi
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+#   readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+#   set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+        printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+        xargs -n1 |
+        sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+        tr '\n' ' '
+    )" '"$@"'
+
+exec "$JAVACMD" "$@"
diff --git a/javatests/artifacts/hilt-android/lazyclasskey/gradlew.bat b/javatests/artifacts/hilt-android/lazyclasskey/gradlew.bat
new file mode 100644
index 0000000..93e3f59
--- /dev/null
+++ b/javatests/artifacts/hilt-android/lazyclasskey/gradlew.bat
@@ -0,0 +1,92 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem      https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%"=="" @echo off
+@rem ##########################################################################
+@rem
+@rem  Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%"=="" set DIRNAME=.
+@rem This is normally unused
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if %ERRORLEVEL% equ 0 goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if %ERRORLEVEL% equ 0 goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+set EXIT_CODE=%ERRORLEVEL%
+if %EXIT_CODE% equ 0 set EXIT_CODE=1
+if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
+exit /b %EXIT_CODE%
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/javatests/artifacts/hilt-android/lazyclasskey/settings.gradle b/javatests/artifacts/hilt-android/lazyclasskey/settings.gradle
new file mode 100644
index 0000000..5bb49fa
--- /dev/null
+++ b/javatests/artifacts/hilt-android/lazyclasskey/settings.gradle
@@ -0,0 +1,2 @@
+rootProject.name = 'lazyclasskey'
+include('app')
diff --git a/javatests/artifacts/hilt-android/pluginMarker/app/build.gradle b/javatests/artifacts/hilt-android/pluginMarker/app/build.gradle
index d07d68c..e4cde41 100644
--- a/javatests/artifacts/hilt-android/pluginMarker/app/build.gradle
+++ b/javatests/artifacts/hilt-android/pluginMarker/app/build.gradle
@@ -20,13 +20,13 @@
 }
 
 android {
-    compileSdkVersion 32
-    buildToolsVersion "32.0.0"
+    compileSdkVersion 33
+    buildToolsVersion "33.0.0"
 
     defaultConfig {
         applicationId "dagger.hilt.android.simple"
-        minSdkVersion 21
-        targetSdkVersion 32
+        minSdkVersion 16
+        targetSdkVersion 33
     }
 
     compileOptions {
diff --git a/javatests/artifacts/hilt-android/pluginMarker/gradle.properties b/javatests/artifacts/hilt-android/pluginMarker/gradle.properties
index 6cde789..0bdf325 100644
--- a/javatests/artifacts/hilt-android/pluginMarker/gradle.properties
+++ b/javatests/artifacts/hilt-android/pluginMarker/gradle.properties
@@ -1,3 +1,4 @@
 android.useAndroidX=true
 org.gradle.caching=true
-org.gradle.parallel=true
\ No newline at end of file
+org.gradle.parallel=true
+org.gradle.jvmargs=-Xmx2048m
\ No newline at end of file
diff --git a/javatests/artifacts/hilt-android/pluginMarker/gradle/wrapper/gradle-wrapper.properties b/javatests/artifacts/hilt-android/pluginMarker/gradle/wrapper/gradle-wrapper.properties
index 0f80bbf..98debb8 100644
--- a/javatests/artifacts/hilt-android/pluginMarker/gradle/wrapper/gradle-wrapper.properties
+++ b/javatests/artifacts/hilt-android/pluginMarker/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.2-bin.zip
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
diff --git a/javatests/artifacts/hilt-android/simple/app-java-only/build.gradle b/javatests/artifacts/hilt-android/simple/app-java-only/build.gradle
index 823b202..7a156ef 100644
--- a/javatests/artifacts/hilt-android/simple/app-java-only/build.gradle
+++ b/javatests/artifacts/hilt-android/simple/app-java-only/build.gradle
@@ -18,13 +18,13 @@
 apply plugin: 'com.google.dagger.hilt.android'
 
 android {
-    compileSdkVersion 32
-    buildToolsVersion "32.0.0"
+    compileSdkVersion 33
+    buildToolsVersion "33.0.0"
 
     defaultConfig {
         applicationId "dagger.hilt.android.simple"
-        minSdkVersion 15
-        targetSdkVersion 32
+        minSdkVersion 16
+        targetSdkVersion 33
         versionCode 1
         versionName "1.0"
         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
diff --git a/javatests/artifacts/hilt-android/simple/app/build.gradle b/javatests/artifacts/hilt-android/simple/app/build.gradle
index 48d9b99..8a196cf 100644
--- a/javatests/artifacts/hilt-android/simple/app/build.gradle
+++ b/javatests/artifacts/hilt-android/simple/app/build.gradle
@@ -43,13 +43,13 @@
 }
 
 android {
-    compileSdkVersion 32
-    buildToolsVersion "32.0.0"
+    compileSdkVersion 33
+    buildToolsVersion "33.0.0"
 
     defaultConfig {
         applicationId "dagger.hilt.android.simple"
-        minSdkVersion 15
-        targetSdkVersion 32
+        minSdkVersion 16
+        targetSdkVersion 33
         versionCode 1
         versionName "1.0"
         testInstrumentationRunner "dagger.hilt.android.simple.SimpleEmulatorTestRunner"
diff --git a/javatests/artifacts/hilt-android/simple/build.gradle b/javatests/artifacts/hilt-android/simple/build.gradle
index ac3230e..e0f39a3 100644
--- a/javatests/artifacts/hilt-android/simple/build.gradle
+++ b/javatests/artifacts/hilt-android/simple/build.gradle
@@ -17,7 +17,7 @@
 buildscript {
     ext {
         dagger_version = 'LOCAL-SNAPSHOT'
-        kotlin_version = '1.8.0'
+        kotlin_version = '1.9.20'
         agp_version = System.getenv('AGP_VERSION') ?: "7.1.2"
     }
     repositories {
diff --git a/javatests/artifacts/hilt-android/simple/deep-android-lib/build.gradle b/javatests/artifacts/hilt-android/simple/deep-android-lib/build.gradle
index 41b125d..ab5424e 100644
--- a/javatests/artifacts/hilt-android/simple/deep-android-lib/build.gradle
+++ b/javatests/artifacts/hilt-android/simple/deep-android-lib/build.gradle
@@ -4,12 +4,12 @@
 }
 
 android {
-    compileSdkVersion 32
-    buildToolsVersion "32.0.0"
+    compileSdkVersion 33
+    buildToolsVersion "33.0.0"
 
     defaultConfig {
-        minSdkVersion 15
-        targetSdkVersion 32
+        minSdkVersion 16
+        targetSdkVersion 33
         versionCode 1
         versionName "1.0"
     }
diff --git a/javatests/artifacts/hilt-android/simple/earlyentrypoint/build.gradle b/javatests/artifacts/hilt-android/simple/earlyentrypoint/build.gradle
index 4c3d8c8..2a36e6f 100644
--- a/javatests/artifacts/hilt-android/simple/earlyentrypoint/build.gradle
+++ b/javatests/artifacts/hilt-android/simple/earlyentrypoint/build.gradle
@@ -4,12 +4,12 @@
 }
 
 android {
-    compileSdkVersion 32
-    buildToolsVersion "32.0.0"
+    compileSdkVersion 33
+    buildToolsVersion "33.0.0"
 
     defaultConfig {
-        minSdkVersion 15
-        targetSdkVersion 32
+        minSdkVersion 16
+        targetSdkVersion 33
         versionCode 1
         versionName "1.0"
     }
diff --git a/javatests/artifacts/hilt-android/simple/feature/build.gradle b/javatests/artifacts/hilt-android/simple/feature/build.gradle
index ab9a343..dd33e29 100644
--- a/javatests/artifacts/hilt-android/simple/feature/build.gradle
+++ b/javatests/artifacts/hilt-android/simple/feature/build.gradle
@@ -20,12 +20,12 @@
 apply plugin: 'com.google.dagger.hilt.android'
 
 android {
-    compileSdkVersion 32
-    buildToolsVersion "32.0.0"
+    compileSdkVersion 33
+    buildToolsVersion "33.0.0"
 
     defaultConfig {
-        minSdkVersion 15
-        targetSdkVersion 32
+        minSdkVersion 16
+        targetSdkVersion 33
         versionCode 1
         versionName "1.0"
     }
diff --git a/javatests/artifacts/hilt-android/simple/gradle.properties b/javatests/artifacts/hilt-android/simple/gradle.properties
index b88e839..1efa70f 100644
--- a/javatests/artifacts/hilt-android/simple/gradle.properties
+++ b/javatests/artifacts/hilt-android/simple/gradle.properties
@@ -9,3 +9,4 @@
 org.gradle.unsafe.configuration-cache.max-problems=0
 org.gradle.caching=true
 org.gradle.parallel=true
+org.gradle.jvmargs=-Xmx2048m
\ No newline at end of file
diff --git a/javatests/artifacts/hilt-android/simple/gradle/wrapper/gradle-wrapper.properties b/javatests/artifacts/hilt-android/simple/gradle/wrapper/gradle-wrapper.properties
index 00e33ed..98debb8 100644
--- a/javatests/artifacts/hilt-android/simple/gradle/wrapper/gradle-wrapper.properties
+++ b/javatests/artifacts/hilt-android/simple/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.1-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.2-bin.zip
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
diff --git a/javatests/artifacts/hilt-android/simple/uitest/build.gradle b/javatests/artifacts/hilt-android/simple/uitest/build.gradle
index 9875b64..7c4e0fd 100644
--- a/javatests/artifacts/hilt-android/simple/uitest/build.gradle
+++ b/javatests/artifacts/hilt-android/simple/uitest/build.gradle
@@ -18,12 +18,12 @@
 apply plugin: 'com.google.dagger.hilt.android'
 
 android {
-    compileSdkVersion 32
-    buildToolsVersion "32.0.0"
+    compileSdkVersion 33
+    buildToolsVersion "33.0.0"
 
     defaultConfig {
-        minSdkVersion 15
-        targetSdkVersion 32
+        minSdkVersion 16
+        targetSdkVersion 33
         testInstrumentationRunner "dagger.hilt.android.simple.uitest.TestRunner"
         missingDimensionStrategy 'tier', 'free'
     }
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/android-library/build.gradle b/javatests/artifacts/hilt-android/simpleKotlin/android-library/build.gradle
index 3c97d6f..1e83543 100644
--- a/javatests/artifacts/hilt-android/simpleKotlin/android-library/build.gradle
+++ b/javatests/artifacts/hilt-android/simpleKotlin/android-library/build.gradle
@@ -6,12 +6,12 @@
 }
 
 android {
-    compileSdkVersion 32
-    buildToolsVersion "32.0.0"
+    compileSdkVersion 33
+    buildToolsVersion "33.0.0"
 
     defaultConfig {
-        minSdkVersion 15
-        targetSdkVersion 32
+        minSdkVersion 16
+        targetSdkVersion 33
         versionCode 1
         versionName "1.0"
     }
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/app/build.gradle b/javatests/artifacts/hilt-android/simpleKotlin/app/build.gradle
index 0b860af..fe4f5b4 100644
--- a/javatests/artifacts/hilt-android/simpleKotlin/app/build.gradle
+++ b/javatests/artifacts/hilt-android/simpleKotlin/app/build.gradle
@@ -21,13 +21,13 @@
 apply plugin: 'com.google.devtools.ksp'
 
 android {
-    compileSdkVersion 32
-    buildToolsVersion "32.0.0"
+    compileSdkVersion 33
+    buildToolsVersion "33.0.0"
 
     defaultConfig {
         applicationId "dagger.hilt.android.simpleKotlin"
-        minSdkVersion 15
-        targetSdkVersion 32
+        minSdkVersion 16
+        targetSdkVersion 33
         versionCode 1
         versionName "1.0"
         testInstrumentationRunner "dagger.hilt.android.example.gradle.simpleKotlin.TestRunner"
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/build.gradle b/javatests/artifacts/hilt-android/simpleKotlin/build.gradle
index eee4806..3773deb 100644
--- a/javatests/artifacts/hilt-android/simpleKotlin/build.gradle
+++ b/javatests/artifacts/hilt-android/simpleKotlin/build.gradle
@@ -16,8 +16,8 @@
 
 buildscript {
     ext {
-        kotlin_version = '1.8.20'
-        ksp_version = '1.0.11'
+        kotlin_version = '1.9.20'
+        ksp_version = "$kotlin_version-1.0.14"
         agp_version = System.getenv('AGP_VERSION') ?: "7.1.2"
     }
     repositories {
@@ -28,7 +28,7 @@
     dependencies {
         classpath "com.android.tools.build:gradle:$agp_version"
         classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
-        classpath "com.google.devtools.ksp:symbol-processing-gradle-plugin:$kotlin_version-$ksp_version"
+        classpath "com.google.devtools.ksp:symbol-processing-gradle-plugin:$ksp_version"
         classpath 'com.google.dagger:hilt-android-gradle-plugin:LOCAL-SNAPSHOT'
     }
 }
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/deep-android-lib/build.gradle b/javatests/artifacts/hilt-android/simpleKotlin/deep-android-lib/build.gradle
index b248a0b..8973bb9 100644
--- a/javatests/artifacts/hilt-android/simpleKotlin/deep-android-lib/build.gradle
+++ b/javatests/artifacts/hilt-android/simpleKotlin/deep-android-lib/build.gradle
@@ -7,12 +7,12 @@
 }
 
 android {
-    compileSdkVersion 32
-    buildToolsVersion "32.0.0"
+    compileSdkVersion 33
+    buildToolsVersion "33.0.0"
 
     defaultConfig {
-        minSdkVersion 15
-        targetSdkVersion 32
+        minSdkVersion 16
+        targetSdkVersion 33
         versionCode 1
         versionName "1.0"
 
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/gradle.properties b/javatests/artifacts/hilt-android/simpleKotlin/gradle.properties
index b88e839..1efa70f 100644
--- a/javatests/artifacts/hilt-android/simpleKotlin/gradle.properties
+++ b/javatests/artifacts/hilt-android/simpleKotlin/gradle.properties
@@ -9,3 +9,4 @@
 org.gradle.unsafe.configuration-cache.max-problems=0
 org.gradle.caching=true
 org.gradle.parallel=true
+org.gradle.jvmargs=-Xmx2048m
\ No newline at end of file
diff --git a/javatests/artifacts/hilt-android/simpleKotlin/gradle/wrapper/gradle-wrapper.properties b/javatests/artifacts/hilt-android/simpleKotlin/gradle/wrapper/gradle-wrapper.properties
index 00e33ed..98debb8 100644
--- a/javatests/artifacts/hilt-android/simpleKotlin/gradle/wrapper/gradle-wrapper.properties
+++ b/javatests/artifacts/hilt-android/simpleKotlin/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.1-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.2-bin.zip
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
diff --git a/javatests/artifacts/hilt-android/viewmodel/app/build.gradle b/javatests/artifacts/hilt-android/viewmodel/app/build.gradle
new file mode 100644
index 0000000..a212b3c
--- /dev/null
+++ b/javatests/artifacts/hilt-android/viewmodel/app/build.gradle
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+plugins {
+    id 'com.android.application'
+    id 'com.google.dagger.hilt.android'
+}
+
+android {
+
+    namespace 'dagger.hilt.viewmodel'
+    compileSdkVersion 33
+    defaultConfig {
+        applicationId 'dagger.hilt.viewmodel'
+        minSdk 16
+        targetSdk 33
+        versionCode 1
+        versionName "1.0"
+        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+    }
+
+    buildTypes {
+        debug {
+            minifyEnabled true
+            shrinkResources true
+            proguardFiles getDefaultProguardFile(
+                    'proguard-android-optimize.txt'),
+                    'proguard-rules.pro'
+
+        }
+    }
+
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_11
+        targetCompatibility JavaVersion.VERSION_11
+    }
+}
+
+dependencies {
+    implementation 'androidx.appcompat:appcompat:1.2.0'
+    implementation 'com.google.errorprone:error_prone_annotations:2.15.0'
+
+    androidTestImplementation 'androidx.test:core:1.5.0-alpha02'
+    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
+    androidTestImplementation "androidx.test:runner:1.5.2"
+    androidTestImplementation "androidx.test:rules:1.5.0"
+    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
+
+    // Hilt dependencies
+    implementation "com.google.dagger:hilt-android:$hilt_version"
+    annotationProcessor "com.google.dagger:hilt-compiler:$hilt_version"
+}
diff --git a/javatests/artifacts/hilt-android/viewmodel/app/proguard-rules.pro b/javatests/artifacts/hilt-android/viewmodel/app/proguard-rules.pro
new file mode 100644
index 0000000..0929028
--- /dev/null
+++ b/javatests/artifacts/hilt-android/viewmodel/app/proguard-rules.pro
@@ -0,0 +1,2 @@
+-dontwarn com.google.errorprone.annotations.MustBeClosed
+-keep class kotlin.**
diff --git a/javatests/artifacts/hilt-android/viewmodel/app/src/androidTest/java/dagger/hilt/viewmodel/SimpleApplicationTest.java b/javatests/artifacts/hilt-android/viewmodel/app/src/androidTest/java/dagger/hilt/viewmodel/SimpleApplicationTest.java
new file mode 100644
index 0000000..bf47235
--- /dev/null
+++ b/javatests/artifacts/hilt-android/viewmodel/app/src/androidTest/java/dagger/hilt/viewmodel/SimpleApplicationTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.hilt.viewmodel;
+
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.matcher.ViewMatchers.withResourceName;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
+import static org.hamcrest.Matchers.startsWith;
+
+import android.content.Intent;
+import androidx.test.core.app.ActivityScenario;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class SimpleApplicationTest {
+    @Test
+    public void testHiltViewModelWithR8DoesNotCrash() {
+        Intent mainIntent =
+            new Intent(ApplicationProvider.getApplicationContext(), SimpleActivity.class);
+        try (ActivityScenario<SimpleActivity> scenario = ActivityScenario.launch(mainIntent)) {
+            onView(withResourceName("greeting"))
+                .check(matches(withText(startsWith("Hello"))));
+        }
+    }
+}
diff --git a/javatests/artifacts/hilt-android/viewmodel/app/src/main/AndroidManifest.xml b/javatests/artifacts/hilt-android/viewmodel/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..82afa17
--- /dev/null
+++ b/javatests/artifacts/hilt-android/viewmodel/app/src/main/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<!--
+  ~ Copyright (C) 2023 The Dagger Authors.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~ http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
+
+  <application android:name=".SimpleApplication" android:label="@string/appName">
+    <activity
+        android:name=".SimpleActivity"
+        android:theme="@style/Theme.AppCompat.Light"
+        android:exported="true">
+      <intent-filter>
+        <action android:name="android.intent.action.MAIN" />
+        <category android:name="android.intent.category.LAUNCHER" />
+      </intent-filter>
+    </activity>
+  </application>
+</manifest>
diff --git a/javatests/artifacts/hilt-android/viewmodel/app/src/main/java/dagger/hilt/viewmodel/SimpleActivity.java b/javatests/artifacts/hilt-android/viewmodel/app/src/main/java/dagger/hilt/viewmodel/SimpleActivity.java
new file mode 100644
index 0000000..ad6e738
--- /dev/null
+++ b/javatests/artifacts/hilt-android/viewmodel/app/src/main/java/dagger/hilt/viewmodel/SimpleActivity.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.hilt.viewmodel;
+
+import android.os.Bundle;
+import android.widget.TextView;
+import androidx.annotation.OptIn;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.lifecycle.SavedStateHandle;
+import androidx.lifecycle.ViewModelProvider;
+import dagger.hilt.android.AndroidEntryPoint;
+import dagger.hilt.android.UnstableApi;
+import dagger.hilt.android.lifecycle.ActivityRetainedSavedState;
+import javax.inject.Inject;
+
+/** The main activity of the application. */
+@OptIn(markerClass = UnstableApi.class)
+@AndroidEntryPoint
+public class SimpleActivity extends AppCompatActivity {
+  private static final String TAG = SimpleActivity.class.getSimpleName();
+
+  @Inject
+  @ActivityRetainedSavedState
+  SavedStateHandle savedStateHandle;
+
+  @Override
+  protected void onCreate(Bundle savedInstanceState) {
+    super.onCreate(savedInstanceState);
+    SimpleViewModel viewModel = new ViewModelProvider(this).get(SimpleViewModel.class);
+    savedStateHandle.set("some_key", "some_content");
+    setContentView(R.layout.activity_main);
+
+    ((TextView) findViewById(R.id.greeting))
+        .setText(getResources().getString(R.string.welcome, viewModel.userName));
+  }
+}
diff --git a/java/dagger/spi/model/CompilerEnvironment.java b/javatests/artifacts/hilt-android/viewmodel/app/src/main/java/dagger/hilt/viewmodel/SimpleApplication.java
similarity index 60%
copy from java/dagger/spi/model/CompilerEnvironment.java
copy to javatests/artifacts/hilt-android/viewmodel/app/src/main/java/dagger/hilt/viewmodel/SimpleApplication.java
index 28553e4..eed62b1 100644
--- a/java/dagger/spi/model/CompilerEnvironment.java
+++ b/javatests/artifacts/hilt-android/viewmodel/app/src/main/java/dagger/hilt/viewmodel/SimpleApplication.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Dagger Authors.
+ * Copyright (C) 2023 The Dagger Authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,10 +14,14 @@
  * limitations under the License.
  */
 
-package dagger.spi.model;
+package dagger.hilt.viewmodel;
 
-/** Types for the compiler in use for annotation processing. */
-public enum CompilerEnvironment {
-  JAVA,
-  KSP
-}
+import android.app.Application;
+import dagger.hilt.android.HiltAndroidApp;
+
+/**
+ * A simple, skeletal application that demonstrates a dependency-injected application using the
+ * utilities in {@code Hilt} in Android.
+ */
+@HiltAndroidApp
+public class SimpleApplication extends Application {}
diff --git a/javatests/artifacts/hilt-android/viewmodel/app/src/main/java/dagger/hilt/viewmodel/SimpleViewModel.java b/javatests/artifacts/hilt-android/viewmodel/app/src/main/java/dagger/hilt/viewmodel/SimpleViewModel.java
new file mode 100644
index 0000000..0509d23
--- /dev/null
+++ b/javatests/artifacts/hilt-android/viewmodel/app/src/main/java/dagger/hilt/viewmodel/SimpleViewModel.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.hilt.viewmodel;
+
+import androidx.lifecycle.ViewModel;
+import dagger.hilt.android.lifecycle.HiltViewModel;
+import javax.inject.Inject;
+
+/** The view model requires creation by hilt. */
+@HiltViewModel
+public final class SimpleViewModel extends ViewModel {
+  String userName;
+
+  @Inject
+  SimpleViewModel(@UserName String userName) {
+    this.userName = userName;
+  }
+}
diff --git a/java/dagger/spi/model/CompilerEnvironment.java b/javatests/artifacts/hilt-android/viewmodel/app/src/main/java/dagger/hilt/viewmodel/UserName.java
similarity index 60%
copy from java/dagger/spi/model/CompilerEnvironment.java
copy to javatests/artifacts/hilt-android/viewmodel/app/src/main/java/dagger/hilt/viewmodel/UserName.java
index 28553e4..6bed1cb 100644
--- a/java/dagger/spi/model/CompilerEnvironment.java
+++ b/javatests/artifacts/hilt-android/viewmodel/app/src/main/java/dagger/hilt/viewmodel/UserName.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Dagger Authors.
+ * Copyright (C) 2023 The Dagger Authors.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,10 +14,16 @@
  * limitations under the License.
  */
 
-package dagger.spi.model;
+package dagger.hilt.viewmodel;
 
-/** Types for the compiler in use for annotation processing. */
-public enum CompilerEnvironment {
-  JAVA,
-  KSP
-}
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import javax.inject.Qualifier;
+
+/** Qualifies bindings relating to the user name. */
+@Qualifier
+@Retention(RUNTIME)
+@Documented
+@interface UserName {}
diff --git a/javatests/artifacts/hilt-android/viewmodel/app/src/main/java/dagger/hilt/viewmodel/UserNameModule.java b/javatests/artifacts/hilt-android/viewmodel/app/src/main/java/dagger/hilt/viewmodel/UserNameModule.java
new file mode 100644
index 0000000..e1d5bd5
--- /dev/null
+++ b/javatests/artifacts/hilt-android/viewmodel/app/src/main/java/dagger/hilt/viewmodel/UserNameModule.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.hilt.viewmodel;
+
+import dagger.Module;
+import dagger.Provides;
+import dagger.hilt.InstallIn;
+import dagger.hilt.android.components.ViewModelComponent;
+import java.util.Random;
+
+@Module
+@InstallIn(ViewModelComponent.class)
+final class UserNameModule {
+  @UserName
+  @Provides
+  static String provideUserName() {
+    return "ProdUser-" + new Random().nextInt();
+  }
+
+  private UserNameModule() {}
+}
diff --git a/javatests/artifacts/hilt-android/viewmodel/app/src/main/res/layout/activity_main.xml b/javatests/artifacts/hilt-android/viewmodel/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..d785a7f
--- /dev/null
+++ b/javatests/artifacts/hilt-android/viewmodel/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2023 The Dagger Authors.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~ http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+  android:layout_width="match_parent"
+  android:layout_height="match_parent"
+  android:background="@android:color/background_light">
+
+  <TextView
+    android:id="@+id/greeting"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:layout_alignParentTop="true"
+    android:textColor="@android:color/primary_text_light"
+    />
+
+  <Button
+    android:id="@+id/goto_feature"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:layout_below="@id/greeting"
+    android:text="@string/navigateToFeature"
+    />
+</RelativeLayout>
diff --git a/javatests/artifacts/hilt-android/viewmodel/app/src/main/res/values/strings.xml b/javatests/artifacts/hilt-android/viewmodel/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..519ca44
--- /dev/null
+++ b/javatests/artifacts/hilt-android/viewmodel/app/src/main/res/values/strings.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2023 The Dagger Authors.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~ http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<resources>
+  <!--The app name [CHAR_LIMIT=20]-->
+  <string name="appName">Simple Hilt Android</string>
+
+  <!--The greeting message [CHAR_LIMIT=100]-->
+  <string name="welcome">Hello, %1$s!</string>
+
+  <!--The feature button message [CHAR_LIMIT=100]-->
+  <string name="navigateToFeature">Navigate to a feature!</string>
+</resources>
diff --git a/javatests/artifacts/hilt-android/viewmodel/build.gradle b/javatests/artifacts/hilt-android/viewmodel/build.gradle
new file mode 100644
index 0000000..bbcc108
--- /dev/null
+++ b/javatests/artifacts/hilt-android/viewmodel/build.gradle
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+buildscript {
+    ext {
+        hilt_version = 'LOCAL-SNAPSHOT'
+        // AGP is set below 7.2.0 on purpose to be able to obfuscate debug apk.
+        agp_version = "7.1.2"
+        kotlin_version = '1.9.20'
+    }
+    repositories {
+        google()
+        mavenCentral()
+        mavenLocal()
+    }
+    dependencies {
+        classpath "com.android.tools.build:gradle:$agp_version"
+        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+	classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version"
+    }
+}
+
+allprojects {
+    repositories {
+        google()
+        mavenCentral()
+        mavenLocal()
+    }
+}
+
+subprojects {
+    afterEvaluate {
+        dependencies {
+            // This is needed to align older versions of kotlin-stdlib.
+            // The main issue is that in v1.8.0 the jdk7 and jdk8 artifacts were
+            // merged into kotlin-stdlib, so without this alignment we end up
+            // getting duplicate classes by pulling in both artifacts.
+            // See: https://kotlinlang.org/docs/whatsnew18.html#usage-of-the-latest-kotlin-stdlib-version-in-transitive-dependencies
+            implementation(platform("org.jetbrains.kotlin:kotlin-bom:$kotlin_version"))
+        }
+    }
+}
+
+task clean(type: Delete) {
+    delete rootProject.buildDir
+}
diff --git a/javatests/artifacts/hilt-android/viewmodel/gradle.properties b/javatests/artifacts/hilt-android/viewmodel/gradle.properties
new file mode 100644
index 0000000..1efa70f
--- /dev/null
+++ b/javatests/artifacts/hilt-android/viewmodel/gradle.properties
@@ -0,0 +1,12 @@
+android.useAndroidX=true
+android.enableJetifier=true
+
+# Enable and fail the build if an issue is found that disallows the
+# configuration cache. These options along with this app being built in
+# presubmit helps us cache changes that would cause config cache to be disabled
+# via the HiltGradlePlugin.
+org.gradle.unsafe.configuration-cache-problems=fail
+org.gradle.unsafe.configuration-cache.max-problems=0
+org.gradle.caching=true
+org.gradle.parallel=true
+org.gradle.jvmargs=-Xmx2048m
\ No newline at end of file
diff --git a/javatests/artifacts/hilt-android/viewmodel/gradle/wrapper/gradle-wrapper.jar b/javatests/artifacts/hilt-android/viewmodel/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..7f93135
--- /dev/null
+++ b/javatests/artifacts/hilt-android/viewmodel/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/javatests/artifacts/hilt-android/viewmodel/gradle/wrapper/gradle-wrapper.properties b/javatests/artifacts/hilt-android/viewmodel/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..9623276
--- /dev/null
+++ b/javatests/artifacts/hilt-android/viewmodel/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,7 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
+networkTimeout=10000
+validateDistributionUrl=true
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/javatests/artifacts/hilt-android/viewmodel/gradlew b/javatests/artifacts/hilt-android/viewmodel/gradlew
new file mode 100755
index 0000000..1aa94a4
--- /dev/null
+++ b/javatests/artifacts/hilt-android/viewmodel/gradlew
@@ -0,0 +1,249 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+#
+#   Gradle start up script for POSIX generated by Gradle.
+#
+#   Important for running:
+#
+#   (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+#       noncompliant, but you have some other compliant shell such as ksh or
+#       bash, then to run this script, type that shell name before the whole
+#       command line, like:
+#
+#           ksh Gradle
+#
+#       Busybox and similar reduced shells will NOT work, because this script
+#       requires all of these POSIX shell features:
+#         * functions;
+#         * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+#           «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+#         * compound commands having a testable exit status, especially «case»;
+#         * various built-in commands including «command», «set», and «ulimit».
+#
+#   Important for patching:
+#
+#   (2) This script targets any POSIX shell, so it avoids extensions provided
+#       by Bash, Ksh, etc; in particular arrays are avoided.
+#
+#       The "traditional" practice of packing multiple parameters into a
+#       space-separated string is a well documented source of bugs and security
+#       problems, so this is (mostly) avoided, by progressively accumulating
+#       options in "$@", and eventually passing that to Java.
+#
+#       Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+#       and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+#       see the in-line comments for details.
+#
+#       There are tweaks for specific operating systems such as AIX, CygWin,
+#       Darwin, MinGW, and NonStop.
+#
+#   (3) This script is generated from the Groovy template
+#       https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+#       within the Gradle project.
+#
+#       You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+    APP_HOME=${app_path%"${app_path##*/}"}  # leaves a trailing /; empty if no leading path
+    [ -h "$app_path" ]
+do
+    ls=$( ls -ld "$app_path" )
+    link=${ls#*' -> '}
+    case $link in             #(
+      /*)   app_path=$link ;; #(
+      *)    app_path=$APP_HOME$link ;;
+    esac
+done
+
+# This is normally unused
+# shellcheck disable=SC2034
+APP_BASE_NAME=${0##*/}
+# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
+APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+    echo "$*"
+} >&2
+
+die () {
+    echo
+    echo "$*"
+    echo
+    exit 1
+} >&2
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "$( uname )" in                #(
+  CYGWIN* )         cygwin=true  ;; #(
+  Darwin* )         darwin=true  ;; #(
+  MSYS* | MINGW* )  msys=true    ;; #(
+  NONSTOP* )        nonstop=true ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD=$JAVA_HOME/jre/sh/java
+    else
+        JAVACMD=$JAVA_HOME/bin/java
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD=java
+    if ! command -v java >/dev/null 2>&1
+    then
+        die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+    case $MAX_FD in #(
+      max*)
+        # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
+        # shellcheck disable=SC2039,SC3045
+        MAX_FD=$( ulimit -H -n ) ||
+            warn "Could not query maximum file descriptor limit"
+    esac
+    case $MAX_FD in  #(
+      '' | soft) :;; #(
+      *)
+        # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
+        # shellcheck disable=SC2039,SC3045
+        ulimit -n "$MAX_FD" ||
+            warn "Could not set maximum file descriptor limit to $MAX_FD"
+    esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+#   * args from the command line
+#   * the main class name
+#   * -classpath
+#   * -D...appname settings
+#   * --module-path (only if needed)
+#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+    APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+    CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+    JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    for arg do
+        if
+            case $arg in                                #(
+              -*)   false ;;                            # don't mess with options #(
+              /?*)  t=${arg#/} t=/${t%%/*}              # looks like a POSIX filepath
+                    [ -e "$t" ] ;;                      #(
+              *)    false ;;
+            esac
+        then
+            arg=$( cygpath --path --ignore --mixed "$arg" )
+        fi
+        # Roll the args list around exactly as many times as the number of
+        # args, so each arg winds up back in the position where it started, but
+        # possibly modified.
+        #
+        # NB: a `for` loop captures its iteration list before it begins, so
+        # changing the positional parameters here affects neither the number of
+        # iterations, nor the values presented in `arg`.
+        shift                   # remove old arg
+        set -- "$@" "$arg"      # push replacement arg
+    done
+fi
+
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Collect all arguments for the java command:
+#   * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
+#     and any embedded shellness will be escaped.
+#   * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
+#     treated as '${Hostname}' itself on the command line.
+
+set -- \
+        "-Dorg.gradle.appname=$APP_BASE_NAME" \
+        -classpath "$CLASSPATH" \
+        org.gradle.wrapper.GradleWrapperMain \
+        "$@"
+
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+    die "xargs is not available"
+fi
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+#   readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+#   set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+        printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+        xargs -n1 |
+        sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+        tr '\n' ' '
+    )" '"$@"'
+
+exec "$JAVACMD" "$@"
diff --git a/javatests/artifacts/hilt-android/viewmodel/gradlew.bat b/javatests/artifacts/hilt-android/viewmodel/gradlew.bat
new file mode 100644
index 0000000..93e3f59
--- /dev/null
+++ b/javatests/artifacts/hilt-android/viewmodel/gradlew.bat
@@ -0,0 +1,92 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem      https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%"=="" @echo off
+@rem ##########################################################################
+@rem
+@rem  Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%"=="" set DIRNAME=.
+@rem This is normally unused
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if %ERRORLEVEL% equ 0 goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if %ERRORLEVEL% equ 0 goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+set EXIT_CODE=%ERRORLEVEL%
+if %EXIT_CODE% equ 0 set EXIT_CODE=1
+if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
+exit /b %EXIT_CODE%
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/javatests/artifacts/hilt-android/viewmodel/settings.gradle b/javatests/artifacts/hilt-android/viewmodel/settings.gradle
new file mode 100644
index 0000000..5a0650e
--- /dev/null
+++ b/javatests/artifacts/hilt-android/viewmodel/settings.gradle
@@ -0,0 +1,2 @@
+rootProject.name = "Simple ViewModel"
+include ':app'
\ No newline at end of file
diff --git a/javatests/dagger/android/processor/AndroidMapKeyValidatorTest.java b/javatests/dagger/android/processor/AndroidMapKeyValidatorTest.java
index cfa6e90..fc05b61 100644
--- a/javatests/dagger/android/processor/AndroidMapKeyValidatorTest.java
+++ b/javatests/dagger/android/processor/AndroidMapKeyValidatorTest.java
@@ -16,22 +16,18 @@
 
 package dagger.android.processor;
 
-import static com.google.testing.compile.CompilationSubject.assertThat;
-import static com.google.testing.compile.Compiler.javac;
-
+import androidx.room.compiler.processing.util.Source;
 import com.google.common.base.Joiner;
-import com.google.testing.compile.Compilation;
-import com.google.testing.compile.JavaFileObjects;
-import dagger.internal.codegen.ComponentProcessor;
-import javax.tools.JavaFileObject;
+import dagger.testing.compile.CompilerTests;
+import dagger.testing.compile.CompilerTests.DaggerCompiler;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
 
 @RunWith(JUnit4.class)
 public class AndroidMapKeyValidatorTest {
-  private static final JavaFileObject FOO_ACTIVITY =
-      JavaFileObjects.forSourceLines(
+  private static final Source FOO_ACTIVITY =
+      CompilerTests.javaSource(
           "test.FooActivity",
           "package test;",
           "",
@@ -42,8 +38,8 @@
           "  interface Factory extends AndroidInjector.Factory<FooActivity> {}",
           "  abstract static class Builder extends AndroidInjector.Builder<FooActivity> {}",
           "}");
-  private static final JavaFileObject BAR_ACTIVITY =
-      JavaFileObjects.forSourceLines(
+  private static final Source BAR_ACTIVITY =
+      CompilerTests.javaSource(
           "test.BarActivity",
           "package test;",
           "",
@@ -51,8 +47,8 @@
           "",
           "public class BarActivity extends Activity {}");
 
-  private static JavaFileObject moduleWithMethod(String... lines) {
-    return JavaFileObjects.forSourceLines(
+  private static Source moduleWithMethod(String... lines) {
+    return CompilerTests.javaSource(
         "test.AndroidModule",
         "package test;",
         "",
@@ -75,56 +71,86 @@
 
   @Test
   public void rawFactoryType() {
-    JavaFileObject module =
+    Source module =
         moduleWithMethod(
             "@Binds",
             "@IntoMap",
             "@ClassKey(FooActivity.class)",
             "abstract AndroidInjector.Factory bindRawFactory(FooActivity.Factory factory);");
-    Compilation compilation = compile(module, FOO_ACTIVITY);
-    assertThat(compilation).failed();
-    assertThat(compilation)
-        .hadErrorContaining(
-            "should bind dagger.android.AndroidInjector.Factory<?>, "
-                + "not dagger.android.AndroidInjector.Factory");
+    compile(module, FOO_ACTIVITY)
+        .compile(
+            subject -> {
+              subject.compilationDidFail();
+              subject.hasErrorContaining(
+                  "should bind dagger.android.AndroidInjector.Factory<?>, "
+                      + "not dagger.android.AndroidInjector.Factory");
+            });
+  }
+
+  @Test
+  public void wildCardFactoryType() {
+    Source module =
+        CompilerTests.kotlinSource(
+            "AndroidModule.kt",
+            "package test",
+            "",
+            "import dagger.Module",
+            "import dagger.Binds",
+            "import dagger.android.AndroidInjector",
+            "import dagger.multibindings.ClassKey",
+            "import dagger.multibindings.IntoMap",
+            "",
+            "@Module",
+            "internal abstract class AndroidModule {",
+            "   @Binds",
+            "   @IntoMap",
+            "   @ClassKey(FooActivity::class)",
+            "   abstract fun bindWildcardFactory(factory: FooActivity.Factory):"
+                + " AndroidInjector.Factory<*>",
+            "}");
+    compile(module, FOO_ACTIVITY).compile(subject -> subject.hasErrorCount(0));
   }
 
   @Test
   public void rawBuilderType() {
-    JavaFileObject module =
+    Source module =
         moduleWithMethod(
             "@Binds",
             "@IntoMap",
             "@ClassKey(FooActivity.class)",
             "abstract AndroidInjector.Builder bindRawBuilder(FooActivity.Builder builder);");
-    Compilation compilation = compile(module, FOO_ACTIVITY);
-    assertThat(compilation).failed();
-    assertThat(compilation)
-        .hadErrorContaining(
-            "should bind dagger.android.AndroidInjector.Factory<?>, "
-                + "not dagger.android.AndroidInjector.Builder");
+    compile(module, FOO_ACTIVITY)
+        .compile(
+            subject -> {
+              subject.compilationDidFail();
+              subject.hasErrorContaining(
+                  "should bind dagger.android.AndroidInjector.Factory<?>, "
+                      + "not dagger.android.AndroidInjector.Builder");
+            });
   }
 
   @Test
   public void bindsToBuilderNotFactory() {
-    JavaFileObject module =
+    Source module =
         moduleWithMethod(
             "@Binds",
             "@IntoMap",
             "@ClassKey(FooActivity.class)",
             "abstract AndroidInjector.Builder<?> bindBuilder(",
             "    FooActivity.Builder builder);");
-    Compilation compilation = compile(module, FOO_ACTIVITY);
-    assertThat(compilation).failed();
-    assertThat(compilation)
-        .hadErrorContaining(
-            "should bind dagger.android.AndroidInjector.Factory<?>, not "
-                + "dagger.android.AndroidInjector.Builder<?>");
+    compile(module, FOO_ACTIVITY)
+        .compile(
+            subject -> {
+              subject.compilationDidFail();
+              subject.hasErrorContaining(
+                  "should bind dagger.android.AndroidInjector.Factory<?>, not "
+                      + "dagger.android.AndroidInjector.Builder<?>");
+            });
   }
 
   @Test
   public void providesToBuilderNotFactory() {
-    JavaFileObject module =
+    Source module =
         moduleWithMethod(
             "@Provides",
             "@IntoMap",
@@ -132,99 +158,121 @@
             "static AndroidInjector.Builder<?> bindBuilder(FooActivity.Builder builder) {",
             "  return builder;",
             "}");
-    Compilation compilation = compile(module, FOO_ACTIVITY);
-    assertThat(compilation).failed();
-    assertThat(compilation)
-        .hadErrorContaining(
-            "should bind dagger.android.AndroidInjector.Factory<?>, not "
-                + "dagger.android.AndroidInjector.Builder<?>");
+    compile(module, FOO_ACTIVITY)
+        .compile(
+            subject -> {
+              subject.compilationDidFail();
+              subject.hasErrorContaining(
+                  "should bind dagger.android.AndroidInjector.Factory<?>, not "
+                      + "dagger.android.AndroidInjector.Builder<?>");
+            });
   }
 
   @Test
   public void bindsToConcreteTypeInsteadOfWildcard() {
-    JavaFileObject module =
+    Source module =
         moduleWithMethod(
             "@Binds",
             "@IntoMap",
             "@ClassKey(FooActivity.class)",
             "abstract AndroidInjector.Builder<FooActivity> bindBuilder(",
             "    FooActivity.Builder builder);");
-    Compilation compilation = compile(module, FOO_ACTIVITY);
-    assertThat(compilation).failed();
-    assertThat(compilation)
-        .hadErrorContaining(
-            "should bind dagger.android.AndroidInjector.Factory<?>, not "
-                + "dagger.android.AndroidInjector.Builder<test.FooActivity>");
+    compile(module, FOO_ACTIVITY)
+        .compile(
+            subject -> {
+              subject.compilationDidFail();
+              subject.hasErrorContaining(
+                  "should bind dagger.android.AndroidInjector.Factory<?>, not "
+                      + "dagger.android.AndroidInjector.Builder<test.FooActivity>");
+            });
   }
 
   @Test
   public void bindsToBaseTypeInsteadOfWildcard() {
-    JavaFileObject module =
+    Source module =
         moduleWithMethod(
             "@Binds",
             "@IntoMap",
             "@ClassKey(FooActivity.class)",
             "abstract AndroidInjector.Builder<Activity> bindBuilder(",
             "    FooActivity.Builder builder);");
-    Compilation compilation = compile(module, FOO_ACTIVITY);
-    assertThat(compilation).failed();
-    assertThat(compilation)
-        .hadErrorContaining("@Binds methods' parameter type must be assignable to the return type");
+    compile(module, FOO_ACTIVITY)
+        .compile(
+            subject -> {
+              subject.compilationDidFail();
+              subject.hasErrorContaining(
+                  "@Binds methods' parameter type must be assignable to the return type");
+            });
   }
 
   @Test
   public void bindsCorrectType() {
-    JavaFileObject module =
+    Source module =
         moduleWithMethod(
             "@Binds",
             "@IntoMap",
             "@ClassKey(FooActivity.class)",
             "abstract AndroidInjector.Factory<?> bindCorrectType(FooActivity.Builder builder);");
-    Compilation compilation = compile(module, FOO_ACTIVITY);
-    assertThat(compilation).succeededWithoutWarnings();
+    compile(module, FOO_ACTIVITY)
+        .compile(
+            subject -> {
+              subject.hasErrorCount(0);
+              subject.hasNoWarnings();
+            });
   }
 
   @Test
   public void bindsCorrectType_AndroidInjectionKey() {
-    JavaFileObject module =
+    Source module =
         moduleWithMethod(
             "@Binds",
             "@IntoMap",
             "@AndroidInjectionKey(\"test.FooActivity\")",
             "abstract AndroidInjector.Factory<?> bindCorrectType(FooActivity.Builder builder);");
-    Compilation compilation = compile(module, FOO_ACTIVITY);
-    assertThat(compilation).succeededWithoutWarnings();
+    compile(module, FOO_ACTIVITY)
+        .compile(
+            subject -> {
+              subject.hasErrorCount(0);
+              subject.hasNoWarnings();
+            });
   }
 
   @Test
   public void bindsCorrectType_AndroidInjectionKey_unbounded() {
-    JavaFileObject module =
+    Source module =
         moduleWithMethod(
             "@Binds",
             "@IntoMap",
             "@AndroidInjectionKey(\"test.FooActivity\")",
             "abstract AndroidInjector.Factory<?> bindCorrectType(FooActivity.Builder builder);");
-    Compilation compilation = compile(module, FOO_ACTIVITY);
-    assertThat(compilation).succeededWithoutWarnings();
+    compile(module, FOO_ACTIVITY)
+        .compile(
+            subject -> {
+              subject.hasErrorCount(0);
+              subject.hasNoWarnings();
+            });
   }
 
   @Test
   public void bindsWithScope() {
-    JavaFileObject module =
+    Source module =
         moduleWithMethod(
             "@Binds",
             "@IntoMap",
             "@ClassKey(FooActivity.class)",
             "@Singleton",
             "abstract AndroidInjector.Factory<?> bindWithScope(FooActivity.Builder builder);");
-    Compilation compilation = compile(module, FOO_ACTIVITY);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorContaining("should not be scoped");
+    compile(module, FOO_ACTIVITY)
+        .compile(
+            subject -> {
+              subject.compilationDidFail();
+              subject.hasErrorContaining("should not be scoped");
+            });
   }
 
   @Test
   public void bindsWithScope_suppressWarnings() {
-    JavaFileObject module =
+    Source module =
         moduleWithMethod(
             "@SuppressWarnings(\"dagger.android.ScopedInjectorFactory\")",
             "@Binds",
@@ -232,64 +280,77 @@
             "@ClassKey(FooActivity.class)",
             "@Singleton",
             "abstract AndroidInjector.Factory<?> bindWithScope(FooActivity.Builder builder);");
-    Compilation compilation = compile(module, FOO_ACTIVITY);
-    assertThat(compilation).succeededWithoutWarnings();
+    compile(module, FOO_ACTIVITY)
+        .compile(
+            subject -> {
+              subject.hasErrorCount(0);
+              subject.hasNoWarnings();
+            });
   }
 
   @Test
   public void mismatchedMapKey_bindsFactory() {
-    JavaFileObject module =
+    Source module =
         moduleWithMethod(
             "@Binds",
             "@IntoMap",
             "@ClassKey(BarActivity.class)",
             "abstract AndroidInjector.Factory<?> mismatchedFactory(FooActivity.Factory factory);");
-    Compilation compilation = compile(module, FOO_ACTIVITY, BAR_ACTIVITY);
-    assertThat(compilation).failed();
-    assertThat(compilation)
-        .hadErrorContaining(
-            "test.FooActivity.Factory does not implement AndroidInjector<test.BarActivity>")
-        .inFile(module)
-        .onLine(LINES_BEFORE_METHOD + 3);
+    compile(module, FOO_ACTIVITY, BAR_ACTIVITY)
+        .compile(
+            subject -> {
+              subject.compilationDidFail();
+              subject
+                  .hasErrorContaining(
+                      "test.FooActivity.Factory does not implement"
+                          + " AndroidInjector<test.BarActivity>")
+                  .onLine(LINES_BEFORE_METHOD + 3);
+            });
   }
 
   @Test
   public void mismatchedMapKey_bindsBuilder() {
-    JavaFileObject module =
+    Source module =
         moduleWithMethod(
             "@Binds",
             "@IntoMap",
             "@ClassKey(BarActivity.class)",
             "abstract AndroidInjector.Factory<?> mismatchedBuilder(FooActivity.Builder builder);");
-    Compilation compilation = compile(module, FOO_ACTIVITY, BAR_ACTIVITY);
-    assertThat(compilation).failed();
-    assertThat(compilation)
-        .hadErrorContaining(
-            "test.FooActivity.Builder does not implement AndroidInjector<test.BarActivity>")
-        .inFile(module)
-        .onLine(LINES_BEFORE_METHOD + 3);
+    compile(module, FOO_ACTIVITY, BAR_ACTIVITY)
+        .compile(
+            subject -> {
+              subject.compilationDidFail();
+              subject
+                  .hasErrorContaining(
+                      "test.FooActivity.Builder does not implement"
+                          + " AndroidInjector<test.BarActivity>")
+                  .onLine(LINES_BEFORE_METHOD + 3);
+            });
   }
 
   @Test
   public void mismatchedMapKey_bindsBuilder_androidInjectionKey() {
-    JavaFileObject module =
+    Source module =
         moduleWithMethod(
             "@Binds",
             "@IntoMap",
             "@AndroidInjectionKey(\"test.BarActivity\")",
             "abstract AndroidInjector.Factory<?> mismatchedBuilder(FooActivity.Builder builder);");
-    Compilation compilation = compile(module, FOO_ACTIVITY, BAR_ACTIVITY);
-    assertThat(compilation).failed();
-    assertThat(compilation)
-        .hadErrorContaining(
-            "test.FooActivity.Builder does not implement AndroidInjector<test.BarActivity>")
-        .inFile(module)
-        .onLine(LINES_BEFORE_METHOD + 3);
+    compile(module, FOO_ACTIVITY, BAR_ACTIVITY)
+        .compile(
+            subject -> {
+              subject.compilationDidFail();
+              subject
+                  .hasErrorContaining(
+                      "test.FooActivity.Builder does not implement"
+                          + " AndroidInjector<test.BarActivity>")
+                  .onLine(LINES_BEFORE_METHOD + 3);
+            });
   }
 
   @Test
   public void mismatchedMapKey_providesBuilder() {
-    JavaFileObject module =
+    Source module =
         moduleWithMethod(
             "@Provides",
             "@IntoMap",
@@ -297,13 +358,17 @@
             "static AndroidInjector.Factory<?> mismatchedBuilder(FooActivity.Builder builder) {",
             "  return builder;",
             "}");
-    Compilation compilation = compile(module, FOO_ACTIVITY, BAR_ACTIVITY);
-    assertThat(compilation).succeededWithoutWarnings();
+    compile(module, FOO_ACTIVITY, BAR_ACTIVITY)
+        .compile(
+            subject -> {
+              subject.hasErrorCount(0);
+              subject.hasNoWarnings();
+            });
   }
 
   @Test
   public void bindsQualifier_ignoresChecks() {
-    JavaFileObject module =
+    Source module =
         moduleWithMethod(
             "@Binds",
             "@IntoMap",
@@ -312,48 +377,61 @@
             // normally this should fail, since it is binding to a Builder not a Factory
             "abstract AndroidInjector.Builder<?> bindsBuilderWithQualifier(",
             "    FooActivity.Builder builder);");
-    Compilation compilation = compile(module, FOO_ACTIVITY);
-    assertThat(compilation).succeededWithoutWarnings();
+    compile(module, FOO_ACTIVITY)
+        .compile(
+            subject -> {
+              subject.hasErrorCount(0);
+              subject.hasNoWarnings();
+            });
   }
 
   @Test
   public void bindToPrimitive() {
-    JavaFileObject module =
+    Source module =
         moduleWithMethod(
             "@Binds",
             "@IntoMap",
             "@AndroidInjectionKey(\"test.FooActivity\")",
             "abstract int bindInt(@Named(\"unused\") int otherInt);");
-    Compilation compilation = compile(module, FOO_ACTIVITY);
-    assertThat(compilation).succeededWithoutWarnings();
+    compile(module, FOO_ACTIVITY)
+        .compile(
+            subject -> {
+              subject.hasErrorCount(0);
+              subject.hasNoWarnings();
+            });
   }
 
   @Test
   public void bindToNonFrameworkClass() {
-    JavaFileObject module =
+    Source module =
         moduleWithMethod(
             "@Binds",
             "@IntoMap",
             "@AndroidInjectionKey(\"test.FooActivity\")",
             "abstract Number bindInt(Integer integer);");
-    Compilation compilation = compile(module, FOO_ACTIVITY);
-    assertThat(compilation).succeededWithoutWarnings();
+    compile(module, FOO_ACTIVITY)
+        .compile(
+            subject -> {
+              subject.hasErrorCount(0);
+              subject.hasNoWarnings();
+            });
   }
 
   @Test
   public void invalidBindsMethod() {
-    JavaFileObject module =
+    Source module =
         moduleWithMethod(
             "@Binds",
             "@IntoMap",
             "@ClassKey(FooActivity.class)",
             "abstract AndroidInjector.Factory<?> bindCorrectType(",
             "    FooActivity.Builder builder, FooActivity.Builder builder2);");
-    Compilation compilation = compile(module, FOO_ACTIVITY);
-    assertThat(compilation).failed();
+    compile(module, FOO_ACTIVITY).compile(subject -> subject.compilationDidFail());
   }
 
-  private Compilation compile(JavaFileObject... files) {
-    return javac().withProcessors(new ComponentProcessor(), new AndroidProcessor()).compile(files);
+  private DaggerCompiler compile(Source... files) {
+    return CompilerTests.daggerCompiler(files)
+        .withAdditionalJavacProcessors(new AndroidProcessor())
+        .withAdditionalKspProcessors(new KspAndroidProcessor.Provider());
   }
 }
diff --git a/javatests/dagger/android/processor/BUILD b/javatests/dagger/android/processor/BUILD
index 321293d..518234d 100644
--- a/javatests/dagger/android/processor/BUILD
+++ b/javatests/dagger/android/processor/BUILD
@@ -30,6 +30,7 @@
         "//java/dagger/android",
         "//java/dagger/android/processor",
         "//java/dagger/internal/codegen:processor",
+        "//java/dagger/testing/compile",
         "//third_party/java/compile_testing",
         "//third_party/java/guava/base",
         "//third_party/java/guava/collect",
diff --git a/javatests/dagger/android/processor/ContributesAndroidInjectorTest.java b/javatests/dagger/android/processor/ContributesAndroidInjectorTest.java
index 1718737..70e885f 100644
--- a/javatests/dagger/android/processor/ContributesAndroidInjectorTest.java
+++ b/javatests/dagger/android/processor/ContributesAndroidInjectorTest.java
@@ -16,20 +16,17 @@
 
 package dagger.android.processor;
 
-import static com.google.testing.compile.CompilationSubject.assertThat;
-import static com.google.testing.compile.Compiler.javac;
-
-import com.google.testing.compile.Compilation;
-import com.google.testing.compile.JavaFileObjects;
-import javax.tools.JavaFileObject;
+import androidx.room.compiler.processing.util.Source;
+import dagger.testing.compile.CompilerTests;
+import dagger.testing.compile.CompilerTests.DaggerCompiler;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
 
 @RunWith(JUnit4.class)
 public final class ContributesAndroidInjectorTest {
-  private static final JavaFileObject TEST_ACTIVITY =
-      JavaFileObjects.forSourceLines(
+  private static final Source TEST_ACTIVITY =
+      CompilerTests.javaSource(
           "test.TestActivity",
           "package test;",
           "",
@@ -39,8 +36,8 @@
 
   @Test
   public void notAbstract() {
-    JavaFileObject module =
-        JavaFileObjects.forSourceLines(
+    Source module =
+        CompilerTests.javaSource(
             "test.TestModule",
             "package test;",
             "",
@@ -55,26 +52,26 @@
             "  }",
             "}");
 
-    Compilation compilation = compile(module, TEST_ACTIVITY);
-    assertThat(compilation).failed();
-    assertThat(compilation)
-        .hadErrorContaining("must be abstract")
-        .inFile(module)
-        .onLineContaining("test()");
+    compile(module, TEST_ACTIVITY)
+        .compile(
+            subject -> {
+              subject.compilationDidFail();
+              subject.hasErrorContaining("must be abstract").onLineContaining("test()");
+            });
   }
 
   @Test
   public void hasParameters() {
-    JavaFileObject otherActivity =
-        JavaFileObjects.forSourceLines(
+    Source otherActivity =
+        CompilerTests.javaSource(
             "test.OtherActivity",
             "package test;",
             "",
             "import android.app.Activity;",
             "",
             "class OtherActivity extends Activity {}");
-    JavaFileObject module =
-        JavaFileObjects.forSourceLines(
+    Source module =
+        CompilerTests.javaSource(
             "test.TestModule",
             "package test;",
             "",
@@ -90,22 +87,19 @@
             "  abstract OtherActivity manyParams(OtherActivity two, Object o);",
             "}");
 
-    Compilation compilation = compile(module, TEST_ACTIVITY, otherActivity);
-    assertThat(compilation).failed();
-    assertThat(compilation)
-        .hadErrorContaining("cannot have parameters")
-        .inFile(module)
-        .onLineContaining("oneParam(");
-    assertThat(compilation)
-        .hadErrorContaining("cannot have parameters")
-        .inFile(module)
-        .onLineContaining("manyParams(");
+    compile(module, TEST_ACTIVITY, otherActivity)
+        .compile(
+            subject -> {
+              subject.compilationDidFail();
+              subject.hasErrorContaining("cannot have parameters").onLineContaining("oneParam(");
+              subject.hasErrorContaining("cannot have parameters").onLineContaining("manyParams(");
+            });
   }
 
   @Test
   public void notInAModule() {
-    JavaFileObject randomFile =
-        JavaFileObjects.forSourceLines(
+    Source randomFile =
+        CompilerTests.javaSource(
             "test.RandomFile",
             "package test;",
             "",
@@ -116,26 +110,26 @@
             "  abstract TestActivity test() {}",
             "}");
 
-    Compilation compilation = compile(randomFile, TEST_ACTIVITY);
-    assertThat(compilation).failed();
-    assertThat(compilation)
-        .hadErrorContaining("must be in a @Module")
-        .inFile(randomFile)
-        .onLineContaining("test()");
+    compile(randomFile, TEST_ACTIVITY)
+        .compile(
+            subject -> {
+              subject.compilationDidFail();
+              subject.hasErrorContaining("must be in a @Module").onLineContaining("test()");
+            });
   }
 
   @Test
   public void parameterizedReturnType() {
-    JavaFileObject parameterizedActivity =
-        JavaFileObjects.forSourceLines(
+    Source parameterizedActivity =
+        CompilerTests.javaSource(
             "test.ParameterizedActivity",
             "package test;",
             "",
             "import android.app.Activity;",
             "",
             "class ParameterizedActivity<T> extends Activity {}");
-    JavaFileObject module =
-        JavaFileObjects.forSourceLines(
+    Source module =
+        CompilerTests.javaSource(
             "test.TestModule",
             "package test;",
             "",
@@ -148,18 +142,20 @@
             "  abstract <T> ParameterizedActivity<T> test();",
             "}");
 
-    Compilation compilation = compile(module, TEST_ACTIVITY, parameterizedActivity);
-    assertThat(compilation).failed();
-    assertThat(compilation)
-        .hadErrorContaining("cannot return parameterized types")
-        .inFile(module)
-        .onLineContaining("test()");
+    compile(module, TEST_ACTIVITY, parameterizedActivity)
+        .compile(
+            subject -> {
+              subject.compilationDidFail();
+              subject
+                  .hasErrorContaining("cannot return parameterized types")
+                  .onLineContaining("test()");
+            });
   }
 
   @Test
   public void moduleIsntModule() {
-    JavaFileObject module =
-        JavaFileObjects.forSourceLines(
+    Source module =
+        CompilerTests.javaSource(
             "test.TestModule",
             "package test;",
             "",
@@ -172,18 +168,20 @@
             "  abstract TestActivity test();",
             "}");
 
-    Compilation compilation = compile(module, TEST_ACTIVITY);
-    assertThat(compilation).failed();
-    assertThat(compilation)
-        .hadErrorContaining("Intent is not a @Module")
-        .inFile(module)
-        .onLineContaining("modules = android.content.Intent.class");
+    compile(module, TEST_ACTIVITY)
+        .compile(
+            subject -> {
+              subject.compilationDidFail();
+              subject
+                  .hasErrorContaining("Intent is not a @Module")
+                  .onLineContaining("modules = android.content.Intent.class");
+            });
   }
 
   @Test
   public void hasQualifier() {
-    JavaFileObject module =
-        JavaFileObjects.forSourceLines(
+    Source module =
+        CompilerTests.javaSource(
             "test.TestModule",
             "package test;",
             "",
@@ -200,15 +198,19 @@
             "  abstract TestActivity test();",
             "}");
 
-    Compilation compilation = compile(module, TEST_ACTIVITY);
-    assertThat(compilation).failed();
-    assertThat(compilation)
-        .hadErrorContaining("@ContributesAndroidInjector methods cannot have qualifiers")
-        .inFile(module)
-        .onLineContaining("@AndroidQualifier");
+    compile(module, TEST_ACTIVITY)
+        .compile(
+            subject -> {
+              subject.compilationDidFail();
+              subject
+                  .hasErrorContaining("@ContributesAndroidInjector methods cannot have qualifiers")
+                  .onLineContaining("@AndroidQualifier");
+            });
   }
 
-  private static Compilation compile(JavaFileObject... javaFileObjects) {
-    return javac().withProcessors(new AndroidProcessor()).compile(javaFileObjects);
+  private static DaggerCompiler compile(Source... sources) {
+    return CompilerTests.daggerCompiler(sources)
+        .withAdditionalJavacProcessors(new AndroidProcessor())
+        .withAdditionalKspProcessors(new KspAndroidProcessor.Provider());
   }
 }
diff --git a/javatests/dagger/android/processor/DuplicateAndroidInjectorsCheckerTest.java b/javatests/dagger/android/processor/DuplicateAndroidInjectorsCheckerTest.java
index a84c7eb..65f8076 100644
--- a/javatests/dagger/android/processor/DuplicateAndroidInjectorsCheckerTest.java
+++ b/javatests/dagger/android/processor/DuplicateAndroidInjectorsCheckerTest.java
@@ -16,13 +16,10 @@
 
 package dagger.android.processor;
 
-import static com.google.testing.compile.CompilationSubject.assertThat;
-import static com.google.testing.compile.Compiler.javac;
-
-import com.google.testing.compile.Compilation;
-import com.google.testing.compile.JavaFileObjects;
+import androidx.room.compiler.processing.util.Source;
 import dagger.internal.codegen.ComponentProcessor;
-import javax.tools.JavaFileObject;
+import dagger.internal.codegen.KspComponentProcessor;
+import dagger.testing.compile.CompilerTests;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -31,16 +28,16 @@
 public final class DuplicateAndroidInjectorsCheckerTest {
   @Test
   public void conflictingMapKeys() {
-    JavaFileObject activity =
-        JavaFileObjects.forSourceLines(
+    Source activity =
+        CompilerTests.javaSource(
             "test.TestActivity",
             "package test;",
             "",
             "import android.app.Activity;",
             "",
             "public class TestActivity extends Activity {}");
-    JavaFileObject injectorFactory =
-        JavaFileObjects.forSourceLines(
+    Source injectorFactory =
+        CompilerTests.javaSource(
             "test.TestInjectorFactory",
             "package test;",
             "",
@@ -53,8 +50,8 @@
             "  @Override",
             "  public AndroidInjector<TestActivity> create(TestActivity instance) { return null; }",
             "}");
-    JavaFileObject module =
-        JavaFileObjects.forSourceLines(
+    Source module =
+        CompilerTests.javaSource(
             "test.TestModule",
             "package test;",
             "",
@@ -76,8 +73,8 @@
             "  @AndroidInjectionKey(\"test.TestActivity\")",
             "  AndroidInjector.Factory<?> stringKey(TestInjectorFactory factory);",
             "}");
-    JavaFileObject component =
-        JavaFileObjects.forSourceLines(
+    Source component =
+        CompilerTests.javaSource(
             "test.TestComponent",
             "package test;",
             "",
@@ -90,17 +87,20 @@
             "  DispatchingAndroidInjector<Activity> dispatchingInjector();",
             "}");
 
-    Compilation compilation =
-        javac()
-            .withProcessors(ComponentProcessor.forTesting(new DuplicateAndroidInjectorsChecker()))
-            .compile(activity, injectorFactory, module, component);
-    assertThat(compilation).failed();
-    assertThat(compilation)
-        .hadErrorContaining("Multiple injector factories bound for the same type")
-        .inFile(component)
-        .onLineContaining("interface TestComponent");
-    assertThat(compilation).hadErrorContaining("classKey(test.TestInjectorFactory)");
-    assertThat(compilation).hadErrorContaining("stringKey(test.TestInjectorFactory)");
-    assertThat(compilation).hadErrorCount(1);
+    CompilerTests.daggerCompiler(activity, injectorFactory, module, component)
+        .withAdditionalJavacProcessors(
+            ComponentProcessor.withTestPlugins(new DuplicateAndroidInjectorsChecker()))
+        .withAdditionalKspProcessors(
+            KspComponentProcessor.Provider.withTestPlugins(new DuplicateAndroidInjectorsChecker()))
+        .compile(
+            subject -> {
+              subject.compilationDidFail();
+              subject
+                  .hasErrorContaining("Multiple injector factories bound for the same type")
+                  .onLineContaining("interface TestComponent");
+              subject.hasErrorContaining("classKey(test.TestInjectorFactory)");
+              subject.hasErrorContaining("stringKey(test.TestInjectorFactory)");
+              subject.hasErrorCount(1);
+            });
   }
 }
diff --git a/javatests/dagger/functional/assisted/AssistedFactoryAsQualifiedBindingTest.java b/javatests/dagger/functional/assisted/AssistedFactoryAsQualifiedBindingTest.java
index 494372a..afb5f7a 100644
--- a/javatests/dagger/functional/assisted/AssistedFactoryAsQualifiedBindingTest.java
+++ b/javatests/dagger/functional/assisted/AssistedFactoryAsQualifiedBindingTest.java
@@ -17,7 +17,6 @@
 package dagger.functional.assisted;
 
 import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth8.assertThat;
 import static java.lang.annotation.RetentionPolicy.RUNTIME;
 
 import dagger.Binds;
diff --git a/javatests/dagger/functional/basic/BUILD b/javatests/dagger/functional/basic/BUILD
index 18be5e1..9ed6fc2 100644
--- a/javatests/dagger/functional/basic/BUILD
+++ b/javatests/dagger/functional/basic/BUILD
@@ -26,7 +26,9 @@
 
 GenJavaTests(
     name = "basic",
-    srcs = glob(["*.java"]),
+    srcs = glob(
+        ["*.java"],
+    ),
     gen_library_deps = [
         "//javatests/dagger/functional/basic/subpackage",
     ],
diff --git a/javatests/dagger/functional/basic/ComponentNestedTypeTest.java b/javatests/dagger/functional/basic/ComponentNestedTypeTest.java
index b9e0cf4..837228f 100644
--- a/javatests/dagger/functional/basic/ComponentNestedTypeTest.java
+++ b/javatests/dagger/functional/basic/ComponentNestedTypeTest.java
@@ -54,8 +54,7 @@
 
   @Test
   public void typeNameWontClashWithNestedTypeName() {
-    TestComponent component =
-        DaggerComponentNestedTypeTest_TestComponent.builder().testModule(new TestModule()).build();
+    TestComponent component = DaggerComponentNestedTypeTest_TestComponent.create();
     assertThat(component.nestedType()).isNotNull();
   }
 }
diff --git a/javatests/dagger/functional/jdk8/OptionalBindingComponentsEmptyTest.java b/javatests/dagger/functional/jdk8/OptionalBindingComponentsEmptyTest.java
index 21bdd3c..8f63190 100644
--- a/javatests/dagger/functional/jdk8/OptionalBindingComponentsEmptyTest.java
+++ b/javatests/dagger/functional/jdk8/OptionalBindingComponentsEmptyTest.java
@@ -16,7 +16,7 @@
 
 package dagger.functional.jdk8;
 
-import static com.google.common.truth.Truth8.assertThat;
+import static com.google.common.truth.Truth.assertThat;
 
 import dagger.functional.jdk8.OptionalBindingComponents.EmptyOptionalBindingComponent;
 import org.junit.Before;
diff --git a/javatests/dagger/functional/jdk8/OptionalBindingComponentsPresentTest.java b/javatests/dagger/functional/jdk8/OptionalBindingComponentsPresentTest.java
index 50fbefe..0e91dc5 100644
--- a/javatests/dagger/functional/jdk8/OptionalBindingComponentsPresentTest.java
+++ b/javatests/dagger/functional/jdk8/OptionalBindingComponentsPresentTest.java
@@ -17,7 +17,6 @@
 package dagger.functional.jdk8;
 
 import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth8.assertThat;
 import static dagger.functional.jdk8.OptionalBindingComponents.Value.QUALIFIED_VALUE;
 import static dagger.functional.jdk8.OptionalBindingComponents.Value.VALUE;
 
diff --git a/javatests/dagger/functional/kotlinsrc/assisted/AssistedFactoryAsQualifiedBindingTest.kt b/javatests/dagger/functional/kotlinsrc/assisted/AssistedFactoryAsQualifiedBindingTest.kt
index 8c8dafa..af891d7 100644
--- a/javatests/dagger/functional/kotlinsrc/assisted/AssistedFactoryAsQualifiedBindingTest.kt
+++ b/javatests/dagger/functional/kotlinsrc/assisted/AssistedFactoryAsQualifiedBindingTest.kt
@@ -17,7 +17,6 @@
 package dagger.functional.kotlinsrc.assisted
 
 import com.google.common.truth.Truth.assertThat
-import com.google.common.truth.Truth8.assertThat
 import dagger.Binds
 import dagger.BindsInstance
 import dagger.BindsOptionalOf
@@ -56,7 +55,7 @@
     interface Factory {
       fun create(
         @BindsInstance @AsComponentDependency bar: Bar,
-        @BindsInstance @AsComponentDependency barFactory: BarFactory
+        @BindsInstance @AsComponentDependency barFactory: BarFactory,
       ): TestComponent
     }
   }
@@ -132,7 +131,7 @@
     @AsMultibinding val barSet: Set<Bar>,
     @AsMultibinding val barFactorySet: Set<@JvmSuppressWildcards BarFactory>,
     val unqualifiedBarSet: Set<Bar>,
-    val unqualifiedBarFactorySet: Set<@JvmSuppressWildcards BarFactory>
+    val unqualifiedBarFactorySet: Set<@JvmSuppressWildcards BarFactory>,
   )
 
   class Bar @AssistedInject constructor()
diff --git a/javatests/dagger/functional/kotlinsrc/assisted/AssistedFactoryWithJavaKeyWordNamesTest.kt b/javatests/dagger/functional/kotlinsrc/assisted/AssistedFactoryWithJavaKeyWordNamesTest.kt
new file mode 100644
index 0000000..84aaa62
--- /dev/null
+++ b/javatests/dagger/functional/kotlinsrc/assisted/AssistedFactoryWithJavaKeyWordNamesTest.kt
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.functional.kotlinsrc.assisted
+
+import com.google.common.truth.Truth.assertThat
+import dagger.BindsInstance
+import dagger.Component
+import dagger.assisted.Assisted
+import dagger.assisted.AssistedFactory
+import dagger.assisted.AssistedInject
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+// Regression test for https://github.com/google/dagger/issues/3995.
+@RunWith(JUnit4::class)
+internal class AssistedFactoryWithJavaKeyWordNamesTest {
+  @Component
+  interface MyComponent {
+    fun myAssistedFactory(): MyAssistedFactory
+
+    @Component.Builder
+    interface Builder {
+      @BindsInstance fun addInteger(int: Int): Builder
+      fun build(): MyComponent
+    }
+  }
+
+  data class MyAssistedClass @AssistedInject constructor(
+    val int: Int,
+    @Assisted val string: String,
+    @Assisted val long: Long
+  )
+
+  @AssistedFactory
+  interface MyAssistedFactory {
+    fun create(long: Long, string: String): MyAssistedClass
+  }
+
+  @Test
+  fun testParametersWithJavaKeywordNames() {
+    val int = 1
+    val long = 2L
+    val string = "string"
+    val myAssistedFactory =
+      DaggerAssistedFactoryWithJavaKeyWordNamesTest_MyComponent.builder()
+        .addInteger(int)
+        .build()
+        .myAssistedFactory()
+        .create(long, string)
+    assertThat(myAssistedFactory.int).isEqualTo(int)
+    assertThat(myAssistedFactory.long).isEqualTo(long)
+    assertThat(myAssistedFactory.string).isEqualTo(string)
+  }
+}
diff --git a/javatests/dagger/functional/kotlinsrc/assisted/BUILD b/javatests/dagger/functional/kotlinsrc/assisted/BUILD
index a90f83c..57242b3 100644
--- a/javatests/dagger/functional/kotlinsrc/assisted/BUILD
+++ b/javatests/dagger/functional/kotlinsrc/assisted/BUILD
@@ -132,3 +132,14 @@
         "//third_party/java/junit",
     ],
 )
+
+GenKtTests(
+    name = "AssistedFactoryWithJavaKeyWordNamesTest",
+    srcs = ["AssistedFactoryWithJavaKeyWordNamesTest.kt"],
+    javacopts = DOCLINT_HTML_AND_SYNTAX,
+    test_only_deps = [
+        "//:dagger_with_compiler",
+        "//third_party/java/truth",
+        "//third_party/java/junit",
+    ],
+)
diff --git a/javatests/dagger/functional/kotlinsrc/membersinject/MembersInjectTest.kt b/javatests/dagger/functional/kotlinsrc/membersinject/MembersInjectTest.kt
index 2fc4425..e7a751f 100644
--- a/javatests/dagger/functional/kotlinsrc/membersinject/MembersInjectTest.kt
+++ b/javatests/dagger/functional/kotlinsrc/membersinject/MembersInjectTest.kt
@@ -23,8 +23,8 @@
 import dagger.functional.kotlinsrc.membersinject.subpackage.a.AGrandchild
 import dagger.functional.kotlinsrc.membersinject.subpackage.a.AParent
 import dagger.functional.kotlinsrc.membersinject.subpackage.b.BChild
+import dagger.internal.Provider
 import javax.inject.Inject
-import javax.inject.Provider
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
@@ -85,7 +85,9 @@
   }
 
   class A : B() // No injected members
+
   open class B : C() // No injected members
+
   open class C {
     @Inject lateinit var value: String
   }
diff --git a/javatests/dagger/functional/kotlinsrc/membersinject/MembersInjectionWithJavaKeywordNamesTest.kt b/javatests/dagger/functional/kotlinsrc/membersinject/MembersInjectionWithJavaKeywordNamesTest.kt
new file mode 100644
index 0000000..adbfd50
--- /dev/null
+++ b/javatests/dagger/functional/kotlinsrc/membersinject/MembersInjectionWithJavaKeywordNamesTest.kt
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.functional.kotlinsrc.membersinject
+
+import com.google.common.truth.Truth.assertThat
+import dagger.BindsInstance
+import dagger.Component
+import dagger.assisted.Assisted
+import dagger.assisted.AssistedFactory
+import dagger.assisted.AssistedInject
+import javax.inject.Inject
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+// Regression test for https://github.com/google/dagger/issues/3995.
+@RunWith(JUnit4::class)
+internal class MembersInjectionWithJavaKeywordNamesTest {
+  @Component
+  interface MyComponent {
+    fun myClass(): MyClass
+
+    @Component.Builder
+    interface Builder {
+      @BindsInstance fun addInteger(int: Int): Builder
+      @BindsInstance fun addString(string: String): Builder
+      @BindsInstance fun addLong(long: Long): Builder
+      fun build(): MyComponent
+    }
+  }
+
+  @Suppress("BadInject")
+  class MyClass @Inject constructor(val int: Int) {
+    @Inject @JvmField var string: String = ""
+
+    var long: Long? = null
+
+    @Inject fun injectMethod(long: Long) {
+      this.long = long
+    }
+  }
+
+  @Test
+  fun testParametersWithJavaKeywordNames() {
+    val int = 1
+    val long = 2L
+    val string = "string"
+    val myClass =
+      DaggerMembersInjectionWithJavaKeywordNamesTest_MyComponent.builder()
+        .addInteger(int)
+        .addString(string)
+        .addLong(long)
+        .build()
+        .myClass()
+    assertThat(myClass.int).isEqualTo(int)
+    assertThat(myClass.long).isEqualTo(long)
+    assertThat(myClass.string).isEqualTo(string)
+  }
+}
diff --git a/javatests/dagger/functional/kotlinsrc/membersinject/MembersInjectionWithTypeAliasSuperclassTest.kt b/javatests/dagger/functional/kotlinsrc/membersinject/MembersInjectionWithTypeAliasSuperclassTest.kt
new file mode 100644
index 0000000..e45f63e
--- /dev/null
+++ b/javatests/dagger/functional/kotlinsrc/membersinject/MembersInjectionWithTypeAliasSuperclassTest.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2024 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.functional.kotlinsrc.membersinject
+
+import com.google.common.truth.Truth.assertThat
+import dagger.Component
+import javax.inject.Inject
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+/** This is a regression test for https://github.com/google/dagger/issues/4199 */
+@RunWith(JUnit4::class)
+class MembersInjectionWithTypeAliasSuperclassTest {
+  @Test
+  fun testMembersInjection() {
+    val myClass = MyClass()
+    DaggerTestComponent.create().inject(myClass)
+    assertThat(myClass.foo).isNotNull()
+    assertThat(myClass.bar).isNotNull()
+  }
+}
+
+@Component
+interface TestComponent {
+  fun inject(myClass: MyClass)
+}
+
+class MyClass: MyBaseClassAlias() {
+  @Inject lateinit var foo: Foo
+}
+
+typealias MyBaseClassAlias = MyBaseClass
+
+abstract class MyBaseClass {
+  @Inject lateinit var bar: Bar
+}
+
+class Foo @Inject constructor()
+class Bar @Inject constructor()
diff --git a/javatests/dagger/functional/kotlinsrc/multibindings/ClassKeyWithGenericsTest.kt b/javatests/dagger/functional/kotlinsrc/multibindings/ClassKeyWithGenericsTest.kt
new file mode 100644
index 0000000..25d8c56
--- /dev/null
+++ b/javatests/dagger/functional/kotlinsrc/multibindings/ClassKeyWithGenericsTest.kt
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.functional.kotlinsrc.multibindings
+
+import com.google.common.truth.Truth.assertThat
+import dagger.Component
+import dagger.Module
+import dagger.Provides
+import dagger.multibindings.ClassKey
+import dagger.multibindings.IntoMap
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class ClassKeyWithGenericsTest {
+  @Component(modules = [TestModule::class])
+  interface TestComponent {
+    val map: Map<Class<*>, String>
+  }
+
+  @Module
+  internal object TestModule {
+    @Provides
+    @IntoMap
+    @ClassKey(Thing::class)
+    fun provideThingValue(): String = "Thing"
+
+    @Provides
+    @IntoMap
+    @ClassKey(GenericThing::class)
+    fun provideAbstractThingValue(): String = "GenericThing"
+  }
+
+  class Thing
+
+  class GenericThing<T>
+
+  @Test
+  fun test() {
+    val map = DaggerClassKeyWithGenericsTest_TestComponent.create().map
+    assertThat(map)
+        .containsExactly(
+            Thing::class.java, "Thing",
+            GenericThing::class.java, "GenericThing");
+  }
+}
diff --git a/javatests/dagger/functional/kotlinsrc/nullables/BUILD b/javatests/dagger/functional/kotlinsrc/nullables/BUILD
index e9db7a7..ad9ad77 100644
--- a/javatests/dagger/functional/kotlinsrc/nullables/BUILD
+++ b/javatests/dagger/functional/kotlinsrc/nullables/BUILD
@@ -25,6 +25,18 @@
 package(default_visibility = ["//:src"])
 
 GenKtTests(
+    name = "JspecifyNullableTest",
+    srcs = ["JspecifyNullableTest.kt"],
+    javacopts = DOCLINT_HTML_AND_SYNTAX + DOCLINT_REFERENCES,
+    deps = [
+        "//:dagger_with_compiler",
+        "//third_party/java/jspecify_annotations",
+        "//third_party/java/junit",
+        "//third_party/java/truth",
+    ],
+)
+
+GenKtTests(
     name = "NullabilityTest",
     srcs = ["NullabilityTest.kt"],
     javacopts = DOCLINT_HTML_AND_SYNTAX + DOCLINT_REFERENCES,
diff --git a/javatests/dagger/functional/kotlinsrc/nullables/JspecifyNullableTest.kt b/javatests/dagger/functional/kotlinsrc/nullables/JspecifyNullableTest.kt
new file mode 100644
index 0000000..9490f6f
--- /dev/null
+++ b/javatests/dagger/functional/kotlinsrc/nullables/JspecifyNullableTest.kt
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.functional.kotlinsrc.nullables
+
+import com.google.common.truth.Truth.assertThat
+import dagger.Component
+import dagger.Module
+import dagger.Provides
+import org.jspecify.annotations.Nullable
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+// This is a regression test for b/290632844.
+@RunWith(JUnit4::class)
+public final class JspecifyNullableTest {
+  @Component(modules = [MyIntComponent.MyModule::class])
+  interface MyIntComponent {
+    fun getInt(): Int
+
+    @Module
+    class MyModule(val intValue: Int) {
+      // Check that using @Nullable on the type is ignored (matching KAPT).
+      @Provides fun provideInt(): @Nullable Int = intValue
+    }
+  }
+
+  @Component(modules = [MyNullableStringComponent.MyModule::class])
+  interface MyNullableStringComponent {
+    fun getString(): String?
+
+    @Module
+    class MyModule(val stringValue: String?) {
+      // Check that using @Nullable on the type is ignored (matching KAPT).
+      @Provides fun provideString(): @Nullable String? = stringValue
+    }
+  }
+
+  @Test
+  public fun testIntWithValue() {
+    val component =
+      DaggerJspecifyNullableTest_MyIntComponent.builder()
+        .myModule(MyIntComponent.MyModule(15))
+        .build()
+    assertThat(component.getInt()).isEqualTo(15)
+  }
+
+  @Test
+  public fun testStringWithValue() {
+    val component =
+      DaggerJspecifyNullableTest_MyNullableStringComponent.builder()
+        .myModule(MyNullableStringComponent.MyModule("TEST_VALUE"))
+        .build()
+    assertThat(component.getString()).isEqualTo("TEST_VALUE")
+  }
+
+  @Test
+  public fun testStringWithNull() {
+    val component =
+      DaggerJspecifyNullableTest_MyNullableStringComponent.builder()
+        .myModule(MyNullableStringComponent.MyModule(null))
+        .build()
+    assertThat(component.getString()).isNull()
+  }
+}
diff --git a/javatests/dagger/functional/membersinject/MembersInjectTest.java b/javatests/dagger/functional/membersinject/MembersInjectTest.java
index 06e17f9..c6a13dd 100644
--- a/javatests/dagger/functional/membersinject/MembersInjectTest.java
+++ b/javatests/dagger/functional/membersinject/MembersInjectTest.java
@@ -24,8 +24,8 @@
 import dagger.functional.membersinject.subpackage.a.AGrandchild;
 import dagger.functional.membersinject.subpackage.a.AParent;
 import dagger.functional.membersinject.subpackage.b.BChild;
+import dagger.internal.Provider;
 import javax.inject.Inject;
-import javax.inject.Provider;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
diff --git a/javatests/dagger/functional/multibindings/ClassKeyWithGenericsTest.java b/javatests/dagger/functional/multibindings/ClassKeyWithGenericsTest.java
new file mode 100644
index 0000000..2cc3ad8
--- /dev/null
+++ b/javatests/dagger/functional/multibindings/ClassKeyWithGenericsTest.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2018 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.functional.multibindings;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import dagger.Component;
+import dagger.Module;
+import dagger.Provides;
+import dagger.multibindings.ClassKey;
+import dagger.multibindings.IntoMap;
+import java.util.Map;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+// This is a regression test for https://github.com/google/dagger/issues/4055.
+@RunWith(JUnit4.class)
+public final class ClassKeyWithGenericsTest {
+  @Component(modules = TestModule.class)
+  interface TestComponent {
+    Map<Class<?>, String> map();
+  }
+
+  @Module
+  interface TestModule {
+    @Provides
+    @IntoMap
+    @ClassKey(Thing.class)
+    static String provideThingValue() {
+      return "Thing";
+    }
+
+    @Provides
+    @IntoMap
+    @ClassKey(GenericThing.class)
+    static String provideGenericThingValue() {
+      return "GenericThing";
+    }
+  }
+
+  class Thing {}
+
+  class GenericThing<T> {}
+
+  @Test
+  public void test() {
+    Map<Class<?>, String> map = DaggerClassKeyWithGenericsTest_TestComponent.create().map();
+    assertThat(map)
+        .containsExactly(
+            Thing.class, "Thing",
+            GenericThing.class, "GenericThing");
+  }
+}
diff --git a/javatests/dagger/functional/nullables/BUILD b/javatests/dagger/functional/nullables/BUILD
index 323e6a5..52fb843 100644
--- a/javatests/dagger/functional/nullables/BUILD
+++ b/javatests/dagger/functional/nullables/BUILD
@@ -25,6 +25,18 @@
 package(default_visibility = ["//:src"])
 
 GenJavaTests(
+    name = "JspecifyNullableTest",
+    srcs = ["JspecifyNullableTest.java"],
+    javacopts = DOCLINT_HTML_AND_SYNTAX + DOCLINT_REFERENCES,
+    deps = [
+        "//:dagger_with_compiler",
+        "//third_party/java/jspecify_annotations",
+        "//third_party/java/junit",
+        "//third_party/java/truth",
+    ],
+)
+
+GenJavaTests(
     name = "NullabilityTest",
     srcs = ["NullabilityTest.java"],
     javacopts = DOCLINT_HTML_AND_SYNTAX + DOCLINT_REFERENCES,
diff --git a/javatests/dagger/functional/nullables/JspecifyNullableTest.java b/javatests/dagger/functional/nullables/JspecifyNullableTest.java
new file mode 100644
index 0000000..b5d42f3
--- /dev/null
+++ b/javatests/dagger/functional/nullables/JspecifyNullableTest.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.functional.nullables;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertThrows;
+
+import dagger.Component;
+import dagger.Module;
+import dagger.Provides;
+import javax.inject.Provider;
+import org.jspecify.annotations.Nullable;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class JspecifyNullableTest {
+  @Component(modules = MyModule.class, dependencies = ComponentDependency.class)
+  interface MyComponent {
+    Integer getInt();
+    InnerType getInnerType();
+        Provider<Dependency> getDependencyProvider();
+  }
+
+  interface Dependency {}
+
+  interface InnerType {}
+
+  @Module
+  static class MyModule {
+    private final Integer integer;
+    private final InnerType innerType;
+
+    MyModule(Integer integer, InnerType innerType) {
+      this.integer = integer;
+      this.innerType = innerType;
+    }
+
+    @Provides
+    @Nullable Integer provideInt() {
+      return integer;
+    }
+
+    @Provides
+    @Nullable InnerType provideInnerType() {
+      return innerType;
+    }
+  }
+
+  @Component(modules = DependencyModule.class)
+  interface ComponentDependency {
+    @Nullable Dependency dependency();
+  }
+
+  @Module
+  static class DependencyModule {
+    private final Dependency dependency;
+
+    DependencyModule(Dependency dependency) {
+      this.dependency = dependency;
+    }
+
+    @Provides
+    @Nullable Dependency provideDependency() {
+      return dependency;
+    }
+  }
+
+  @Test
+  public void testWithValue() {
+    MyComponent component = DaggerJspecifyNullableTest_MyComponent.builder()
+        .myModule(new MyModule(15, new InnerType() {}))
+        .componentDependency(
+            DaggerJspecifyNullableTest_ComponentDependency.builder()
+                .dependencyModule(new DependencyModule(new Dependency() {})).build())
+        .build();
+    assertThat(component.getInt()).isEqualTo(15);
+    assertThat(component.getInnerType()).isNotNull();
+    assertThat(component.getDependencyProvider().get()).isNotNull();
+  }
+
+  @Test
+  public void testWithNull() {
+    MyComponent component = DaggerJspecifyNullableTest_MyComponent.builder()
+        .myModule(new MyModule(null, null))
+        .componentDependency(
+            DaggerJspecifyNullableTest_ComponentDependency.builder()
+                .dependencyModule(new DependencyModule(null)).build())
+        .build();
+    NullPointerException expectedException =
+        assertThrows(NullPointerException.class, component::getInt);
+    assertThat(expectedException)
+        .hasMessageThat()
+        .contains("Cannot return null from a non-@Nullable @Provides method");
+    NullPointerException expectedException2 =
+        assertThrows(NullPointerException.class, component::getInnerType);
+    assertThat(expectedException2)
+        .hasMessageThat()
+        .contains("Cannot return null from a non-@Nullable @Provides method");
+    NullPointerException expectedException3 =
+        assertThrows(NullPointerException.class, () -> component.getDependencyProvider().get());
+    assertThat(expectedException3)
+        .hasMessageThat()
+        .contains("Cannot return null from a non-@Nullable @Provides method");
+  }
+}
diff --git a/javatests/dagger/functional/producers/ProducerFactoryTest.java b/javatests/dagger/functional/producers/ProducerFactoryTest.java
index 6df526e..f821ab9 100644
--- a/javatests/dagger/functional/producers/ProducerFactoryTest.java
+++ b/javatests/dagger/functional/producers/ProducerFactoryTest.java
@@ -25,6 +25,7 @@
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.MoreExecutors;
 import com.google.common.util.concurrent.SettableFuture;
+import dagger.internal.Provider;
 import dagger.producers.Producer;
 import dagger.producers.internal.AbstractProducer;
 import dagger.producers.internal.CancellableProducer;
@@ -33,7 +34,6 @@
 import dagger.producers.monitoring.ProductionComponentMonitor;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executor;
-import javax.inject.Provider;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -55,7 +55,6 @@
     MockitoAnnotations.initMocks(this);
     monitor = Mockito.mock(ProducerMonitor.class, Mockito.CALLS_REAL_METHODS);
     when(componentMonitor.producerMonitorFor(any(ProducerToken.class))).thenReturn(monitor);
-    // TODO(beder): Use Providers.of when available.
     executorProvider =
         new Provider<Executor>() {
           @Override
diff --git a/javatests/dagger/functional/producers/aot/ProducesMethodShadowsInjectConstructorTest.java b/javatests/dagger/functional/producers/aot/ProducesMethodShadowsInjectConstructorTest.java
index ef37df2..548ad1d 100644
--- a/javatests/dagger/functional/producers/aot/ProducesMethodShadowsInjectConstructorTest.java
+++ b/javatests/dagger/functional/producers/aot/ProducesMethodShadowsInjectConstructorTest.java
@@ -17,7 +17,6 @@
 package dagger.functional.producers.aot;
 
 import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth8.assertThat;
 
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.MoreExecutors;
diff --git a/javatests/dagger/hilt/android/AndroidManifest.xml b/javatests/dagger/hilt/android/AndroidManifest.xml
index 3c0fa84..ed24e45 100644
--- a/javatests/dagger/hilt/android/AndroidManifest.xml
+++ b/javatests/dagger/hilt/android/AndroidManifest.xml
@@ -66,10 +66,38 @@
         android:exported="false"
         tools:ignore="MissingClass"/>
     <activity
+        android:name=".ViewModelAssistedTest$TestConfigChangeActivity"
+        android:exported="false"
+        tools:ignore="MissingClass"/>
+    <activity
+        android:name=".ViewModelAssistedTest$TestKeyedViewModelActivity"
+        android:exported="false"
+        tools:ignore="MissingClass"/>
+    <activity
+        android:name=".ViewModelAssistedTest$TestNoCreationCallbacksActivity"
+        android:exported="false"
+        tools:ignore="MissingClass"/>
+    <activity
+        android:name=".ViewModelAssistedTest$TestNoFactoryActivity"
+        android:exported="false"
+        tools:ignore="MissingClass"/>
+    <activity
+        android:name=".ViewModelAssistedTest$TestFragmentArgsActivity"
+        android:exported="false"
+        tools:ignore="MissingClass"/>
+    <activity
+        android:name=".ViewModelAssistedTest$TestIncompatibleFactoriesActivity"
+        android:exported="false"
+        tools:ignore="MissingClass"/>
+    <activity
         android:name=".ViewModelSavedStateOwnerTest$TestActivity"
         android:exported="false"
         tools:ignore="MissingClass"/>
     <activity
+        android:name=".ViewModelSavedStateOwnerTest$ErrorTestActivity"
+        android:exported="false"
+        tools:ignore="MissingClass"/>
+    <activity
         android:name=".ViewModelWithBaseTest$TestActivity"
         android:exported="false"
         tools:ignore="MissingClass"/>
diff --git a/javatests/dagger/hilt/android/BUILD b/javatests/dagger/hilt/android/BUILD
index 8f927fb..b3da0d2 100644
--- a/javatests/dagger/hilt/android/BUILD
+++ b/javatests/dagger/hilt/android/BUILD
@@ -543,6 +543,39 @@
 )
 
 android_local_test(
+    name = "ViewModelAssistedTest",
+    srcs = ["ViewModelAssistedTest.java"],
+    javacopts = ["-Adagger.hilt.enableAssistedInjectViewModels=true"],
+    manifest = "AndroidManifest.xml",
+    manifest_values = {
+        "minSdkVersion": "14",
+    },
+    deps = [
+        "//:android_local_test_exports",
+        "//:dagger_with_compiler",
+        "//java/dagger/hilt:install_in",
+        "//java/dagger/hilt/android:android_entry_point",
+        "//java/dagger/hilt/android:package_info",
+        "//java/dagger/hilt/android:view_model_lifecycle",
+        "//java/dagger/hilt/android/internal/lifecycle",
+        "//java/dagger/hilt/android/lifecycle:hilt_view_model",
+        "//java/dagger/hilt/android/lifecycle:hilt_view_model_extensions",
+        "//java/dagger/hilt/android/scopes",
+        "//java/dagger/hilt/android/testing:hilt_android_test",
+        "//third_party/java/jsr330_inject",
+        "//third_party/java/truth",
+        "@maven//:androidx_activity_activity",
+        "@maven//:androidx_fragment_fragment",
+        "@maven//:androidx_lifecycle_lifecycle_common",
+        "@maven//:androidx_lifecycle_lifecycle_viewmodel",
+        "@maven//:androidx_lifecycle_lifecycle_viewmodel_savedstate",
+        "@maven//:androidx_test_core",
+        "@maven//:junit_junit",
+        "@maven//:org_jetbrains_kotlin_kotlin_stdlib",
+    ],
+)
+
+android_local_test(
     name = "ViewModelSavedStateOwnerTest",
     srcs = ["ViewModelSavedStateOwnerTest.java"],
     manifest = "AndroidManifest.xml",
@@ -556,12 +589,15 @@
         "//java/dagger/hilt:install_in",
         "//java/dagger/hilt/android:android_entry_point",
         "//java/dagger/hilt/android:package_info",
+        "//java/dagger/hilt/android:unstable_api",
+        "//java/dagger/hilt/android/lifecycle:activity_retained_saved_state",
         "//java/dagger/hilt/android/lifecycle:hilt_view_model",
         "//java/dagger/hilt/android/scopes",
         "//java/dagger/hilt/android/testing:hilt_android_test",
         "//third_party/java/jsr330_inject",
         "//third_party/java/truth",
         "@maven//:androidx_activity_activity",
+        "@maven//:androidx_annotation_annotation_experimental",
         "@maven//:androidx_fragment_fragment",
         "@maven//:androidx_lifecycle_lifecycle_common",
         "@maven//:androidx_lifecycle_lifecycle_viewmodel",
diff --git a/javatests/dagger/hilt/android/InjectionTest.java b/javatests/dagger/hilt/android/InjectionTest.java
index 426fc6d..3760782 100644
--- a/javatests/dagger/hilt/android/InjectionTest.java
+++ b/javatests/dagger/hilt/android/InjectionTest.java
@@ -19,7 +19,6 @@
 import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
 import static com.google.common.truth.Truth.assertThat;
 import static java.lang.annotation.RetentionPolicy.RUNTIME;
-import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.fail;
 
 import android.annotation.TargetApi;
@@ -439,21 +438,6 @@
   }
 
   @Test
-  @Config(sdk = 19)
-  public void testViewNoFragmentBindingsWithFragment_fourthConstructor_notPresentOnTwenty() {
-    TestFragment fragment = setupFragment(TestActivity.class, new TestFragment());
-
-    assertThrows(
-        NoSuchMethodError.class,
-        () ->
-            new TestView(
-                fragment.getContext(),
-                /* attrs= */ null,
-                /* defStyleAttr= */ 0,
-                /* defStyleRes= */ 0));
-  }
-
-  @Test
   public void testServiceInjection() throws Exception {
     TestService testService = Robolectric.setupService(TestService.class);
     assertThat(testService.appBinding).isEqualTo(APP_BINDING);
diff --git a/javatests/dagger/hilt/android/ViewModelAssistedTest.java b/javatests/dagger/hilt/android/ViewModelAssistedTest.java
new file mode 100644
index 0000000..e466423
--- /dev/null
+++ b/javatests/dagger/hilt/android/ViewModelAssistedTest.java
@@ -0,0 +1,374 @@
+/*
+ * Copyright (C) 2020 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.hilt.android;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertThrows;
+
+import android.os.Build;
+import android.os.Bundle;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentActivity;
+import androidx.annotation.Nullable;
+import androidx.lifecycle.SavedStateHandle;
+import androidx.lifecycle.ViewModel;
+import androidx.lifecycle.ViewModelProvider;
+import androidx.test.core.app.ActivityScenario;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import dagger.assisted.Assisted;
+import dagger.assisted.AssistedFactory;
+import dagger.assisted.AssistedInject;
+import dagger.hilt.android.lifecycle.HiltViewModel;
+import dagger.hilt.android.lifecycle.HiltViewModelExtensions;
+import dagger.hilt.android.scopes.ViewModelScoped;
+import dagger.hilt.android.testing.HiltAndroidRule;
+import dagger.hilt.android.testing.HiltAndroidTest;
+import dagger.hilt.android.testing.HiltTestApplication;
+import javax.inject.Inject;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+
+@HiltAndroidTest
+@RunWith(AndroidJUnit4.class)
+// Robolectric requires Java9 to run API 29 and above, so use API 28 instead
+@Config(sdk = Build.VERSION_CODES.P, application = HiltTestApplication.class)
+public class ViewModelAssistedTest {
+
+  @Rule public final HiltAndroidRule rule = new HiltAndroidRule(this);
+
+  @Test
+  public void testConfigChange() {
+    try (ActivityScenario<TestConfigChangeActivity> scenario =
+        ActivityScenario.launch(TestConfigChangeActivity.class)) {
+      scenario.onActivity(
+          activity -> {
+            assertThat(activity.vm.one.bar).isNotNull();
+            assertThat(activity.vm.one.bar).isSameInstanceAs(activity.vm.two.bar);
+            assertThat(activity.vm.s).isEqualTo("foo");
+          });
+      scenario.recreate();
+      scenario.onActivity(
+          activity -> {
+            // Check that we still get the same ViewModel instance after config change and the
+            // passed assisted arg has no effect anymore.
+            assertThat(activity.vm.s).isEqualTo("foo");
+          });
+    }
+  }
+
+  @Test
+  public void testKeyedViewModels() {
+    try (ActivityScenario<TestKeyedViewModelActivity> scenario =
+        ActivityScenario.launch(TestKeyedViewModelActivity.class)) {
+      scenario.onActivity(
+          activity -> {
+            assertThat(activity.vm1.s).isEqualTo("foo");
+            assertThat(activity.vm2.s).isEqualTo("bar");
+          });
+    }
+  }
+
+  @Test
+  public void testNoCreationCallbacks() {
+    Exception exception =
+        assertThrows(
+            IllegalStateException.class,
+            () -> ActivityScenario.launch(TestNoCreationCallbacksActivity.class).close());
+    assertThat(exception)
+        .hasMessageThat()
+        .contains(
+            "Found @HiltViewModel-annotated class"
+                + " dagger.hilt.android.ViewModelAssistedTest$MyViewModel"
+                + " using @AssistedInject but no creation callback was provided"
+                + " in CreationExtras.");
+  }
+
+  @Test
+  public void testNoFactory() {
+    Exception exception =
+        assertThrows(
+            RuntimeException.class,
+            () -> ActivityScenario.launch(TestNoFactoryActivity.class).close());
+    assertThat(exception)
+        .hasMessageThat()
+        .contains(
+            "Found creation callback but class"
+                + " dagger.hilt.android.ViewModelAssistedTest$MyInjectedViewModel does not have an"
+                + " assisted factory specified in @HiltViewModel.");
+  }
+
+  @Test
+  public void testFragmentArgs() {
+    try (ActivityScenario<TestFragmentArgsActivity> scenario =
+        ActivityScenario.launch(TestFragmentArgsActivity.class)) {
+      scenario.onActivity(
+          activity -> {
+            TestFragment fragment =
+                (TestFragment) activity.getSupportFragmentManager().findFragmentByTag("tag");
+            assertThat(fragment.vm.handle.<String>get("key")).isEqualTo("foobar");
+          });
+    }
+  }
+
+  @Test
+  public void testIncompatibleFactories() {
+    Exception exception =
+        assertThrows(
+            ClassCastException.class,
+            () -> ActivityScenario.launch(TestIncompatibleFactoriesActivity.class).close());
+    assertThat(exception)
+        .hasMessageThat()
+        .contains(
+            "class dagger.hilt.android.ViewModelAssistedTest_MyViewModel_Factory_Impl cannot be"
+                + " cast to class"
+                + " dagger.hilt.android.ViewModelAssistedTest$MyViewModel$AnotherFactory");
+  }
+
+  @AndroidEntryPoint(FragmentActivity.class)
+  public static class TestConfigChangeActivity
+      extends Hilt_ViewModelAssistedTest_TestConfigChangeActivity {
+
+    MyViewModel vm;
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+      super.onCreate(savedInstanceState);
+      if (savedInstanceState == null) {
+        vm =
+            new ViewModelProvider(
+                    getViewModelStore(),
+                    getDefaultViewModelProviderFactory(),
+                    HiltViewModelExtensions.withCreationCallback(
+                        getDefaultViewModelCreationExtras(),
+                        (MyViewModel.Factory factory) -> factory.create("foo")))
+                .get(MyViewModel.class);
+      } else {
+        vm =
+            new ViewModelProvider(
+                    getViewModelStore(),
+                    getDefaultViewModelProviderFactory(),
+                    HiltViewModelExtensions.withCreationCallback(
+                        getDefaultViewModelCreationExtras(),
+                        (MyViewModel.Factory factory) -> factory.create("bar")))
+                .get(MyViewModel.class);
+      }
+    }
+  }
+
+  @AndroidEntryPoint(FragmentActivity.class)
+  public static class TestKeyedViewModelActivity
+      extends Hilt_ViewModelAssistedTest_TestKeyedViewModelActivity {
+
+    MyViewModel vm1;
+    MyViewModel vm2;
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+      super.onCreate(savedInstanceState);
+      vm1 =
+          new ViewModelProvider(
+                  getViewModelStore(),
+                  getDefaultViewModelProviderFactory(),
+                  HiltViewModelExtensions.withCreationCallback(
+                      getDefaultViewModelCreationExtras(),
+                      (MyViewModel.Factory factory) -> factory.create("foo")))
+              .get("a", MyViewModel.class);
+
+      vm2 =
+          new ViewModelProvider(
+                  getViewModelStore(),
+                  getDefaultViewModelProviderFactory(),
+                  HiltViewModelExtensions.withCreationCallback(
+                      getDefaultViewModelCreationExtras(),
+                      (MyViewModel.Factory factory) -> factory.create("bar")))
+              .get("b", MyViewModel.class);
+    }
+  }
+
+  @AndroidEntryPoint(FragmentActivity.class)
+  public static class TestNoCreationCallbacksActivity
+      extends Hilt_ViewModelAssistedTest_TestNoCreationCallbacksActivity {
+
+    MyViewModel vm;
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+      super.onCreate(savedInstanceState);
+      vm = new ViewModelProvider(this).get(MyViewModel.class);
+    }
+  }
+
+  @AndroidEntryPoint(FragmentActivity.class)
+  public static class TestNoFactoryActivity
+      extends Hilt_ViewModelAssistedTest_TestNoFactoryActivity {
+
+    MyInjectedViewModel vm;
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+      super.onCreate(savedInstanceState);
+
+      vm =
+          new ViewModelProvider(
+                  getViewModelStore(),
+                  getDefaultViewModelProviderFactory(),
+                  HiltViewModelExtensions.withCreationCallback(
+                      getDefaultViewModelCreationExtras(),
+                      (MyViewModel.Factory factory) -> factory.create("bar")))
+              .get(MyInjectedViewModel.class);
+    }
+  }
+
+  @AndroidEntryPoint(FragmentActivity.class)
+  public static class TestFragmentArgsActivity
+      extends Hilt_ViewModelAssistedTest_TestFragmentArgsActivity {
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+      super.onCreate(savedInstanceState);
+      if (savedInstanceState == null) {
+        Fragment f =
+            getSupportFragmentManager()
+                .getFragmentFactory()
+                .instantiate(TestFragment.class.getClassLoader(), TestFragment.class.getName());
+        Bundle b = new Bundle();
+        b.putString("key", "foobar");
+        f.setArguments(b);
+        getSupportFragmentManager().beginTransaction().add(0, f, "tag").commitNow();
+      }
+    }
+  }
+
+  @AndroidEntryPoint(FragmentActivity.class)
+  public static class TestIncompatibleFactoriesActivity
+      extends Hilt_ViewModelAssistedTest_TestIncompatibleFactoriesActivity {
+
+    MyViewModel vm;
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+      super.onCreate(savedInstanceState);
+      vm =
+          new ViewModelProvider(
+                  getViewModelStore(),
+                  getDefaultViewModelProviderFactory(),
+                  HiltViewModelExtensions.withCreationCallback(
+                      getDefaultViewModelCreationExtras(),
+                      (MyViewModel.AnotherFactory factory) -> factory.create("foo")))
+              .get(MyViewModel.class);
+    }
+  }
+
+  @AndroidEntryPoint(Fragment.class)
+  public static class TestFragment extends Hilt_ViewModelAssistedTest_TestFragment {
+
+    MyViewModel vm;
+
+    @Override
+    public void onCreate(@Nullable Bundle bundle) {
+      super.onCreate(bundle);
+      vm =
+          new ViewModelProvider(
+                  getViewModelStore(),
+                  getDefaultViewModelProviderFactory(),
+                  HiltViewModelExtensions.withCreationCallback(
+                      getDefaultViewModelCreationExtras(),
+                      (MyViewModel.Factory factory) -> factory.create("foo")))
+              .get(MyViewModel.class);
+    }
+  }
+
+  @HiltViewModel(assistedFactory = MyViewModel.Factory.class)
+  static class MyViewModel extends ViewModel {
+
+    final DependsOnBarOne one;
+    final DependsOnBarTwo two;
+    final SavedStateHandle handle;
+    final String s;
+    boolean cleared = false;
+
+    @AssistedInject
+    MyViewModel(
+        DependsOnBarOne one,
+        DependsOnBarTwo two,
+        ViewModelLifecycle lifecycle,
+        SavedStateHandle handle,
+        @Assisted String s) {
+      this.one = one;
+      this.two = two;
+      this.s = s;
+      this.handle = handle;
+      lifecycle.addOnClearedListener(() -> cleared = true);
+    }
+
+    @AssistedFactory
+    interface Factory {
+      MyViewModel create(String s);
+    }
+
+    @AssistedFactory
+    interface AnotherFactory {
+      MyViewModel create(String s);
+    }
+  }
+
+  @HiltViewModel
+  static class MyInjectedViewModel extends ViewModel {
+
+    final DependsOnBarOne one;
+    final DependsOnBarTwo two;
+    final SavedStateHandle handle;
+    boolean cleared = false;
+
+    @Inject
+    MyInjectedViewModel(
+        DependsOnBarOne one,
+        DependsOnBarTwo two,
+        ViewModelLifecycle lifecycle,
+        SavedStateHandle handle) {
+      this.one = one;
+      this.two = two;
+      this.handle = handle;
+      lifecycle.addOnClearedListener(() -> cleared = true);
+    }
+  }
+
+  @ViewModelScoped
+  static class Bar {
+    @Inject
+    Bar() {}
+  }
+
+  static class DependsOnBarOne {
+    final Bar bar;
+
+    @Inject
+    DependsOnBarOne(Bar bar) {
+      this.bar = bar;
+    }
+  }
+
+  static class DependsOnBarTwo {
+    final Bar bar;
+
+    @Inject
+    DependsOnBarTwo(Bar bar) {
+      this.bar = bar;
+    }
+  }
+}
diff --git a/javatests/dagger/hilt/android/ViewModelSavedStateOwnerTest.java b/javatests/dagger/hilt/android/ViewModelSavedStateOwnerTest.java
index eab206e..3e522b9 100644
--- a/javatests/dagger/hilt/android/ViewModelSavedStateOwnerTest.java
+++ b/javatests/dagger/hilt/android/ViewModelSavedStateOwnerTest.java
@@ -17,12 +17,14 @@
 package dagger.hilt.android;
 
 import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertThrows;
 
 import android.os.Build;
 import android.os.Bundle;
 import androidx.fragment.app.Fragment;
 import androidx.fragment.app.FragmentActivity;
 import androidx.annotation.Nullable;
+import androidx.annotation.OptIn;
 import androidx.lifecycle.SavedStateHandle;
 import androidx.lifecycle.ViewModel;
 import androidx.lifecycle.ViewModelProvider;
@@ -31,17 +33,20 @@
 import androidx.navigation.Navigation;
 import androidx.test.core.app.ActivityScenario;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
+import dagger.hilt.android.lifecycle.ActivityRetainedSavedState;
 import dagger.hilt.android.lifecycle.HiltViewModel;
 import dagger.hilt.android.testing.HiltAndroidRule;
 import dagger.hilt.android.testing.HiltAndroidTest;
 import dagger.hilt.android.testing.HiltTestApplication;
 import javax.inject.Inject;
+import javax.inject.Provider;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.annotation.Config;
 
 /** Test that you can use the Hilt ViewModel factory with other owners. */
+@OptIn(markerClass = UnstableApi.class)
 @HiltAndroidTest
 @RunWith(AndroidJUnit4.class)
 // Robolectric requires Java9 to run API 29 and above, so use API 28 instead
@@ -51,6 +56,40 @@
   @Rule public final HiltAndroidRule rule = new HiltAndroidRule(this);
 
   @Test
+  public void activityRetainedComponentSaveState_configurationChange_successfullySavedState() {
+    try (ActivityScenario<TestActivity> scenario = ActivityScenario.launch(TestActivity.class)) {
+      scenario.onActivity(
+          activity -> {
+            assertThat((String) activity.savedStateHandle.get("argument_key")).isNull();
+            activity.savedStateHandle.set("other_key", "activity_other_key");
+          });
+      scenario.recreate();
+      scenario.onActivity(
+          activity -> {
+            assertThat((String) activity.savedStateHandle.get("argument_key")).isNull();
+            assertThat((String) activity.savedStateHandle.get("other_key"))
+                .isEqualTo("activity_other_key");
+          });
+    }
+  }
+
+  @Test
+  public void firstTimeAccessToActivityRetainedSaveState_inActivityOnDestroy_fails() {
+    Exception exception =
+        assertThrows(
+            NullPointerException.class,
+            () -> {
+              try (ActivityScenario<ErrorTestActivity> scenario =
+                  ActivityScenario.launch(ErrorTestActivity.class)) {}
+            });
+    assertThat(exception)
+        .hasMessageThat()
+        .contains(
+            "The first access to SavedStateHandle should happen between super.onCreate() and"
+                + " super.onDestroy()");
+  }
+
+  @Test
   public void testViewModelSavedState() {
     try (ActivityScenario<TestActivity> scenario = ActivityScenario.launch(TestActivity.class)) {
       scenario.onActivity(
@@ -156,13 +195,30 @@
 
   @AndroidEntryPoint(FragmentActivity.class)
   public static class TestActivity extends Hilt_ViewModelSavedStateOwnerTest_TestActivity {
+    @Inject @ActivityRetainedSavedState Provider<SavedStateHandle> provider;
+    SavedStateHandle savedStateHandle;
+
     @Override
     protected void onCreate(@Nullable Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
+      savedStateHandle = provider.get();
       setContentView(R.layout.navigation_activity);
     }
   }
 
+  @AndroidEntryPoint(FragmentActivity.class)
+  public static class ErrorTestActivity
+      extends Hilt_ViewModelSavedStateOwnerTest_ErrorTestActivity {
+    @Inject @ActivityRetainedSavedState Provider<SavedStateHandle> provider;
+
+    @SuppressWarnings("unused")
+    @Override
+    protected void onDestroy() {
+      super.onDestroy();
+      SavedStateHandle savedStateHandle = provider.get();
+    }
+  }
+
   @AndroidEntryPoint(Fragment.class)
   public static class TestFragment extends Hilt_ViewModelSavedStateOwnerTest_TestFragment {
     @Override
diff --git a/javatests/dagger/hilt/android/processor/internal/BUILD b/javatests/dagger/hilt/android/processor/internal/BUILD
index 8f2c2d9..ac89e9d 100644
--- a/javatests/dagger/hilt/android/processor/internal/BUILD
+++ b/javatests/dagger/hilt/android/processor/internal/BUILD
@@ -29,7 +29,9 @@
     ],
     deps = [
         "//java/dagger/hilt/android/testing/compile",
-        "//third_party/java/compile_testing",
+        "//java/dagger/internal/codegen/xprocessing",
+        "//java/dagger/internal/codegen/xprocessing:xprocessing-testing",
+        "//third_party/java/guava/base",
         "//third_party/java/junit",
         "//third_party/java/truth",
     ],
diff --git a/javatests/dagger/hilt/android/processor/internal/GeneratorsTest.java b/javatests/dagger/hilt/android/processor/internal/GeneratorsTest.java
index 19f950c..55e6966 100644
--- a/javatests/dagger/hilt/android/processor/internal/GeneratorsTest.java
+++ b/javatests/dagger/hilt/android/processor/internal/GeneratorsTest.java
@@ -16,23 +16,23 @@
 
 package dagger.hilt.android.processor.internal;
 
-import static com.google.testing.compile.CompilationSubject.assertThat;
-import static dagger.hilt.android.testing.compile.HiltCompilerTests.compiler;
-
-import com.google.testing.compile.Compilation;
-import com.google.testing.compile.JavaFileObjects;
-import javax.tools.JavaFileObject;
+import androidx.room.compiler.processing.XProcessingEnv.Backend;
+import androidx.room.compiler.processing.util.Source;
+import com.google.common.base.Joiner;
+import com.google.common.truth.StringSubject;
+import dagger.hilt.android.testing.compile.HiltCompilerTests;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
 
 @RunWith(JUnit4.class)
 public final class GeneratorsTest {
+  private static final Joiner JOINER = Joiner.on("\n");
 
   @Test
   public void copyConstructorParametersCopiesExternalNullables() {
-    JavaFileObject baseActivity =
-        JavaFileObjects.forSourceLines(
+    Source baseActivity =
+        HiltCompilerTests.javaSource(
             "test.BaseActivity",
             "package test;",
             "",
@@ -44,8 +44,8 @@
             "      @androidx.annotation.Nullable String androidxNullable,",
             "      @javax.annotation.Nullable String javaxNullable) { }",
             "}");
-    JavaFileObject myActivity =
-        JavaFileObjects.forSourceLines(
+    Source myActivity =
+        HiltCompilerTests.javaSource(
             "test.MyActivity",
             "package test;",
             "",
@@ -60,36 +60,36 @@
             "    super(supportNullable, androidxNullable, javaxNullable);",
             "  }",
             "}");
-    Compilation compilation = compiler().compile(baseActivity, myActivity);
-    assertThat(compilation).succeeded();
-    assertThat(compilation)
-        .generatedSourceFile("test/Hilt_MyActivity")
-        .containsElementsIn(
-            JavaFileObjects.forSourceLines(
-                "test.Hilt_MyActivity",
-                "package test;",
-                "",
-                "import androidx.annotation.Nullable;",
-                "",
-                "@Generated(\"dagger.hilt.android.processor.internal.androidentrypoint.ActivityGenerator\")",
-                "abstract class Hilt_MyActivity extends BaseActivity implements",
-                "    GeneratedComponentManagerHolder {",
-                "  Hilt_MyActivity(",
-                "      @Nullable String supportNullable,",
-                "      @Nullable String androidxNullable,",
-                "      @javax.annotation.Nullable String javaxNullable) {",
-                "    super(supportNullable, androidxNullable, javaxNullable);",
-                "    _initHiltInternal();",
-                "  }",
-                "}"));
+    HiltCompilerTests.hiltCompiler(baseActivity, myActivity)
+        .compile(
+            subject -> {
+              subject.hasErrorCount(0);
+              StringSubject stringSubject =
+                  subject.generatedSourceFileWithPath("test/Hilt_MyActivity.java");
+              stringSubject.contains("package test;");
+              stringSubject.contains("import androidx.annotation.Nullable;");
+              stringSubject.contains(
+                  JOINER.join(
+                      "@Generated(\"dagger.hilt.android.processor.internal.androidentrypoint.ActivityGenerator\")",
+                      "abstract class Hilt_MyActivity extends BaseActivity implements "
+                          + "GeneratedComponentManagerHolder {"));
+              stringSubject.contains(
+                  JOINER.join(
+                      "  Hilt_MyActivity(@Nullable String supportNullable,"
+                      + " @Nullable String androidxNullable,",
+                      "      @javax.annotation.Nullable String javaxNullable) {",
+                      "    super(supportNullable, androidxNullable, javaxNullable);",
+                      "    _initHiltInternal();",
+                      "  }"));
+            });
   }
 
   @Test
   public void copyConstructorParametersConvertsAndroidInternalNullableToExternal() {
     // Relies on View(Context, AttributeSet), which has android-internal
     // @android.annotation.Nullable on AttributeSet.
-    JavaFileObject myView =
-        JavaFileObjects.forSourceLines(
+    Source myView =
+        HiltCompilerTests.javaSource(
             "test.MyView",
             "package test;",
             "",
@@ -104,30 +104,43 @@
             "    super(context, attrs);",
             "  }",
             "}");
-    Compilation compilation = compiler().compile(myView);
-    assertThat(compilation).succeeded();
-    assertThat(compilation)
-        .generatedSourceFile("test/Hilt_MyView")
-        .containsElementsIn(
-            JavaFileObjects.forSourceLines(
-                "test.Hilt_MyView",
-                "package test;",
-                "",
-                "@Generated(\"dagger.hilt.android.processor.internal.androidentrypoint.ViewGenerator\")",
-                "abstract class Hilt_MyView extends View implements",
-                "GeneratedComponentManagerHolder {",
-                "  Hilt_MyView(Context context, @Nullable AttributeSet attrs) {",
-                "    super(context, attrs);",
-                "    inject();",
-                "  }",
-                "}"));
+    HiltCompilerTests.hiltCompiler(myView)
+        .compile(
+            subject -> {
+              subject.hasErrorCount(0);
+              StringSubject stringSubject =
+                  subject.generatedSourceFileWithPath("test/Hilt_MyView.java");
+              stringSubject.contains("import androidx.annotation.Nullable;");
+              stringSubject.contains(
+                  JOINER.join(
+                      "@Generated(\"dagger.hilt.android.processor.internal.androidentrypoint.ViewGenerator\")",
+                      "abstract class Hilt_MyView extends View implements"
+                          + " GeneratedComponentManagerHolder {"));
+              // TODO(kuanyingchou): Remove the condition once
+              //  https://github.com/google/ksp/issues/1459 is fixed
+              if (HiltCompilerTests.backend(subject) == Backend.KSP) {
+                stringSubject.contains(
+                    JOINER.join(
+                        "  Hilt_MyView(Context p0, @Nullable AttributeSet p1) {",
+                        "    super(p0, p1);",
+                        "    inject();",
+                        "  }"));
+              } else {
+                stringSubject.contains(
+                    JOINER.join(
+                        "  Hilt_MyView(Context context, @Nullable AttributeSet attrs) {",
+                        "    super(context, attrs);",
+                        "    inject();",
+                        "  }"));
+              }
+            });
   }
 
   // This is a regression test for https://github.com/google/dagger/issues/3296
   @Test
   public void isRestrictedApiConstructorWithPrimitiveParameterTest() {
-    JavaFileObject baseView =
-        JavaFileObjects.forSourceLines(
+    Source baseView =
+        HiltCompilerTests.javaSource(
             "test.BaseView",
             "package test;",
             "",
@@ -140,8 +153,8 @@
             "    super(context, attrs);",
             "  }",
             "}");
-    JavaFileObject myView =
-        JavaFileObjects.forSourceLines(
+    Source myView =
+        HiltCompilerTests.javaSource(
             "test.MyView",
             "package test;",
             "",
@@ -156,15 +169,14 @@
             "    super(i, j, context, attrs);",
             "  }",
             "}");
-    Compilation compilation = compiler().compile(baseView, myView);
-    assertThat(compilation).succeeded();
+    HiltCompilerTests.hiltCompiler(baseView, myView).compile(subject -> subject.hasErrorCount(0));
   }
 
   // This is a regression test for https://github.com/google/dagger/issues/3296
   @Test
   public void isRestrictedApiConstructorWithArrayParameterTest() {
-    JavaFileObject baseView =
-        JavaFileObjects.forSourceLines(
+    Source baseView =
+        HiltCompilerTests.javaSource(
             "test.BaseView",
             "package test;",
             "",
@@ -177,8 +189,8 @@
             "    super(context, attrs);",
             "  }",
             "}");
-    JavaFileObject myView =
-        JavaFileObjects.forSourceLines(
+    Source myView =
+        HiltCompilerTests.javaSource(
             "test.MyView",
             "package test;",
             "",
@@ -193,15 +205,14 @@
             "    super(strs, i, context, attrs);",
             "  }",
             "}");
-    Compilation compilation = compiler().compile(baseView, myView);
-    assertThat(compilation).succeeded();
+    HiltCompilerTests.hiltCompiler(baseView, myView).compile(subject -> subject.hasErrorCount(0));
   }
 
   // This is a regression test for https://github.com/google/dagger/issues/3296
   @Test
   public void isRestrictedApiConstructorWithTypeParameterTest() {
-    JavaFileObject baseView =
-        JavaFileObjects.forSourceLines(
+    Source baseView =
+        HiltCompilerTests.javaSource(
             "test.BaseView",
             "package test;",
             "",
@@ -214,8 +225,8 @@
             "    super(context, attrs);",
             "  }",
             "}");
-    JavaFileObject myView =
-        JavaFileObjects.forSourceLines(
+    Source myView =
+        HiltCompilerTests.javaSource(
             "test.MyView",
             "package test;",
             "",
@@ -230,14 +241,13 @@
             "    super(str, i, context, attrs);",
             "  }",
             "}");
-    Compilation compilation = compiler().compile(baseView, myView);
-    assertThat(compilation).succeeded();
+    HiltCompilerTests.hiltCompiler(baseView, myView).compile(subject -> subject.hasErrorCount(0));
   }
 
   @Test
   public void copyTargetApiAnnotationActivity() {
-    JavaFileObject myActivity =
-        JavaFileObjects.forSourceLines(
+    Source myActivity =
+        HiltCompilerTests.javaSource(
             "test.MyActivity",
             "package test;",
             "",
@@ -248,26 +258,25 @@
             "@TargetApi(24)",
             "@AndroidEntryPoint(FragmentActivity.class)",
             "public class MyActivity extends Hilt_MyActivity {}");
-    Compilation compilation = compiler().compile(myActivity);
-    assertThat(compilation).succeeded();
-    assertThat(compilation)
-        .generatedSourceFile("test/Hilt_MyActivity")
-        .containsElementsIn(
-            JavaFileObjects.forSourceLines(
-                "test.Hilt_MyActivity",
-                " package test;",
-                "",
-                "@Generated(\"dagger.hilt.android.processor.internal.androidentrypoint.ActivityGenerator\")",
-                "@TargetApi(24)",
-                "abstract class Hilt_MyActivity extends FragmentActivity ",
-                "implements GeneratedComponentManagerHolder {",
-                "}"));
+    HiltCompilerTests.hiltCompiler(myActivity)
+        .compile(
+            subject -> {
+              subject.hasErrorCount(0);
+              StringSubject stringSubject =
+                  subject.generatedSourceFileWithPath("test/Hilt_MyActivity.java");
+              stringSubject.contains(
+                  JOINER.join(
+                      "@Generated(\"dagger.hilt.android.processor.internal.androidentrypoint.ActivityGenerator\")",
+                      "@TargetApi(24)",
+                      "abstract class Hilt_MyActivity extends FragmentActivity"
+                          + " implements GeneratedComponentManagerHolder {"));
+            });
   }
 
   @Test
   public void copyTargetApiAnnotationOverView() {
-    JavaFileObject myView =
-        JavaFileObjects.forSourceLines(
+    Source myView =
+        HiltCompilerTests.javaSource(
             "test.MyView",
             "package test;",
             "",
@@ -284,27 +293,26 @@
             "   super(context, attributeSet);",
             " }",
             "}");
-    Compilation compilation = compiler().compile(myView);
-    assertThat(compilation).succeeded();
-    assertThat(compilation)
-        .generatedSourceFile("test/Hilt_MyView")
-        .containsElementsIn(
-            JavaFileObjects.forSourceLines(
-                "test.Hilt_MyView",
-                "",
-                "package test;",
-                "",
-                "@Generated(\"dagger.hilt.android.processor.internal.androidentrypoint.ViewGenerator\")",
-                "@TargetApi(24)",
-                "abstract class Hilt_MyView extends LinearLayout implements"
-                    + " GeneratedComponentManagerHolder {",
-                "}"));
+    HiltCompilerTests.hiltCompiler(myView)
+        .compile(
+            subject -> {
+              subject.hasErrorCount(0);
+              StringSubject stringSubject =
+                  subject.generatedSourceFileWithPath("test/Hilt_MyView.java");
+              stringSubject.contains("package test;");
+              stringSubject.contains(
+                  JOINER.join(
+                      "@Generated(\"dagger.hilt.android.processor.internal.androidentrypoint.ViewGenerator\")",
+                      "@TargetApi(24)",
+                      "abstract class Hilt_MyView extends LinearLayout implements"
+                          + " GeneratedComponentManagerHolder {"));
+            });
   }
 
   @Test
   public void copyTargetApiAnnotationApplication() {
-    JavaFileObject myApplication =
-        JavaFileObjects.forSourceLines(
+    Source myApplication =
+        HiltCompilerTests.javaSource(
             "test.MyApplication",
             "package test;",
             "",
@@ -315,25 +323,27 @@
             "@TargetApi(24)",
             "@HiltAndroidApp(Application.class)",
             "public class MyApplication extends Hilt_MyApplication {}");
-    Compilation compilation = compiler().compile(myApplication);
-    assertThat(compilation).succeeded();
-    assertThat(compilation)
-        .generatedSourceFile("test/Hilt_MyApplication")
-        .containsElementsIn(
-            JavaFileObjects.forSourceLines(
-                "test.Hilt_MyApplication",
-                " package test;",
-                "",
-                "@Generated(\"dagger.hilt.android.processor.internal.androidentrypoint.ApplicationGenerator\")",
-                "@TargetApi(24)",
-                "abstract class Hilt_MyApplication extends Application implements"
-                    + " GeneratedComponentManagerHolder {}"));
+    HiltCompilerTests.hiltCompiler(myApplication)
+        .compile(
+            subject -> {
+              subject.hasErrorCount(0);
+              StringSubject stringSubject =
+                  subject.generatedSourceFileWithPath("test/Hilt_MyApplication.java");
+              stringSubject.contains("package test;");
+              stringSubject.contains(
+                  JOINER.join(
+                      "@Generated(\"dagger.hilt.android.processor.internal.androidentrypoint."
+                          + "ApplicationGenerator\")",
+                      "@TargetApi(24)",
+                      "abstract class Hilt_MyApplication extends Application implements"
+                          + " GeneratedComponentManagerHolder {"));
+            });
   }
 
   @Test
   public void copyTargetApiAnnotationFragment() {
-    JavaFileObject myApplication =
-        JavaFileObjects.forSourceLines(
+    Source myApplication =
+        HiltCompilerTests.javaSource(
             "test.MyFragment",
             "package test;",
             "",
@@ -344,25 +354,26 @@
             "@TargetApi(24)",
             "@AndroidEntryPoint(Fragment.class)",
             "public class MyFragment extends Hilt_MyFragment {}");
-    Compilation compilation = compiler().compile(myApplication);
-    assertThat(compilation).succeeded();
-    assertThat(compilation)
-        .generatedSourceFile("test/Hilt_MyFragment")
-        .containsElementsIn(
-            JavaFileObjects.forSourceLines(
-                "test.Hilt_MyFragment",
-                "package test;",
-                "",
-                "@Generated(\"dagger.hilt.android.processor.internal.androidentrypoint.FragmentGenerator\")",
-                "@TargetApi(24)",
-                "abstract class Hilt_MyFragment extends Fragment implements"
-                    + " GeneratedComponentManagerHolder {}"));
+    HiltCompilerTests.hiltCompiler(myApplication)
+        .compile(
+            subject -> {
+              subject.hasErrorCount(0);
+              StringSubject stringSubject =
+                  subject.generatedSourceFileWithPath("test/Hilt_MyFragment.java");
+              stringSubject.contains("package test;");
+              stringSubject.contains(
+                  JOINER.join(
+                      "@Generated(\"dagger.hilt.android.processor.internal.androidentrypoint.FragmentGenerator\")",
+                      "@TargetApi(24)",
+                      "abstract class Hilt_MyFragment extends Fragment implements"
+                          + " GeneratedComponentManagerHolder {"));
+            });
   }
 
   @Test
   public void copyTargetApiBroadcastRecieverGenerator() {
-    JavaFileObject myBroadcastReceiver =
-        JavaFileObjects.forSourceLines(
+    Source myBroadcastReceiver =
+        HiltCompilerTests.javaSource(
             "test.MyBroadcastReceiver",
             "package test;",
             "",
@@ -373,24 +384,25 @@
             "@TargetApi(24)",
             "@AndroidEntryPoint(BroadcastReceiver.class)",
             "public class MyBroadcastReceiver extends Hilt_MyBroadcastReceiver {}");
-    Compilation compilation = compiler().compile(myBroadcastReceiver);
-    assertThat(compilation).succeeded();
-    assertThat(compilation)
-        .generatedSourceFile("test/Hilt_MyBroadcastReceiver")
-        .containsElementsIn(
-            JavaFileObjects.forSourceLines(
-                "test.Hilt_MyBroadcastReceiver",
-                "package test;",
-                "",
-                "@Generated(\"dagger.hilt.android.processor.internal.androidentrypoint.BroadcastReceiverGenerator\")",
-                "@TargetApi(24)",
-                "abstract class Hilt_MyBroadcastReceiver extends BroadcastReceiver {}"));
+    HiltCompilerTests.hiltCompiler(myBroadcastReceiver)
+        .compile(
+            subject -> {
+              subject.hasErrorCount(0);
+              StringSubject stringSubject =
+                  subject.generatedSourceFileWithPath("test/Hilt_MyBroadcastReceiver.java");
+              stringSubject.contains("package test;");
+              stringSubject.contains(
+                  JOINER.join(
+                      "@Generated(\"dagger.hilt.android.processor.internal.androidentrypoint.BroadcastReceiverGenerator\")",
+                      "@TargetApi(24)",
+                      "abstract class Hilt_MyBroadcastReceiver extends BroadcastReceiver {"));
+            });
   }
 
   @Test
   public void copyTargetApiServiceGenerator() {
-    JavaFileObject myService =
-        JavaFileObjects.forSourceLines(
+    Source myService =
+        HiltCompilerTests.javaSource(
             "test.MyService",
             "package test;",
             "",
@@ -408,25 +420,26 @@
             "     return null;",
             "   }",
             "}");
-    Compilation compilation = compiler().compile(myService);
-    assertThat(compilation).succeeded();
-    assertThat(compilation)
-        .generatedSourceFile("test/Hilt_MyService")
-        .containsElementsIn(
-            JavaFileObjects.forSourceLines(
-                "test.Hilt_MyService",
-                "package test;",
-                "",
-                "@Generated(\"dagger.hilt.android.processor.internal.androidentrypoint.ServiceGenerator\")",
-                "@TargetApi(24)",
-                "abstract class Hilt_MyService extends Service implements"
-                    + " GeneratedComponentManagerHolder{}"));
+    HiltCompilerTests.hiltCompiler(myService)
+        .compile(
+            subject -> {
+              subject.hasErrorCount(0);
+              StringSubject stringSubject =
+                  subject.generatedSourceFileWithPath("test/Hilt_MyService.java");
+              stringSubject.contains("package test;");
+              stringSubject.contains(
+                  JOINER.join(
+                      "@Generated(\"dagger.hilt.android.processor.internal.androidentrypoint.ServiceGenerator\")",
+                      "@TargetApi(24)",
+                      "abstract class Hilt_MyService extends Service implements"
+                          + " GeneratedComponentManagerHolder {"));
+            });
   }
 
   @Test
   public void copySuppressWarningsAnnotationActivity_annotationCopied() {
-    JavaFileObject myActivity =
-        JavaFileObjects.forSourceLines(
+    Source myActivity =
+        HiltCompilerTests.javaSource(
             "test.MyActivity",
             "package test;",
             "",
@@ -437,26 +450,26 @@
             "@SuppressWarnings(\"deprecation\")",
             "@AndroidEntryPoint(FragmentActivity.class)",
             "public class MyActivity extends Hilt_MyActivity {}");
-    Compilation compilation = compiler().compile(myActivity);
-    assertThat(compilation).succeeded();
-    assertThat(compilation)
-        .generatedSourceFile("test/Hilt_MyActivity")
-        .containsElementsIn(
-            JavaFileObjects.forSourceLines(
-                "test.Hilt_MyActivity",
-                " package test;",
-                "",
-                "@Generated(\"dagger.hilt.android.processor.internal.androidentrypoint.ActivityGenerator\")",
-                "@SuppressWarnings(\"deprecation\")",
-                "abstract class Hilt_MyActivity extends FragmentActivity ",
-                "implements GeneratedComponentManagerHolder {",
-                "}"));
+    HiltCompilerTests.hiltCompiler(myActivity)
+        .compile(
+            subject -> {
+              subject.hasErrorCount(0);
+              StringSubject stringSubject =
+                  subject.generatedSourceFileWithPath("test/Hilt_MyActivity.java");
+              stringSubject.contains("package test;");
+              stringSubject.contains(
+                  JOINER.join(
+                      "@Generated(\"dagger.hilt.android.processor.internal.androidentrypoint.ActivityGenerator\")",
+                      "@SuppressWarnings(\"deprecation\")",
+                      "abstract class Hilt_MyActivity extends FragmentActivity "
+                          + "implements GeneratedComponentManagerHolder {"));
+            });
   }
 
   @Test
   public void copySuppressWarningsAnnotation_onView_annotationCopied() {
-    JavaFileObject myView =
-        JavaFileObjects.forSourceLines(
+    Source myView =
+        HiltCompilerTests.javaSource(
             "test.MyView",
             "package test;",
             "",
@@ -473,27 +486,26 @@
             "   super(context, attributeSet);",
             " }",
             "}");
-    Compilation compilation = compiler().compile(myView);
-    assertThat(compilation).succeeded();
-    assertThat(compilation)
-        .generatedSourceFile("test/Hilt_MyView")
-        .containsElementsIn(
-            JavaFileObjects.forSourceLines(
-                "test.Hilt_MyView",
-                "",
-                "package test;",
-                "",
-                "@Generated(\"dagger.hilt.android.processor.internal.androidentrypoint.ViewGenerator\")",
-                "@SuppressWarnings(\"deprecation\")",
-                "abstract class Hilt_MyView extends LinearLayout implements"
-                    + " GeneratedComponentManagerHolder {",
-                "}"));
+    HiltCompilerTests.hiltCompiler(myView)
+        .compile(
+            subject -> {
+              subject.hasErrorCount(0);
+              StringSubject stringSubject =
+                  subject.generatedSourceFileWithPath("test/Hilt_MyView.java");
+              stringSubject.contains("package test;");
+              stringSubject.contains(
+                  JOINER.join(
+                      "@Generated(\"dagger.hilt.android.processor.internal.androidentrypoint.ViewGenerator\")",
+                      "@SuppressWarnings(\"deprecation\")",
+                      "abstract class Hilt_MyView extends LinearLayout implements"
+                          + " GeneratedComponentManagerHolder {"));
+            });
   }
 
   @Test
   public void copySuppressWarningsAnnotation_onApplication_annotationCopied() {
-    JavaFileObject myApplication =
-        JavaFileObjects.forSourceLines(
+    Source myApplication =
+        HiltCompilerTests.javaSource(
             "test.MyApplication",
             "package test;",
             "",
@@ -504,25 +516,26 @@
             "@SuppressWarnings(\"deprecation\")",
             "@HiltAndroidApp(Application.class)",
             "public class MyApplication extends Hilt_MyApplication {}");
-    Compilation compilation = compiler().compile(myApplication);
-    assertThat(compilation).succeeded();
-    assertThat(compilation)
-        .generatedSourceFile("test/Hilt_MyApplication")
-        .containsElementsIn(
-            JavaFileObjects.forSourceLines(
-                "test.Hilt_MyApplication",
-                " package test;",
-                "",
-                "@Generated(\"dagger.hilt.android.processor.internal.androidentrypoint.ApplicationGenerator\")",
-                "@SuppressWarnings(\"deprecation\")",
-                "abstract class Hilt_MyApplication extends Application implements"
-                    + " GeneratedComponentManagerHolder {}"));
+    HiltCompilerTests.hiltCompiler(myApplication)
+        .compile(
+            subject -> {
+              subject.hasErrorCount(0);
+              StringSubject stringSubject =
+                  subject.generatedSourceFileWithPath("test/Hilt_MyApplication.java");
+              stringSubject.contains("package test;");
+              stringSubject.contains(
+                  JOINER.join(
+                      "@Generated(\"dagger.hilt.android.processor.internal.androidentrypoint.ApplicationGenerator\")",
+                      "@SuppressWarnings(\"deprecation\")",
+                      "abstract class Hilt_MyApplication extends Application implements"
+                          + " GeneratedComponentManagerHolder {"));
+            });
   }
 
   @Test
   public void copySuppressWarningsAnnotation_onFragment_annotationCopied() {
-    JavaFileObject myApplication =
-        JavaFileObjects.forSourceLines(
+    Source myApplication =
+        HiltCompilerTests.javaSource(
             "test.MyFragment",
             "package test;",
             "",
@@ -533,25 +546,26 @@
             "@SuppressWarnings(\"rawtypes\")",
             "@AndroidEntryPoint(Fragment.class)",
             "public class MyFragment extends Hilt_MyFragment {}");
-    Compilation compilation = compiler().compile(myApplication);
-    assertThat(compilation).succeeded();
-    assertThat(compilation)
-        .generatedSourceFile("test/Hilt_MyFragment")
-        .containsElementsIn(
-            JavaFileObjects.forSourceLines(
-                "test.Hilt_MyFragment",
-                "package test;",
-                "",
-                "@Generated(\"dagger.hilt.android.processor.internal.androidentrypoint.FragmentGenerator\")",
-                "@SuppressWarnings(\"rawtypes\")",
-                "abstract class Hilt_MyFragment extends Fragment implements"
-                    + " GeneratedComponentManagerHolder {}"));
+    HiltCompilerTests.hiltCompiler(myApplication)
+        .compile(
+            subject -> {
+              subject.hasErrorCount(0);
+              StringSubject stringSubject =
+                  subject.generatedSourceFileWithPath("test/Hilt_MyFragment.java");
+              stringSubject.contains("package test;");
+              stringSubject.contains(
+                  JOINER.join(
+                      "@Generated(\"dagger.hilt.android.processor.internal.androidentrypoint.FragmentGenerator\")",
+                      "@SuppressWarnings(\"rawtypes\")",
+                      "abstract class Hilt_MyFragment extends Fragment implements"
+                          + " GeneratedComponentManagerHolder {"));
+            });
   }
 
   @Test
   public void copySuppressWarnings_onBroadcastRecieverGenerator_annotationCopied() {
-    JavaFileObject myBroadcastReceiver =
-        JavaFileObjects.forSourceLines(
+    Source myBroadcastReceiver =
+        HiltCompilerTests.javaSource(
             "test.MyBroadcastReceiver",
             "package test;",
             "",
@@ -562,24 +576,26 @@
             "@SuppressWarnings(\"deprecation\")",
             "@AndroidEntryPoint(BroadcastReceiver.class)",
             "public class MyBroadcastReceiver extends Hilt_MyBroadcastReceiver {}");
-    Compilation compilation = compiler().compile(myBroadcastReceiver);
-    assertThat(compilation).succeeded();
-    assertThat(compilation)
-        .generatedSourceFile("test/Hilt_MyBroadcastReceiver")
-        .containsElementsIn(
-            JavaFileObjects.forSourceLines(
-                "test.Hilt_MyBroadcastReceiver",
-                "package test;",
-                "",
-                "@Generated(\"dagger.hilt.android.processor.internal.androidentrypoint.BroadcastReceiverGenerator\")",
-                "@SuppressWarnings(\"deprecation\")",
-                "abstract class Hilt_MyBroadcastReceiver extends BroadcastReceiver {}"));
+    HiltCompilerTests.hiltCompiler(myBroadcastReceiver)
+        .compile(
+            subject -> {
+              subject.hasErrorCount(0);
+              StringSubject stringSubject =
+                  subject.generatedSourceFileWithPath("test/Hilt_MyBroadcastReceiver.java");
+              stringSubject.contains("package test;");
+              stringSubject.contains(
+                  JOINER.join(
+                      "@Generated(\"dagger.hilt.android.processor.internal.androidentrypoint."
+                          + "BroadcastReceiverGenerator\")",
+                      "@SuppressWarnings(\"deprecation\")",
+                      "abstract class Hilt_MyBroadcastReceiver extends BroadcastReceiver {"));
+            });
   }
 
   @Test
   public void copySuppressWarnings_onServiceGenerator_annotationCopied() {
-    JavaFileObject myService =
-        JavaFileObjects.forSourceLines(
+    Source myService =
+        HiltCompilerTests.javaSource(
             "test.MyService",
             "package test;",
             "",
@@ -597,18 +613,20 @@
             "     return null;",
             "   }",
             "}");
-    Compilation compilation = compiler().compile(myService);
-    assertThat(compilation).succeeded();
-    assertThat(compilation)
-        .generatedSourceFile("test/Hilt_MyService")
-        .containsElementsIn(
-            JavaFileObjects.forSourceLines(
-                "test.Hilt_MyService",
-                "package test;",
-                "",
-                "@Generated(\"dagger.hilt.android.processor.internal.androidentrypoint.ServiceGenerator\")",
-                "@SuppressWarnings(\"deprecation\")",
-                "abstract class Hilt_MyService extends Service implements"
-                    + " GeneratedComponentManagerHolder{}"));
+    HiltCompilerTests.hiltCompiler(myService)
+        .compile(
+            subject -> {
+              subject.hasErrorCount(0);
+              StringSubject stringSubject =
+                  subject.generatedSourceFileWithPath("test/Hilt_MyService.java");
+              stringSubject.contains("package test;");
+              stringSubject.contains(
+                  JOINER.join(
+                      "@Generated(\"dagger.hilt.android.processor.internal.androidentrypoint."
+                          + "ServiceGenerator\")",
+                      "@SuppressWarnings(\"deprecation\")",
+                      "abstract class Hilt_MyService extends Service implements"
+                          + " GeneratedComponentManagerHolder {"));
+            });
   }
 }
diff --git a/javatests/dagger/hilt/android/processor/internal/androidentrypoint/ActivityGeneratorTest.java b/javatests/dagger/hilt/android/processor/internal/androidentrypoint/ActivityGeneratorTest.java
index b58c355..a056670 100644
--- a/javatests/dagger/hilt/android/processor/internal/androidentrypoint/ActivityGeneratorTest.java
+++ b/javatests/dagger/hilt/android/processor/internal/androidentrypoint/ActivityGeneratorTest.java
@@ -71,4 +71,108 @@
     HiltCompilerTests.hiltCompiler(baseActivity, myActivity)
         .compile(subject -> subject.hasErrorCount(0));
   }
+
+  @Test
+  public void baseActivityHasFinalOnDestroy_fails() {
+    Source myActivity =
+        HiltCompilerTests.javaSource(
+            "test.MyActivity",
+            "package test;",
+            "",
+            "import dagger.hilt.android.AndroidEntryPoint;",
+            "",
+            "@AndroidEntryPoint(BaseActivity.class)",
+            "public class MyActivity extends Hilt_MyActivity {}");
+    Source baseActivity =
+        HiltCompilerTests.javaSource(
+            "test.BaseActivity",
+            "package test;",
+            "",
+            "import androidx.activity.ComponentActivity;",
+            "",
+            "public class BaseActivity extends ComponentActivity {",
+            "   @Override public final void onDestroy() {}",
+            "}");
+    HiltCompilerTests.hiltCompiler(myActivity, baseActivity)
+        .compile(
+            subject -> {
+              // TODO(b/319663779) make error count consistent.
+              // subject.hasErrorCount(1);
+              subject.hasErrorContaining(
+                  "Do not mark onDestroy as final in base Activity class, as Hilt needs to override"
+                      + " it to clean up SavedStateHandle");
+            });
+  }
+
+  @Test
+  public void baseActivityHasFinalOnCreate_fails() {
+    Source myActivity =
+        HiltCompilerTests.javaSource(
+            "test.MyActivity",
+            "package test;",
+            "",
+            "import dagger.hilt.android.AndroidEntryPoint;",
+            "",
+            "@AndroidEntryPoint(BaseActivity.class)",
+            "public class MyActivity extends Hilt_MyActivity {}");
+    Source baseActivity =
+        HiltCompilerTests.javaSource(
+            "test.BaseActivity",
+            "package test;",
+            "",
+            "import android.os.Bundle;",
+            "import androidx.activity.ComponentActivity;",
+            "",
+            "public class BaseActivity extends ComponentActivity {",
+            "   @Override public final void onCreate(Bundle bundle) {}",
+            "}");
+    HiltCompilerTests.hiltCompiler(myActivity, baseActivity)
+        .compile(
+            subject -> {
+              // TODO(b/319663779) make error count consistent.
+              // subject.hasErrorCount(1);
+              subject.hasErrorContaining(
+                  "Do not mark onCreate as final in base Activity class, as Hilt needs to override"
+                      + " it to inject SavedStateHandle");
+            });
+  }
+
+  @Test
+  public void secondBaseActivityHasFinalOnCreate_fails() {
+    Source myActivity =
+        HiltCompilerTests.javaSource(
+            "test.MyActivity",
+            "package test;",
+            "",
+            "import dagger.hilt.android.AndroidEntryPoint;",
+            "",
+            "@AndroidEntryPoint(BaseActivity.class)",
+            "public class MyActivity extends Hilt_MyActivity {}");
+    Source baseActivity =
+        HiltCompilerTests.javaSource(
+            "test.BaseActivity",
+            "package test;",
+            "",
+            "public class BaseActivity extends BaseActivity2 {}");
+    Source baseActivity2 =
+        HiltCompilerTests.javaSource(
+            "test.BaseActivity2",
+            "package test;",
+            "",
+            "import android.os.Bundle;",
+            "import androidx.activity.ComponentActivity;",
+            "",
+            "public class BaseActivity2 extends ComponentActivity {",
+            "   @Override public final void onCreate(Bundle bundle) {}",
+            "}");
+    HiltCompilerTests.hiltCompiler(myActivity, baseActivity, baseActivity2)
+        .compile(
+            subject -> {
+              // TODO(b/319663779) make error count consistent.
+              // subject.hasErrorCount(1);
+              subject.hasErrorContaining(
+                  "Do not mark onCreate as final in base Activity class, as Hilt needs to override"
+                      + " it to inject SavedStateHandle");
+            });
+  }
 }
diff --git a/javatests/dagger/hilt/android/processor/internal/androidentrypoint/AndroidEntryPointProcessorTest.java b/javatests/dagger/hilt/android/processor/internal/androidentrypoint/AndroidEntryPointProcessorTest.java
index f39d897..0c11f6e 100644
--- a/javatests/dagger/hilt/android/processor/internal/androidentrypoint/AndroidEntryPointProcessorTest.java
+++ b/javatests/dagger/hilt/android/processor/internal/androidentrypoint/AndroidEntryPointProcessorTest.java
@@ -16,16 +16,12 @@
 
 package dagger.hilt.android.processor.internal.androidentrypoint;
 
-import static com.google.testing.compile.CompilationSubject.assertThat;
-import static dagger.hilt.android.testing.compile.HiltCompilerTests.compiler;
-
 import androidx.room.compiler.processing.XProcessingEnv;
+import androidx.room.compiler.processing.XProcessingEnv.Backend;
 import androidx.room.compiler.processing.util.CompilationResultSubject;
 import androidx.room.compiler.processing.util.Source;
-import com.google.testing.compile.Compilation;
-import com.google.testing.compile.JavaFileObjects;
+import com.google.common.collect.ImmutableMap;
 import dagger.hilt.android.testing.compile.HiltCompilerTests;
-import javax.tools.JavaFileObject;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -106,8 +102,8 @@
 
   @Test
   public void disableSuperclassValidation_activity() {
-    JavaFileObject testActivity =
-        JavaFileObjects.forSourceLines(
+    Source testActivity =
+        HiltCompilerTests.javaSource(
             "test.MyActivity",
             "package test;",
             "",
@@ -116,17 +112,17 @@
             "",
             "@AndroidEntryPoint",
             "public class MyActivity extends ComponentActivity { }");
-    Compilation compilation =
-        compiler()
-            .withOptions("-Adagger.hilt.android.internal.disableAndroidSuperclassValidation=true")
-            .compile(testActivity);
-    assertThat(compilation).succeeded();
+    HiltCompilerTests.hiltCompiler(testActivity)
+        .withProcessorOptions(
+            ImmutableMap.of(
+                "dagger.hilt.android.internal.disableAndroidSuperclassValidation", "true"))
+        .compile(subject -> subject.hasErrorCount(0));
   }
 
   @Test
   public void disableSuperclassValidation_application() {
-    JavaFileObject testApplication =
-        JavaFileObjects.forSourceLines(
+    Source testApplication =
+        HiltCompilerTests.javaSource(
             "test.MyApp",
             "package test;",
             "",
@@ -135,17 +131,17 @@
             "",
             "@HiltAndroidApp",
             "public class MyApp extends Application { }");
-    Compilation compilation =
-        compiler()
-            .withOptions("-Adagger.hilt.android.internal.disableAndroidSuperclassValidation=true")
-            .compile(testApplication);
-    assertThat(compilation).succeeded();
+    HiltCompilerTests.hiltCompiler(testApplication)
+        .withProcessorOptions(
+            ImmutableMap.of(
+                "dagger.hilt.android.internal.disableAndroidSuperclassValidation", "true"))
+        .compile(subject -> subject.hasErrorCount(0));
   }
 
   @Test
   public void checkBaseActivityExtendsComponentActivity() {
-    JavaFileObject testActivity =
-        JavaFileObjects.forSourceLines(
+    Source testActivity =
+        HiltCompilerTests.javaSource(
             "test.MyActivity",
             "package test;",
             "",
@@ -154,18 +150,18 @@
             "",
             "@AndroidEntryPoint(Activity.class)",
             "public class MyActivity extends Hilt_MyActivity { }");
-    Compilation compilation = compiler().compile(testActivity);
-    assertThat(compilation).failed();
-    assertThat(compilation)
-        .hadErrorContaining("Activities annotated with @AndroidEntryPoint must be a subclass of "
-            + "androidx.activity.ComponentActivity. (e.g. FragmentActivity, AppCompatActivity, "
-            + "etc.)");
+    HiltCompilerTests.hiltCompiler(testActivity).compile(subject -> {
+        subject.compilationDidFail();
+        subject.hasErrorContaining(
+            "Activities annotated with @AndroidEntryPoint must be a subclass of "
+                + "androidx.activity.ComponentActivity. (e.g. FragmentActivity, AppCompatActivity, "
+                + "etc.)"); });
   }
 
   @Test
   public void checkBaseActivityWithTypeParameters() {
-    JavaFileObject testActivity =
-        JavaFileObjects.forSourceLines(
+    Source testActivity =
+        HiltCompilerTests.javaSource(
             "test.BaseActivity",
             "package test;",
             "",
@@ -174,13 +170,18 @@
             "",
             "@AndroidEntryPoint(ComponentActivity.class)",
             "public class BaseActivity<T> extends Hilt_BaseActivity {}");
-    Compilation compilation = compiler().compile(testActivity);
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(2);
-    assertThat(compilation).hadErrorContaining(
-        "cannot find symbol\n  symbol: class Hilt_BaseActivity");
-    assertThat(compilation).hadErrorContaining(
-        "@AndroidEntryPoint-annotated classes cannot have type parameters.");
+    HiltCompilerTests.hiltCompiler(testActivity)
+        .compile(
+            subject -> {
+              subject.compilationDidFail();
+              if (HiltCompilerTests.backend(subject) == Backend.JAVAC) {
+                subject.hasErrorCount(2);
+              } else {
+                subject.hasErrorCount(1);
+              }
+              subject.hasErrorContaining(
+                  "@AndroidEntryPoint-annotated classes cannot have type parameters.");
+            });
   }
 
   @Test
diff --git a/javatests/dagger/hilt/android/processor/internal/androidentrypoint/BUILD b/javatests/dagger/hilt/android/processor/internal/androidentrypoint/BUILD
index 10be147..8a39641 100644
--- a/javatests/dagger/hilt/android/processor/internal/androidentrypoint/BUILD
+++ b/javatests/dagger/hilt/android/processor/internal/androidentrypoint/BUILD
@@ -49,7 +49,7 @@
         "//java/dagger/hilt/android/testing/compile",
         "//java/dagger/internal/codegen/xprocessing",
         "//java/dagger/internal/codegen/xprocessing:xprocessing-testing",
-        "//third_party/java/compile_testing",
+        "//third_party/java/guava/collect",
         "//third_party/java/junit",
     ],
 )
diff --git a/javatests/dagger/hilt/android/processor/internal/viewmodel/BUILD b/javatests/dagger/hilt/android/processor/internal/viewmodel/BUILD
index 79d7cbe..eb73b3f 100644
--- a/javatests/dagger/hilt/android/processor/internal/viewmodel/BUILD
+++ b/javatests/dagger/hilt/android/processor/internal/viewmodel/BUILD
@@ -15,8 +15,8 @@
 # Description:
 #   Tests for internal code for implementing Hilt processors.
 
-load("@io_bazel_rules_kotlin//kotlin:kotlin.bzl", "kt_jvm_library")
 load("//java/dagger/testing/compile:macros.bzl", "kt_compiler_test")
+load("@io_bazel_rules_kotlin//kotlin:kotlin.bzl", "kt_jvm_library")
 
 package(default_visibility = ["//:src"])
 
@@ -33,37 +33,11 @@
         "//java/dagger/hilt/android/testing/compile",
         "//java/dagger/internal/codegen/xprocessing",
         "//java/dagger/internal/codegen/xprocessing:xprocessing-testing",
+        "//third_party/java/guava/collect",
         "//third_party/java/junit",
     ],
 )
 
-java_test(
-    name = "ViewModelGeneratorTest",
-    runtime_deps = [
-        ":ViewModelGeneratorTestLib",
-        "//java/dagger/hilt/android/lifecycle:hilt_view_model",
-        "//third_party/java/compile_testing",
-        "//third_party/java/truth",
-        "@androidsdk//:platforms/android-32/android.jar",
-        "@maven//:androidx_lifecycle_lifecycle_viewmodel",
-        "@maven//:androidx_lifecycle_lifecycle_viewmodel_savedstate",
-    ],
-)
-
-kt_jvm_library(
-    name = "ViewModelGeneratorTestLib",
-    srcs = [
-        "ViewModelGeneratorTest.kt",
-    ],
-    deps = [
-        ":test_utils",
-        "//java/dagger/hilt/android/processor/internal/viewmodel:processor_lib",
-        "//third_party/java/compile_testing",
-        "//third_party/java/junit",
-        "//third_party/java/truth",
-    ],
-)
-
 kt_compiler_test(
     name = "ViewModelValidationPluginTest",
     srcs = [
@@ -79,13 +53,50 @@
         "//java/dagger/hilt/android:android_entry_point",
         "//java/dagger/hilt/android:hilt_android_app",
     ],
+    resources = glob(["goldens/*"]),
     deps = [
         ":test_utils",
         "//:compiler_internals",
         "//java/dagger/hilt/android/processor/internal/viewmodel:processor_lib",
         "//java/dagger/hilt/android/processor/internal/viewmodel:validation_plugin_lib",
         "//java/dagger/hilt/android/testing/compile",
+        "//java/dagger/internal/codegen/xprocessing",
+        "//java/dagger/internal/codegen/xprocessing:xprocessing-testing",
+        "//java/dagger/testing/golden",
         "//third_party/java/compile_testing",
+        "//third_party/java/guava/collect",
+        "//third_party/java/junit",
+        "//third_party/java/truth",
+    ],
+)
+
+kt_compiler_test(
+    name = "ViewModelValidationPluginWithAssistedInjectTest",
+    srcs = [
+        "ViewModelValidationPluginWithAssistedInjectTest.kt",
+    ],
+    compiler_deps = [
+        "@androidsdk//:platforms/android-32/android.jar",
+        "@maven//:androidx_lifecycle_lifecycle_viewmodel",
+        "@maven//:androidx_lifecycle_lifecycle_viewmodel_savedstate",
+        "//third_party/java/compile_testing",
+        "//third_party/java/truth",
+        "//java/dagger/hilt/android/lifecycle:hilt_view_model",
+        "//java/dagger/hilt/android:android_entry_point",
+        "//java/dagger/hilt/android:hilt_android_app",
+    ],
+    resources = glob(["goldens/*"]),
+    deps = [
+        ":test_utils",
+        "//:compiler_internals",
+        "//java/dagger/hilt/android/processor/internal/viewmodel:processor_lib",
+        "//java/dagger/hilt/android/processor/internal/viewmodel:validation_plugin_lib",
+        "//java/dagger/hilt/android/testing/compile",
+        "//java/dagger/internal/codegen/xprocessing",
+        "//java/dagger/internal/codegen/xprocessing:xprocessing-testing",
+        "//java/dagger/testing/golden",
+        "//third_party/java/compile_testing",
+        "//third_party/java/guava/collect",
         "//third_party/java/junit",
         "//third_party/java/truth",
     ],
@@ -97,6 +108,6 @@
         "TestUtils.kt",
     ],
     deps = [
-        "//third_party/java/compile_testing",
+        "//java/dagger/hilt/android/testing/compile",
     ],
 )
diff --git a/javatests/dagger/hilt/android/processor/internal/viewmodel/TestUtils.kt b/javatests/dagger/hilt/android/processor/internal/viewmodel/TestUtils.kt
index 713cd22..d833c32 100644
--- a/javatests/dagger/hilt/android/processor/internal/viewmodel/TestUtils.kt
+++ b/javatests/dagger/hilt/android/processor/internal/viewmodel/TestUtils.kt
@@ -1,15 +1,16 @@
 package dagger.hilt.android.processor.internal.viewmodel
 
-import com.google.testing.compile.JavaFileObjects
+import dagger.hilt.android.testing.compile.HiltCompilerTests
 
-val GENERATED_TYPE = try {
-  Class.forName("javax.annotation.processing.Generated")
-  "javax.annotation.processing.Generated"
-} catch (_: ClassNotFoundException) {
-  "javax.annotation.Generated"
-}
+val GENERATED_TYPE =
+  try {
+    Class.forName("javax.annotation.processing.Generated")
+    "javax.annotation.processing.Generated"
+  } catch (_: ClassNotFoundException) {
+    "javax.annotation.Generated"
+  }
 
 const val GENERATED_ANNOTATION =
   "@Generated(\"dagger.hilt.android.processor.internal.viewmodel.ViewModelProcessor\")"
 
-fun String.toJFO(qName: String) = JavaFileObjects.forSourceString(qName, this.trimIndent())
+fun String.toJFO(qName: String) = HiltCompilerTests.javaSource(qName, this.trimIndent())
diff --git a/javatests/dagger/hilt/android/processor/internal/viewmodel/ViewModelGeneratorTest.kt b/javatests/dagger/hilt/android/processor/internal/viewmodel/ViewModelGeneratorTest.kt
deleted file mode 100644
index c2378e0..0000000
--- a/javatests/dagger/hilt/android/processor/internal/viewmodel/ViewModelGeneratorTest.kt
+++ /dev/null
@@ -1,449 +0,0 @@
-/*
- * Copyright (C) 2020 The Dagger Authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package dagger.hilt.android.processor.internal.viewmodel
-
-import com.google.testing.compile.CompilationSubject.assertThat
-import com.google.testing.compile.Compiler
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-@RunWith(JUnit4::class)
-class ViewModelGeneratorTest {
-
-  private fun compiler(): Compiler = Compiler.javac().withProcessors(ViewModelProcessor())
-
-  @Test
-  fun verifyModule_noArg() {
-    val myViewModel = """
-        package dagger.hilt.android.test;
-
-        import dagger.hilt.android.lifecycle.HiltViewModel;
-        import androidx.lifecycle.ViewModel;
-        import javax.inject.Inject;
-
-        @HiltViewModel
-        class MyViewModel extends ViewModel {
-            @Inject
-            MyViewModel() { }
-        }
-        """.toJFO("dagger.hilt.android.test.MyViewModel")
-
-    val expected = """
-        package dagger.hilt.android.test;
-
-        $GENERATED_ANNOTATION
-        @OriginatingElement(
-            topLevelClass = MyViewModel.class
-        )
-        public final class MyViewModel_HiltModules {
-          private MyViewModel_HiltModules() {
-          }
-
-          @Module
-          @InstallIn(ViewModelComponent.class)
-          public static abstract class BindsModule {
-            private BindsModule() {}
-
-            @Binds
-            @IntoMap
-            @StringKey("dagger.hilt.android.test.MyViewModel")
-            @HiltViewModelMap
-            public abstract ViewModel binds(MyViewModel vm);
-          }
-
-          @Module
-          @InstallIn(ActivityRetainedComponent.class)
-          public static final class KeyModule {
-            private KeyModule() {
-            }
-
-            @Provides
-            @IntoSet
-            @HiltViewModelMap.KeySet
-            public static String provide() {
-              return "dagger.hilt.android.test.MyViewModel";
-            }
-          }
-        }
-        """.toJFO("dagger.hilt.android.test.MyViewModel_HiltModule")
-
-    val compilation = compiler()
-      .compile(myViewModel)
-    assertThat(compilation).apply {
-      succeeded()
-      generatedSourceFile("dagger.hilt.android.test.MyViewModel_HiltModules")
-        .containsElementsIn(expected)
-    }
-  }
-
-  @Test
-  fun verifyModule_savedStateOnlyArg() {
-    val myViewModel = """
-        package dagger.hilt.android.test;
-
-        import dagger.hilt.android.lifecycle.HiltViewModel;
-        import androidx.lifecycle.ViewModel;
-        import androidx.lifecycle.SavedStateHandle;
-        import javax.inject.Inject;
-
-        @HiltViewModel
-        class MyViewModel extends ViewModel {
-            @Inject
-            MyViewModel(SavedStateHandle savedState) { }
-        }
-        """.toJFO("dagger.hilt.android.test.MyViewModel")
-
-    val expected = """
-        package dagger.hilt.android.test;
-
-        $GENERATED_ANNOTATION
-        @OriginatingElement(
-            topLevelClass = MyViewModel.class
-        )
-        public final class MyViewModel_HiltModules {
-          private MyViewModel_HiltModules() {
-          }
-
-          @Module
-          @InstallIn(ViewModelComponent.class)
-          public static abstract class BindsModule {
-            private BindsModule() {}
-
-            @Binds
-            @IntoMap
-            @StringKey("dagger.hilt.android.test.MyViewModel")
-            @HiltViewModelMap
-            public abstract ViewModel binds(MyViewModel vm);
-          }
-
-          @Module
-          @InstallIn(ActivityRetainedComponent.class)
-          public static final class KeyModule {
-            private KeyModule() {
-            }
-
-            @Provides
-            @IntoSet
-            @HiltViewModelMap.KeySet
-            public static String provide() {
-              return "dagger.hilt.android.test.MyViewModel";
-            }
-          }
-        }
-        """.toJFO("dagger.hilt.android.test.MyViewModel_HiltModule")
-
-    val compilation = compiler()
-      .compile(myViewModel)
-    assertThat(compilation).apply {
-      succeeded()
-      generatedSourceFile("dagger.hilt.android.test.MyViewModel_HiltModules")
-        .containsElementsIn(expected)
-    }
-  }
-
-  @Test
-  fun verifyModule_mixedArgs() {
-    val foo = """
-        package dagger.hilt.android.test;
-
-        public class Foo { }
-        """.toJFO("dagger.hilt.android.test.Foo")
-
-    val myViewModel = """
-        package dagger.hilt.android.test;
-
-        import dagger.hilt.android.lifecycle.HiltViewModel;
-        import androidx.lifecycle.ViewModel;
-        import androidx.lifecycle.SavedStateHandle;
-        import java.lang.String;
-        import javax.inject.Inject;
-
-        @HiltViewModel
-        class MyViewModel extends ViewModel {
-            @Inject
-            MyViewModel(String s, Foo f, SavedStateHandle savedState, long l) { }
-        }
-        """.toJFO("dagger.hilt.android.test.MyViewModel")
-
-    val expected = """
-        package dagger.hilt.android.test;
-
-        $GENERATED_ANNOTATION
-        @OriginatingElement(
-            topLevelClass = MyViewModel.class
-        )
-        public final class MyViewModel_HiltModules {
-          private MyViewModel_HiltModules() {
-          }
-
-          @Module
-          @InstallIn(ViewModelComponent.class)
-          public static abstract class BindsModule {
-            private BindsModule() {}
-
-            @Binds
-            @IntoMap
-            @StringKey("dagger.hilt.android.test.MyViewModel")
-            @HiltViewModelMap
-            public abstract ViewModel binds(MyViewModel vm);
-          }
-
-          @Module
-          @InstallIn(ActivityRetainedComponent.class)
-          public static final class KeyModule {
-            private KeyModule() {
-            }
-
-            @Provides
-            @IntoSet
-            @HiltViewModelMap.KeySet
-            public static String provide() {
-              return "dagger.hilt.android.test.MyViewModel";
-            }
-          }
-        }
-        """.toJFO("dagger.hilt.android.test.MyViewModel_HiltModule")
-
-    val compilation = compiler()
-      .compile(foo, myViewModel)
-    assertThat(compilation).apply {
-      succeeded()
-      generatedSourceFile("dagger.hilt.android.test.MyViewModel_HiltModules")
-        .containsElementsIn(expected)
-    }
-  }
-
-  @Test
-  fun verifyModule_mixedAndProviderArgs() {
-    val foo = """
-        package dagger.hilt.android.test;
-
-        public class Foo { }
-        """.toJFO("dagger.hilt.android.test.Foo")
-
-    val myViewModel = """
-        package dagger.hilt.android.test;
-
-        import dagger.hilt.android.lifecycle.HiltViewModel;
-        import androidx.lifecycle.ViewModel;
-        import androidx.lifecycle.SavedStateHandle;
-        import java.lang.String;
-        import javax.inject.Inject;
-        import javax.inject.Provider;
-
-        @HiltViewModel
-        class MyViewModel extends ViewModel {
-            @Inject
-            MyViewModel(String s, Provider<Foo> f, SavedStateHandle savedState) { }
-        }
-        """.toJFO("dagger.hilt.android.test.MyViewModel")
-
-    val expected = """
-        package dagger.hilt.android.test;
-
-        $GENERATED_ANNOTATION
-        @OriginatingElement(
-            topLevelClass = MyViewModel.class
-        )
-        public final class MyViewModel_HiltModules {
-          private MyViewModel_HiltModules() {
-          }
-
-          @Module
-          @InstallIn(ViewModelComponent.class)
-          public static abstract class BindsModule {
-            private BindsModule() {}
-
-            @Binds
-            @IntoMap
-            @StringKey("dagger.hilt.android.test.MyViewModel")
-            @HiltViewModelMap
-            public abstract ViewModel binds(MyViewModel vm);
-          }
-
-          @Module
-          @InstallIn(ActivityRetainedComponent.class)
-          public static final class KeyModule {
-            private KeyModule() {
-            }
-
-            @Provides
-            @IntoSet
-            @HiltViewModelMap.KeySet
-            public static String provide() {
-              return "dagger.hilt.android.test.MyViewModel";
-            }
-          }
-        }
-        """.toJFO("dagger.hilt.android.test.MyViewModel_HiltModules")
-
-    val compilation = compiler()
-      .compile(foo, myViewModel)
-    assertThat(compilation).apply {
-      succeeded()
-      generatedSourceFile("dagger.hilt.android.test.MyViewModel_HiltModules")
-        .containsElementsIn(expected)
-    }
-  }
-
-  @Test
-  fun verifyModule_qualifiedArgs() {
-    val myQualifier = """
-        package dagger.hilt.android.test;
-
-        import javax.inject.Qualifier;
-
-        @Qualifier
-        public @interface MyQualifier { }
-        """.toJFO("dagger.hilt.android.test.MyQualifier")
-
-    val myViewModel = """
-        package dagger.hilt.android.test;
-
-        import dagger.hilt.android.lifecycle.HiltViewModel;
-        import androidx.lifecycle.ViewModel;
-        import androidx.lifecycle.SavedStateHandle;
-        import java.lang.Long;
-        import java.lang.String;
-        import javax.inject.Inject;
-        import javax.inject.Named;
-        import javax.inject.Provider;
-
-        @HiltViewModel
-        class MyViewModel extends ViewModel {
-            @Inject
-            MyViewModel(@Named("TheString") String s, @MyQualifier Provider<Long> l,
-                    SavedStateHandle savedState) {
-            }
-        }
-        """.toJFO("dagger.hilt.android.test.MyViewModel")
-
-    val expected = """
-        package dagger.hilt.android.test;
-
-        $GENERATED_ANNOTATION
-        @OriginatingElement(
-            topLevelClass = MyViewModel.class
-        )
-        public final class MyViewModel_HiltModules {
-          private MyViewModel_HiltModules() {
-          }
-
-          @Module
-          @InstallIn(ViewModelComponent.class)
-          public static abstract class BindsModule {
-            private BindsModule() {}
-
-            @Binds
-            @IntoMap
-            @StringKey("dagger.hilt.android.test.MyViewModel")
-            @HiltViewModelMap
-            public abstract ViewModel binds(MyViewModel vm);
-          }
-
-          @Module
-          @InstallIn(ActivityRetainedComponent.class)
-          public static final class KeyModule {
-            private KeyModule() {
-            }
-
-            @Provides
-            @IntoSet
-            @HiltViewModelMap.KeySet
-            public static String provide() {
-              return "dagger.hilt.android.test.MyViewModel";
-            }
-          }
-        }
-        """.toJFO("dagger.hilt.android.test.MyViewModel_HiltModules")
-
-    val compilation = compiler()
-      .compile(myQualifier, myViewModel)
-    assertThat(compilation).apply {
-      succeeded()
-      generatedSourceFile("dagger.hilt.android.test.MyViewModel_HiltModules")
-        .containsElementsIn(expected)
-    }
-  }
-
-  @Test
-  fun verifyInnerClass() {
-    val viewModel = """
-        package dagger.hilt.android.test;
-
-        import dagger.hilt.android.lifecycle.HiltViewModel;
-        import androidx.lifecycle.ViewModel;
-        import javax.inject.Inject;
-
-        class Outer {
-            @HiltViewModel
-            static class InnerViewModel extends ViewModel {
-                @Inject
-                InnerViewModel() { }
-            }
-        }
-        """.toJFO("dagger.hilt.android.test.Outer")
-
-    val expectedModule = """
-        package dagger.hilt.android.test;
-
-        $GENERATED_ANNOTATION
-        @OriginatingElement(
-            topLevelClass = Outer.class
-        )
-        public final class Outer_InnerViewModel_HiltModules {
-          private Outer_InnerViewModel_HiltModules() {
-          }
-
-          @Module
-          @InstallIn(ViewModelComponent.class)
-          public static abstract class BindsModule {
-            private BindsModule() {}
-
-            @Binds
-            @IntoMap
-            @StringKey("dagger.hilt.android.test.Outer${'$'}InnerViewModel")
-            @HiltViewModelMap
-            public abstract ViewModel binds(Outer.InnerViewModel vm);
-          }
-
-          @Module
-          @InstallIn(ActivityRetainedComponent.class)
-          public static final class KeyModule {
-            private KeyModule() {
-            }
-
-            @Provides
-            @IntoSet
-            @HiltViewModelMap.KeySet
-            public static String provide() {
-              return "dagger.hilt.android.test.Outer${'$'}InnerViewModel";
-            }
-          }
-        }
-        """.toJFO("dagger.hilt.android.test.Outer_InnerViewModel_HiltModules")
-
-    val compilation = compiler()
-      .compile(viewModel)
-    assertThat(compilation).apply {
-      succeeded()
-      generatedSourceFile("dagger.hilt.android.test.Outer_InnerViewModel_HiltModules")
-        .containsElementsIn(expectedModule)
-    }
-  }
-}
diff --git a/javatests/dagger/hilt/android/processor/internal/viewmodel/ViewModelProcessorTest.kt b/javatests/dagger/hilt/android/processor/internal/viewmodel/ViewModelProcessorTest.kt
index b35aed2..1337700 100644
--- a/javatests/dagger/hilt/android/processor/internal/viewmodel/ViewModelProcessorTest.kt
+++ b/javatests/dagger/hilt/android/processor/internal/viewmodel/ViewModelProcessorTest.kt
@@ -18,6 +18,7 @@
 
 import androidx.room.compiler.processing.ExperimentalProcessingApi
 import androidx.room.compiler.processing.util.Source
+import com.google.common.collect.ImmutableMap
 import dagger.hilt.android.testing.compile.HiltCompilerTests
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -84,6 +85,42 @@
   }
 
   @Test
+  fun verifyNoAssistedInjectViewModels() {
+    val myViewModel =
+      Source.java(
+        "dagger.hilt.android.test.MyViewModel",
+        """
+        package dagger.hilt.android.test;
+
+        import dagger.assisted.AssistedInject;
+        import dagger.assisted.Assisted;
+        import androidx.lifecycle.ViewModel;
+        import dagger.hilt.android.lifecycle.HiltViewModel;
+        import javax.inject.Inject;
+
+        @HiltViewModel
+        class MyViewModel extends ViewModel {
+            @AssistedInject
+            MyViewModel(String s, @Assisted int i) { }
+        }
+        """
+          .trimIndent()
+      )
+
+    HiltCompilerTests.hiltCompiler(myViewModel)
+      .withAdditionalJavacProcessors(ViewModelProcessor())
+      .withAdditionalKspProcessors(KspViewModelProcessor.Provider())
+      .withProcessorOptions(ImmutableMap.of("dagger.hilt.enableAssistedInjectViewModels", "false"))
+      .compile { subject ->
+        subject.compilationDidFail()
+        subject.hasErrorCount(1)
+        subject.hasErrorContaining(
+          "ViewModel constructor should be annotated with @Inject instead of @AssistedInject."
+        )
+      }
+  }
+
+  @Test
   fun verifySingleAnnotatedConstructor() {
     val myViewModel =
       Source.java(
@@ -107,19 +144,31 @@
           .trimIndent()
       )
 
-    HiltCompilerTests.hiltCompiler(myViewModel)
-      .withAdditionalJavacProcessors(ViewModelProcessor())
-      .withAdditionalKspProcessors(KspViewModelProcessor.Provider())
-      .compile { subject ->
-        subject.compilationDidFail()
-        subject.hasErrorCount(2)
-        subject.hasErrorContaining(
-          "Type dagger.hilt.android.test.MyViewModel may only contain one injected constructor. Found: [@Inject dagger.hilt.android.test.MyViewModel(), @Inject dagger.hilt.android.test.MyViewModel(String)]"
+    listOf(false, true).forEach { enableAssistedInjectViewModels ->
+      HiltCompilerTests.hiltCompiler(myViewModel)
+        .withAdditionalJavacProcessors(ViewModelProcessor())
+        .withAdditionalKspProcessors(KspViewModelProcessor.Provider())
+        .withProcessorOptions(
+          ImmutableMap.of(
+            "dagger.hilt.enableAssistedInjectViewModels",
+            enableAssistedInjectViewModels.toString()
+          )
         )
-        subject.hasErrorContaining(
-          "@HiltViewModel annotated class should contain exactly one @Inject annotated constructor."
-        )
-      }
+        .compile { subject ->
+          subject.compilationDidFail()
+          subject.hasErrorCount(2)
+          subject.hasErrorContaining(
+            "Type dagger.hilt.android.test.MyViewModel may only contain one injected constructor. Found: [@Inject dagger.hilt.android.test.MyViewModel(), @Inject dagger.hilt.android.test.MyViewModel(String)]"
+          )
+          subject.hasErrorContaining(
+            if (enableAssistedInjectViewModels) {
+              "@HiltViewModel annotated class should contain exactly one @Inject or @AssistedInject annotated constructor."
+            } else {
+              "@HiltViewModel annotated class should contain exactly one @Inject annotated constructor."
+            }
+          )
+        }
+    }
   }
 
   @Test
@@ -143,15 +192,29 @@
           .trimIndent()
       )
 
-    HiltCompilerTests.hiltCompiler(myViewModel)
-      .withAdditionalJavacProcessors(ViewModelProcessor())
-      .withAdditionalKspProcessors(KspViewModelProcessor.Provider())
-      .compile { subject ->
-        subject.compilationDidFail()
-        subject.hasErrorCount(2)
-        subject.hasErrorContaining("Dagger does not support injection into private constructors")
-        subject.hasErrorContaining("@Inject annotated constructors must not be private.")
-      }
+    listOf(false, true).forEach { enableAssistedInjectViewModels ->
+      HiltCompilerTests.hiltCompiler(myViewModel)
+        .withAdditionalJavacProcessors(ViewModelProcessor())
+        .withAdditionalKspProcessors(KspViewModelProcessor.Provider())
+        .withProcessorOptions(
+          ImmutableMap.of(
+            "dagger.hilt.enableAssistedInjectViewModels",
+            enableAssistedInjectViewModels.toString()
+          )
+        )
+        .compile { subject ->
+          subject.compilationDidFail()
+          subject.hasErrorCount(2)
+          subject.hasErrorContaining("Dagger does not support injection into private constructors")
+          subject.hasErrorContaining(
+            if (enableAssistedInjectViewModels) {
+              "@Inject or @AssistedInject annotated constructors must not be private."
+            } else {
+              "@Inject annotated constructors must not be private."
+            }
+          )
+        }
+    }
   }
 
   @Test
@@ -225,4 +288,340 @@
         )
       }
   }
+
+  @Test
+  fun verifyAssistedFlagIsEnabled() {
+    val myViewModel =
+      Source.java(
+        "dagger.hilt.android.test.MyViewModel",
+        """
+        package dagger.hilt.android.test;
+
+        import dagger.assisted.Assisted;
+        import dagger.assisted.AssistedInject;
+        import androidx.lifecycle.ViewModel;
+        import dagger.hilt.android.lifecycle.HiltViewModel;
+
+        @HiltViewModel(assistedFactory = MyFactory.class)
+        class MyViewModel extends ViewModel {
+            @AssistedInject
+            MyViewModel(String s, @Assisted int i) { }
+        }
+        """
+          .trimIndent()
+      )
+    val myFactory =
+      Source.java(
+        "dagger.hilt.android.test.MyFactory",
+        """
+        package dagger.hilt.android.test;
+        import dagger.assisted.AssistedFactory;
+        @AssistedFactory
+        interface MyFactory {
+            MyViewModel create(int i);
+        }
+        """
+      )
+
+    HiltCompilerTests.hiltCompiler(myViewModel, myFactory)
+      .withAdditionalJavacProcessors(ViewModelProcessor())
+      .withAdditionalKspProcessors(KspViewModelProcessor.Provider())
+      .withProcessorOptions(ImmutableMap.of("dagger.hilt.enableAssistedInjectViewModels", "false"))
+      .compile { subject ->
+        subject.compilationDidFail()
+        subject.hasErrorCount(1)
+        subject.hasErrorContaining(
+          "Specified assisted factory dagger.hilt.android.test.MyFactory for dagger.hilt.android.test.MyViewModel in @HiltViewModel but compiler option 'enableAssistedInjectViewModels' was not enabled."
+        )
+      }
+  }
+
+  @Test
+  fun verifyAssistedFactoryHasMethod() {
+    val myViewModel =
+      Source.java(
+        "dagger.hilt.android.test.MyViewModel",
+        """
+        package dagger.hilt.android.test;
+
+        import dagger.assisted.Assisted;
+        import dagger.assisted.AssistedInject;
+        import androidx.lifecycle.ViewModel;
+        import dagger.hilt.android.lifecycle.HiltViewModel;
+
+        @HiltViewModel(assistedFactory = MyFactory.class)
+        class MyViewModel extends ViewModel {
+            @AssistedInject
+            MyViewModel(String s, @Assisted int i) { }
+        }
+        """
+          .trimIndent()
+      )
+    val myFactory =
+      Source.java(
+        "dagger.hilt.android.test.MyFactory",
+        """
+        package dagger.hilt.android.test;
+        import dagger.assisted.AssistedFactory;
+        @AssistedFactory
+        interface MyFactory {}
+        """
+      )
+
+    HiltCompilerTests.hiltCompiler(myViewModel, myFactory)
+      .withAdditionalJavacProcessors(ViewModelProcessor())
+      .withAdditionalKspProcessors(KspViewModelProcessor.Provider())
+      .withProcessorOptions(ImmutableMap.of("dagger.hilt.enableAssistedInjectViewModels", "true"))
+      .compile { subject ->
+        subject.compilationDidFail()
+        subject.hasErrorCount(2)
+        subject.hasErrorContaining(
+          "The @AssistedFactory-annotated type is missing an abstract, non-default method whose return type matches the assisted injection type."
+        )
+        subject.hasErrorContaining(
+          "Cannot find assisted factory method in dagger.hilt.android.test.MyFactory."
+        )
+      }
+  }
+
+  @Test
+  fun verifyAssistedFactoryHasOnlyOneMethod() {
+    val myViewModel =
+      Source.java(
+        "dagger.hilt.android.test.MyViewModel",
+        """
+        package dagger.hilt.android.test;
+
+        import dagger.assisted.Assisted;
+        import dagger.assisted.AssistedInject;
+        import androidx.lifecycle.ViewModel;
+        import dagger.hilt.android.lifecycle.HiltViewModel;
+
+        @HiltViewModel(assistedFactory = MyFactory.class)
+        class MyViewModel extends ViewModel {
+            @AssistedInject
+            MyViewModel(String s, @Assisted int i) { }
+        }
+        """
+          .trimIndent()
+      )
+    val myFactory =
+      Source.java(
+        "dagger.hilt.android.test.MyFactory",
+        """
+        package dagger.hilt.android.test;
+        import dagger.assisted.AssistedFactory;
+        @AssistedFactory
+        interface MyFactory {
+            MyViewModel create(int i);
+            String createString(int i);
+            Integer createInteger(int i);
+        }
+        """
+      )
+
+    HiltCompilerTests.hiltCompiler(myViewModel, myFactory)
+      .withAdditionalJavacProcessors(ViewModelProcessor())
+      .withAdditionalKspProcessors(KspViewModelProcessor.Provider())
+      .withProcessorOptions(ImmutableMap.of("dagger.hilt.enableAssistedInjectViewModels", "true"))
+      .compile { subject ->
+        subject.compilationDidFail()
+        subject.hasErrorCount(4)
+        subject.hasErrorContaining(
+          "The @AssistedFactory-annotated type should contain a single abstract, non-default method but found multiple: [dagger.hilt.android.test.MyFactory.create(int), dagger.hilt.android.test.MyFactory.createString(int), dagger.hilt.android.test.MyFactory.createInteger(int)]"
+        )
+        subject.hasErrorContaining(
+          "Invalid return type: java.lang.String. An assisted factory's abstract method must return a type with an @AssistedInject-annotated constructor."
+        )
+        subject.hasErrorContaining(
+          "Invalid return type: java.lang.Integer. An assisted factory's abstract method must return a type with an @AssistedInject-annotated constructor."
+        )
+        subject.hasErrorContaining(
+          "Cannot find assisted factory method in dagger.hilt.android.test.MyFactory."
+        )
+      }
+  }
+
+  @Test
+  fun verifyAssistedFactoryIsAnnotatedWithAssistedFactory() {
+    val myViewModel =
+      Source.java(
+        "dagger.hilt.android.test.MyViewModel",
+        """
+        package dagger.hilt.android.test;
+
+        import dagger.assisted.Assisted;
+        import dagger.assisted.AssistedInject;
+        import androidx.lifecycle.ViewModel;
+        import dagger.hilt.android.lifecycle.HiltViewModel;
+
+        @HiltViewModel(assistedFactory = Integer.class)
+        class MyViewModel extends ViewModel {
+            @AssistedInject
+            MyViewModel(String s, @Assisted int i) { }
+        }
+        """
+          .trimIndent()
+      )
+
+    HiltCompilerTests.hiltCompiler(myViewModel)
+      .withAdditionalJavacProcessors(ViewModelProcessor())
+      .withAdditionalKspProcessors(KspViewModelProcessor.Provider())
+      .withProcessorOptions(ImmutableMap.of("dagger.hilt.enableAssistedInjectViewModels", "true"))
+      .compile { subject ->
+        subject.compilationDidFail()
+        subject.hasErrorCount(1)
+        subject.hasErrorContaining(
+          "Class java.lang.Integer is not annotated with @AssistedFactory."
+        )
+      }
+  }
+
+  @Test
+  fun verifyFactoryMethodHasCorrectReturnType() {
+    val myViewModel =
+      Source.java(
+        "dagger.hilt.android.test.MyViewModel",
+        """
+        package dagger.hilt.android.test;
+
+        import dagger.assisted.Assisted;
+        import dagger.assisted.AssistedInject;
+        import androidx.lifecycle.ViewModel;
+        import dagger.hilt.android.lifecycle.HiltViewModel;
+
+        @HiltViewModel(assistedFactory = MyFactory.class)
+        class MyViewModel extends ViewModel {
+            @AssistedInject
+            MyViewModel(String s, @Assisted int i) { }
+        }
+        """
+          .trimIndent()
+      )
+    val myFactory =
+      Source.java(
+        "dagger.hilt.android.test.MyFactory",
+        """
+        package dagger.hilt.android.test;
+        import dagger.assisted.AssistedFactory;
+        @AssistedFactory
+        interface MyFactory {
+            String create(int i);
+        }
+        """
+      )
+
+    HiltCompilerTests.hiltCompiler(myViewModel, myFactory)
+      .withAdditionalJavacProcessors(ViewModelProcessor())
+      .withAdditionalKspProcessors(KspViewModelProcessor.Provider())
+      .withProcessorOptions(ImmutableMap.of("dagger.hilt.enableAssistedInjectViewModels", "true"))
+      .compile { subject ->
+        subject.compilationDidFail()
+        subject.hasErrorCount(2)
+        subject.hasErrorContaining(
+          "Invalid return type: java.lang.String. An assisted factory's abstract method must return a type with an @AssistedInject-annotated constructor."
+        )
+        subject.hasErrorContaining(
+          "Class dagger.hilt.android.test.MyFactory must have a factory method that returns a dagger.hilt.android.test.MyViewModel. Found java.lang.String."
+        )
+      }
+  }
+
+  @Test
+  fun verifyAssistedFactoryIsSpecified() {
+    val myViewModel =
+      Source.java(
+        "dagger.hilt.android.test.MyViewModel",
+        """
+        package dagger.hilt.android.test;
+
+        import dagger.assisted.Assisted;
+        import dagger.assisted.AssistedInject;
+        import androidx.lifecycle.ViewModel;
+        import dagger.hilt.android.lifecycle.HiltViewModel;
+
+        @HiltViewModel
+        class MyViewModel extends ViewModel {
+            @AssistedInject
+            MyViewModel(String s, @Assisted int i) { }
+        }
+        """
+          .trimIndent()
+      )
+    val myFactory =
+      Source.java(
+        "dagger.hilt.android.test.MyFactory",
+        """
+        package dagger.hilt.android.test;
+        import dagger.assisted.AssistedFactory;
+        @AssistedFactory
+        interface MyFactory {
+            MyViewModel create(int i);
+        }
+        """
+      )
+
+    HiltCompilerTests.hiltCompiler(myViewModel, myFactory)
+      .withAdditionalJavacProcessors(ViewModelProcessor())
+      .withAdditionalKspProcessors(KspViewModelProcessor.Provider())
+      .withProcessorOptions(ImmutableMap.of("dagger.hilt.enableAssistedInjectViewModels", "true"))
+      .compile { subject ->
+        subject.compilationDidFail()
+        subject.hasErrorCount(1)
+        subject.hasErrorContaining(
+          "dagger.hilt.android.test.MyViewModel must have a valid assisted factory specified in @HiltViewModel when used with assisted injection. Found java.lang.Object."
+        )
+      }
+  }
+
+  @Test
+  fun verifyConstructorHasRightInjectAnnotation() {
+    val myViewModel =
+      Source.java(
+        "dagger.hilt.android.test.MyViewModel",
+        """
+        package dagger.hilt.android.test;
+
+        import dagger.assisted.Assisted;
+        import dagger.assisted.AssistedInject;
+        import androidx.lifecycle.ViewModel;
+        import dagger.hilt.android.lifecycle.HiltViewModel;
+        import javax.inject.Inject;
+
+        @HiltViewModel(assistedFactory = MyFactory.class)
+        class MyViewModel extends ViewModel {
+            @Inject
+            MyViewModel(String s, int i) { }
+        }
+        """
+          .trimIndent()
+      )
+    val myFactory =
+      Source.java(
+        "dagger.hilt.android.test.MyFactory",
+        """
+        package dagger.hilt.android.test;
+        import dagger.assisted.AssistedFactory;
+        @AssistedFactory
+        interface MyFactory {
+            MyViewModel create(int i);
+        }
+        """
+      )
+
+    HiltCompilerTests.hiltCompiler(myViewModel, myFactory)
+      .withAdditionalJavacProcessors(ViewModelProcessor())
+      .withAdditionalKspProcessors(KspViewModelProcessor.Provider())
+      .withProcessorOptions(ImmutableMap.of("dagger.hilt.enableAssistedInjectViewModels", "true"))
+      .compile { subject ->
+        subject.compilationDidFail()
+        subject.hasErrorCount(2)
+        subject.hasErrorContaining(
+          "Invalid return type: dagger.hilt.android.test.MyViewModel. An assisted factory's abstract method must return a type with an @AssistedInject-annotated constructor."
+        )
+        subject.hasErrorContaining(
+          "Found assisted factory dagger.hilt.android.test.MyFactory in @HiltViewModel but the constructor was annotated with @Inject instead of @AssistedInject."
+        )
+      }
+  }
 }
diff --git a/javatests/dagger/hilt/android/processor/internal/viewmodel/ViewModelValidationPluginTest.kt b/javatests/dagger/hilt/android/processor/internal/viewmodel/ViewModelValidationPluginTest.kt
index 89a79bb..2bee9d5 100644
--- a/javatests/dagger/hilt/android/processor/internal/viewmodel/ViewModelValidationPluginTest.kt
+++ b/javatests/dagger/hilt/android/processor/internal/viewmodel/ViewModelValidationPluginTest.kt
@@ -16,22 +16,33 @@
 
 package dagger.hilt.android.processor.internal.viewmodel
 
-import com.google.testing.compile.CompilationSubject.assertThat
-import com.google.testing.compile.Compiler
-import dagger.hilt.android.testing.compile.HiltCompilerTests.compiler
+import androidx.room.compiler.processing.ExperimentalProcessingApi
+import androidx.room.compiler.processing.util.Source
+import com.google.common.collect.ImmutableList
+import dagger.hilt.android.testing.compile.HiltCompilerTests
 import dagger.internal.codegen.ComponentProcessor
+import dagger.internal.codegen.KspComponentProcessor
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
 
+@ExperimentalProcessingApi
 @RunWith(JUnit4::class)
 class ViewModelValidationPluginTest {
 
-  private fun testCompiler(): Compiler = compiler(
-    ComponentProcessor.withTestPlugins(ViewModelValidationPlugin()), ViewModelProcessor()
-  )
+  private fun testCompiler(vararg sources: Source): HiltCompilerTests.HiltCompiler =
+    HiltCompilerTests.hiltCompiler(ImmutableList.copyOf(sources))
+      .withAdditionalJavacProcessors(
+        ComponentProcessor.withTestPlugins(ViewModelValidationPlugin()),
+        ViewModelProcessor()
+      )
+      .withAdditionalKspProcessors(
+        KspComponentProcessor.Provider.withTestPlugins(ViewModelValidationPlugin()),
+        KspViewModelProcessor.Provider()
+      )
 
-  private val hiltAndroidApp = """
+  private val hiltAndroidApp =
+    """
       package test;
 
       import android.app.Application;
@@ -39,11 +50,13 @@
 
       @HiltAndroidApp(Application.class)
       public class TestApplication extends Hilt_TestApplication {}
-      """.toJFO("test.TestApplication")
+      """
+      .toJFO("test.TestApplication")
 
   @Test
   fun injectViewModelIsProhibited() {
-    val hiltActivity = """
+    val hiltActivity =
+      """
       package test;
 
       import androidx.fragment.app.FragmentActivity;
@@ -54,8 +67,10 @@
       public class TestActivity extends Hilt_TestActivity {
         @Inject Foo foo;
       }
-      """.toJFO("test.TestActivity")
-    val hiltViewModel = """
+      """
+        .toJFO("test.TestActivity")
+    val hiltViewModel =
+      """
         package test;
 
         import androidx.lifecycle.ViewModel;
@@ -66,8 +81,10 @@
         class MyViewModel extends ViewModel {
             @Inject MyViewModel() { }
         }
-        """.toJFO("test.MyViewModel")
-    val foo = """
+        """
+        .toJFO("test.MyViewModel")
+    val foo =
+      """
         package test;
 
         import javax.inject.Inject;
@@ -75,21 +92,20 @@
         final class Foo {
             @Inject Foo(MyViewModel viewModel) {}
         }
-    """.toJFO("test.Foo")
+    """
+        .toJFO("test.Foo")
 
-    val compilation = testCompiler().compile(foo, hiltViewModel, hiltAndroidApp, hiltActivity)
-    assertThat(compilation).apply {
-      failed()
-      hadErrorCount(1)
-      hadErrorContainingMatch(
-        "Injection of an @HiltViewModel class is prohibited"
-      )
+    testCompiler(foo, hiltViewModel, hiltAndroidApp, hiltActivity).compile() { subject ->
+      subject.compilationDidFail()
+      subject.hasErrorCount(1)
+      subject.hasErrorContaining("Injection of an @HiltViewModel class is prohibited")
     }
   }
 
   @Test
   fun fieldInjectedViewModelIsProhibited() {
-    val hiltActivity = """
+    val hiltActivity =
+      """
       package test;
 
       import androidx.fragment.app.FragmentActivity;
@@ -100,8 +116,10 @@
       public class TestActivity extends Hilt_TestActivity {
         @Inject MyViewModel viewModel;
       }
-      """.toJFO("test.TestActivity")
-    val hiltViewModel = """
+      """
+        .toJFO("test.TestActivity")
+    val hiltViewModel =
+      """
         package test;
 
         import androidx.lifecycle.ViewModel;
@@ -112,22 +130,21 @@
         class MyViewModel extends ViewModel {
             @Inject MyViewModel() { }
         }
-        """.toJFO("test.MyViewModel")
+        """
+        .toJFO("test.MyViewModel")
 
-    val compilation = testCompiler().compile(hiltViewModel, hiltAndroidApp, hiltActivity)
-    assertThat(compilation).apply {
-      failed()
-      hadErrorCount(1)
-      hadErrorContainingMatch(
-        "Injection of an @HiltViewModel class is prohibited"
-      )
+    testCompiler(hiltViewModel, hiltAndroidApp, hiltActivity).compile() { subject ->
+      subject.compilationDidFail()
+      subject.hasErrorCount(1)
+      subject.hasErrorContaining("Injection of an @HiltViewModel class is prohibited")
     }
   }
 
   @Test
   fun injectViewModelFromViewModelComponentIsProhibited() {
     // Use an @HiltViewModel that injects a Foo to get the binding inside the ViewModelComponent
-    val hiltViewModel = """
+    val hiltViewModel =
+      """
         package test;
 
         import androidx.lifecycle.ViewModel;
@@ -138,9 +155,11 @@
         class MyViewModel extends ViewModel {
             @Inject MyViewModel(Foo foo) { }
         }
-        """.toJFO("test.MyViewModel")
+        """
+        .toJFO("test.MyViewModel")
 
-    val foo = """
+    val foo =
+      """
         package test;
 
         import javax.inject.Inject;
@@ -149,21 +168,20 @@
         final class Foo {
             @Inject Foo(Provider<MyViewModel> viewModelProvider) {}
         }
-    """.toJFO("test.Foo")
+    """
+        .toJFO("test.Foo")
 
-    val compilation = testCompiler().compile(foo, hiltViewModel, hiltAndroidApp)
-    assertThat(compilation).apply {
-      failed()
-      hadErrorCount(1)
-      hadErrorContainingMatch(
-        "Injection of an @HiltViewModel class is prohibited"
-      )
+    testCompiler(foo, hiltViewModel, hiltAndroidApp).compile() { subject ->
+      subject.compilationDidFail()
+      subject.hasErrorCount(1)
+      subject.hasErrorContaining("Injection of an @HiltViewModel class is prohibited")
     }
   }
 
   @Test
   fun injectOverriddenViewModelBindingIsAllowed() {
-    val hiltActivity = """
+    val hiltActivity =
+      """
       package test;
 
       import androidx.fragment.app.FragmentActivity;
@@ -174,8 +192,10 @@
       public class TestActivity extends Hilt_TestActivity {
         @Inject Foo foo;
       }
-      """.toJFO("test.TestActivity")
-    val hiltViewModel = """
+      """
+        .toJFO("test.TestActivity")
+    val hiltViewModel =
+      """
         package test;
 
         import androidx.lifecycle.ViewModel;
@@ -186,8 +206,10 @@
         class MyViewModel extends ViewModel {
             @Inject MyViewModel() { }
         }
-        """.toJFO("test.MyViewModel")
-    val foo = """
+        """
+        .toJFO("test.MyViewModel")
+    val foo =
+      """
         package test;
 
         import javax.inject.Inject;
@@ -195,8 +217,10 @@
         final class Foo {
             @Inject Foo(MyViewModel viewModel) {}
         }
-    """.toJFO("test.Foo")
-    val activityModule = """
+    """
+        .toJFO("test.Foo")
+    val activityModule =
+      """
         package test;
 
         import dagger.Module;
@@ -214,17 +238,19 @@
             return null;
           }
         }
-    """.toJFO("test.ActivityModule")
+    """
+        .toJFO("test.ActivityModule")
 
-    val compilation = testCompiler().compile(
-      foo, activityModule, hiltViewModel, hiltAndroidApp, hiltActivity
-    )
-    assertThat(compilation).succeeded()
+    testCompiler(foo, activityModule, hiltViewModel, hiltAndroidApp, hiltActivity).compile() {
+      subject ->
+      subject.hasErrorCount(0)
+    }
   }
 
   @Test
   fun injectQualifiedViewModelBindingIsAllowed() {
-    val hiltActivity = """
+    val hiltActivity =
+      """
       package test;
 
       import androidx.fragment.app.FragmentActivity;
@@ -235,8 +261,10 @@
       public class TestActivity extends Hilt_TestActivity {
         @Inject Foo foo;
       }
-      """.toJFO("test.TestActivity")
-    val hiltViewModel = """
+      """
+        .toJFO("test.TestActivity")
+    val hiltViewModel =
+      """
         package test;
 
         import androidx.lifecycle.ViewModel;
@@ -247,8 +275,10 @@
         class MyViewModel extends ViewModel {
             @Inject MyViewModel() { }
         }
-        """.toJFO("test.MyViewModel")
-    val foo = """
+        """
+        .toJFO("test.MyViewModel")
+    val foo =
+      """
         package test;
 
         import javax.inject.Inject;
@@ -256,8 +286,10 @@
         final class Foo {
             @Inject Foo(@ActivityModule.MyQualifier MyViewModel viewModel) {}
         }
-    """.toJFO("test.Foo")
-    val activityModule = """
+    """
+        .toJFO("test.Foo")
+    val activityModule =
+      """
         package test;
 
         import dagger.Module;
@@ -281,18 +313,20 @@
             return null;
           }
         }
-    """.toJFO("test.ActivityModule")
+    """
+        .toJFO("test.ActivityModule")
 
-    val compilation = testCompiler().compile(
-      foo, activityModule, hiltViewModel, hiltAndroidApp, hiltActivity
-    )
-    assertThat(compilation).succeeded()
+    testCompiler(foo, activityModule, hiltViewModel, hiltAndroidApp, hiltActivity).compile() {
+      subject ->
+      subject.hasErrorCount(0)
+    }
   }
 
   // Regression test for not handling array types properly
   @Test
   fun correctlyAllowsOtherBindings() {
-    val hiltActivity = """
+    val hiltActivity =
+      """
       package test;
 
       import androidx.fragment.app.FragmentActivity;
@@ -303,8 +337,10 @@
       public class TestActivity extends Hilt_TestActivity {
         @Inject Foo foo;
       }
-      """.toJFO("test.TestActivity")
-    val hiltViewModel = """
+      """
+        .toJFO("test.TestActivity")
+    val hiltViewModel =
+      """
         package test;
 
         import androidx.lifecycle.ViewModel;
@@ -315,8 +351,10 @@
         class MyViewModel extends ViewModel {
             @Inject MyViewModel() { }
         }
-        """.toJFO("test.MyViewModel")
-    val foo = """
+        """
+        .toJFO("test.MyViewModel")
+    val foo =
+      """
         package test;
 
         import javax.inject.Inject;
@@ -324,8 +362,10 @@
         final class Foo {
             @Inject Foo(Long[] longArray) {}
         }
-    """.toJFO("test.Foo")
-    val activityModule = """
+    """
+        .toJFO("test.Foo")
+    val activityModule =
+      """
         package test;
 
         import dagger.Module;
@@ -341,11 +381,12 @@
             return null;
           }
         }
-    """.toJFO("test.ActivityModule")
+    """
+        .toJFO("test.ActivityModule")
 
-    val compilation = testCompiler().compile(
-      foo, activityModule, hiltViewModel, hiltAndroidApp, hiltActivity
-    )
-    assertThat(compilation).succeeded()
+    testCompiler(foo, activityModule, hiltViewModel, hiltAndroidApp, hiltActivity).compile() {
+      subject ->
+      subject.hasErrorCount(0)
+    }
   }
 }
diff --git a/javatests/dagger/hilt/android/processor/internal/viewmodel/ViewModelValidationPluginWithAssistedInjectTest.kt b/javatests/dagger/hilt/android/processor/internal/viewmodel/ViewModelValidationPluginWithAssistedInjectTest.kt
new file mode 100644
index 0000000..f8f04fe
--- /dev/null
+++ b/javatests/dagger/hilt/android/processor/internal/viewmodel/ViewModelValidationPluginWithAssistedInjectTest.kt
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.hilt.android.processor.internal.viewmodel
+
+import androidx.room.compiler.processing.ExperimentalProcessingApi
+import androidx.room.compiler.processing.util.Source
+import com.google.common.collect.ImmutableList
+import com.google.common.collect.ImmutableMap
+import dagger.hilt.android.testing.compile.HiltCompilerTests
+import dagger.internal.codegen.ComponentProcessor
+import dagger.internal.codegen.KspComponentProcessor
+import dagger.testing.compile.CompilerTests.*
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@ExperimentalProcessingApi
+@RunWith(JUnit4::class)
+class ViewModelValidationPluginWithAssistedInjectTest {
+
+  private fun testCompiler(vararg sources: Source): HiltCompilerTests.HiltCompiler =
+    HiltCompilerTests.hiltCompiler(ImmutableList.copyOf(sources))
+      .withAdditionalJavacProcessors(
+        ComponentProcessor.withTestPlugins(ViewModelValidationPlugin()),
+        ViewModelProcessor()
+      )
+      .withAdditionalKspProcessors(
+        KspComponentProcessor.Provider.withTestPlugins(ViewModelValidationPlugin()),
+        KspViewModelProcessor.Provider()
+      )
+      .withProcessorOptions(ImmutableMap.of("dagger.hilt.enableAssistedInjectViewModels", "true"))
+
+  private val hiltAndroidApp =
+    """
+      package dagger.hilt.android.test;
+
+      import android.app.Application;
+      import dagger.hilt.android.HiltAndroidApp;
+
+      @HiltAndroidApp(Application.class)
+      public class TestApplication extends Hilt_TestApplication {}
+      """
+      .toJFO("dagger.hilt.android.test.TestApplication")
+
+  @Test
+  fun injectViewModelAssistedFactoryProhibited() {
+    val hiltActivity =
+      """
+      package dagger.hilt.android.test;
+
+      import androidx.fragment.app.FragmentActivity;
+      import dagger.hilt.android.AndroidEntryPoint;
+      import javax.inject.Inject;
+
+      @AndroidEntryPoint(FragmentActivity.class)
+      public class TestActivity extends Hilt_TestActivity {
+        @Inject Foo foo;
+      }
+      """
+        .toJFO("dagger.hilt.android.test.TestActivity")
+    val hiltViewModel =
+      """
+      package dagger.hilt.android.test;
+
+      import androidx.lifecycle.ViewModel;
+      import dagger.assisted.Assisted;
+      import dagger.assisted.AssistedFactory;
+      import dagger.assisted.AssistedInject;
+      import dagger.hilt.android.lifecycle.HiltViewModel;
+      import javax.inject.Inject;
+
+      @HiltViewModel(assistedFactory = MyViewModel.Factory.class)
+      class MyViewModel extends ViewModel {
+          @AssistedInject MyViewModel(@Assisted String s) { }
+          @AssistedFactory interface Factory {
+              MyViewModel create(String s);
+          }
+      }
+      """
+        .toJFO("dagger.hilt.android.test.MyViewModel")
+    val foo =
+      """
+      package dagger.hilt.android.test;
+
+      import javax.inject.Inject;
+
+      final class Foo {
+          @Inject Foo(MyViewModel.Factory factory) {}
+      }
+      """
+        .toJFO("dagger.hilt.android.test.Foo")
+
+    testCompiler(foo, hiltViewModel, hiltAndroidApp, hiltActivity).compile { subject ->
+      subject.compilationDidFail()
+      subject.hasErrorCount(1)
+      subject.hasErrorContaining(
+        "Injection of an assisted factory for Hilt ViewModel is prohibited since it can not be " +
+          "used to create a ViewModel instance correctly.\n" +
+          "Access the ViewModel via the Android APIs (e.g. ViewModelProvider) instead.\n" +
+          "Injected factory: dagger.hilt.android.test.MyViewModel.Factory"
+      )
+    }
+  }
+
+  @Test
+  fun fieldInjectViewModelAssistedFactoryProhibited() {
+    val hiltActivity =
+      """
+      package dagger.hilt.android.test;
+
+      import androidx.fragment.app.FragmentActivity;
+      import dagger.hilt.android.AndroidEntryPoint;
+      import javax.inject.Inject;
+
+      @AndroidEntryPoint(FragmentActivity.class)
+      public class TestActivity extends Hilt_TestActivity {
+        @Inject MyViewModel.Factory factory;
+      }
+      """
+        .toJFO("dagger.hilt.android.test.TestActivity")
+    val hiltViewModel =
+      """
+      package dagger.hilt.android.test;
+
+      import androidx.lifecycle.ViewModel;
+      import dagger.assisted.Assisted;
+      import dagger.assisted.AssistedFactory;
+      import dagger.assisted.AssistedInject;
+      import dagger.hilt.android.lifecycle.HiltViewModel;
+      import javax.inject.Inject;
+
+      @HiltViewModel(assistedFactory = MyViewModel.Factory.class)
+      class MyViewModel extends ViewModel {
+          @AssistedInject MyViewModel(@Assisted String s) { }
+          @AssistedFactory interface Factory {
+              MyViewModel create(String s);
+          }
+      }
+      """
+        .toJFO("dagger.hilt.android.test.MyViewModel")
+
+    testCompiler(hiltViewModel, hiltAndroidApp, hiltActivity).compile { subject ->
+      subject.compilationDidFail()
+      subject.hasErrorCount(1)
+      subject.hasErrorContaining(
+        "Injection of an assisted factory for Hilt ViewModel is prohibited since it can not be " +
+          "used to create a ViewModel instance correctly.\n" +
+          "Access the ViewModel via the Android APIs (e.g. ViewModelProvider) instead.\n" +
+          "Injected factory: dagger.hilt.android.test.MyViewModel.Factory"
+      )
+    }
+  }
+
+  @Test
+  fun injectGenericViewModelAssistedFactoryProhibited() {
+    val hiltActivity =
+      """
+      package dagger.hilt.android.test;
+
+      import androidx.fragment.app.FragmentActivity;
+      import dagger.hilt.android.AndroidEntryPoint;
+      import javax.inject.Inject;
+
+      @AndroidEntryPoint(FragmentActivity.class)
+      public class TestActivity extends Hilt_TestActivity {
+        @Inject MyViewModel.Factory factory;
+      }
+      """
+        .toJFO("dagger.hilt.android.test.TestActivity")
+    val hiltViewModel =
+      """
+      package dagger.hilt.android.test;
+
+      import androidx.lifecycle.ViewModel;
+      import dagger.assisted.Assisted;
+      import dagger.assisted.AssistedFactory;
+      import dagger.assisted.AssistedInject;
+      import dagger.hilt.android.lifecycle.HiltViewModel;
+      import javax.inject.Inject;
+
+      @HiltViewModel(assistedFactory = MyViewModel.Factory.class)
+      class MyViewModel extends ViewModel {
+          @AssistedInject MyViewModel(@Assisted String s) { }
+          interface SingleAssistedFactory<A, T> {
+              T create(A a);
+          }
+          @AssistedFactory interface Factory extends SingleAssistedFactory<String, MyViewModel> {}
+      }
+      """
+        .toJFO("dagger.hilt.android.test.MyViewModel")
+
+    testCompiler(hiltViewModel, hiltAndroidApp, hiltActivity).compile { subject ->
+      subject.compilationDidFail()
+      subject.hasErrorCount(1)
+      subject.hasErrorContaining(
+        "Injection of an assisted factory for Hilt ViewModel is prohibited since it can not be " +
+          "used to create a ViewModel instance correctly.\n" +
+          "Access the ViewModel via the Android APIs (e.g. ViewModelProvider) instead.\n" +
+          "Injected factory: dagger.hilt.android.test.MyViewModel.Factory"
+      )
+    }
+  }
+}
diff --git a/javatests/dagger/hilt/android/testing/BUILD b/javatests/dagger/hilt/android/testing/BUILD
index 7dc1e48..9731610 100644
--- a/javatests/dagger/hilt/android/testing/BUILD
+++ b/javatests/dagger/hilt/android/testing/BUILD
@@ -158,3 +158,37 @@
         "//third_party/java/truth",
     ],
 )
+
+android_local_test(
+    name = "SkipTestInjectionTest",
+    srcs = ["SkipTestInjectionTest.java"],
+    manifest_values = {
+        "minSdkVersion": "15",
+        "targetSdkVersion": "27",
+    },
+    deps = [
+        "//:android_local_test_exports",
+        "//:dagger_with_compiler",
+        "//java/dagger/hilt/android/testing:hilt_android_test",
+        "//java/dagger/hilt/android/testing:skip_test_injection",
+        "//third_party/java/jsr330_inject",
+        "//third_party/java/truth",
+    ],
+)
+
+android_local_test(
+    name = "SkipTestInjectionAnnotationTest",
+    srcs = ["SkipTestInjectionAnnotationTest.java"],
+    manifest_values = {
+        "minSdkVersion": "15",
+        "targetSdkVersion": "27",
+    },
+    deps = [
+        "//:android_local_test_exports",
+        "//:dagger_with_compiler",
+        "//java/dagger/hilt/android/testing:hilt_android_test",
+        "//java/dagger/hilt/android/testing:skip_test_injection",
+        "//third_party/java/jsr330_inject",
+        "//third_party/java/truth",
+    ],
+)
diff --git a/javatests/dagger/hilt/android/testing/SkipTestInjectionAnnotationTest.java b/javatests/dagger/hilt/android/testing/SkipTestInjectionAnnotationTest.java
new file mode 100644
index 0000000..60d2bb3
--- /dev/null
+++ b/javatests/dagger/hilt/android/testing/SkipTestInjectionAnnotationTest.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2024 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.hilt.android.testing;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertThrows;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import javax.inject.Inject;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+
+@HiltAndroidTest
+@SkipTestInjectionAnnotationTest.TestAnnotation
+@RunWith(AndroidJUnit4.class)
+@Config(application = HiltTestApplication.class)
+public final class SkipTestInjectionAnnotationTest {
+  @Rule public final HiltAndroidRule rule = new HiltAndroidRule(this);
+
+  @SkipTestInjection
+  @interface TestAnnotation {}
+
+  @Inject String string;  // Never provided, shouldn't compile without @SkipTestInjection
+
+  @Test
+  public void testCannotCallInjectOnTestRule() throws Exception {
+    IllegalStateException exception =
+        assertThrows(
+            IllegalStateException.class,
+            () -> rule.inject());
+    assertThat(exception)
+          .hasMessageThat()
+          .isEqualTo("Cannot inject test when using @TestAnnotation");
+  }
+}
diff --git a/javatests/dagger/hilt/android/testing/SkipTestInjectionTest.java b/javatests/dagger/hilt/android/testing/SkipTestInjectionTest.java
new file mode 100644
index 0000000..bf4124c
--- /dev/null
+++ b/javatests/dagger/hilt/android/testing/SkipTestInjectionTest.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2024 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.hilt.android.testing;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertThrows;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import javax.inject.Inject;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+
+@HiltAndroidTest
+@SkipTestInjection
+@RunWith(AndroidJUnit4.class)
+@Config(application = HiltTestApplication.class)
+public final class SkipTestInjectionTest {
+  @Rule public final HiltAndroidRule rule = new HiltAndroidRule(this);
+
+  @Inject String string;  // Never provided, shouldn't compile without @SkipTestInjection
+
+  @Test
+  public void testCannotCallInjectOnTestRule() throws Exception {
+    IllegalStateException exception =
+        assertThrows(
+            IllegalStateException.class,
+            () -> rule.inject());
+    assertThat(exception)
+          .hasMessageThat()
+          .isEqualTo("Cannot inject test when using @SkipTestInjection");
+  }
+}
diff --git a/javatests/dagger/hilt/processor/internal/aliasof/AliasOfProcessorTest.java b/javatests/dagger/hilt/processor/internal/aliasof/AliasOfProcessorTest.java
index 0654e34..d326f11 100644
--- a/javatests/dagger/hilt/processor/internal/aliasof/AliasOfProcessorTest.java
+++ b/javatests/dagger/hilt/processor/internal/aliasof/AliasOfProcessorTest.java
@@ -16,15 +16,11 @@
 
 package dagger.hilt.processor.internal.aliasof;
 
-import static com.google.testing.compile.CompilationSubject.assertThat;
-import static dagger.hilt.android.testing.compile.HiltCompilerTests.compiler;
-
 import androidx.room.compiler.processing.util.Source;
-import com.google.testing.compile.Compilation;
-import com.google.testing.compile.JavaFileObjects;
 import dagger.hilt.android.testing.compile.HiltCompilerTests;
-import javax.tools.JavaFileObject;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
 
@@ -33,8 +29,8 @@
 public final class AliasOfProcessorTest {
   @Test
   public void fails_componentScopedWithAliasScope() {
-    JavaFileObject scope =
-        JavaFileObjects.forSourceLines(
+    Source scope =
+        HiltCompilerTests.javaSource(
             "test.AliasScope",
             "package test;",
             "",
@@ -46,8 +42,8 @@
             "@AliasOf(Singleton.class)",
             "public @interface AliasScope{}");
 
-    JavaFileObject root =
-        JavaFileObjects.forSourceLines(
+    Source root =
+        HiltCompilerTests.javaSource(
             "test.MyApp",
             "package test;",
             "",
@@ -57,8 +53,8 @@
             "@HiltAndroidApp(Application.class)",
             "public final class MyApp extends Hilt_MyApp {}");
 
-    JavaFileObject defineComponent =
-        JavaFileObjects.forSourceLines(
+    Source defineComponent =
+        HiltCompilerTests.javaSource(
             "test.ChildComponent",
             "package test;",
             "",
@@ -69,17 +65,20 @@
             "@AliasScope",
             "public interface ChildComponent {}");
 
-    Compilation compilation =
-        compiler()
-            .withOptions("-Xlint:-processing") // Suppresses unclaimed annotation warning
-            .compile(root, defineComponent, scope);
-
-    assertThat(compilation).failed();
-    assertThat(compilation)
-        .hadErrorContaining(
-            "@DefineComponent test.ChildComponent, references invalid scope(s) annotated with"
-                + " @AliasOf. @DefineComponent scopes cannot be aliases of other scopes:"
-                + " [@test.AliasScope]");
+    HiltCompilerTests.hiltCompiler(root, defineComponent, scope)
+        .withJavacArguments("-Xlint:-processing") // Suppresses unclaimed annotation warning
+        .compile(
+            subject ->
+                // TODO(user): TAP result inconsistent with local build.
+                // if (HiltCompilerTests.backend(subject) == Backend.JAVAC) {
+                //   subject.hasErrorCount(2);
+                // } else {
+                //   subject.hasErrorCount(1);
+                // }
+                subject.hasErrorContaining(
+                    "@DefineComponent test.ChildComponent, references invalid scope(s) annotated" 
+                    + " with @AliasOf. @DefineComponent scopes cannot be aliases of other scopes:"
+                    + " [@test.AliasScope]"));
   }
 
   @Test
@@ -106,10 +105,12 @@
             });
   }
 
+  @Rule public TemporaryFolder tempFolderRule = new TemporaryFolder();
+
   @Test
   public void fails_conflictingAliasScope() {
-    JavaFileObject scope =
-        JavaFileObjects.forSourceLines(
+    Source scope =
+        HiltCompilerTests.javaSource(
             "test.AliasScope",
             "package test;",
             "",
@@ -122,8 +123,8 @@
             "@AliasOf({Singleton.class, ActivityScoped.class})",
             "public @interface AliasScope{}");
 
-    JavaFileObject root =
-        JavaFileObjects.forSourceLines(
+    Source root =
+        HiltCompilerTests.javaSource(
             "test.MyApp",
             "package test;",
             "",
@@ -133,13 +134,11 @@
             "@HiltAndroidApp(Application.class)",
             "public final class MyApp extends Hilt_MyApp {}");
 
-    Compilation compilation =
-        compiler()
-            .withOptions("-Xlint:-processing") // Suppresses unclaimed annotation warning
-            .compile(root, scope);
-
-    assertThat(compilation).failed();
-    assertThat(compilation).hadErrorCount(1);
-    assertThat(compilation).hadErrorContaining("has conflicting scopes");
+    HiltCompilerTests.hiltCompiler(root, scope)
+        .compile(
+            subject -> {
+              subject.hasErrorCount(1);
+              subject.hasErrorContaining("has conflicting scopes");
+            });
   }
 }
diff --git a/javatests/dagger/hilt/processor/internal/aliasof/BUILD b/javatests/dagger/hilt/processor/internal/aliasof/BUILD
index bc7874f..a56e140 100644
--- a/javatests/dagger/hilt/processor/internal/aliasof/BUILD
+++ b/javatests/dagger/hilt/processor/internal/aliasof/BUILD
@@ -34,7 +34,6 @@
     deps = [
         "//java/dagger/hilt/android/testing/compile",
         "//java/dagger/internal/codegen/xprocessing:xprocessing-testing",
-        "//third_party/java/compile_testing",
         "//third_party/java/junit",
     ],
 )
diff --git a/javatests/dagger/hilt/processor/internal/root/BUILD b/javatests/dagger/hilt/processor/internal/root/BUILD
index 0da11f1..bdc69dc 100644
--- a/javatests/dagger/hilt/processor/internal/root/BUILD
+++ b/javatests/dagger/hilt/processor/internal/root/BUILD
@@ -114,8 +114,9 @@
     ],
     deps = [
         "//java/dagger/hilt/android/testing/compile",
-        "//third_party/java/compile_testing",
+        "//java/dagger/internal/codegen/xprocessing:xprocessing-testing",
         "//third_party/java/guava/base",
+        "//third_party/java/guava/collect",
         "//third_party/java/junit",
         "//third_party/java/truth",
     ],
diff --git a/javatests/dagger/hilt/processor/internal/root/RootFileFormatterTest.java b/javatests/dagger/hilt/processor/internal/root/RootFileFormatterTest.java
index 2a946b7..751f74d 100644
--- a/javatests/dagger/hilt/processor/internal/root/RootFileFormatterTest.java
+++ b/javatests/dagger/hilt/processor/internal/root/RootFileFormatterTest.java
@@ -16,13 +16,11 @@
 
 package dagger.hilt.processor.internal.root;
 
-import static com.google.testing.compile.CompilationSubject.assertThat;
-import static dagger.hilt.android.testing.compile.HiltCompilerTests.compiler;
-
+import androidx.room.compiler.processing.util.Source;
 import com.google.common.base.Joiner;
-import com.google.testing.compile.Compilation;
-import com.google.testing.compile.JavaFileObjects;
-import javax.tools.JavaFileObject;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.truth.StringSubject;
+import dagger.hilt.android.testing.compile.HiltCompilerTests;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -34,141 +32,138 @@
 
   @Test
   public void testProdComponents() {
-    Compilation compilation =
-        compiler()
-            .compile(
-                JavaFileObjects.forSourceLines(
-                    "test.TestApplication",
-                    "package test;",
-                    "",
-                    "import android.app.Application;",
-                    "import dagger.hilt.android.HiltAndroidApp;",
-                    "",
-                    "@HiltAndroidApp(Application.class)",
-                    "public class TestApplication extends Hilt_TestApplication {}"),
-                entryPoint("SingletonComponent", "EntryPoint1"),
-                entryPoint("SingletonComponent", "EntryPoint2"),
-                entryPoint("ActivityComponent", "EntryPoint3"),
-                entryPoint("ActivityComponent", "EntryPoint4"));
-    assertThat(compilation).succeeded();
-    assertThat(compilation)
-        .generatedSourceFile("test/TestApplication_HiltComponents")
-        .contentsAsUtf8String()
-        .contains(
-            JOINER.join(
-                "  public abstract static class SingletonC implements"
-                + " HiltWrapper_ActivityRetainedComponentManager"
-                + "_ActivityRetainedComponentBuilderEntryPoint,",
-                "      ServiceComponentManager.ServiceComponentBuilderEntryPoint,",
-                "      SingletonComponent,",
-                "      GeneratedComponent,",
-                "      EntryPoint1,",
-                "      EntryPoint2,",
-                "      TestApplication_GeneratedInjector {"));
-
-    assertThat(compilation)
-        .generatedSourceFile("test/TestApplication_HiltComponents")
-        .contentsAsUtf8String()
-        .contains(
-            JOINER.join(
-                "  public abstract static class ActivityC implements ActivityComponent,",
-                "      DefaultViewModelFactories.ActivityEntryPoint,",
-                "      HiltWrapper_HiltViewModelFactory_ActivityCreatorEntryPoint,",
-                "      FragmentComponentManager.FragmentComponentBuilderEntryPoint,",
-                "      ViewComponentManager.ViewComponentBuilderEntryPoint,",
-                "      GeneratedComponent,",
-                "      EntryPoint3,",
-                "      EntryPoint4 {"));
+    HiltCompilerTests.hiltCompiler(
+            HiltCompilerTests.javaSource(
+                "test.TestApplication",
+                "package test;",
+                "",
+                "import android.app.Application;",
+                "import dagger.hilt.android.HiltAndroidApp;",
+                "",
+                "@HiltAndroidApp(Application.class)",
+                "public class TestApplication extends Hilt_TestApplication {}"),
+            entryPoint("SingletonComponent", "EntryPoint1"),
+            entryPoint("SingletonComponent", "EntryPoint2"),
+            entryPoint("ActivityComponent", "EntryPoint3"),
+            entryPoint("ActivityComponent", "EntryPoint4"))
+        .compile(
+            subject -> {
+              subject.hasErrorCount(0);
+              StringSubject stringSubject =
+                  subject.generatedSourceFileWithPath("test/TestApplication_HiltComponents.java");
+              stringSubject.contains(
+                  JOINER.join(
+                      "  public abstract static class SingletonC implements"
+                         + " HiltWrapper_ActivityRetainedComponentManager"
+                         + "_ActivityRetainedComponentBuilderEntryPoint,",
+                      "      ServiceComponentManager.ServiceComponentBuilderEntryPoint,",
+                      "      SingletonComponent,",
+                      "      GeneratedComponent,",
+                      "      EntryPoint1,",
+                      "      EntryPoint2,",
+                      "      TestApplication_GeneratedInjector {"));
+              stringSubject.contains(
+                  JOINER.join(
+                      "  public abstract static class ActivityC implements ActivityComponent,",
+                      "      DefaultViewModelFactories.ActivityEntryPoint,",
+                      "      HiltWrapper_HiltViewModelFactory_ActivityCreatorEntryPoint,",
+                      "      FragmentComponentManager.FragmentComponentBuilderEntryPoint,",
+                      "      ViewComponentManager.ViewComponentBuilderEntryPoint,",
+                      "      GeneratedComponent,",
+                      "      EntryPoint3,",
+                      "      EntryPoint4 {"));
+            });
   }
 
   @Test
   public void testTestComponents() {
-    Compilation compilation =
-        compiler()
-            .withOptions("-Adagger.hilt.shareTestComponents=false")
-            .compile(
-                JavaFileObjects.forSourceLines(
-                    "test.MyTest",
-                    "package test;",
-                    "",
-                    "import dagger.hilt.android.testing.HiltAndroidTest;",
-                    "",
-                    "@HiltAndroidTest",
-                    "public class MyTest {}"),
-                entryPoint("SingletonComponent", "EntryPoint1"),
-                entryPoint("SingletonComponent", "EntryPoint2"),
-                entryPoint("ActivityComponent", "EntryPoint3"),
-                entryPoint("ActivityComponent", "EntryPoint4"));
-    assertThat(compilation).succeeded();
-    assertThat(compilation)
-        .generatedSourceFile("test/MyTest_HiltComponents")
-        .contentsAsUtf8String()
-        .contains(
-            JOINER.join(
-                "  public abstract static class SingletonC implements"
-                + " HiltWrapper_ActivityRetainedComponentManager"
-                + "_ActivityRetainedComponentBuilderEntryPoint,",
-                "      ServiceComponentManager.ServiceComponentBuilderEntryPoint,",
-                "      SingletonComponent,",
-                "      TestSingletonComponent,",
-                "      EntryPoint1,",
-                "      EntryPoint2,",
-                "      MyTest_GeneratedInjector {"));
+    HiltCompilerTests.hiltCompiler(
+            HiltCompilerTests.javaSource(
+                "test.MyTest",
+                "package test;",
+                "",
+                "import dagger.hilt.android.testing.HiltAndroidTest;",
+                "",
+                "@HiltAndroidTest",
+                "public class MyTest {}"),
+            entryPoint("SingletonComponent", "EntryPoint1"),
+            entryPoint("SingletonComponent", "EntryPoint2"),
+            entryPoint("ActivityComponent", "EntryPoint3"),
+            entryPoint("ActivityComponent", "EntryPoint4"))
+        .withProcessorOptions(
+            ImmutableMap.of("dagger.hilt.shareTestComponents", Boolean.toString(false)))
+        .compile(
+            subject -> {
+              subject.hasErrorCount(0);
+              StringSubject stringSubject =
+                  subject.generatedSourceFileWithPath("test/MyTest_HiltComponents.java");
+              stringSubject.contains(
+                  JOINER.join(
+                      "  public abstract static class SingletonC implements"
+                      + " HiltWrapper_ActivityRetainedComponentManager"
+                      + "_ActivityRetainedComponentBuilderEntryPoint,",
+                      "      ServiceComponentManager.ServiceComponentBuilderEntryPoint,",
+                      "      SingletonComponent,",
+                      "      TestSingletonComponent,",
+                      "      EntryPoint1,",
+                      "      EntryPoint2,",
+                      "      MyTest_GeneratedInjector {"));
 
-    assertThat(compilation)
-        .generatedSourceFile("test/MyTest_HiltComponents")
-        .contentsAsUtf8String()
-        .contains(
-            JOINER.join(
-                "  public abstract static class ActivityC implements ActivityComponent,",
-                "      DefaultViewModelFactories.ActivityEntryPoint,",
-                "      HiltWrapper_HiltViewModelFactory_ActivityCreatorEntryPoint,",
-                "      FragmentComponentManager.FragmentComponentBuilderEntryPoint,",
-                "      ViewComponentManager.ViewComponentBuilderEntryPoint,",
-                "      GeneratedComponent,",
-                "      EntryPoint3,",
-                "      EntryPoint4 {"));
+              stringSubject.contains(
+                  JOINER.join(
+                      "  public abstract static class ActivityC implements ActivityComponent,",
+                      "      DefaultViewModelFactories.ActivityEntryPoint,",
+                      "      HiltWrapper_HiltViewModelFactory_ActivityCreatorEntryPoint,",
+                      "      FragmentComponentManager.FragmentComponentBuilderEntryPoint,",
+                      "      ViewComponentManager.ViewComponentBuilderEntryPoint,",
+                      "      GeneratedComponent,",
+                      "      EntryPoint3,",
+                      "      EntryPoint4 {"));
+            });
   }
 
   @Test
   public void testSharedTestComponents() {
-    Compilation compilation =
-        compiler()
-            .withOptions("-Adagger.hilt.shareTestComponents=true")
-            .compile(
-                JavaFileObjects.forSourceLines(
-                    "test.MyTest",
-                    "package test;",
-                    "",
-                    "import dagger.hilt.android.testing.HiltAndroidTest;",
-                    "",
-                    "@HiltAndroidTest",
-                    "public class MyTest {}"),
-                entryPoint("SingletonComponent", "EntryPoint1"));
-    assertThat(compilation).succeeded();
-    assertThat(compilation)
-        .generatedSourceFile("dagger/hilt/android/internal/testing/root/Default_HiltComponents")
-        .contentsAsUtf8String()
-        .contains(
-            JOINER.join(
-                "  public abstract static class SingletonC implements"
-                + " HiltWrapper_ActivityRetainedComponentManager"
-                + "_ActivityRetainedComponentBuilderEntryPoint,",
-                "      ServiceComponentManager.ServiceComponentBuilderEntryPoint,",
-                "      SingletonComponent,",
-                "      TestSingletonComponent,",
-                "      EntryPoint1,",
-                "      MyTest_GeneratedInjector {"));
+    HiltCompilerTests.hiltCompiler(
+            HiltCompilerTests.javaSource(
+                "test.MyTest",
+                "package test;",
+                "",
+                "import dagger.hilt.android.testing.HiltAndroidTest;",
+                "",
+                "@HiltAndroidTest",
+                "public class MyTest {}"),
+            entryPoint("SingletonComponent", "EntryPoint1"))
+        .withProcessorOptions(
+            ImmutableMap.of("dagger.hilt.shareTestComponents", Boolean.toString(true)))
+        .compile(
+            subject -> {
+              subject.hasErrorCount(0);
+              StringSubject stringSubject =
+                  subject.generatedSourceFileWithPath(
+                      "dagger/hilt/android/internal/testing/root/Default_HiltComponents.java");
+              stringSubject.contains(
+                  JOINER.join(
+                      "  public abstract static class SingletonC implements"
+                      + " HiltWrapper_ActivityRetainedComponentManager"
+                      + "_ActivityRetainedComponentBuilderEntryPoint,",
+                      "      ServiceComponentManager.ServiceComponentBuilderEntryPoint,",
+                      "      SingletonComponent,",
+                      "      TestSingletonComponent,",
+                      "      EntryPoint1,",
+                      "      MyTest_GeneratedInjector {"));
+            });
   }
 
-  private static JavaFileObject entryPoint(String component, String name) {
-    return JavaFileObjects.forSourceLines(
+  private static Source entryPoint(String component, String name) {
+    return HiltCompilerTests.javaSource(
         "test." + name,
         "package test;",
         "",
         "import dagger.hilt.EntryPoint;",
         "import dagger.hilt.InstallIn;",
-        component.equals("SingletonComponent") ? "import dagger.hilt.components.SingletonComponent;"
+        component.equals("SingletonComponent")
+            ? "import dagger.hilt.components.SingletonComponent;"
             : "import dagger.hilt.android.components." + component + ";",
         "",
         "@EntryPoint",
diff --git a/javatests/dagger/internal/DoubleCheckTest.java b/javatests/dagger/internal/DoubleCheckTest.java
index e36c1bc..6bf220d 100644
--- a/javatests/dagger/internal/DoubleCheckTest.java
+++ b/javatests/dagger/internal/DoubleCheckTest.java
@@ -32,7 +32,6 @@
 import java.util.concurrent.Future;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
-import javax.inject.Provider;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
diff --git a/javatests/dagger/internal/MapProviderFactoryTest.java b/javatests/dagger/internal/MapProviderFactoryTest.java
index c55bee3..e64df8d 100644
--- a/javatests/dagger/internal/MapProviderFactoryTest.java
+++ b/javatests/dagger/internal/MapProviderFactoryTest.java
@@ -21,7 +21,6 @@
 import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicInteger;
-import javax.inject.Provider;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
diff --git a/javatests/dagger/internal/SetFactoryTest.java b/javatests/dagger/internal/SetFactoryTest.java
index 0032578..5e109dd 100644
--- a/javatests/dagger/internal/SetFactoryTest.java
+++ b/javatests/dagger/internal/SetFactoryTest.java
@@ -23,7 +23,6 @@
 import java.util.LinkedHashSet;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicInteger;
-import javax.inject.Provider;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
diff --git a/javatests/dagger/internal/codegen/AssistedFactoryTest.java b/javatests/dagger/internal/codegen/AssistedFactoryTest.java
index 18de701..6f38f8f 100644
--- a/javatests/dagger/internal/codegen/AssistedFactoryTest.java
+++ b/javatests/dagger/internal/codegen/AssistedFactoryTest.java
@@ -326,4 +326,110 @@
               subject.generatedSource(goldenFileRule.goldenSource("test/DaggerTestComponent"));
             });
   }
+
+  // This is a regression test for b/305748522
+  // The important thing for this test is that we have two assisted factories for the same assisted
+  // injection class and that they are requested in different components.
+  @Test
+  public void testMultipleAssistedFactoryInDifferentComponents() throws Exception {
+    Source component =
+        CompilerTests.javaSource(
+            "test.MyComponent",
+            "package test;",
+            "",
+            "import dagger.Component;",
+            "",
+            "@Component",
+            "interface MyComponent {",
+            "  MyComponentAssistedFactory myComponentAssistedFactory();",
+            "  MySubcomponent mySubcomponent();",
+            "}");
+    Source subcomponent =
+        CompilerTests.javaSource(
+            "test.MySubcomponent",
+            "package test;",
+            "",
+            "import dagger.Subcomponent;",
+            "",
+            "@Subcomponent",
+            "interface MySubcomponent {",
+            "  MySubcomponentAssistedFactory mySubcomponentAssistedFactory();",
+            "}");
+    Source assistedClass =
+        CompilerTests.javaSource(
+            "test.MyAssistedClass",
+            "package test;",
+            "",
+            "import dagger.assisted.Assisted;",
+            "import dagger.assisted.AssistedInject;",
+            "",
+            "final class MyAssistedClass {",
+            "  private final Foo foo;",
+            "  private final Bar bar;",
+            "",
+            "  @AssistedInject",
+            "  MyAssistedClass(@Assisted Foo foo, Baz baz, @Assisted Bar bar) {",
+            "    this.foo = foo;",
+            "    this.bar = bar;",
+            "  }",
+            "}");
+    Source componentAssistedFactory =
+        CompilerTests.javaSource(
+            "test.MyComponentAssistedFactory",
+            "package test;",
+            "",
+            "import dagger.assisted.AssistedFactory;",
+            "",
+            "@AssistedFactory",
+            "interface MyComponentAssistedFactory {",
+            "  MyAssistedClass create(Bar bar, Foo foo);",
+            "}");
+    Source subcomponentAssistedFactory =
+        CompilerTests.javaSource(
+            "test.MySubcomponentAssistedFactory",
+            "package test;",
+            "",
+            "import dagger.assisted.AssistedFactory;",
+            "",
+            "@AssistedFactory",
+            "interface MySubcomponentAssistedFactory {",
+            "  MyAssistedClass create(Bar bar, Foo foo);",
+            "}");
+    Source foo =
+        CompilerTests.javaSource(
+            "test.Foo",
+            "package test;",
+            "final class Foo {}");
+    Source bar =
+        CompilerTests.javaSource(
+            "test.Bar",
+            "package test;",
+            "final class Bar {}");
+    Source baz =
+        CompilerTests.javaSource(
+            "test.Baz",
+            "package test;",
+            "",
+            "import javax.inject.Inject;",
+            "",
+            "final class Baz {",
+            "  @Inject Baz() {}",
+            "}");
+
+    CompilerTests.daggerCompiler(
+            component,
+            subcomponent,
+            assistedClass,
+            componentAssistedFactory,
+            subcomponentAssistedFactory,
+            foo,
+            bar,
+            baz)
+        .withProcessingOptions(compilerMode.processorOptions())
+        .compile(
+            subject -> {
+              subject.hasErrorCount(0);
+              subject.generatedSource(goldenFileRule.goldenSource("test/DaggerMyComponent"));
+            });
+  }
 }
diff --git a/javatests/dagger/internal/codegen/AssistedInjectErrorsTest.java b/javatests/dagger/internal/codegen/AssistedInjectErrorsTest.java
index 1d3628e..e8e7fd7 100644
--- a/javatests/dagger/internal/codegen/AssistedInjectErrorsTest.java
+++ b/javatests/dagger/internal/codegen/AssistedInjectErrorsTest.java
@@ -243,4 +243,66 @@
         .withProcessingOptions(compilerMode.processorOptions())
         .compile(subject -> subject.hasErrorCount(0));
   }
+
+  @Test
+  public void testMultipleInjectedConstructors() {
+    Source foo =
+        CompilerTests.kotlinSource(
+            "test.Foo.kt",
+            "package test;",
+            "",
+            "import dagger.assisted.Assisted",
+            "import dagger.assisted.AssistedInject",
+            "import dagger.assisted.AssistedFactory",
+            "import javax.inject.Inject",
+            "",
+            "class Foo @AssistedInject constructor(@Assisted i: Int) {",
+            "",
+            "  @Inject",
+            "  constructor(s: String, @Assisted i: Int): this(i) {}",
+            "}");
+
+    CompilerTests.daggerCompiler(foo)
+        .withProcessingOptions(compilerMode.processorOptions())
+        .compile(
+            subject -> {
+              subject.hasErrorCount(2);
+              subject.hasErrorContaining(
+                  "Type test.Foo may only contain one injected constructor."
+                      + " Found: [@Inject test.Foo(String, int),"
+                      + " @dagger.assisted.AssistedInject test.Foo(int)]");
+              subject.hasErrorContaining(
+                  "@Assisted parameters can only be used within an"
+                      + " @AssistedInject-annotated constructor.");
+            });
+  }
+
+  @Test
+  public void testMultipleAssistedInjectedConstructors() {
+    Source foo =
+        CompilerTests.kotlinSource(
+            "test.Foo.kt",
+            "package test;",
+            "",
+            "import dagger.assisted.Assisted",
+            "import dagger.assisted.AssistedInject",
+            "import dagger.assisted.AssistedFactory",
+            "",
+            "class Foo @AssistedInject constructor(@Assisted i: Int) {",
+            "",
+            "  @AssistedInject",
+            "  constructor(s: String, @Assisted i: Int): this(i) {}",
+            "}");
+
+    CompilerTests.daggerCompiler(foo)
+        .withProcessingOptions(compilerMode.processorOptions())
+        .compile(
+            subject -> {
+              subject.hasErrorCount(1);
+              subject.hasErrorContaining(
+                  "Type test.Foo may only contain one injected constructor."
+                      + " Found: [@dagger.assisted.AssistedInject test.Foo(int),"
+                      + " @dagger.assisted.AssistedInject test.Foo(String, int)]");
+            });
+  }
 }
diff --git a/javatests/dagger/internal/codegen/BUILD b/javatests/dagger/internal/codegen/BUILD
index 5984e53..b189fe5 100644
--- a/javatests/dagger/internal/codegen/BUILD
+++ b/javatests/dagger/internal/codegen/BUILD
@@ -51,74 +51,137 @@
     srcs = [
         "CompilerMode.java",
         "Compilers.java",
+        "ComponentCreatorTestHelper.java",
+        "DaggerModuleMethodSubject.java",
+        "GeneratingProcessingStep.java",
         "JavaFileBuilder.java",
+        "TestUtils.java",
     ],
     deps = [
+        "//java/dagger:core",
         "//java/dagger/internal/codegen:package_info",
         "//java/dagger/internal/codegen:processor",
+        "//java/dagger/internal/codegen/base",
+        "//java/dagger/internal/codegen/binding",
+        "//java/dagger/internal/codegen/xprocessing",
         "//java/dagger/internal/codegen/xprocessing:xprocessing-testing",
+        "//java/dagger/producers",
         "//java/dagger/testing/compile",
         "//third_party/java/compile_testing",
         "//third_party/java/guava/base",
         "//third_party/java/guava/collect",
+        "//third_party/java/javapoet",
+        "//third_party/java/truth",
         "@com_google_auto_value_auto_value//jar",
     ],
 )
 
+# These are tests with over 25 test cases.
+LARGE_TESTS = [
+    "ComponentCreatorTest.java",
+    "ComponentProcessorTest.java",
+    "InjectConstructorFactoryGeneratorTest.java",
+    "MembersInjectionTest.java",
+    "MissingBindingValidationTest.java",
+    "ModuleFactoryGeneratorTest.java",
+    "ProducerModuleFactoryGeneratorTest.java",
+    "SubcomponentCreatorValidationTest.java",
+]
+
+# These are tests with over 10 test cases
+MEDIUM_TESTS = [
+    "BindsMethodValidationTest.java",
+    "DaggerSuperficialValidationTest.java",
+    "DelegateRequestRepresentationTest.java",
+    "DuplicateBindingsValidationTest.java",
+    "IgnoreProvisionKeyWildcardsTest.java",
+    "MapMultibindingValidationTest.java",
+    "MultibindsValidationTest.java",
+    "ProductionComponentProcessorTest.java",
+    "ProductionGraphValidationTest.java",
+    "SubcomponentValidationTest.java",
+]
+
+DEPS = [
+    ":compilers",
+    ":java_lib_no_dagger_compiler",
+    ":kt_lib_no_dagger_compiler",
+    "//third_party/java/guava/base",
+    "//third_party/java/guava/collect",
+    "//third_party/java/guava/util/concurrent",
+    "//third_party/java/auto:value",
+    "@com_google_auto_value_auto_value//jar",
+    "//third_party/java/auto:common",
+    "//third_party/java/compile_testing",
+    "//third_party/java/javapoet",
+    "//third_party/java/jsr250_annotations",  # Include @Generated in generated files.
+    "//third_party/java/jsr330_inject",
+    "//third_party/java/junit",
+    "//third_party/java/mockito",
+    "//third_party/java/truth",
+    "//java/dagger:core",
+    "//java/dagger/internal/codegen:package_info",
+    "//java/dagger/internal/codegen:processor",
+    "//java/dagger/internal/codegen/base",
+    "//java/dagger/internal/codegen/binding",
+    "//java/dagger/internal/codegen/bindinggraphvalidation",
+    "//java/dagger/internal/codegen/compileroption",
+    "//java/dagger/internal/codegen/extension",
+    "//java/dagger/internal/codegen/javac",
+    "//java/dagger/internal/codegen/javapoet",
+    "//java/dagger/internal/codegen/kotlin",
+    "//java/dagger/internal/codegen/langmodel",
+    "//java/dagger/internal/codegen/model",
+    "//java/dagger/internal/codegen/validation",
+    "//java/dagger/internal/codegen/writing",
+    "//java/dagger/internal/codegen/xprocessing",
+    "//java/dagger/internal/codegen/xprocessing:xprocessing-testing",
+    "//java/dagger/model/testing",
+    "//java/dagger/producers",
+    "//java/dagger/spi",
+    "//java/dagger/spi/model/testing",
+    "//java/dagger/testing/compile",
+    "//java/dagger/testing/golden",
+]
+
+GenJavaTests(
+    name = "large_compiler_tests",
+    srcs = LARGE_TESTS,
+    functional = False,
+    javacopts = DOCLINT_HTML_AND_SYNTAX,
+    plugins = ["//java/dagger/internal/codegen/bootstrap"],
+    shard_count = 7,
+    deps = DEPS,
+)
+
+GenJavaTests(
+    name = "medium_compiler_tests",
+    srcs = MEDIUM_TESTS,
+    functional = False,
+    javacopts = DOCLINT_HTML_AND_SYNTAX,
+    plugins = ["//java/dagger/internal/codegen/bootstrap"],
+    shard_count = 3,
+    deps = DEPS,
+)
+
 GenJavaTests(
     name = "compiler_tests",
     srcs = glob(
         ["*.java"],
         exclude = [
-            "ComponentProcessorTestClasses.java",
             "CompilerMode.java",
             "Compilers.java",
+            "ComponentCreatorTestHelper.java",
+            "ComponentProcessorTestClasses.java",
+            "DaggerModuleMethodSubject.java",
+            "GeneratingProcessingStep.java",
             "InvalidInjectConstructor.java",
             "JavaFileBuilder.java",
-        ],
+            "TestUtils.java",
+        ] + LARGE_TESTS + MEDIUM_TESTS,
     ),
     functional = False,
     javacopts = DOCLINT_HTML_AND_SYNTAX,
     plugins = ["//java/dagger/internal/codegen/bootstrap"],
-    deps = [
-        ":compilers",
-        ":java_lib_no_dagger_compiler",
-        ":kt_lib_no_dagger_compiler",
-        "//java/dagger:core",
-        "//java/dagger/internal/codegen:package_info",
-        "//java/dagger/internal/codegen:processor",
-        "//java/dagger/internal/codegen/base",
-        "//java/dagger/internal/codegen/binding",
-        "//java/dagger/internal/codegen/bindinggraphvalidation",
-        "//java/dagger/internal/codegen/compileroption",
-        "//java/dagger/internal/codegen/extension",
-        "//java/dagger/internal/codegen/javac",
-        "//java/dagger/internal/codegen/javapoet",
-        "//java/dagger/internal/codegen/kotlin",
-        "//java/dagger/internal/codegen/langmodel",
-        "//java/dagger/internal/codegen/model",
-        "//java/dagger/internal/codegen/validation",
-        "//java/dagger/internal/codegen/writing",
-        "//java/dagger/internal/codegen/xprocessing",
-        "//java/dagger/internal/codegen/xprocessing:xprocessing-testing",
-        "//java/dagger/model/testing",
-        "//java/dagger/producers",
-        "//java/dagger/spi",
-        "//java/dagger/spi/model/testing",
-        "//java/dagger/testing/compile",
-        "//java/dagger/testing/golden",
-        "//third_party/java/auto:common",
-        "//third_party/java/auto:value",
-        "//third_party/java/compile_testing",
-        "//third_party/java/guava/base",
-        "//third_party/java/guava/collect",
-        "//third_party/java/guava/util/concurrent",
-        "//third_party/java/javapoet",
-        "//third_party/java/jsr250_annotations",  # Include @Generated in generated files.
-        "//third_party/java/jsr330_inject",
-        "//third_party/java/junit",
-        "//third_party/java/mockito",
-        "//third_party/java/truth",
-        "@com_google_auto_value_auto_value//jar",
-    ],
+    deps = DEPS,
 )
diff --git a/javatests/dagger/internal/codegen/BindsMethodValidationTest.java b/javatests/dagger/internal/codegen/BindsMethodValidationTest.java
index b7c8e13..cb94f75 100644
--- a/javatests/dagger/internal/codegen/BindsMethodValidationTest.java
+++ b/javatests/dagger/internal/codegen/BindsMethodValidationTest.java
@@ -53,6 +53,70 @@
   }
 
   @Test
+  public void noExtensionForBinds() {
+    Source module =
+        CompilerTests.kotlinSource(
+            "test.TestModule.kt",
+            "package test",
+            "",
+            "import dagger.Binds",
+            "",
+            moduleAnnotation,
+            "interface TestModule {",
+            "  @Binds fun FooImpl.bindObject(): Foo",
+            "}");
+    Source foo =
+        CompilerTests.javaSource(
+            "test.Foo", // Prevents formatting onto a single line
+            "package test;",
+            "",
+            "interface Foo {}");
+    Source fooImpl =
+        CompilerTests.javaSource(
+            "test.FooImpl", // Prevents formatting onto a single line
+            "package test;",
+            "",
+            "class FooImpl implements Foo {",
+            "   @Inject FooImpl() {}",
+            "}");
+    CompilerTests.daggerCompiler(module, foo, fooImpl)
+        .compile(
+            subject -> {
+              subject.hasErrorCount(1);
+              subject.hasErrorContaining("@Binds methods can not be an extension function");
+            });
+  }
+
+  @Test
+  public void noExtensionForProvides() {
+    Source module =
+        CompilerTests.kotlinSource(
+            "test.TestModule.kt",
+            "package test",
+            "",
+            "import dagger.Provides",
+            "",
+            moduleAnnotation,
+            "object TestModule {",
+            "  @Provides fun Foo.providesString(): String = \"hello\"",
+            "}");
+    Source foo =
+        CompilerTests.javaSource(
+            "test.Foo", // Prevents formatting onto a single line
+            "package test;",
+            "",
+            "class Foo {",
+            "  @Inject Foo() {}",
+            "}");
+    CompilerTests.daggerCompiler(module, foo)
+        .compile(
+            subject -> {
+              subject.hasErrorCount(1);
+              subject.hasErrorContaining("@Provides methods can not be an extension function");
+            });
+  }
+
+  @Test
   public void nonAbstract() {
     assertThatMethod("@Binds Object concrete(String impl) { return null; }")
         .hasError("must be abstract");
diff --git a/javatests/dagger/internal/codegen/ComponentProcessorTest.java b/javatests/dagger/internal/codegen/ComponentProcessorTest.java
index e7f9b8e..90c7b29 100644
--- a/javatests/dagger/internal/codegen/ComponentProcessorTest.java
+++ b/javatests/dagger/internal/codegen/ComponentProcessorTest.java
@@ -16,7 +16,12 @@
 
 package dagger.internal.codegen;
 
+import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertThrows;
+
+import androidx.room.compiler.processing.util.CompilationResultSubject;
 import androidx.room.compiler.processing.util.Source;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.squareup.javapoet.AnnotationSpec;
 import com.squareup.javapoet.MethodSpec;
@@ -27,6 +32,7 @@
 import dagger.testing.golden.GoldenFileRule;
 import java.util.Collection;
 import javax.inject.Inject;
+import javax.tools.Diagnostic;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -1380,21 +1386,57 @@
             subject -> {
               subject.hasErrorCount(0);
               subject.hasWarningCount(0);
-              subject.hasNoteContaining(
-                  String.format(
-                      "Generating a MembersInjector for dagger.internal.codegen.%s.",
-                      "ComponentProcessorTestClasses.LocalInjectMemberNoConstructor"));
-              subject.hasNoteContaining(
-                  String.format(
-                      "Generating a MembersInjector for dagger.internal.codegen.%s.",
-                      "ComponentProcessorTestClasses.LocalInjectMemberWithConstructor"));
-              subject.hasNoteContaining(
-                  String.format(
-                      "Generating a MembersInjector for dagger.internal.codegen.%s.",
-                      "ComponentProcessorTestClasses.ParentInjectMemberWithConstructor"));
+
+              String generatedFileTemplate =
+                  "dagger/internal/codegen/ComponentProcessorTestClasses_%s_MembersInjector.java";
+              String noteTemplate =
+                  "Generating a MembersInjector for "
+                      + "dagger.internal.codegen.ComponentProcessorTestClasses.%s.";
+
+              // Assert that we generate sources and notes for the following classes.
+              ImmutableList.of(
+                      "LocalInjectMemberNoConstructor",
+                      "LocalInjectMemberWithConstructor",
+                      "ParentInjectMemberWithConstructor")
+                  .forEach(
+                      className -> {
+                        subject.generatedSourceFileWithPath(
+                            String.format(generatedFileTemplate, className));
+                        subject.hasNoteContaining(String.format(noteTemplate, className));
+                      });
+
+              // Assert that we **do not** generate sources and notes for the following classes.
+              ImmutableList.of(
+                      "ParentInjectMemberNoConstructor",
+                      "NoInjectMemberNoConstructor",
+                      "NoInjectMemberWithConstructor")
+                  .forEach(
+                      className -> {
+                        assertFileNotGenerated(
+                            subject, String.format(generatedFileTemplate, className));
+                        assertDoesNotHaveNoteContaining(
+                            subject, String.format(noteTemplate, className));
+                      });
             });
   }
 
+  private void assertFileNotGenerated(CompilationResultSubject subject, String filePath) {
+    // TODO(b/303653163): replace this with better XProcessing API once we have the ability to get a
+    // list of all generated sources.
+    AssertionError error =
+        assertThrows(
+            AssertionError.class,
+            () -> subject.generatedSourceFileWithPath(filePath));
+    assertThat(error).hasMessageThat().contains("Didn't generate file");
+  }
+
+  private void assertDoesNotHaveNoteContaining(CompilationResultSubject subject, String content) {
+    assertThat(
+            subject.getCompilationResult().getDiagnostics().get(Diagnostic.Kind.NOTE).stream()
+                .filter(diagnostic -> diagnostic.getMsg().contains(content)))
+        .isEmpty();
+  }
+
   @Test
   public void scopeAnnotationOnInjectConstructorNotValid() {
     Source aScope =
@@ -2045,4 +2087,76 @@
               subject.hasWarningCount(0);
           });
   }
+
+  @Test
+  public void abstractVarFieldInComponent_failsValidation() {
+    Source component =
+        CompilerTests.kotlinSource(
+            "test.TestComponent.kt",
+            "package test",
+            "",
+            "import dagger.Component",
+            "",
+            "@Component(modules = [TestModule::class])",
+            "interface TestComponent {",
+            " var foo: String",
+            "}");
+
+    Source module =
+        CompilerTests.javaSource(
+            "test.TestModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "",
+            "@Module",
+            "abstract class TestModule {",
+            "  @Provides",
+            "  static String provideString() { return \"hello\"; }",
+            "}");
+
+    CompilerTests.daggerCompiler(component, module)
+        .withProcessingOptions(compilerMode.processorOptions())
+        .compile(
+            subject -> {
+              subject.hasErrorCount(1);
+              subject.hasErrorContaining(
+                  "Cannot use 'abstract var' property in a component declaration to get a binding."
+                      + " Use 'val' or 'fun' instead: foo");
+            });
+  }
+
+  @Test
+  public void nonAbstractVarFieldInComponent_passesValidation() {
+    Source component =
+        CompilerTests.kotlinSource(
+            "test.TestComponent.kt",
+            "package test",
+            "",
+            "import dagger.Component",
+            "",
+            "@Component(modules = [TestModule::class])",
+            "abstract class TestComponent {",
+            " var foo: String = \"hello\"",
+            "}");
+
+    Source module =
+        CompilerTests.javaSource(
+            "test.TestModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "",
+            "@Module",
+            "abstract class TestModule {",
+            "  @Provides",
+            "  static String provideString() { return \"hello\"; }",
+            "}");
+
+    CompilerTests.daggerCompiler(component, module)
+        .withProcessingOptions(compilerMode.processorOptions())
+        .compile(subject -> subject.hasErrorCount(0));
+  }
 }
diff --git a/javatests/dagger/internal/codegen/DuplicateBindingsValidationTest.java b/javatests/dagger/internal/codegen/DuplicateBindingsValidationTest.java
index b45357c..c352a28 100644
--- a/javatests/dagger/internal/codegen/DuplicateBindingsValidationTest.java
+++ b/javatests/dagger/internal/codegen/DuplicateBindingsValidationTest.java
@@ -1052,9 +1052,8 @@
     CompilerTests.daggerCompiler(foo, injected1, injected2, provided1, provided2)
         .compile(
             subject -> {
-              subject.hasErrorCount(0);
-              subject.hasWarningCount(1);
-              subject.hasWarningContaining(
+              subject.hasErrorCount(1);
+              subject.hasErrorContaining(
                       message(
                           "Foo is bound multiple times:",
                           "    @Inject Foo(Set<String>) [Injected1]",
diff --git a/javatests/dagger/internal/codegen/FrameworkFieldTest.java b/javatests/dagger/internal/codegen/FrameworkFieldTest.java
index be495d7..ba5b88f 100644
--- a/javatests/dagger/internal/codegen/FrameworkFieldTest.java
+++ b/javatests/dagger/internal/codegen/FrameworkFieldTest.java
@@ -24,6 +24,7 @@
 
 import com.google.testing.compile.CompilationRule;
 import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.ParameterizedTypeName;
 import dagger.internal.codegen.binding.FrameworkField;
 import javax.inject.Inject;
 import org.junit.Before;
@@ -47,16 +48,20 @@
   }
 
   @Test public void frameworkType() {
-    assertThat(FrameworkField.create(PROVIDER, xTypeName, "test").type())
+    assertThat(FrameworkField.create(ParameterizedTypeName.get(PROVIDER, xTypeName), "test").type())
         .isEqualTo(providerOf(xTypeName));
-    assertThat(FrameworkField.create(MEMBERS_INJECTOR, xTypeName, "test").type())
+    assertThat(
+            FrameworkField.create(ParameterizedTypeName.get(MEMBERS_INJECTOR, xTypeName), "test")
+                .type())
         .isEqualTo(membersInjectorOf(xTypeName));
   }
 
   @Test public void nameSuffix() {
-    assertThat(FrameworkField.create(PROVIDER, xTypeName, "foo").name())
+    assertThat(FrameworkField.create(ParameterizedTypeName.get(PROVIDER, xTypeName), "foo").name())
         .isEqualTo("fooProvider");
-    assertThat(FrameworkField.create(PROVIDER, xTypeName, "fooProvider").name())
+    assertThat(
+            FrameworkField.create(ParameterizedTypeName.get(PROVIDER, xTypeName), "fooProvider")
+                .name())
         .isEqualTo("fooProvider");
   }
 
diff --git a/javatests/dagger/internal/codegen/GeneratedLines.java b/javatests/dagger/internal/codegen/GeneratedLines.java
index 308904a..d8a0388 100644
--- a/javatests/dagger/internal/codegen/GeneratedLines.java
+++ b/javatests/dagger/internal/codegen/GeneratedLines.java
@@ -33,7 +33,7 @@
 
   private static final String SUPPRESS_WARNINGS_ANNOTATION =
       "@SuppressWarnings({"
-          + "\"unchecked\", \"rawtypes\", \"KotlinInternal\", \"KotlinInternalInJava\""
+          + "\"unchecked\", \"rawtypes\", \"KotlinInternal\", \"KotlinInternalInJava\", \"cast\""
           + "})";
 
   private static final String IMPORT_DAGGER_GENERATED = "import dagger.internal.DaggerGenerated;";
diff --git a/javatests/dagger/internal/codegen/HjarTest.java b/javatests/dagger/internal/codegen/HjarTest.java
new file mode 100644
index 0000000..e8f67b7
--- /dev/null
+++ b/javatests/dagger/internal/codegen/HjarTest.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2014 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.internal.codegen;
+
+import androidx.room.compiler.processing.util.Source;
+import com.google.common.collect.ImmutableMap;
+import dagger.testing.compile.CompilerTests;
+import dagger.testing.compile.CompilerTests.DaggerCompiler;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Tests compilation with the {@code experimental_turbine_hjar} flag enabled. */
+@RunWith(JUnit4.class)
+public class HjarTest {
+  /** Returns a {@link DaggerCompiler} with hjar generation enabled. */
+  private static DaggerCompiler daggerCompiler(Source... sources) {
+    return CompilerTests.daggerCompiler(sources)
+        .withProcessingOptions(ImmutableMap.of("experimental_turbine_hjar", ""));
+  }
+
+  @Test
+  public void componentTest() {
+    Source component =
+        CompilerTests.javaSource(
+            "test.MyComponent",
+            "package test;",
+            "",
+            "import dagger.Component;",
+            "",
+            "@Component",
+            "interface MyComponent {",
+            "  String getString();",
+            "  int getInt();",
+            "  void inject(String str);",
+            "}");
+    daggerCompiler(component).compile(subject -> subject.hasErrorCount(0));
+  }
+
+  @Test
+  public void moduleTest() {
+    Source module =
+        CompilerTests.javaSource(
+            "test.MyModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "",
+            "@Module",
+            "interface MyModule {",
+            "  @Provides static int provideInt() { return 0; }",
+            "  @Provides static String provideString() { return null; }",
+            "  @Provides static String[] provideStringArray() { return null; }",
+            "  @Provides static int[] provideIntArray() { return null; }",
+            "  @Provides static boolean provideBoolean() { return false; }",
+            "}");
+    daggerCompiler(module).compile(subject -> subject.hasErrorCount(0));
+  }
+
+  @Test
+  public void producerModuleTest() {
+    Source module =
+        CompilerTests.javaSource(
+            "test.MyModule",
+            "package test;",
+            "",
+            "import com.google.common.util.concurrent.ListenableFuture;",
+            "import dagger.producers.ProducerModule;",
+            "import dagger.producers.Produces;",
+            "",
+            "@ProducerModule",
+            "interface MyModule {",
+            "  @Produces static ListenableFuture<String> produceString() { return null; }",
+            "}");
+    daggerCompiler(module).compile(subject -> subject.hasErrorCount(0));
+  }
+}
diff --git a/javatests/dagger/internal/codegen/IgnoreProvisionKeyWildcardsTest.java b/javatests/dagger/internal/codegen/IgnoreProvisionKeyWildcardsTest.java
index 008a0a8..7b17058 100644
--- a/javatests/dagger/internal/codegen/IgnoreProvisionKeyWildcardsTest.java
+++ b/javatests/dagger/internal/codegen/IgnoreProvisionKeyWildcardsTest.java
@@ -16,7 +16,6 @@
 
 package dagger.internal.codegen;
 
-import androidx.room.compiler.processing.XProcessingEnv;
 import androidx.room.compiler.processing.util.CompilationResultSubject;
 import com.google.common.base.Joiner;
 import com.google.common.collect.ImmutableList;
@@ -57,7 +56,7 @@
     processingOptions =
         isIgnoreProvisionKeyWildcardsEnabled
             ? ImmutableMap.of("dagger.ignoreProvisionKeyWildcards", "enabled")
-            : ImmutableMap.of();
+            : ImmutableMap.of("dagger.ignoreProvisionKeyWildcards", "disabled");
   }
 
   @Test
@@ -219,8 +218,7 @@
   @Test
   public void testProvidesMultibindsSetContributionsWithDifferentTypeVariances() {
     compile(
-        /* javaComponentClass = */
-        NEW_LINES.join(
+        /* javaComponentClass= */ NEW_LINES.join(
             "@Component(modules = MyModule.class)",
             "interface MyComponent {",
             "  Set<Foo<? extends Bar>> setExtends();",
@@ -231,8 +229,7 @@
             "  @Provides @IntoSet static Foo<? extends Bar> setExtends() { return null; }",
             "  @Provides @IntoSet static Foo<Bar> set() { return null; }",
             "}"),
-        /* kotlinComponentClass = */
-        NEW_LINES.join(
+        /* kotlinComponentClass= */ NEW_LINES.join(
             "@Component(modules = [MyModule::class])",
             "interface MyComponent {",
             "  fun setExtends(): Set<Foo<out Bar>>",
@@ -247,14 +244,12 @@
           if (isIgnoreProvisionKeyWildcardsEnabled) {
             subject.hasErrorCount(1);
             subject.hasErrorContaining(
-                String.format(
-                    NEW_LINES_FOR_ERROR_MSG.join(
-                        "Set<Foo<? extends Bar>> has incompatible bindings or declarations:",
-                        "    Set bindings and declarations:",
-                        "        %1$s Foo<Bar> MyModule.set()",
-                        "        %1$s Foo<? extends Bar> MyModule.setExtends()",
-                        "    in component: [MyComponent]"),
-                    isKapt(subject) ? "@IntoSet @Provides" : "@Provides @IntoSet"));
+                NEW_LINES_FOR_ERROR_MSG.join(
+                    "Set<Foo<? extends Bar>> has incompatible bindings or declarations:",
+                    "    Set bindings and declarations:",
+                    "        @Provides @IntoSet Foo<Bar> MyModule.set()",
+                    "        @Provides @IntoSet Foo<? extends Bar> MyModule.setExtends()",
+                    "    in component: [MyComponent]"));
           } else {
             subject.hasErrorCount(0);
           }
@@ -300,9 +295,8 @@
                         "Set<Foo<? extends Bar>> has incompatible bindings or declarations:",
                         "    Set bindings and declarations:",
                         "        @Multibinds Set<Foo<Bar>> MyModule.mulitbindSet()",
-                        "        %s Foo<? extends Bar> %s.setExtends()",
+                        "        @Provides @IntoSet Foo<? extends Bar> %s.setExtends()",
                         "    in component: [MyComponent]"),
-                    isKapt(subject) ? "@IntoSet @Provides" : "@Provides @IntoSet",
                     sourceKind == SourceKind.KOTLIN ? "MyModule.Companion" : "MyModule"));
           } else {
             subject.hasErrorCount(0);
@@ -313,8 +307,7 @@
   @Test
   public void testProvidesIntoSetAndElementsIntoSetContributionsWithDifferentVariances() {
     compile(
-        /* javaComponentClass = */
-        NEW_LINES.join(
+        /* javaComponentClass= */ NEW_LINES.join(
             "@Component(modules = MyModule.class)",
             "interface MyComponent {",
             "  Set<Foo<? extends Bar>> setExtends();",
@@ -328,8 +321,7 @@
             "  @ElementsIntoSet",
             "  static Set<Foo<Bar>> set() { return null; }",
             "}"),
-        /* kotlinComponentClass = */
-        NEW_LINES.join(
+        /* kotlinComponentClass= */ NEW_LINES.join(
             "@Component(modules = [MyModule::class])",
             "interface MyComponent {",
             "  fun setExtends(): Set<Foo<out Bar>>",
@@ -344,15 +336,12 @@
           if (isIgnoreProvisionKeyWildcardsEnabled) {
             subject.hasErrorCount(1);
             subject.hasErrorContaining(
-                String.format(
-                    NEW_LINES_FOR_ERROR_MSG.join(
-                        "Set<Foo<? extends Bar>> has incompatible bindings or declarations:",
-                        "    Set bindings and declarations:",
-                        "        %s Set<Foo<Bar>> MyModule.set()",
-                        "        %s Foo<? extends Bar> MyModule.setExtends()",
-                        "    in component: [MyComponent]"),
-                    isKapt(subject) ? "@ElementsIntoSet @Provides" : "@Provides @ElementsIntoSet",
-                    isKapt(subject) ? "@IntoSet @Provides" : "@Provides @IntoSet"));
+                NEW_LINES_FOR_ERROR_MSG.join(
+                    "Set<Foo<? extends Bar>> has incompatible bindings or declarations:",
+                    "    Set bindings and declarations:",
+                    "        @Provides @ElementsIntoSet Set<Foo<Bar>> MyModule.set()",
+                    "        @Provides @IntoSet Foo<? extends Bar> MyModule.setExtends()",
+                    "    in component: [MyComponent]"));
           } else {
             subject.hasErrorCount(0);
           }
@@ -526,12 +515,8 @@
                         "        %s Foo<Bar> MyModule.foo()",
                         "        %s Foo<? extends Bar> MyModule.fooExtends()",
                         "    in component: [MyComponent]"),
-                    isKapt(subject)
-                        ? "@StringKey(\"foo\") @IntoMap @Provides"
-                        : "@Provides @IntoMap @StringKey(\"foo\")",
-                    isKapt(subject)
-                        ? "@StringKey(\"fooExtends\") @IntoMap @Provides"
-                        : "@Provides @IntoMap @StringKey(\"fooExtends\")"));
+                    "@Provides @IntoMap @StringKey(\"foo\")",
+                    "@Provides @IntoMap @StringKey(\"fooExtends\")"));
           } else {
             subject.hasErrorCount(0);
           }
@@ -584,6 +569,27 @@
       String javaComponentClass,
       String kotlinComponentClass,
       Consumer<CompilationResultSubject> onCompilationResult) {
+    compileInternal(
+        javaComponentClass,
+        kotlinComponentClass,
+        subject -> {
+          if (!isIgnoreProvisionKeyWildcardsEnabled) {
+            if (CompilerTests.backend(subject) ==
+                androidx.room.compiler.processing.XProcessingEnv.Backend.KSP) {
+              subject.hasErrorCount(1);
+              subject.hasErrorContaining(
+                  "When using KSP, you must also enable the 'dagger.ignoreProvisionKeyWildcards'");
+              return;
+            }
+          }
+          onCompilationResult.accept(subject);
+        });
+  }
+
+  private void compileInternal(
+      String javaComponentClass,
+      String kotlinComponentClass,
+      Consumer<CompilationResultSubject> onCompilationResult) {
     if (sourceKind == SourceKind.JAVA) {
       // Compile with Java sources
       CompilerTests.daggerCompiler(
@@ -649,9 +655,4 @@
           .compile(onCompilationResult);
     }
   }
-
-  private boolean isKapt(CompilationResultSubject subject) {
-    return sourceKind == SourceKind.KOTLIN
-        && CompilerTests.backend(subject) == XProcessingEnv.Backend.JAVAC;
-  }
 }
diff --git a/javatests/dagger/internal/codegen/LazyClassKeyMapBindingComponentProcessorTest.java b/javatests/dagger/internal/codegen/LazyClassKeyMapBindingComponentProcessorTest.java
new file mode 100644
index 0000000..9937d05
--- /dev/null
+++ b/javatests/dagger/internal/codegen/LazyClassKeyMapBindingComponentProcessorTest.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2024 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.internal.codegen;
+
+import static com.google.testing.compile.CompilationSubject.assertThat;
+
+import androidx.room.compiler.processing.util.Source;
+import com.google.testing.compile.Compilation;
+import com.google.testing.compile.JavaFileObjects;
+import dagger.testing.compile.CompilerTests;
+import dagger.testing.golden.GoldenFileRule;
+import java.util.Collection;
+import javax.tools.JavaFileObject;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class LazyClassKeyMapBindingComponentProcessorTest {
+  @Parameters(name = "{0}")
+  public static Collection<Object[]> parameters() {
+    return CompilerMode.TEST_PARAMETERS;
+  }
+
+  @Rule public GoldenFileRule goldenFileRule = new GoldenFileRule();
+
+  private final CompilerMode compilerMode;
+
+  public LazyClassKeyMapBindingComponentProcessorTest(CompilerMode compilerMode) {
+    this.compilerMode = compilerMode;
+  }
+
+  // Cannot convert to use ksp as this test relies on AutoAnnotationProcessor.
+  @Test
+  public void mapBindingsWithInaccessibleKeys() throws Exception {
+    JavaFileObject mapKeys =
+        JavaFileObjects.forSourceLines(
+            "mapkeys.MapKeys",
+            "package mapkeys;",
+            "",
+            "import dagger.MapKey;",
+            "import dagger.multibindings.LazyClassKey;",
+            "",
+            "public class MapKeys {",
+            "  @MapKey(unwrapValue = false)",
+            "  public @interface ComplexKey {",
+            "    Class<?>[] manyClasses();",
+            "    Class<?> oneClass();",
+            "    LazyClassKey annotation();",
+            "  }",
+            "",
+            "  interface Inaccessible {}",
+            "}");
+    JavaFileObject moduleFile =
+        JavaFileObjects.forSourceLines(
+            "mapkeys.MapModule",
+            "package mapkeys;",
+            "",
+            "import dagger.Binds;",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "import dagger.multibindings.LazyClassKey;",
+            "import dagger.multibindings.IntoMap;",
+            "import java.util.Map;",
+            "import javax.inject.Provider;",
+            "",
+            "@Module",
+            "public interface MapModule {",
+            "  @Provides @IntoMap @LazyClassKey(MapKeys.Inaccessible.class)",
+            "  static int classKey() { return 1; }",
+            "",
+            "  @Provides @IntoMap",
+            "  @MapKeys.ComplexKey(",
+            "    manyClasses = {java.lang.Object.class, java.lang.String.class},",
+            "    oneClass = MapKeys.Inaccessible.class,",
+            "    annotation = @LazyClassKey(java.lang.Object.class)",
+            "  )",
+            "  static int complexKeyWithInaccessibleValue() { return 1; }",
+            "",
+            "  @Provides @IntoMap",
+            "  @MapKeys.ComplexKey(",
+            "    manyClasses = {MapKeys.Inaccessible.class, java.lang.String.class},",
+            "    oneClass = java.lang.String.class,",
+            "    annotation = @LazyClassKey(java.lang.Object.class)",
+            "  )",
+            "  static int complexKeyWithInaccessibleArrayValue() { return 1; }",
+            "",
+            "  @Provides @IntoMap",
+            "  @MapKeys.ComplexKey(",
+            "    manyClasses = {java.lang.String.class},",
+            "    oneClass = java.lang.String.class,",
+            "    annotation = @LazyClassKey(MapKeys.Inaccessible.class)",
+            "  )",
+            "  static int complexKeyWithInaccessibleAnnotationValue() { return 1; }",
+            "}");
+    JavaFileObject componentFile =
+        JavaFileObjects.forSourceLines(
+            "test.TestComponent",
+            "package test;",
+            "",
+            "import dagger.Component;",
+            "import java.util.Map;",
+            "import javax.inject.Provider;",
+            "import mapkeys.MapKeys;",
+            "import mapkeys.MapModule;",
+            "",
+            "@Component(modules = MapModule.class)",
+            "interface TestComponent {",
+            "  Map<Class<?>, Integer> classKey();",
+            "  Provider<Map<Class<?>, Integer>> classKeyProvider();",
+            "",
+            "  Map<MapKeys.ComplexKey, Integer> complexKey();",
+            "  Provider<Map<MapKeys.ComplexKey, Integer>> complexKeyProvider();",
+            "}");
+    Compilation compilation =
+        Compilers.compilerWithOptions(compilerMode.javacopts())
+            .compile(mapKeys, moduleFile, componentFile);
+    assertThat(compilation).succeeded();
+    assertThat(compilation)
+        .generatedSourceFile("test.DaggerTestComponent")
+        .hasSourceEquivalentTo(goldenFileRule.goldenFile("test.DaggerTestComponent"));
+    assertThat(compilation)
+        .generatedSourceFile(
+            "mapkeys.MapModule_ComplexKeyWithInaccessibleAnnotationValueMapKey")
+        .hasSourceEquivalentTo(
+            goldenFileRule.goldenFile(
+                "mapkeys.MapModule_ComplexKeyWithInaccessibleAnnotationValueMapKey"));
+    assertThat(compilation)
+        .generatedSourceFile("mapkeys.MapModule_ClassKeyMapKey")
+        .hasSourceEquivalentTo(goldenFileRule.goldenFile("mapkeys.MapModule_ClassKeyMapKey"));
+  }
+
+  @Test
+  public void lazyClassKeySimilarQualifiedName_doesNotConflict() throws Exception {
+    Source fooBar =
+        CompilerTests.javaSource("test.Foo_Bar", "package test;", "", "interface Foo_Bar {}");
+    Source fooBar2 =
+        CompilerTests.javaSource(
+            "test.Foo", "package test;", "", "interface Foo { interface Bar {} }");
+    Source mapKeyBindingsModule =
+        CompilerTests.javaSource(
+            "test.MapKeyBindingsModule",
+            "package test;",
+            "",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "import dagger.multibindings.LazyClassKey;",
+            "import dagger.multibindings.IntoMap;",
+            "",
+            "@Module",
+            "public interface MapKeyBindingsModule {",
+            " @Provides @IntoMap @LazyClassKey(test.Foo_Bar.class)",
+            " static int classKey() { return 1; }",
+            "",
+            " @Provides @IntoMap @LazyClassKey(test.Foo.Bar.class)",
+            " static int classKey2() { return 1; }",
+            "}");
+
+    Source componentFile =
+        CompilerTests.javaSource(
+            "test.TestComponent",
+            "package test;",
+            "",
+            "import dagger.Component;",
+            "import java.util.Map;",
+            "",
+            "@Component(modules = MapKeyBindingsModule.class)",
+            "interface TestComponent {",
+            "  Map<Class<?>, Integer> classKey();",
+            "}");
+    CompilerTests.daggerCompiler(fooBar, fooBar2, mapKeyBindingsModule, componentFile)
+        .withProcessingOptions(compilerMode.processorOptions())
+        .compile(subject -> subject.hasErrorCount(0));
+  }
+}
diff --git a/javatests/dagger/internal/codegen/MembersInjectionTest.java b/javatests/dagger/internal/codegen/MembersInjectionTest.java
index 8d2ff0b..4748853 100644
--- a/javatests/dagger/internal/codegen/MembersInjectionTest.java
+++ b/javatests/dagger/internal/codegen/MembersInjectionTest.java
@@ -46,6 +46,88 @@
   }
 
   @Test
+  public void injectKotlinProtectField_fails() {
+    Source injectFieldSrc =
+        CompilerTests.kotlinSource(
+            "MyClass.kt",
+            "package test",
+            "",
+            "import javax.inject.Inject",
+            "",
+            "class MyClass @Inject constructor() {",
+            "  @Inject protected lateinit var protectedField: String",
+            "}");
+    Source moduleSrc =
+        CompilerTests.kotlinSource(
+            "MyModule.kt",
+            "package test",
+            "",
+            "import dagger.Module",
+            "import dagger.Provides",
+            "",
+            "@Module",
+            "object MyModule {",
+            "  @Provides",
+            "  fun providesString() = \"hello\"",
+            "}");
+    Source componentSrc =
+        CompilerTests.kotlinSource(
+            "MyComponent.kt",
+            "package test",
+            "",
+            "import dagger.Component",
+            "@Component(modules = [MyModule::class])",
+            "interface MyComponent {}");
+    CompilerTests.daggerCompiler(injectFieldSrc, moduleSrc, componentSrc)
+        .withProcessingOptions(compilerMode.processorOptions())
+        .compile(
+            subject -> {
+              subject.hasErrorCount(1);
+              subject.hasErrorContaining(
+                  "Dagger injector does not have access to kotlin protected fields");
+            });
+  }
+
+  @Test
+  public void injectJavaProtectField_succeeds() {
+    Source injectFieldSrc =
+        CompilerTests.javaSource(
+            "test.MyClass",
+            "package test;",
+            "",
+            "import javax.inject.Inject;",
+            "",
+            "public final class MyClass {",
+            "  @Inject MyClass() {}",
+            "  @Inject protected String protectedField;",
+            "}");
+    Source moduleSrc =
+        CompilerTests.kotlinSource(
+            "MyModule.kt",
+            "package test",
+            "",
+            "import dagger.Module",
+            "import dagger.Provides",
+            "",
+            "@Module",
+            "object MyModule {",
+            "  @Provides",
+            "  fun providesString() = \"hello\"",
+            "}");
+    Source componentSrc =
+        CompilerTests.kotlinSource(
+            "MyComponent.kt",
+            "package test",
+            "",
+            "import dagger.Component",
+            "@Component(modules = [MyModule::class])",
+            "interface MyComponent {}");
+    CompilerTests.daggerCompiler(injectFieldSrc, moduleSrc, componentSrc)
+        .withProcessingOptions(compilerMode.processorOptions())
+        .compile(subject -> subject.hasErrorCount(0));
+  }
+
+  @Test
   public void parentClass_noInjectedMembers() throws Exception {
     Source childFile =
         CompilerTests.javaSource(
@@ -159,7 +241,8 @@
         .compile(
             subject -> {
               subject.hasErrorCount(0);
-              subject.generatedSource(goldenFileRule.goldenSource("test/GenericClass_MembersInjector"));
+              subject.generatedSource(
+                  goldenFileRule.goldenSource("test/GenericClass_MembersInjector"));
             });
   }
 
diff --git a/javatests/dagger/internal/codegen/MissingBindingSuggestionsTest.java b/javatests/dagger/internal/codegen/MissingBindingSuggestionsTest.java
deleted file mode 100644
index 5e64c12..0000000
--- a/javatests/dagger/internal/codegen/MissingBindingSuggestionsTest.java
+++ /dev/null
@@ -1,352 +0,0 @@
-/*
- * Copyright (C) 2015 The Dagger Authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package dagger.internal.codegen;
-
-import androidx.room.compiler.processing.util.Source;
-import com.google.common.collect.ImmutableList;
-import dagger.testing.compile.CompilerTests;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(Parameterized.class)
-public class MissingBindingSuggestionsTest {
-  @Parameters(name = "{0}")
-  public static ImmutableList<Object[]> parameters() {
-    return CompilerMode.TEST_PARAMETERS;
-  }
-
-  private final CompilerMode compilerMode;
-
-  public MissingBindingSuggestionsTest(CompilerMode compilerMode) {
-    this.compilerMode = compilerMode;
-  }
-
-  private static Source injectable(String className, String constructorParams) {
-    return CompilerTests.javaSource(
-        "test." + className,
-        "package test;",
-        "",
-        "import javax.inject.Inject;",
-        "",
-        "class " + className + " {",
-        "  @Inject " + className + "(" + constructorParams + ") {}",
-        "}");
-  }
-
-  private static Source emptyInterface(String interfaceName) {
-    return CompilerTests.javaSource(
-        "test." + interfaceName,
-        "package test;",
-        "",
-        "import javax.inject.Inject;",
-        "",
-        "interface " + interfaceName + " {}");
-  }
-
-  @Test public void suggestsBindingInSeparateComponent() {
-    Source fooComponent =
-        CompilerTests.javaSource(
-            "test.FooComponent",
-            "package test;",
-            "",
-            "import dagger.Subcomponent;",
-            "",
-            "@Subcomponent",
-            "interface FooComponent {",
-            "  Foo getFoo();",
-            "}");
-    Source barModule =
-        CompilerTests.javaSource(
-            "test.BarModule",
-            "package test;",
-            "",
-            "import dagger.Provides;",
-            "import javax.inject.Inject;",
-            "",
-            "@dagger.Module",
-            "final class BarModule {",
-            "  @Provides Bar provideBar() {return null;}",
-            "}");
-    Source barComponent =
-        CompilerTests.javaSource(
-            "test.BarComponent",
-            "package test;",
-            "",
-            "import dagger.Subcomponent;",
-            "",
-            "@Subcomponent(modules = {BarModule.class})",
-            "interface BarComponent {",
-            "  Bar getBar();",
-            "}");
-    Source foo = injectable("Foo", "Bar bar");
-    Source bar = emptyInterface("Bar");
-
-    Source topComponent =
-        CompilerTests.javaSource(
-            "test.TopComponent",
-            "package test;",
-            "",
-            "import dagger.Component;",
-            "",
-            "@Component",
-            "interface TopComponent {",
-            "  FooComponent getFoo();",
-            "  BarComponent getBar(BarModule barModule);",
-            "}");
-
-    CompilerTests.daggerCompiler(fooComponent, barComponent, topComponent, foo, bar, barModule)
-        .withProcessingOptions(compilerMode.processorOptions())
-        .compile(
-            subject -> {
-              subject.hasErrorCount(1);
-              subject.hasErrorContaining("A binding for Bar exists in BarComponent:");
-            });
-  }
-
-  @Test public void suggestsBindingInNestedSubcomponent() {
-    Source fooComponent =
-        CompilerTests.javaSource(
-            "test.FooComponent",
-            "package test;",
-            "",
-            "import dagger.Subcomponent;",
-            "",
-            "@Subcomponent",
-            "interface FooComponent {",
-            "  Foo getFoo();",
-            "}");
-    Source barComponent =
-        CompilerTests.javaSource(
-            "test.BarComponent",
-            "package test;",
-            "",
-            "import dagger.Subcomponent;",
-            "",
-            "@Subcomponent()",
-            "interface BarComponent {",
-            "  BazComponent getBaz();",
-            "}");
-    Source bazModule =
-        CompilerTests.javaSource(
-            "test.BazModule",
-            "package test;",
-            "",
-            "import dagger.Provides;",
-            "import javax.inject.Inject;",
-            "",
-            "@dagger.Module",
-            "final class BazModule {",
-            "  @Provides Baz provideBaz() {return null;}",
-            "}");
-    Source bazComponent =
-        CompilerTests.javaSource(
-            "test.BazComponent",
-            "package test;",
-            "",
-            "import dagger.Subcomponent;",
-            "",
-            "@Subcomponent(modules = {BazModule.class})",
-            "interface BazComponent {",
-            "  Baz getBaz();",
-            "}");
-    Source foo = injectable("Foo", "Baz baz");
-    Source baz = emptyInterface("Baz");
-
-    Source topComponent =
-        CompilerTests.javaSource(
-            "test.TopComponent",
-            "package test;",
-            "",
-            "import dagger.Component;",
-            "",
-            "@Component",
-            "interface TopComponent {",
-            "  FooComponent getFoo();",
-            "  BarComponent getBar();",
-            "}");
-
-    CompilerTests.daggerCompiler(
-            fooComponent, barComponent, bazComponent, topComponent, foo, baz, bazModule)
-        .withProcessingOptions(compilerMode.processorOptions())
-        .compile(
-            subject -> {
-              subject.hasErrorCount(1);
-              subject.hasErrorContaining("A binding for Baz exists in BazComponent:");
-            });
-  }
-
-  @Test
-  public void missingBindingInParentComponent() {
-    Source parent =
-        CompilerTests.javaSource(
-            "Parent",
-            "import dagger.Component;",
-            "",
-            "@Component",
-            "interface Parent {",
-            "  Foo foo();",
-            "  Bar bar();",
-            "  Child child();",
-            "}");
-    Source child =
-        CompilerTests.javaSource(
-            "Child",
-            "import dagger.Subcomponent;",
-            "",
-            "@Subcomponent(modules=BazModule.class)",
-            "interface Child {",
-            "  Foo foo();",
-            "  Baz baz();",
-            "}");
-    Source foo =
-        CompilerTests.javaSource(
-            "Foo",
-            "import javax.inject.Inject;",
-            "",
-            "class Foo {",
-            "  @Inject Foo(Bar bar) {}",
-            "}");
-    Source bar =
-        CompilerTests.javaSource(
-            "Bar",
-            "import javax.inject.Inject;",
-            "",
-            "class Bar {",
-            "  @Inject Bar(Baz baz) {}",
-            "}");
-    Source baz = CompilerTests.javaSource("Baz", "class Baz {}");
-    Source bazModule =
-        CompilerTests.javaSource(
-        "BazModule",
-        "import dagger.Module;",
-        "import dagger.Provides;",
-        "import javax.inject.Inject;",
-        "",
-        "@Module",
-        "final class BazModule {",
-        "  @Provides Baz provideBaz() {return new Baz();}",
-        "}");
-
-    CompilerTests.daggerCompiler(parent, child, foo, bar, baz, bazModule)
-        .withProcessingOptions(compilerMode.processorOptions())
-        .compile(
-            subject -> {
-              subject.hasErrorCount(1);
-              subject.hasErrorContaining(
-                  "\033[1;31m[Dagger/MissingBinding]\033[0m Baz cannot be provided without an "
-                    + "@Inject constructor or an @Provides-annotated method.");
-              subject.hasErrorContaining("A binding for Baz exists in Child:");
-              subject.hasErrorContaining("    Baz is injected at");
-              subject.hasErrorContaining("        [Parent] Bar(baz)");
-              subject.hasErrorContaining("    Bar is requested at");
-              subject.hasErrorContaining("        [Parent] Parent.bar()");
-              subject.hasErrorContaining("The following other entry points also depend on it:");
-              subject.hasErrorContaining("    Parent.foo()");
-              subject.hasErrorContaining("    Child.foo() [Parent → Child]")
-                  .onSource(parent)
-                  .onLineContaining("interface Parent");
-            });
-  }
-
-  @Test
-  public void missingBindingInSiblingComponent() {
-    Source parent =
-        CompilerTests.javaSource(
-            "Parent",
-            "import dagger.Component;",
-            "",
-            "@Component",
-            "interface Parent {",
-            "  Foo foo();",
-            "  Bar bar();",
-            "  Child1 child1();",
-            "  Child2 child2();",
-            "}");
-    Source child1 =
-        CompilerTests.javaSource(
-            "Child1",
-            "import dagger.Subcomponent;",
-            "",
-            "@Subcomponent",
-            "interface Child1 {",
-            "  Foo foo();",
-            "  Baz baz();",
-            "}");
-    Source child2 =
-        CompilerTests.javaSource(
-            "Child2",
-            "import dagger.Subcomponent;",
-            "",
-            "@Subcomponent(modules = BazModule.class)",
-            "interface Child2 {",
-            "  Foo foo();",
-            "  Baz baz();",
-            "}");
-    Source foo =
-        CompilerTests.javaSource(
-            "Foo",
-            "import javax.inject.Inject;",
-            "",
-            "class Foo {",
-            "  @Inject Foo(Bar bar) {}",
-            "}");
-    Source bar =
-        CompilerTests.javaSource(
-            "Bar",
-            "import javax.inject.Inject;",
-            "",
-            "class Bar {",
-            "  @Inject Bar(Baz baz) {}",
-            "}");
-    Source baz = CompilerTests.javaSource("Baz", "class Baz {}");
-    Source bazModule =
-        CompilerTests.javaSource(
-        "BazModule",
-        "import dagger.Module;",
-        "import dagger.Provides;",
-        "import javax.inject.Inject;",
-        "",
-        "@Module",
-        "final class BazModule {",
-        "  @Provides Baz provideBaz() {return new Baz();}",
-        "}");
-
-    CompilerTests.daggerCompiler(parent, child1, child2, foo, bar, baz, bazModule)
-        .withProcessingOptions(compilerMode.processorOptions())
-        .compile(
-            subject -> {
-              subject.hasErrorCount(1);
-              subject.hasErrorContaining(
-                  "\033[1;31m[Dagger/MissingBinding]\033[0m Baz cannot be provided without an "
-                      + "@Inject constructor or an @Provides-annotated method.");
-              subject.hasErrorContaining("A binding for Baz exists in Child2:");
-              subject.hasErrorContaining("    Baz is injected at");
-              subject.hasErrorContaining("        [Parent] Bar(baz)");
-              subject.hasErrorContaining("    Bar is requested at");
-              subject.hasErrorContaining("        [Parent] Parent.bar()");
-              subject.hasErrorContaining("The following other entry points also depend on it:");
-              subject.hasErrorContaining("    Parent.foo()");
-              subject.hasErrorContaining("    Child1.foo() [Parent → Child1]");
-              subject.hasErrorContaining("    Child2.foo() [Parent → Child2]");
-              subject.hasErrorContaining("    Child1.baz() [Parent → Child1]")
-                  .onSource(parent)
-                  .onLineContaining("interface Parent");
-            });
-  }
-}
diff --git a/javatests/dagger/internal/codegen/MissingBindingValidationTest.java b/javatests/dagger/internal/codegen/MissingBindingValidationTest.java
index 919700e..8250861 100644
--- a/javatests/dagger/internal/codegen/MissingBindingValidationTest.java
+++ b/javatests/dagger/internal/codegen/MissingBindingValidationTest.java
@@ -18,6 +18,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import androidx.room.compiler.processing.XProcessingEnv;
 import androidx.room.compiler.processing.util.DiagnosticMessage;
 import androidx.room.compiler.processing.util.Source;
 import com.google.common.collect.ImmutableList;
@@ -348,18 +349,21 @@
             subject -> {
               subject.hasErrorCount(1);
               subject.hasErrorContaining(
-                  "TestClass.A cannot be provided without an @Provides-annotated method.");
-              subject.hasErrorContaining("    TestClass.A is injected at");
-              subject.hasErrorContaining("        TestClass.B(a)");
-              subject.hasErrorContaining("    TestClass.B is injected at");
-              subject.hasErrorContaining("        TestClass.C.b");
-              subject.hasErrorContaining("    TestClass.C is injected at");
-              subject.hasErrorContaining("        TestClass.AComponent.injectC(TestClass.C)");
-              subject.hasErrorContaining("The following other entry points also depend on it:");
-              subject.hasErrorContaining("    TestClass.AComponent.getFoo()");
-              subject.hasErrorContaining("    TestClass.AComponent.cProvider()");
-              subject.hasErrorContaining("    TestClass.AComponent.lazyC()");
-              subject.hasErrorContaining("    TestClass.AComponent.lazyCProvider()")
+                  String.join(
+                      "\n",
+                      "TestClass.A cannot be provided without an @Provides-annotated method.",
+                      "",
+                      "    TestClass.A is injected at",
+                      "        [TestClass.AComponent] TestClass.B(a)",
+                      "    TestClass.B is injected at",
+                      "        [TestClass.AComponent] TestClass.C.b",
+                      "    TestClass.C is injected at",
+                      "        [TestClass.AComponent] TestClass.AComponent.injectC(TestClass.C)",
+                      "The following other entry points also depend on it:",
+                      "    TestClass.AComponent.getFoo()",
+                      "    TestClass.AComponent.cProvider()",
+                      "    TestClass.AComponent.lazyC()",
+                      "    TestClass.AComponent.lazyCProvider()"))
                   .onSource(component)
                   .onLineContaining("interface AComponent");
             });
@@ -403,14 +407,17 @@
             subject -> {
               subject.hasErrorCount(1);
               subject.hasErrorContaining(
-                  "String cannot be provided without an @Inject constructor or an "
-                      + "@Provides-annotated method.");
-              subject.hasErrorContaining("    String is injected at");
-              subject.hasErrorContaining("        TestImplementation(missingBinding)");
-              subject.hasErrorContaining("    TestImplementation is injected at");
-              subject.hasErrorContaining("        TestModule.bindTestInterface(implementation)");
-              subject.hasErrorContaining("    TestInterface is requested at");
-              subject.hasErrorContaining("        TestComponent.testInterface()")
+                  String.join(
+                      "\n",
+                      "String cannot be provided without an @Inject constructor or an "
+                          + "@Provides-annotated method.",
+                      "",
+                      "    String is injected at",
+                      "        [TestComponent] TestImplementation(missingBinding)",
+                      "    TestImplementation is injected at",
+                      "        [TestComponent] TestModule.bindTestInterface(implementation)",
+                      "    TestInterface is requested at",
+                      "        [TestComponent] TestComponent.testInterface()"))
                   .onSource(component)
                   .onLineContaining("interface TestComponent");
             });
@@ -463,15 +470,18 @@
             subject -> {
               subject.hasErrorCount(1);
               subject.hasErrorContaining(
-                  "List cannot be provided without an @Provides-annotated method.");
-              subject.hasErrorContaining("    List is injected at");
-              subject.hasErrorContaining("        TestClass(list)");
-              subject.hasErrorContaining("    TestClass is injected at");
-              subject.hasErrorContaining("        Generic(t)");
-              subject.hasErrorContaining("    Generic<TestClass> is injected at");
-              subject.hasErrorContaining("        UsesTest(genericTestClass)");
-              subject.hasErrorContaining("    UsesTest is requested at");
-              subject.hasErrorContaining("        TestComponent.usesTest()");
+                  String.join(
+                      "\n",
+                      "List cannot be provided without an @Provides-annotated method.",
+                      "",
+                      "    List is injected at",
+                      "        [TestComponent] TestClass(list)",
+                      "    TestClass is injected at",
+                      "        [TestComponent] Generic(t)",
+                      "    Generic<TestClass> is injected at",
+                      "        [TestComponent] UsesTest(genericTestClass)",
+                      "    UsesTest is requested at",
+                      "        [TestComponent] TestComponent.usesTest()"));
             });
   }
 
@@ -527,15 +537,18 @@
             subject -> {
               subject.hasErrorCount(1);
               subject.hasErrorContaining(
-                  "List cannot be provided without an @Provides-annotated method.");
-              subject.hasErrorContaining("    List is injected at");
-              subject.hasErrorContaining("        TestClass(list)");
-              subject.hasErrorContaining("    TestClass is injected at");
-              subject.hasErrorContaining("        Generic.t");
-              subject.hasErrorContaining("    Generic<TestClass> is injected at");
-              subject.hasErrorContaining("        UsesTest(genericTestClass)");
-              subject.hasErrorContaining("    UsesTest is requested at");
-              subject.hasErrorContaining("        TestComponent.usesTest()");
+                  String.join(
+                      "\n",
+                      "List cannot be provided without an @Provides-annotated method.",
+                      "",
+                      "    List is injected at",
+                      "        [TestComponent] TestClass(list)",
+                      "    TestClass is injected at",
+                      "        [TestComponent] Generic.t",
+                      "    Generic<TestClass> is injected at",
+                      "        [TestComponent] UsesTest(genericTestClass)",
+                      "    UsesTest is requested at",
+                      "        [TestComponent] TestComponent.usesTest()"));
             });
   }
 
@@ -669,16 +682,19 @@
               subject.hasErrorCount(1);
               // TODO(b/243720787): Replace with CompilationResultSubject#hasErrorContainingMatch()
               subject.hasErrorContaining(
-                  "Double cannot be provided without an @Inject constructor or an "
-                      + "@Provides-annotated method.");
-              subject.hasErrorContaining("Double is injected at");
-              subject.hasErrorContaining("    ParentModule.missingDependency(dub)");
-              subject.hasErrorContaining("Integer is injected at");
-              subject.hasErrorContaining("    ChildModule.contributesToSet(i)");
-              subject.hasErrorContaining("Set<String> is injected at");
-              subject.hasErrorContaining("    ParentModule.dependsOnSet(strings)");
-              subject.hasErrorContaining("Object is requested at");
-              subject.hasErrorContaining("    Grandchild.object() [Parent → Child → Grandchild]")
+                  String.join(
+                      "\n",
+                      "Double cannot be provided without an @Inject constructor or an "
+                          + "@Provides-annotated method.",
+                      "",
+                      "    Double is injected at",
+                      "        [Parent] ParentModule.missingDependency(dub)",
+                      "    Integer is injected at",
+                      "        [Child] ChildModule.contributesToSet(i)",
+                      "    Set<String> is injected at",
+                      "        [Child] ParentModule.dependsOnSet(strings)",
+                      "    Object is requested at",
+                      "        [Grandchild] Grandchild.object() [Parent → Child → Grandchild]"))
                   .onSource(parent)
                   .onLineContaining("interface Parent");
             });
@@ -727,16 +743,18 @@
             subject -> {
               subject.hasErrorCount(1);
               subject.hasErrorContaining(
-                  "\033[1;31m[Dagger/MissingBinding]\033[0m "
-                      + "NotBound cannot be provided without an @Provides-annotated method.");
-              subject.hasErrorContaining("    NotBound is injected at");
-              subject.hasErrorContaining("        TestModule.object(notBound)");
-              subject.hasErrorContaining("    Object is requested at");
-              subject.hasErrorContaining("        TestComponent.object()");
-              subject.hasErrorContaining("It is also requested at:");
-              subject.hasErrorContaining("    TestModule.string(notBound, …)");
-              subject.hasErrorContaining("The following other entry points also depend on it:");
-              subject.hasErrorContaining("    TestComponent.string()")
+                  String.join(
+                      "\n",
+                      "NotBound cannot be provided without an @Provides-annotated method.",
+                      "",
+                      "    NotBound is injected at",
+                      "        [TestComponent] TestModule.object(notBound)",
+                      "    Object is requested at",
+                      "        [TestComponent] TestComponent.object()",
+                      "It is also requested at:",
+                      "    TestModule.string(notBound, …)",
+                      "The following other entry points also depend on it:",
+                      "    TestComponent.string()"))
                   .onSource(component)
                   .onLineContaining("interface TestComponent");
             });
@@ -787,22 +805,27 @@
             subject -> {
               subject.hasErrorCount(1);
               subject.hasErrorContaining(
-                  "\033[1;31m[Dagger/MissingBinding]\033[0m String cannot be provided without an "
-                      + "@Inject constructor or an @Provides-annotated method.");
-              subject.hasErrorContaining("    String is requested at");
-              subject.hasErrorContaining("        TestComponent.string()");
-              subject.hasErrorContaining("It is also requested at:");
-              subject.hasErrorContaining("    Foo(one, …)");
-              subject.hasErrorContaining("    Foo(…, two, …)");
-              subject.hasErrorContaining("    Foo(…, three, …)");
-              subject.hasErrorContaining("    Foo(…, four, …)");
-              subject.hasErrorContaining("    Foo(…, five, …)");
-              subject.hasErrorContaining("    Foo(…, six, …)");
-              subject.hasErrorContaining("    Foo(…, seven, …)");
-              subject.hasErrorContaining("    Foo(…, eight, …)");
-              subject.hasErrorContaining("    Foo(…, nine, …)");
-              subject.hasErrorContaining("    Foo(…, ten, …)");
-              subject.hasErrorContaining("    and 3 others")
+                  String.join(
+                      "\n",
+                      "String cannot be provided without an @Inject constructor or an "
+                          + "@Provides-annotated method.",
+                      "",
+                      "    String is requested at",
+                      "        [TestComponent] TestComponent.string()",
+                      "It is also requested at:",
+                      "    Foo(one, …)",
+                      "    Foo(…, two, …)",
+                      "    Foo(…, three, …)",
+                      "    Foo(…, four, …)",
+                      "    Foo(…, five, …)",
+                      "    Foo(…, six, …)",
+                      "    Foo(…, seven, …)",
+                      "    Foo(…, eight, …)",
+                      "    Foo(…, nine, …)",
+                      "    Foo(…, ten, …)",
+                      "    and 3 others",
+                      "The following other entry points also depend on it:",
+                      "    TestComponent.foo()"))
                   .onSource(component)
                   .onLineContaining("interface TestComponent");
             });
@@ -839,22 +862,25 @@
             subject -> {
               subject.hasErrorCount(1);
               subject.hasErrorContaining(
-                  "\033[1;31m[Dagger/MissingBinding]\033[0m String cannot be provided without an "
-                      + "@Inject constructor or an @Provides-annotated method.");
-              subject.hasErrorContaining("    String is requested at");
-              subject.hasErrorContaining("        TestComponent.string1()");
-              subject.hasErrorContaining("The following other entry points also depend on it:");
-              subject.hasErrorContaining("    TestComponent.string2()");
-              subject.hasErrorContaining("    TestComponent.string3()");
-              subject.hasErrorContaining("    TestComponent.string4()");
-              subject.hasErrorContaining("    TestComponent.string5()");
-              subject.hasErrorContaining("    TestComponent.string6()");
-              subject.hasErrorContaining("    TestComponent.string7()");
-              subject.hasErrorContaining("    TestComponent.string8()");
-              subject.hasErrorContaining("    TestComponent.string9()");
-              subject.hasErrorContaining("    TestComponent.string10()");
-              subject.hasErrorContaining("    TestComponent.string11()");
-              subject.hasErrorContaining("    and 1 other")
+                  String.join(
+                      "\n",
+                      "String cannot be provided without an @Inject constructor or an "
+                          + "@Provides-annotated method.",
+                      "",
+                      "    String is requested at",
+                      "        [TestComponent] TestComponent.string1()",
+                      "The following other entry points also depend on it:",
+                      "    TestComponent.string2()",
+                      "    TestComponent.string3()",
+                      "    TestComponent.string4()",
+                      "    TestComponent.string5()",
+                      "    TestComponent.string6()",
+                      "    TestComponent.string7()",
+                      "    TestComponent.string8()",
+                      "    TestComponent.string9()",
+                      "    TestComponent.string10()",
+                      "    TestComponent.string11()",
+                      "    and 1 other"))
                   .onSource(component)
                   .onLineContaining("interface TestComponent");
             });
@@ -908,16 +934,19 @@
             subject -> {
               subject.hasErrorCount(1);
               subject.hasErrorContaining(
-                  "\033[1;31m[Dagger/MissingBinding]\033[0m Baz cannot be provided without an "
-                      + "@Inject constructor or an @Provides-annotated method.");
-              subject.hasErrorContaining("    Baz is injected at");
-              subject.hasErrorContaining("        Bar(baz)");
-              subject.hasErrorContaining("    Bar is requested at");
-              subject.hasErrorContaining("        Parent.bar()");
-              subject.hasErrorContaining("The following other entry points also depend on it:");
-              subject.hasErrorContaining("    Parent.foo()");
-              subject.hasErrorContaining("    Child.foo() [Parent → Child]");
-              subject.hasErrorContaining("    Child.baz() [Parent → Child]")
+                  String.join(
+                      "\n",
+                      "Baz cannot be provided without an @Inject constructor or an "
+                          + "@Provides-annotated method.",
+                      "",
+                      "    Baz is injected at",
+                      "        [Parent] Bar(baz)",
+                      "    Bar is requested at",
+                      "        [Parent] Parent.bar()",
+                      "The following other entry points also depend on it:",
+                      "    Parent.foo()",
+                      "    Child.foo() [Parent → Child]",
+                      "    Child.baz() [Parent → Child]"))
                   .onSource(parent)
                   .onLineContaining("interface Parent");
             });
@@ -1061,9 +1090,14 @@
               subject.hasErrorContaining(
                   String.join(
                       "\n",
-                      "A binding for Object exists in Child2:",
-                      "Object is requested at",
-                      "[Child1] Child1.getObject() [Parent → Child1]"));
+                      "Object cannot be provided without an @Inject constructor or an "
+                          + "@Provides-annotated method.",
+                      "",
+                      "    Object is requested at",
+                      "        [Child1] Child1.getObject() [Parent → Child1]",
+                      "",
+                      "Note: Object is provided in the following other components:",
+                      "    [Child2] Child2Module.provideObject()"));
             });
   }
 
@@ -1174,10 +1208,17 @@
             subject -> {
               subject.hasErrorCount(1);
               subject.hasErrorContaining(
-                  "A binding for Object exists in [Parent → Child2 → RepeatedSub]:");
-              subject.hasErrorContaining(
-                  "[Parent → Child1 → RepeatedSub] RepeatedSub.getObject() [Parent → Child1 →"
-                      + " RepeatedSub]");
+                  String.join(
+                      "\n",
+                      "Object cannot be provided without an @Inject constructor or an "
+                          + "@Provides-annotated method.",
+                      "",
+                      "    Object is requested at",
+                      "        [RepeatedSub] RepeatedSub.getObject() "
+                          + "[Parent → Child1 → RepeatedSub]",
+                      "",
+                      "Note: Object is provided in the following other components:",
+                      "    [Child2] Child2Module.provideObject(…)"));
             });
   }
 
@@ -1298,9 +1339,17 @@
         .compile(
             subject -> {
               subject.hasErrorCount(1);
-              subject.hasErrorContaining("A binding for Object exists in bar.Sub:");
               subject.hasErrorContaining(
-                  "[foo.Sub] foo.Sub.getObject() [Parent → Child1 → foo.Sub]");
+                  String.join(
+                      "\n",
+                      "Object cannot be provided without an @Inject constructor or an "
+                          + "@Provides-annotated method.",
+                      "",
+                      "    Object is requested at",
+                      "        [Sub] Sub.getObject() [Parent → Child1 → Sub]",
+                      "",
+                      "Note: Object is provided in the following other components:",
+                      "    [Child2] Child2Module.provideObject(…)"));
             });
   }
 
@@ -1384,11 +1433,25 @@
             subject -> {
               subject.hasErrorCount(1);
               subject
-                  .hasErrorContaining("Found similar bindings:")
+                  .hasErrorContaining(
+                      String.join(
+                          "\n",
+                          "Set<? extends Bar> cannot be provided without an @Provides-annotated "
+                              + "method.",
+                          "",
+                          "    Set<? extends Bar> is injected at",
+                          "        [MyComponent] Foo(bar)",
+                          "    Foo is requested at",
+                          "        [MyComponent] MyComponent.getFoo()",
+                          "",
+                          "Note: Set<? extends Bar> is provided in the following other components:",
+                          "    [Child] ChildModule.provideBar()",
+                          "",
+                          "Note: A similar binding is provided in the following other components:",
+                          "    Set<Bar> is provided at:",
+                          "        [MyComponent] Dagger-generated binding for Set<Bar>"))
                   .onSource(component)
                   .onLineContaining("interface MyComponent");
-              subject.hasErrorContaining("Set<Bar> in [MyComponent");
-              subject.hasErrorContaining("Set<? extends Bar> in [MyComponent → Child]");
             });
   }
 
@@ -1443,7 +1506,20 @@
             subject -> {
               subject.hasErrorCount(1);
               subject
-                  .hasErrorContaining("Set<Bar> in [MyComponent]")
+                  .hasErrorContaining(
+                      String.join(
+                          "\n",
+                          "Set<? extends Bar> cannot be provided without an @Provides-annotated "
+                              + "method.",
+                          "",
+                          "    Set<? extends Bar> is injected at",
+                          "        [MyComponent] Foo(bar)",
+                          "    Foo is requested at",
+                          "        [MyComponent] MyComponent.getFoo()",
+                          "",
+                          "Note: A similar binding is provided in the following other components:",
+                          "    Set<Bar> is provided at:",
+                          "        [MyComponent] Dagger-generated binding for Set<Bar>"))
                   .onSource(component)
                   .onLineContaining("interface MyComponent");
             });
@@ -1503,10 +1579,22 @@
             subject -> {
               subject.hasErrorCount(1);
               subject
-                  .hasErrorContaining("Found similar bindings:")
+                  .hasErrorContaining(
+                      String.join(
+                          "\n",
+                          "Set<? extends Bar> cannot be provided without an @Provides-annotated "
+                              + "method.",
+                          "",
+                          "    Set<? extends Bar> is injected at",
+                          "        [MyComponent] Foo.bar",
+                          "    Foo is requested at",
+                          "        [MyComponent] MyComponent.getFoo()",
+                          "",
+                          "Note: A similar binding is provided in the following other components:",
+                          "    Set<Bar> is provided at:",
+                          "        [MyComponent] Dagger-generated binding for Set<Bar>"))
                   .onSource(component)
                   .onLineContaining("interface MyComponent");
-              subject.hasErrorContaining("Set<Bar> in [MyComponent]");
             });
   }
 
@@ -1554,10 +1642,21 @@
             subject -> {
               subject.hasErrorCount(1);
               subject
-                  .hasErrorContaining("Found similar bindings:")
+                  .hasErrorContaining(
+                      String.join(
+                          "\n",
+                          "List<Bar> cannot be provided without an @Provides-annotated method.",
+                          "",
+                          "    List<Bar> is injected at",
+                          "        [MyComponent] Foo(bar)",
+                          "    Foo is requested at",
+                          "        [MyComponent] MyComponent.getFoo()",
+                          "",
+                          "Note: A similar binding is provided in the following other components:",
+                          "    List<? extends Bar> is provided at:",
+                          "        [MyComponent] TestModule.provideBars()"))
                   .onSource(component)
                   .onLineContaining("interface MyComponent");
-              subject.hasErrorContaining("List<? extends Bar> in [MyComponent]");
             });
   }
 
@@ -1613,7 +1712,24 @@
             subject -> {
               subject.hasErrorCount(1);
               subject
-                  .hasErrorContaining("Bar<Baz,Baz,Set<Baz>> in [MyComponent]")
+                  .hasErrorContaining(
+                      String.join(
+                          "\n",
+                          // TODO(b/324325095): Align KSP and KAPT error message.
+                          CompilerTests.backend(subject) == XProcessingEnv.Backend.KSP
+                              ? "Bar<? extends Baz,Baz,Set<Baz>> cannot be provided without an "
+                                  + "@Inject constructor or an @Provides-annotated method."
+                              : "Bar<? extends Baz,Baz,Set<Baz>> cannot be provided without an "
+                                  + "@Provides-annotated method.",
+                          "",
+                          "    Bar<? extends Baz,Baz,Set<Baz>> is injected at",
+                          "        [MyComponent] Foo(bar)",
+                          "    Foo is requested at",
+                          "        [MyComponent] MyComponent.getFoo()",
+                          "",
+                          "Note: A similar binding is provided in the following other components:",
+                          "    Bar<Baz,Baz,Set<Baz>> is provided at:",
+                          "        [MyComponent] TestModule.provideBar()"))
                   .onSource(component)
                   .onLineContaining("interface MyComponent");
             });
@@ -1733,8 +1849,23 @@
         .compile(
             subject -> {
               subject.hasErrorCount(1);
-              subject.hasErrorContaining("Found similar bindings:");
-              subject.hasErrorContaining("Bar in [MyComponent]");
+              subject.hasErrorContaining(
+                  String.join(
+                      "\n",
+                      // TODO(b/324325095): Align KSP and KAPT error message.
+                      CompilerTests.backend(subject) == XProcessingEnv.Backend.KSP
+                          ? "Bar<?> cannot be provided without an @Inject constructor or an "
+                              + "@Provides-annotated method."
+                          : "Bar<?> cannot be provided without an @Provides-annotated method.",
+                      "",
+                      "    Bar<?> is injected at",
+                      "        [MyComponent] Foo(bar)",
+                      "    Foo is requested at",
+                      "        [MyComponent] MyComponent.getFoo()",
+                      "",
+                      "Note: A similar binding is provided in the following other components:",
+                      "    Bar is provided at:",
+                      "        [MyComponent] TestModule.provideBar()"));
             });
   }
 
diff --git a/javatests/dagger/internal/codegen/ProductionComponentProcessorTest.java b/javatests/dagger/internal/codegen/ProductionComponentProcessorTest.java
index b9758c1..39e63c9 100644
--- a/javatests/dagger/internal/codegen/ProductionComponentProcessorTest.java
+++ b/javatests/dagger/internal/codegen/ProductionComponentProcessorTest.java
@@ -202,6 +202,51 @@
   }
 
   @Test
+  public void dependsOnProductionSubcomponentWithPluginsVisitFullBindingGraphs() throws Exception {
+    Source myComponent =
+        CompilerTests.javaSource(
+            "test.MyComponent",
+            "package test;",
+            "",
+            "import dagger.Component;",
+            "",
+            "@Component(modules = MyModule.class)",
+            "interface MyComponent {}");
+    Source myModule =
+        CompilerTests.javaSource(
+            "test.MyModule",
+            "package test;",
+            "",
+            "import dagger.Component;",
+            "import dagger.Module;",
+            "",
+            "@Module(subcomponents = MyProductionSubcomponent.class)",
+            "interface MyModule {}");
+    Source myProductionSubcomponent =
+        CompilerTests.javaSource(
+            "test.MyProductionSubcomponent",
+            "package test;",
+            "",
+            "import dagger.producers.ProductionSubcomponent;",
+            "",
+            "@ProductionSubcomponent",
+            "interface MyProductionSubcomponent {",
+            "  @ProductionSubcomponent.Builder",
+            "  interface Builder {",
+            "    MyProductionSubcomponent build();",
+            "  }",
+            "}");
+
+    CompilerTests.daggerCompiler(myComponent, myModule, myProductionSubcomponent)
+        .withProcessingOptions(
+            ImmutableMap.<String, String>builder()
+                .putAll(compilerMode.processorOptions())
+                .put("dagger.pluginsVisitFullBindingGraphs", "ENABLED")
+                .buildOrThrow())
+        .compile(subject -> subject.hasErrorCount(0));
+  }
+
+  @Test
   public void simpleComponent() throws Exception {
     Source component =
         CompilerTests.javaSource(
diff --git a/javatests/dagger/internal/codegen/ProductionGraphValidationTest.java b/javatests/dagger/internal/codegen/ProductionGraphValidationTest.java
index 1b0b85b..cfcf8ee 100644
--- a/javatests/dagger/internal/codegen/ProductionGraphValidationTest.java
+++ b/javatests/dagger/internal/codegen/ProductionGraphValidationTest.java
@@ -195,14 +195,11 @@
                 .buildOrThrow())
         .compile(
             subject -> {
-              subject.hasErrorCount(2);
+              subject.hasErrorCount(1);
               subject.hasErrorContaining(
                       "TestClass.A is a provision, which cannot depend on a production.")
                   .onSource(component)
                   .onLineContaining("class AModule");
-              subject.hasErrorContaining("test.TestClass.AModule has errors")
-                  .onSource(component)
-                  .onLineContaining("@ProductionComponent");
             });
   }
 
diff --git a/javatests/dagger/internal/codegen/bindinggraphvalidation/NullableBindingValidationKotlinTest.java b/javatests/dagger/internal/codegen/bindinggraphvalidation/NullableBindingValidationKotlinTest.java
index 6b63b7c..4b49e16 100644
--- a/javatests/dagger/internal/codegen/bindinggraphvalidation/NullableBindingValidationKotlinTest.java
+++ b/javatests/dagger/internal/codegen/bindinggraphvalidation/NullableBindingValidationKotlinTest.java
@@ -18,7 +18,6 @@
 
 import static dagger.internal.codegen.bindinggraphvalidation.NullableBindingValidator.nullableToNonNullable;
 
-import androidx.room.compiler.processing.XProcessingEnv;
 import androidx.room.compiler.processing.util.Source;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
@@ -83,12 +82,7 @@
               subject.hasErrorContaining(
                   nullableToNonNullable(
                       "String",
-                      CompilerTests.backend(subject) == XProcessingEnv.Backend.JAVAC
-                          ? "@Nullable @Provides String TestModule.provideString()"
-                          // TODO(b/268550160): For KSP, we should be including the kotlin typename
-                          // in the error message, e.g. "String?" otherwise the message doesn't make
-                          // a lot of sense.
-                          : "@Provides String TestModule.provideString()"));
+                      "@Provides @Nullable String TestModule.provideString()"));
             });
 
     // but if we disable the validation, then it compiles fine.
@@ -144,12 +138,7 @@
               subject.hasErrorContaining(
                   nullableToNonNullable(
                       "String",
-                      CompilerTests.backend(subject) == XProcessingEnv.Backend.JAVAC
-                          ? "@Nullable @Provides String TestModule.provideString()"
-                          // TODO(b/268550160): For KSP, we should be including the kotlin typename
-                          // in the error message, e.g. "String?" otherwise the message doesn't make
-                          // a lot of sense.
-                          : "@Provides String TestModule.provideString()"));
+                      "@Provides @Nullable String TestModule.provideString()"));
             });
 
     // but if we disable the validation, then it compiles fine.
@@ -205,12 +194,7 @@
               subject.hasErrorContaining(
                   nullableToNonNullable(
                       "String",
-                      CompilerTests.backend(subject) == XProcessingEnv.Backend.JAVAC
-                          ? "@Nullable @Provides String TestModule.provideString()"
-                          // TODO(b/268550160): For KSP, we should be including the kotlin typename
-                          // in the error message, e.g. "String?" otherwise the message doesn't make
-                          // a lot of sense.
-                          : "@Provides String TestModule.provideString()"));
+                      "@Provides @Nullable String TestModule.provideString()"));
             });
 
     // but if we disable the validation, then it compiles fine.
@@ -255,12 +239,7 @@
               subject.hasErrorContaining(
                   nullableToNonNullable(
                       "String",
-                      CompilerTests.backend(subject) == XProcessingEnv.Backend.JAVAC
-                          ? "@Nullable @Provides String TestModule.provideString()"
-                          // TODO(b/268550160): For KSP, we should be including the kotlin typename
-                          // in the error message, e.g. "String?" otherwise the message doesn't make
-                          // a lot of sense.
-                          : "@Provides String TestModule.provideString()"));
+                      "@Provides @Nullable String TestModule.provideString()"));
             });
 
     // but if we disable the validation, then it compiles fine.
@@ -320,12 +299,7 @@
               subject.hasErrorContaining(
                   nullableToNonNullable(
                       "String",
-                      CompilerTests.backend(subject) == XProcessingEnv.Backend.JAVAC
-                          ? "@Nullable @Provides String TestModule.Companion.provideString()"
-                          // TODO(b/268550160): For KSP, we should be including the kotlin typename
-                          // in the error message, e.g. "String?" otherwise the message doesn't make
-                          // a lot of sense.
-                          : "@Provides String TestModule.Companion.provideString()"));
+                      "@Provides @Nullable String TestModule.Companion.provideString()"));
             });
   }
 
@@ -496,12 +470,7 @@
               subject.hasErrorContaining(
                   nullableToNonNullable(
                       "String",
-                      CompilerTests.backend(subject) == XProcessingEnv.Backend.JAVAC
-                          ? "@Nullable @Provides String TestModule.Companion.nullableString()"
-                          // TODO(b/268550160): For KSP, we should be including the kotlin typename
-                          // in the error message, e.g. "String?" otherwise the message doesn't make
-                          // a lot of sense.
-                          : "@Provides String TestModule.Companion.nullableString()"));
+                      "@Provides @Nullable String TestModule.Companion.nullableString()"));
             });
   }
 }
diff --git a/javatests/dagger/internal/codegen/bindinggraphvalidation/SetMultibindingValidationTest.java b/javatests/dagger/internal/codegen/bindinggraphvalidation/SetMultibindingValidationTest.java
index 8eaccae..e68099a 100644
--- a/javatests/dagger/internal/codegen/bindinggraphvalidation/SetMultibindingValidationTest.java
+++ b/javatests/dagger/internal/codegen/bindinggraphvalidation/SetMultibindingValidationTest.java
@@ -95,6 +95,85 @@
             });
   }
 
+  // Regression test for b/316582741 to ensure the duplicate binding gets reported rather than
+  // causing a crash.
+  @Test public void testSetBindingsToDuplicateBinding() {
+    Source module =
+        CompilerTests.javaSource(
+            "test.TestModule",
+            "package test;",
+            "",
+            "import dagger.Binds;",
+            "import dagger.Module;",
+            "import dagger.Provides;",
+            "import dagger.multibindings.IntoSet;",
+            "",
+            "@Module",
+            "interface TestModule {",
+            "  @Binds @IntoSet Foo bindFoo(FooImpl impl);",
+            "",
+            "  @Provides static FooImpl provideFooImpl() { return null; }",
+            "",
+            "  @Provides static FooImpl provideFooImplAgain() { return null; }",
+            "}");
+    Source component =
+        CompilerTests.javaSource(
+            "test.TestComponent",
+            "package test;",
+            "",
+            "import dagger.Component;",
+            "import java.util.Set;",
+            "",
+            "@Component(modules = TestModule.class)",
+            "interface TestComponent {",
+            "  Set<Foo> setOfFoo();",
+            "}");
+    CompilerTests.daggerCompiler(FOO, FOO_IMPL, module, component)
+        .withProcessingOptions(compilerMode.processorOptions())
+        .compile(
+            subject -> {
+              subject.hasErrorCount(1);
+              subject.hasErrorContaining("FooImpl is bound multiple times");
+            });
+  }
+
+  @Test public void testSetBindingsToMissingBinding() {
+    Source module =
+        CompilerTests.javaSource(
+            "test.TestModule",
+            "package test;",
+            "",
+            "import dagger.Binds;",
+            "import dagger.Module;",
+            "import dagger.multibindings.IntoSet;",
+            "",
+            "@Module",
+            "interface TestModule {",
+            "  @Binds @IntoSet Foo bindFoo(MissingFooImpl impl);",
+            "",
+            "  static class MissingFooImpl implements Foo {}",
+            "}");
+    Source component =
+        CompilerTests.javaSource(
+            "test.TestComponent",
+            "package test;",
+            "",
+            "import dagger.Component;",
+            "import java.util.Set;",
+            "",
+            "@Component(modules = TestModule.class)",
+            "interface TestComponent {",
+            "  Set<Foo> setOfFoo();",
+            "}");
+    CompilerTests.daggerCompiler(FOO, module, component)
+        .withProcessingOptions(compilerMode.processorOptions())
+        .compile(
+            subject -> {
+              subject.hasErrorCount(1);
+              subject.hasErrorContaining("MissingFooImpl cannot be provided");
+            });
+  }
+
   @Test public void testMultipleSetBindingsToSameFooThroughMultipleBinds() {
     Source module =
         CompilerTests.javaSource(
diff --git a/javatests/dagger/internal/codegen/goldens/AssistedFactoryTest_assistedParamConflictsWithComponentFieldName_successfulyDeduped_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/AssistedFactoryTest_assistedParamConflictsWithComponentFieldName_successfulyDeduped_DEFAULT_MODE_test.DaggerTestComponent
index 20f38dd..ebea812 100644
--- a/javatests/dagger/internal/codegen/goldens/AssistedFactoryTest_assistedParamConflictsWithComponentFieldName_successfulyDeduped_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/AssistedFactoryTest_assistedParamConflictsWithComponentFieldName_successfulyDeduped_DEFAULT_MODE_test.DaggerTestComponent
@@ -1,8 +1,8 @@
 package test;
 
 import dagger.internal.DaggerGenerated;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -52,7 +53,7 @@
     @SuppressWarnings("unchecked")
     private void initialize() {
       this.fooProvider = Foo_Factory.create(Bar_Factory.create());
-      this.fooFactoryProvider = FooFactory_Impl.create(fooProvider);
+      this.fooFactoryProvider = FooFactory_Impl.createFactoryProvider(fooProvider);
     }
 
     @Override
diff --git a/javatests/dagger/internal/codegen/goldens/AssistedFactoryTest_assistedParamConflictsWithComponentFieldName_successfulyDeduped_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/AssistedFactoryTest_assistedParamConflictsWithComponentFieldName_successfulyDeduped_FAST_INIT_MODE_test.DaggerTestComponent
index c76a5fb..f522a42 100644
--- a/javatests/dagger/internal/codegen/goldens/AssistedFactoryTest_assistedParamConflictsWithComponentFieldName_successfulyDeduped_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/AssistedFactoryTest_assistedParamConflictsWithComponentFieldName_successfulyDeduped_FAST_INIT_MODE_test.DaggerTestComponent
@@ -1,9 +1,9 @@
 package test;
 
 import dagger.internal.DaggerGenerated;
+import dagger.internal.Provider;
 import dagger.internal.SingleCheck;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -14,7 +14,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/AssistedFactoryTest_testAssistedFactoryCycle_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/AssistedFactoryTest_testAssistedFactoryCycle_DEFAULT_MODE_test.DaggerTestComponent
index 7b22b00..bdd35a5 100644
--- a/javatests/dagger/internal/codegen/goldens/AssistedFactoryTest_testAssistedFactoryCycle_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/AssistedFactoryTest_testAssistedFactoryCycle_DEFAULT_MODE_test.DaggerTestComponent
@@ -2,8 +2,8 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DelegateFactory;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -14,7 +14,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -57,7 +58,7 @@
       this.fooFactoryProvider = new DelegateFactory<>();
       this.barProvider = Bar_Factory.create(fooFactoryProvider);
       this.fooProvider = Foo_Factory.create(barProvider);
-      DelegateFactory.setDelegate(fooFactoryProvider, FooFactory_Impl.create(fooProvider));
+      DelegateFactory.setDelegate(fooFactoryProvider, FooFactory_Impl.createFactoryProvider(fooProvider));
     }
 
     @Override
diff --git a/javatests/dagger/internal/codegen/goldens/AssistedFactoryTest_testAssistedFactoryCycle_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/AssistedFactoryTest_testAssistedFactoryCycle_FAST_INIT_MODE_test.DaggerTestComponent
index 48f5174..2d5efe6 100644
--- a/javatests/dagger/internal/codegen/goldens/AssistedFactoryTest_testAssistedFactoryCycle_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/AssistedFactoryTest_testAssistedFactoryCycle_FAST_INIT_MODE_test.DaggerTestComponent
@@ -2,9 +2,9 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DelegateFactory;
+import dagger.internal.Provider;
 import dagger.internal.SingleCheck;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -15,7 +15,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/AssistedFactoryTest_testAssistedFactory_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/AssistedFactoryTest_testAssistedFactory_DEFAULT_MODE_test.DaggerTestComponent
index 20f38dd..ebea812 100644
--- a/javatests/dagger/internal/codegen/goldens/AssistedFactoryTest_testAssistedFactory_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/AssistedFactoryTest_testAssistedFactory_DEFAULT_MODE_test.DaggerTestComponent
@@ -1,8 +1,8 @@
 package test;
 
 import dagger.internal.DaggerGenerated;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -52,7 +53,7 @@
     @SuppressWarnings("unchecked")
     private void initialize() {
       this.fooProvider = Foo_Factory.create(Bar_Factory.create());
-      this.fooFactoryProvider = FooFactory_Impl.create(fooProvider);
+      this.fooFactoryProvider = FooFactory_Impl.createFactoryProvider(fooProvider);
     }
 
     @Override
diff --git a/javatests/dagger/internal/codegen/goldens/AssistedFactoryTest_testAssistedFactory_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/AssistedFactoryTest_testAssistedFactory_FAST_INIT_MODE_test.DaggerTestComponent
index 72f1672..db44f08 100644
--- a/javatests/dagger/internal/codegen/goldens/AssistedFactoryTest_testAssistedFactory_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/AssistedFactoryTest_testAssistedFactory_FAST_INIT_MODE_test.DaggerTestComponent
@@ -1,9 +1,9 @@
 package test;
 
 import dagger.internal.DaggerGenerated;
+import dagger.internal.Provider;
 import dagger.internal.SingleCheck;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -14,7 +14,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/AssistedFactoryTest_testFactoryGeneratorDuplicatedParamNames_DEFAULT_MODE_test.Foo_Factory b/javatests/dagger/internal/codegen/goldens/AssistedFactoryTest_testFactoryGeneratorDuplicatedParamNames_DEFAULT_MODE_test.Foo_Factory
index ed8f098..0ae501c 100644
--- a/javatests/dagger/internal/codegen/goldens/AssistedFactoryTest_testFactoryGeneratorDuplicatedParamNames_DEFAULT_MODE_test.Foo_Factory
+++ b/javatests/dagger/internal/codegen/goldens/AssistedFactoryTest_testFactoryGeneratorDuplicatedParamNames_DEFAULT_MODE_test.Foo_Factory
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class Foo_Factory {
   private final Provider<Bar> argProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/AssistedFactoryTest_testFactoryGeneratorDuplicatedParamNames_FAST_INIT_MODE_test.Foo_Factory b/javatests/dagger/internal/codegen/goldens/AssistedFactoryTest_testFactoryGeneratorDuplicatedParamNames_FAST_INIT_MODE_test.Foo_Factory
index ed8f098..0ae501c 100644
--- a/javatests/dagger/internal/codegen/goldens/AssistedFactoryTest_testFactoryGeneratorDuplicatedParamNames_FAST_INIT_MODE_test.Foo_Factory
+++ b/javatests/dagger/internal/codegen/goldens/AssistedFactoryTest_testFactoryGeneratorDuplicatedParamNames_FAST_INIT_MODE_test.Foo_Factory
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class Foo_Factory {
   private final Provider<Bar> argProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/AssistedFactoryTest_testMultipleAssistedFactoryInDifferentComponents_DEFAULT_MODE_test.DaggerMyComponent b/javatests/dagger/internal/codegen/goldens/AssistedFactoryTest_testMultipleAssistedFactoryInDifferentComponents_DEFAULT_MODE_test.DaggerMyComponent
new file mode 100644
index 0000000..b3fc316
--- /dev/null
+++ b/javatests/dagger/internal/codegen/goldens/AssistedFactoryTest_testMultipleAssistedFactoryInDifferentComponents_DEFAULT_MODE_test.DaggerMyComponent
@@ -0,0 +1,98 @@
+package test;
+
+import dagger.internal.DaggerGenerated;
+import dagger.internal.Provider;
+import javax.annotation.processing.Generated;
+
+@DaggerGenerated
+@Generated(
+    value = "dagger.internal.codegen.ComponentProcessor",
+    comments = "https://dagger.dev"
+)
+@SuppressWarnings({
+    "unchecked",
+    "rawtypes",
+    "KotlinInternal",
+    "KotlinInternalInJava",
+    "cast"
+})
+final class DaggerMyComponent {
+  private DaggerMyComponent() {
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public static MyComponent create() {
+    return new Builder().build();
+  }
+
+  static final class Builder {
+    private Builder() {
+    }
+
+    public MyComponent build() {
+      return new MyComponentImpl();
+    }
+  }
+
+  private static final class MySubcomponentImpl implements MySubcomponent {
+    private final MyComponentImpl myComponentImpl;
+
+    private final MySubcomponentImpl mySubcomponentImpl = this;
+
+    private MyAssistedClass_Factory myAssistedClassProvider;
+
+    private Provider<MySubcomponentAssistedFactory> mySubcomponentAssistedFactoryProvider;
+
+    private MySubcomponentImpl(MyComponentImpl myComponentImpl) {
+      this.myComponentImpl = myComponentImpl;
+
+      initialize();
+
+    }
+
+    @SuppressWarnings("unchecked")
+    private void initialize() {
+      this.myAssistedClassProvider = MyAssistedClass_Factory.create(Baz_Factory.create());
+      this.mySubcomponentAssistedFactoryProvider = MySubcomponentAssistedFactory_Impl.createFactoryProvider(myAssistedClassProvider);
+    }
+
+    @Override
+    public MySubcomponentAssistedFactory mySubcomponentAssistedFactory() {
+      return mySubcomponentAssistedFactoryProvider.get();
+    }
+  }
+
+  private static final class MyComponentImpl implements MyComponent {
+    private final MyComponentImpl myComponentImpl = this;
+
+    private MyAssistedClass_Factory myAssistedClassProvider;
+
+    private Provider<MyComponentAssistedFactory> myComponentAssistedFactoryProvider;
+
+    private MyComponentImpl() {
+
+      initialize();
+
+    }
+
+    @SuppressWarnings("unchecked")
+    private void initialize() {
+      this.myAssistedClassProvider = MyAssistedClass_Factory.create(Baz_Factory.create());
+      this.myComponentAssistedFactoryProvider = MyComponentAssistedFactory_Impl.createFactoryProvider(myAssistedClassProvider);
+    }
+
+    @Override
+    public MyComponentAssistedFactory myComponentAssistedFactory() {
+      return myComponentAssistedFactoryProvider.get();
+    }
+
+    @Override
+    public MySubcomponent mySubcomponent() {
+      return new MySubcomponentImpl(myComponentImpl);
+    }
+  }
+}
+
diff --git a/javatests/dagger/internal/codegen/goldens/AssistedFactoryTest_testMultipleAssistedFactoryInDifferentComponents_FAST_INIT_MODE_test.DaggerMyComponent b/javatests/dagger/internal/codegen/goldens/AssistedFactoryTest_testMultipleAssistedFactoryInDifferentComponents_FAST_INIT_MODE_test.DaggerMyComponent
new file mode 100644
index 0000000..68c5a77
--- /dev/null
+++ b/javatests/dagger/internal/codegen/goldens/AssistedFactoryTest_testMultipleAssistedFactoryInDifferentComponents_FAST_INIT_MODE_test.DaggerMyComponent
@@ -0,0 +1,151 @@
+package test;
+
+import dagger.internal.DaggerGenerated;
+import dagger.internal.Provider;
+import dagger.internal.SingleCheck;
+import javax.annotation.processing.Generated;
+
+@DaggerGenerated
+@Generated(
+    value = "dagger.internal.codegen.ComponentProcessor",
+    comments = "https://dagger.dev"
+)
+@SuppressWarnings({
+    "unchecked",
+    "rawtypes",
+    "KotlinInternal",
+    "KotlinInternalInJava",
+    "cast"
+})
+final class DaggerMyComponent {
+  private DaggerMyComponent() {
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public static MyComponent create() {
+    return new Builder().build();
+  }
+
+  static final class Builder {
+    private Builder() {
+    }
+
+    public MyComponent build() {
+      return new MyComponentImpl();
+    }
+  }
+
+  private static final class MySubcomponentImpl implements MySubcomponent {
+    private final MyComponentImpl myComponentImpl;
+
+    private final MySubcomponentImpl mySubcomponentImpl = this;
+
+    private Provider<MySubcomponentAssistedFactory> mySubcomponentAssistedFactoryProvider;
+
+    private MySubcomponentImpl(MyComponentImpl myComponentImpl) {
+      this.myComponentImpl = myComponentImpl;
+
+      initialize();
+
+    }
+
+    @SuppressWarnings("unchecked")
+    private void initialize() {
+      this.mySubcomponentAssistedFactoryProvider = SingleCheck.provider(new SwitchingProvider<MySubcomponentAssistedFactory>(myComponentImpl, mySubcomponentImpl, 0));
+    }
+
+    @Override
+    public MySubcomponentAssistedFactory mySubcomponentAssistedFactory() {
+      return mySubcomponentAssistedFactoryProvider.get();
+    }
+
+    private static final class SwitchingProvider<T> implements Provider<T> {
+      private final MyComponentImpl myComponentImpl;
+
+      private final MySubcomponentImpl mySubcomponentImpl;
+
+      private final int id;
+
+      SwitchingProvider(MyComponentImpl myComponentImpl, MySubcomponentImpl mySubcomponentImpl,
+          int id) {
+        this.myComponentImpl = myComponentImpl;
+        this.mySubcomponentImpl = mySubcomponentImpl;
+        this.id = id;
+      }
+
+      @SuppressWarnings("unchecked")
+      @Override
+      public T get() {
+        switch (id) {
+          case 0: // test.MySubcomponentAssistedFactory 
+          return (T) new MySubcomponentAssistedFactory() {
+            @Override
+            public MyAssistedClass create(Bar bar, Foo foo) {
+              return new MyAssistedClass(foo, new Baz(), bar);
+            }
+          };
+
+          default: throw new AssertionError(id);
+        }
+      }
+    }
+  }
+
+  private static final class MyComponentImpl implements MyComponent {
+    private final MyComponentImpl myComponentImpl = this;
+
+    private Provider<MyComponentAssistedFactory> myComponentAssistedFactoryProvider;
+
+    private MyComponentImpl() {
+
+      initialize();
+
+    }
+
+    @SuppressWarnings("unchecked")
+    private void initialize() {
+      this.myComponentAssistedFactoryProvider = SingleCheck.provider(new SwitchingProvider<MyComponentAssistedFactory>(myComponentImpl, 0));
+    }
+
+    @Override
+    public MyComponentAssistedFactory myComponentAssistedFactory() {
+      return myComponentAssistedFactoryProvider.get();
+    }
+
+    @Override
+    public MySubcomponent mySubcomponent() {
+      return new MySubcomponentImpl(myComponentImpl);
+    }
+
+    private static final class SwitchingProvider<T> implements Provider<T> {
+      private final MyComponentImpl myComponentImpl;
+
+      private final int id;
+
+      SwitchingProvider(MyComponentImpl myComponentImpl, int id) {
+        this.myComponentImpl = myComponentImpl;
+        this.id = id;
+      }
+
+      @SuppressWarnings("unchecked")
+      @Override
+      public T get() {
+        switch (id) {
+          case 0: // test.MyComponentAssistedFactory 
+          return (T) new MyComponentAssistedFactory() {
+            @Override
+            public MyAssistedClass create(Bar bar, Foo foo) {
+              return new MyAssistedClass(foo, new Baz(), bar);
+            }
+          };
+
+          default: throw new AssertionError(id);
+        }
+      }
+    }
+  }
+}
+
diff --git a/javatests/dagger/internal/codegen/goldens/AssistedFactoryTest_testParameterizedAssistParam_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/AssistedFactoryTest_testParameterizedAssistParam_DEFAULT_MODE_test.DaggerTestComponent
index da1f53e..f94d608 100644
--- a/javatests/dagger/internal/codegen/goldens/AssistedFactoryTest_testParameterizedAssistParam_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/AssistedFactoryTest_testParameterizedAssistParam_DEFAULT_MODE_test.DaggerTestComponent
@@ -1,8 +1,8 @@
 package test;
 
 import dagger.internal.DaggerGenerated;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -52,7 +53,7 @@
     @SuppressWarnings("unchecked")
     private void initialize() {
       this.fooProvider = Foo_Factory.create();
-      this.fooFactoryProvider = FooFactory_Impl.create(fooProvider);
+      this.fooFactoryProvider = FooFactory_Impl.createFactoryProvider(fooProvider);
     }
 
     @Override
diff --git a/javatests/dagger/internal/codegen/goldens/AssistedFactoryTest_testParameterizedAssistParam_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/AssistedFactoryTest_testParameterizedAssistParam_FAST_INIT_MODE_test.DaggerTestComponent
index a56b3e0..0726e0f 100644
--- a/javatests/dagger/internal/codegen/goldens/AssistedFactoryTest_testParameterizedAssistParam_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/AssistedFactoryTest_testParameterizedAssistParam_FAST_INIT_MODE_test.DaggerTestComponent
@@ -1,9 +1,9 @@
 package test;
 
 import dagger.internal.DaggerGenerated;
+import dagger.internal.Provider;
 import dagger.internal.SingleCheck;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -14,7 +14,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentBuilderTest_testUsesBuildAndSetterNames_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentBuilderTest_testUsesBuildAndSetterNames_DEFAULT_MODE_test.DaggerTestComponent
index f5524ec..7aed6ce 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentBuilderTest_testUsesBuildAndSetterNames_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentBuilderTest_testUsesBuildAndSetterNames_DEFAULT_MODE_test.DaggerTestComponent
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentBuilderTest_testUsesBuildAndSetterNames_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentBuilderTest_testUsesBuildAndSetterNames_FAST_INIT_MODE_test.DaggerTestComponent
index f5524ec..7aed6ce 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentBuilderTest_testUsesBuildAndSetterNames_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentBuilderTest_testUsesBuildAndSetterNames_FAST_INIT_MODE_test.DaggerTestComponent
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testCanInstantiateModulesUserCannotSet_compilerMode=DEFAULT_MODE, creatorKind=dagger.Component.Builder_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testCanInstantiateModulesUserCannotSet_compilerMode=DEFAULT_MODE, creatorKind=dagger.Component.Builder_test.DaggerTestComponent
index fd3b2dd..384875a 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testCanInstantiateModulesUserCannotSet_compilerMode=DEFAULT_MODE, creatorKind=dagger.Component.Builder_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testCanInstantiateModulesUserCannotSet_compilerMode=DEFAULT_MODE, creatorKind=dagger.Component.Builder_test.DaggerTestComponent
@@ -12,7 +12,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testCanInstantiateModulesUserCannotSet_compilerMode=DEFAULT_MODE, creatorKind=dagger.Component.Factory_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testCanInstantiateModulesUserCannotSet_compilerMode=DEFAULT_MODE, creatorKind=dagger.Component.Factory_test.DaggerTestComponent
index e2e2d93..b4fa619 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testCanInstantiateModulesUserCannotSet_compilerMode=DEFAULT_MODE, creatorKind=dagger.Component.Factory_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testCanInstantiateModulesUserCannotSet_compilerMode=DEFAULT_MODE, creatorKind=dagger.Component.Factory_test.DaggerTestComponent
@@ -12,7 +12,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testCanInstantiateModulesUserCannotSet_compilerMode=FAST_INIT_MODE, creatorKind=dagger.Component.Builder_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testCanInstantiateModulesUserCannotSet_compilerMode=FAST_INIT_MODE, creatorKind=dagger.Component.Builder_test.DaggerTestComponent
index fd3b2dd..384875a 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testCanInstantiateModulesUserCannotSet_compilerMode=FAST_INIT_MODE, creatorKind=dagger.Component.Builder_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testCanInstantiateModulesUserCannotSet_compilerMode=FAST_INIT_MODE, creatorKind=dagger.Component.Builder_test.DaggerTestComponent
@@ -12,7 +12,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testCanInstantiateModulesUserCannotSet_compilerMode=FAST_INIT_MODE, creatorKind=dagger.Component.Factory_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testCanInstantiateModulesUserCannotSet_compilerMode=FAST_INIT_MODE, creatorKind=dagger.Component.Factory_test.DaggerTestComponent
index e2e2d93..b4fa619 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testCanInstantiateModulesUserCannotSet_compilerMode=FAST_INIT_MODE, creatorKind=dagger.Component.Factory_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testCanInstantiateModulesUserCannotSet_compilerMode=FAST_INIT_MODE, creatorKind=dagger.Component.Factory_test.DaggerTestComponent
@@ -12,7 +12,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testCreatorWithBindsInstanceNoStaticCreateGenerated_compilerMode=DEFAULT_MODE, creatorKind=dagger.Component.Builder_test.DaggerSimpleComponent b/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testCreatorWithBindsInstanceNoStaticCreateGenerated_compilerMode=DEFAULT_MODE, creatorKind=dagger.Component.Builder_test.DaggerSimpleComponent
index dd9662b..510db53 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testCreatorWithBindsInstanceNoStaticCreateGenerated_compilerMode=DEFAULT_MODE, creatorKind=dagger.Component.Builder_test.DaggerSimpleComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testCreatorWithBindsInstanceNoStaticCreateGenerated_compilerMode=DEFAULT_MODE, creatorKind=dagger.Component.Builder_test.DaggerSimpleComponent
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerSimpleComponent {
   private DaggerSimpleComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testCreatorWithBindsInstanceNoStaticCreateGenerated_compilerMode=DEFAULT_MODE, creatorKind=dagger.Component.Factory_test.DaggerSimpleComponent b/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testCreatorWithBindsInstanceNoStaticCreateGenerated_compilerMode=DEFAULT_MODE, creatorKind=dagger.Component.Factory_test.DaggerSimpleComponent
index 05ac4a8..c31b4ab 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testCreatorWithBindsInstanceNoStaticCreateGenerated_compilerMode=DEFAULT_MODE, creatorKind=dagger.Component.Factory_test.DaggerSimpleComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testCreatorWithBindsInstanceNoStaticCreateGenerated_compilerMode=DEFAULT_MODE, creatorKind=dagger.Component.Factory_test.DaggerSimpleComponent
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerSimpleComponent {
   private DaggerSimpleComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testCreatorWithBindsInstanceNoStaticCreateGenerated_compilerMode=FAST_INIT_MODE, creatorKind=dagger.Component.Builder_test.DaggerSimpleComponent b/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testCreatorWithBindsInstanceNoStaticCreateGenerated_compilerMode=FAST_INIT_MODE, creatorKind=dagger.Component.Builder_test.DaggerSimpleComponent
index dd9662b..510db53 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testCreatorWithBindsInstanceNoStaticCreateGenerated_compilerMode=FAST_INIT_MODE, creatorKind=dagger.Component.Builder_test.DaggerSimpleComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testCreatorWithBindsInstanceNoStaticCreateGenerated_compilerMode=FAST_INIT_MODE, creatorKind=dagger.Component.Builder_test.DaggerSimpleComponent
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerSimpleComponent {
   private DaggerSimpleComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testCreatorWithBindsInstanceNoStaticCreateGenerated_compilerMode=FAST_INIT_MODE, creatorKind=dagger.Component.Factory_test.DaggerSimpleComponent b/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testCreatorWithBindsInstanceNoStaticCreateGenerated_compilerMode=FAST_INIT_MODE, creatorKind=dagger.Component.Factory_test.DaggerSimpleComponent
index 05ac4a8..c31b4ab 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testCreatorWithBindsInstanceNoStaticCreateGenerated_compilerMode=FAST_INIT_MODE, creatorKind=dagger.Component.Factory_test.DaggerSimpleComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testCreatorWithBindsInstanceNoStaticCreateGenerated_compilerMode=FAST_INIT_MODE, creatorKind=dagger.Component.Factory_test.DaggerSimpleComponent
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerSimpleComponent {
   private DaggerSimpleComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testCreatorWithPrimitiveBindsInstance_compilerMode=DEFAULT_MODE, creatorKind=dagger.Component.Builder_test.DaggerSimpleComponent b/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testCreatorWithPrimitiveBindsInstance_compilerMode=DEFAULT_MODE, creatorKind=dagger.Component.Builder_test.DaggerSimpleComponent
index bbfedd0..77058c3 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testCreatorWithPrimitiveBindsInstance_compilerMode=DEFAULT_MODE, creatorKind=dagger.Component.Builder_test.DaggerSimpleComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testCreatorWithPrimitiveBindsInstance_compilerMode=DEFAULT_MODE, creatorKind=dagger.Component.Builder_test.DaggerSimpleComponent
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerSimpleComponent {
   private DaggerSimpleComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testCreatorWithPrimitiveBindsInstance_compilerMode=DEFAULT_MODE, creatorKind=dagger.Component.Factory_test.DaggerSimpleComponent b/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testCreatorWithPrimitiveBindsInstance_compilerMode=DEFAULT_MODE, creatorKind=dagger.Component.Factory_test.DaggerSimpleComponent
index fb85beb..6583a23 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testCreatorWithPrimitiveBindsInstance_compilerMode=DEFAULT_MODE, creatorKind=dagger.Component.Factory_test.DaggerSimpleComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testCreatorWithPrimitiveBindsInstance_compilerMode=DEFAULT_MODE, creatorKind=dagger.Component.Factory_test.DaggerSimpleComponent
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerSimpleComponent {
   private DaggerSimpleComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testCreatorWithPrimitiveBindsInstance_compilerMode=FAST_INIT_MODE, creatorKind=dagger.Component.Builder_test.DaggerSimpleComponent b/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testCreatorWithPrimitiveBindsInstance_compilerMode=FAST_INIT_MODE, creatorKind=dagger.Component.Builder_test.DaggerSimpleComponent
index bbfedd0..77058c3 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testCreatorWithPrimitiveBindsInstance_compilerMode=FAST_INIT_MODE, creatorKind=dagger.Component.Builder_test.DaggerSimpleComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testCreatorWithPrimitiveBindsInstance_compilerMode=FAST_INIT_MODE, creatorKind=dagger.Component.Builder_test.DaggerSimpleComponent
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerSimpleComponent {
   private DaggerSimpleComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testCreatorWithPrimitiveBindsInstance_compilerMode=FAST_INIT_MODE, creatorKind=dagger.Component.Factory_test.DaggerSimpleComponent b/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testCreatorWithPrimitiveBindsInstance_compilerMode=FAST_INIT_MODE, creatorKind=dagger.Component.Factory_test.DaggerSimpleComponent
index fb85beb..6583a23 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testCreatorWithPrimitiveBindsInstance_compilerMode=FAST_INIT_MODE, creatorKind=dagger.Component.Factory_test.DaggerSimpleComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testCreatorWithPrimitiveBindsInstance_compilerMode=FAST_INIT_MODE, creatorKind=dagger.Component.Factory_test.DaggerSimpleComponent
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerSimpleComponent {
   private DaggerSimpleComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testEmptyCreator_compilerMode=DEFAULT_MODE, creatorKind=dagger.Component.Builder_test.DaggerSimpleComponent b/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testEmptyCreator_compilerMode=DEFAULT_MODE, creatorKind=dagger.Component.Builder_test.DaggerSimpleComponent
index b117ad8..5040a78 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testEmptyCreator_compilerMode=DEFAULT_MODE, creatorKind=dagger.Component.Builder_test.DaggerSimpleComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testEmptyCreator_compilerMode=DEFAULT_MODE, creatorKind=dagger.Component.Builder_test.DaggerSimpleComponent
@@ -12,7 +12,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerSimpleComponent {
   private DaggerSimpleComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testEmptyCreator_compilerMode=DEFAULT_MODE, creatorKind=dagger.Component.Factory_test.DaggerSimpleComponent b/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testEmptyCreator_compilerMode=DEFAULT_MODE, creatorKind=dagger.Component.Factory_test.DaggerSimpleComponent
index 3e078be..10bc365 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testEmptyCreator_compilerMode=DEFAULT_MODE, creatorKind=dagger.Component.Factory_test.DaggerSimpleComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testEmptyCreator_compilerMode=DEFAULT_MODE, creatorKind=dagger.Component.Factory_test.DaggerSimpleComponent
@@ -12,7 +12,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerSimpleComponent {
   private DaggerSimpleComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testEmptyCreator_compilerMode=FAST_INIT_MODE, creatorKind=dagger.Component.Builder_test.DaggerSimpleComponent b/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testEmptyCreator_compilerMode=FAST_INIT_MODE, creatorKind=dagger.Component.Builder_test.DaggerSimpleComponent
index b117ad8..5040a78 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testEmptyCreator_compilerMode=FAST_INIT_MODE, creatorKind=dagger.Component.Builder_test.DaggerSimpleComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testEmptyCreator_compilerMode=FAST_INIT_MODE, creatorKind=dagger.Component.Builder_test.DaggerSimpleComponent
@@ -12,7 +12,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerSimpleComponent {
   private DaggerSimpleComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testEmptyCreator_compilerMode=FAST_INIT_MODE, creatorKind=dagger.Component.Factory_test.DaggerSimpleComponent b/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testEmptyCreator_compilerMode=FAST_INIT_MODE, creatorKind=dagger.Component.Factory_test.DaggerSimpleComponent
index 3e078be..10bc365 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testEmptyCreator_compilerMode=FAST_INIT_MODE, creatorKind=dagger.Component.Factory_test.DaggerSimpleComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentCreatorTest_testEmptyCreator_compilerMode=FAST_INIT_MODE, creatorKind=dagger.Component.Factory_test.DaggerSimpleComponent
@@ -12,7 +12,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerSimpleComponent {
   private DaggerSimpleComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentFactoryTest_testUsesParameterNames_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentFactoryTest_testUsesParameterNames_DEFAULT_MODE_test.DaggerTestComponent
index d918083..ac6ba38 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentFactoryTest_testUsesParameterNames_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentFactoryTest_testUsesParameterNames_DEFAULT_MODE_test.DaggerTestComponent
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentFactoryTest_testUsesParameterNames_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentFactoryTest_testUsesParameterNames_FAST_INIT_MODE_test.DaggerTestComponent
index d918083..ac6ba38 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentFactoryTest_testUsesParameterNames_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentFactoryTest_testUsesParameterNames_FAST_INIT_MODE_test.DaggerTestComponent
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_arrayComponentDependency_DEFAULT_MODE_test.DaggerBComponent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_arrayComponentDependency_DEFAULT_MODE_test.DaggerBComponent
index a3127fb..dc3a6e7 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_arrayComponentDependency_DEFAULT_MODE_test.DaggerBComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_arrayComponentDependency_DEFAULT_MODE_test.DaggerBComponent
@@ -2,8 +2,8 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.Preconditions;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -14,7 +14,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerBComponent {
   private DaggerBComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_arrayComponentDependency_FAST_INIT_MODE_test.DaggerBComponent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_arrayComponentDependency_FAST_INIT_MODE_test.DaggerBComponent
index bb09e8b..87aba7d 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_arrayComponentDependency_FAST_INIT_MODE_test.DaggerBComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_arrayComponentDependency_FAST_INIT_MODE_test.DaggerBComponent
@@ -2,8 +2,8 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.Preconditions;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -14,7 +14,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerBComponent {
   private DaggerBComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_componentDependency_DEFAULT_MODE_test.DaggerBComponent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_componentDependency_DEFAULT_MODE_test.DaggerBComponent
index eb9476a..0626b32 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_componentDependency_DEFAULT_MODE_test.DaggerBComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_componentDependency_DEFAULT_MODE_test.DaggerBComponent
@@ -2,8 +2,8 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.Preconditions;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -14,7 +14,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerBComponent {
   private DaggerBComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_componentDependency_FAST_INIT_MODE_test.DaggerBComponent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_componentDependency_FAST_INIT_MODE_test.DaggerBComponent
index 7a97ba5..26b5f28 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_componentDependency_FAST_INIT_MODE_test.DaggerBComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_componentDependency_FAST_INIT_MODE_test.DaggerBComponent
@@ -2,8 +2,8 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.Preconditions;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -14,7 +14,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerBComponent {
   private DaggerBComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_componentInjection_DEFAULT_MODE_test.DaggerSimpleComponent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_componentInjection_DEFAULT_MODE_test.DaggerSimpleComponent
index e32f689..66af8f5 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_componentInjection_DEFAULT_MODE_test.DaggerSimpleComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_componentInjection_DEFAULT_MODE_test.DaggerSimpleComponent
@@ -2,8 +2,8 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.InstanceFactory;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -14,7 +14,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerSimpleComponent {
   private DaggerSimpleComponent() {
@@ -59,7 +60,7 @@
     }
 
     @Override
-    public Provider<SimpleComponent> selfProvider() {
+    public javax.inject.Provider<SimpleComponent> selfProvider() {
       return simpleComponentProvider;
     }
   }
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_componentInjection_FAST_INIT_MODE_test.DaggerSimpleComponent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_componentInjection_FAST_INIT_MODE_test.DaggerSimpleComponent
index 4f9289e..4ce6af3 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_componentInjection_FAST_INIT_MODE_test.DaggerSimpleComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_componentInjection_FAST_INIT_MODE_test.DaggerSimpleComponent
@@ -2,8 +2,8 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.InstanceFactory;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -14,7 +14,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerSimpleComponent {
   private DaggerSimpleComponent() {
@@ -59,7 +60,7 @@
     }
 
     @Override
-    public Provider<SimpleComponent> selfProvider() {
+    public javax.inject.Provider<SimpleComponent> selfProvider() {
       return simpleComponentProvider;
     }
   }
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_componentMethodInChildCallsComponentMethodInParent_DEFAULT_MODE_test.DaggerParent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_componentMethodInChildCallsComponentMethodInParent_DEFAULT_MODE_test.DaggerParent
index 1d5bc09..2f1124b 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_componentMethodInChildCallsComponentMethodInParent_DEFAULT_MODE_test.DaggerParent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_componentMethodInChildCallsComponentMethodInParent_DEFAULT_MODE_test.DaggerParent
@@ -2,8 +2,8 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DoubleCheck;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -14,7 +14,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerParent {
   private DaggerParent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_componentMethodInChildCallsComponentMethodInParent_FAST_INIT_MODE_test.DaggerParent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_componentMethodInChildCallsComponentMethodInParent_FAST_INIT_MODE_test.DaggerParent
index af0cdb9..7d9a5d3 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_componentMethodInChildCallsComponentMethodInParent_FAST_INIT_MODE_test.DaggerParent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_componentMethodInChildCallsComponentMethodInParent_FAST_INIT_MODE_test.DaggerParent
@@ -2,8 +2,8 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DoubleCheck;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -14,7 +14,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerParent {
   private DaggerParent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_componentWithAbstractModule_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_componentWithAbstractModule_DEFAULT_MODE_test.DaggerTestComponent
index 8726e72..03fcd70 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_componentWithAbstractModule_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_componentWithAbstractModule_DEFAULT_MODE_test.DaggerTestComponent
@@ -12,7 +12,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_componentWithAbstractModule_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_componentWithAbstractModule_FAST_INIT_MODE_test.DaggerTestComponent
index 8726e72..03fcd70 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_componentWithAbstractModule_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_componentWithAbstractModule_FAST_INIT_MODE_test.DaggerTestComponent
@@ -12,7 +12,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_componentWithModule_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_componentWithModule_DEFAULT_MODE_test.DaggerTestComponent
index fddeb7c..8d8ddad 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_componentWithModule_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_componentWithModule_DEFAULT_MODE_test.DaggerTestComponent
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_componentWithModule_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_componentWithModule_FAST_INIT_MODE_test.DaggerTestComponent
index fddeb7c..8d8ddad 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_componentWithModule_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_componentWithModule_FAST_INIT_MODE_test.DaggerTestComponent
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_componentWithScope_DEFAULT_MODE_test.DaggerSimpleComponent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_componentWithScope_DEFAULT_MODE_test.DaggerSimpleComponent
index 76f4138..b79b07d 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_componentWithScope_DEFAULT_MODE_test.DaggerSimpleComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_componentWithScope_DEFAULT_MODE_test.DaggerSimpleComponent
@@ -3,8 +3,8 @@
 import dagger.Lazy;
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DoubleCheck;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -15,7 +15,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerSimpleComponent {
   private DaggerSimpleComponent() {
@@ -65,7 +66,7 @@
     }
 
     @Override
-    public Provider<SomeInjectableType> someInjectableTypeProvider() {
+    public javax.inject.Provider<SomeInjectableType> someInjectableTypeProvider() {
       return someInjectableTypeProvider;
     }
   }
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_componentWithScope_FAST_INIT_MODE_test.DaggerSimpleComponent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_componentWithScope_FAST_INIT_MODE_test.DaggerSimpleComponent
index 20d695d..e89783c 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_componentWithScope_FAST_INIT_MODE_test.DaggerSimpleComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_componentWithScope_FAST_INIT_MODE_test.DaggerSimpleComponent
@@ -3,8 +3,8 @@
 import dagger.Lazy;
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DoubleCheck;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -15,7 +15,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerSimpleComponent {
   private DaggerSimpleComponent() {
@@ -65,7 +66,7 @@
     }
 
     @Override
-    public Provider<SomeInjectableType> someInjectableTypeProvider() {
+    public javax.inject.Provider<SomeInjectableType> someInjectableTypeProvider() {
       return someInjectableTypeProvider;
     }
 
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_dependencyNameCollision_DEFAULT_MODE_test.DaggerBComponent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_dependencyNameCollision_DEFAULT_MODE_test.DaggerBComponent
index b828497..a2d1d85 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_dependencyNameCollision_DEFAULT_MODE_test.DaggerBComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_dependencyNameCollision_DEFAULT_MODE_test.DaggerBComponent
@@ -2,8 +2,8 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.Preconditions;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 import pkg1.A;
 import pkg1.AComponent;
 
@@ -16,7 +16,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerBComponent {
   private DaggerBComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_dependencyNameCollision_FAST_INIT_MODE_test.DaggerBComponent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_dependencyNameCollision_FAST_INIT_MODE_test.DaggerBComponent
index 99a7e42..42a0386 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_dependencyNameCollision_FAST_INIT_MODE_test.DaggerBComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_dependencyNameCollision_FAST_INIT_MODE_test.DaggerBComponent
@@ -2,8 +2,8 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.Preconditions;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 import pkg1.A;
 import pkg1.AComponent;
 
@@ -16,7 +16,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerBComponent {
   private DaggerBComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_ignoresDependencyMethodsFromObject_DEFAULT_MODE_test.DaggerBComponent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_ignoresDependencyMethodsFromObject_DEFAULT_MODE_test.DaggerBComponent
index 0373c53..b284dbd 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_ignoresDependencyMethodsFromObject_DEFAULT_MODE_test.DaggerBComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_ignoresDependencyMethodsFromObject_DEFAULT_MODE_test.DaggerBComponent
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerBComponent {
   private DaggerBComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_ignoresDependencyMethodsFromObject_FAST_INIT_MODE_test.DaggerBComponent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_ignoresDependencyMethodsFromObject_FAST_INIT_MODE_test.DaggerBComponent
index 0373c53..b284dbd 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_ignoresDependencyMethodsFromObject_FAST_INIT_MODE_test.DaggerBComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_ignoresDependencyMethodsFromObject_FAST_INIT_MODE_test.DaggerBComponent
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerBComponent {
   private DaggerBComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_justInTimeAtInjectConstructor_hasGeneratedQualifier_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_justInTimeAtInjectConstructor_hasGeneratedQualifier_DEFAULT_MODE_test.DaggerTestComponent
index 264aeb3..898e877 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_justInTimeAtInjectConstructor_hasGeneratedQualifier_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_justInTimeAtInjectConstructor_hasGeneratedQualifier_DEFAULT_MODE_test.DaggerTestComponent
@@ -12,7 +12,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_justInTimeAtInjectConstructor_hasGeneratedQualifier_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_justInTimeAtInjectConstructor_hasGeneratedQualifier_FAST_INIT_MODE_test.DaggerTestComponent
index 264aeb3..898e877 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_justInTimeAtInjectConstructor_hasGeneratedQualifier_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_justInTimeAtInjectConstructor_hasGeneratedQualifier_FAST_INIT_MODE_test.DaggerTestComponent
@@ -12,7 +12,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_membersInjection_DEFAULT_MODE_test.DaggerSimpleComponent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_membersInjection_DEFAULT_MODE_test.DaggerSimpleComponent
index e4330ef..d991e42 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_membersInjection_DEFAULT_MODE_test.DaggerSimpleComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_membersInjection_DEFAULT_MODE_test.DaggerSimpleComponent
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerSimpleComponent {
   private DaggerSimpleComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_membersInjection_FAST_INIT_MODE_test.DaggerSimpleComponent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_membersInjection_FAST_INIT_MODE_test.DaggerSimpleComponent
index e4330ef..d991e42 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_membersInjection_FAST_INIT_MODE_test.DaggerSimpleComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_membersInjection_FAST_INIT_MODE_test.DaggerSimpleComponent
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerSimpleComponent {
   private DaggerSimpleComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_moduleHasGeneratedQualifier_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_moduleHasGeneratedQualifier_DEFAULT_MODE_test.DaggerTestComponent
index f7515ed..dd93201 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_moduleHasGeneratedQualifier_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_moduleHasGeneratedQualifier_DEFAULT_MODE_test.DaggerTestComponent
@@ -12,7 +12,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_moduleHasGeneratedQualifier_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_moduleHasGeneratedQualifier_FAST_INIT_MODE_test.DaggerTestComponent
index f7515ed..dd93201 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_moduleHasGeneratedQualifier_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_moduleHasGeneratedQualifier_FAST_INIT_MODE_test.DaggerTestComponent
@@ -12,7 +12,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_moduleNameCollision_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_moduleNameCollision_DEFAULT_MODE_test.DaggerTestComponent
index 137e599..872646f 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_moduleNameCollision_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_moduleNameCollision_DEFAULT_MODE_test.DaggerTestComponent
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_moduleNameCollision_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_moduleNameCollision_FAST_INIT_MODE_test.DaggerTestComponent
index 137e599..872646f 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_moduleNameCollision_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_moduleNameCollision_FAST_INIT_MODE_test.DaggerTestComponent
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_nullCheckingIgnoredWhenProviderReturnsPrimitive_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_nullCheckingIgnoredWhenProviderReturnsPrimitive_DEFAULT_MODE_test.DaggerTestComponent
index 0aaa8d8..b9a27eb 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_nullCheckingIgnoredWhenProviderReturnsPrimitive_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_nullCheckingIgnoredWhenProviderReturnsPrimitive_DEFAULT_MODE_test.DaggerTestComponent
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_nullCheckingIgnoredWhenProviderReturnsPrimitive_DEFAULT_MODE_test.TestModule_PrimitiveIntegerFactory b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_nullCheckingIgnoredWhenProviderReturnsPrimitive_DEFAULT_MODE_test.TestModule_PrimitiveIntegerFactory
index 4b0e557..4caa6e1 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_nullCheckingIgnoredWhenProviderReturnsPrimitive_DEFAULT_MODE_test.TestModule_PrimitiveIntegerFactory
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_nullCheckingIgnoredWhenProviderReturnsPrimitive_DEFAULT_MODE_test.TestModule_PrimitiveIntegerFactory
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class TestModule_PrimitiveIntegerFactory implements Factory<Integer> {
   @Override
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_nullCheckingIgnoredWhenProviderReturnsPrimitive_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_nullCheckingIgnoredWhenProviderReturnsPrimitive_FAST_INIT_MODE_test.DaggerTestComponent
index 0aaa8d8..b9a27eb 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_nullCheckingIgnoredWhenProviderReturnsPrimitive_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_nullCheckingIgnoredWhenProviderReturnsPrimitive_FAST_INIT_MODE_test.DaggerTestComponent
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_nullCheckingIgnoredWhenProviderReturnsPrimitive_FAST_INIT_MODE_test.TestModule_PrimitiveIntegerFactory b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_nullCheckingIgnoredWhenProviderReturnsPrimitive_FAST_INIT_MODE_test.TestModule_PrimitiveIntegerFactory
index 4b0e557..4caa6e1 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_nullCheckingIgnoredWhenProviderReturnsPrimitive_FAST_INIT_MODE_test.TestModule_PrimitiveIntegerFactory
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_nullCheckingIgnoredWhenProviderReturnsPrimitive_FAST_INIT_MODE_test.TestModule_PrimitiveIntegerFactory
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class TestModule_PrimitiveIntegerFactory implements Factory<Integer> {
   @Override
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_nullIncorrectlyReturnedFromNonNullableInlinedProvider_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_nullIncorrectlyReturnedFromNonNullableInlinedProvider_DEFAULT_MODE_test.DaggerTestComponent
index 17727c0..54425a7 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_nullIncorrectlyReturnedFromNonNullableInlinedProvider_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_nullIncorrectlyReturnedFromNonNullableInlinedProvider_DEFAULT_MODE_test.DaggerTestComponent
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_nullIncorrectlyReturnedFromNonNullableInlinedProvider_DEFAULT_MODE_test.TestModule_NonNullableStringFactory b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_nullIncorrectlyReturnedFromNonNullableInlinedProvider_DEFAULT_MODE_test.TestModule_NonNullableStringFactory
index a19af96..96e8708 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_nullIncorrectlyReturnedFromNonNullableInlinedProvider_DEFAULT_MODE_test.TestModule_NonNullableStringFactory
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_nullIncorrectlyReturnedFromNonNullableInlinedProvider_DEFAULT_MODE_test.TestModule_NonNullableStringFactory
@@ -18,7 +18,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class TestModule_NonNullableStringFactory implements Factory<String> {
   @Override
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_nullIncorrectlyReturnedFromNonNullableInlinedProvider_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_nullIncorrectlyReturnedFromNonNullableInlinedProvider_FAST_INIT_MODE_test.DaggerTestComponent
index 17727c0..54425a7 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_nullIncorrectlyReturnedFromNonNullableInlinedProvider_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_nullIncorrectlyReturnedFromNonNullableInlinedProvider_FAST_INIT_MODE_test.DaggerTestComponent
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_nullIncorrectlyReturnedFromNonNullableInlinedProvider_FAST_INIT_MODE_test.TestModule_NonNullableStringFactory b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_nullIncorrectlyReturnedFromNonNullableInlinedProvider_FAST_INIT_MODE_test.TestModule_NonNullableStringFactory
index a19af96..96e8708 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_nullIncorrectlyReturnedFromNonNullableInlinedProvider_FAST_INIT_MODE_test.TestModule_NonNullableStringFactory
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_nullIncorrectlyReturnedFromNonNullableInlinedProvider_FAST_INIT_MODE_test.TestModule_NonNullableStringFactory
@@ -18,7 +18,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class TestModule_NonNullableStringFactory implements Factory<String> {
   @Override
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_primitiveComponentDependency_DEFAULT_MODE_test.DaggerBComponent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_primitiveComponentDependency_DEFAULT_MODE_test.DaggerBComponent
index 755b402..c1a2108 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_primitiveComponentDependency_DEFAULT_MODE_test.DaggerBComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_primitiveComponentDependency_DEFAULT_MODE_test.DaggerBComponent
@@ -2,8 +2,8 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.Preconditions;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -14,7 +14,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerBComponent {
   private DaggerBComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_primitiveComponentDependency_FAST_INIT_MODE_test.DaggerBComponent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_primitiveComponentDependency_FAST_INIT_MODE_test.DaggerBComponent
index 6ce1e24..d88c74e 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_primitiveComponentDependency_FAST_INIT_MODE_test.DaggerBComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_primitiveComponentDependency_FAST_INIT_MODE_test.DaggerBComponent
@@ -2,8 +2,8 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.Preconditions;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -14,7 +14,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerBComponent {
   private DaggerBComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_privateMethodUsedOnlyInChildDoesNotUseQualifiedThis_DEFAULT_MODE_test.DaggerParent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_privateMethodUsedOnlyInChildDoesNotUseQualifiedThis_DEFAULT_MODE_test.DaggerParent
index f26d8a5..73f067b 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_privateMethodUsedOnlyInChildDoesNotUseQualifiedThis_DEFAULT_MODE_test.DaggerParent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_privateMethodUsedOnlyInChildDoesNotUseQualifiedThis_DEFAULT_MODE_test.DaggerParent
@@ -2,8 +2,8 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DoubleCheck;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -14,7 +14,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerParent {
   private DaggerParent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_privateMethodUsedOnlyInChildDoesNotUseQualifiedThis_FAST_INIT_MODE_test.DaggerParent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_privateMethodUsedOnlyInChildDoesNotUseQualifiedThis_FAST_INIT_MODE_test.DaggerParent
index 5edc873..c20b8f0 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_privateMethodUsedOnlyInChildDoesNotUseQualifiedThis_FAST_INIT_MODE_test.DaggerParent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_privateMethodUsedOnlyInChildDoesNotUseQualifiedThis_FAST_INIT_MODE_test.DaggerParent
@@ -2,8 +2,8 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DoubleCheck;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -14,7 +14,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerParent {
   private DaggerParent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_providerComponentType_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_providerComponentType_DEFAULT_MODE_test.DaggerTestComponent
index 19c4c90..5558c81 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_providerComponentType_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_providerComponentType_DEFAULT_MODE_test.DaggerTestComponent
@@ -1,8 +1,8 @@
 package test;
 
 import dagger.internal.DaggerGenerated;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_providerComponentType_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_providerComponentType_FAST_INIT_MODE_test.DaggerTestComponent
index 0af1585..e19505d 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_providerComponentType_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_providerComponentType_FAST_INIT_MODE_test.DaggerTestComponent
@@ -1,8 +1,8 @@
 package test;
 
 import dagger.internal.DaggerGenerated;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_publicComponentType_DEFAULT_MODE_test.DaggerPublicComponent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_publicComponentType_DEFAULT_MODE_test.DaggerPublicComponent
index 71341f0..48c0f34 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_publicComponentType_DEFAULT_MODE_test.DaggerPublicComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_publicComponentType_DEFAULT_MODE_test.DaggerPublicComponent
@@ -12,7 +12,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class DaggerPublicComponent {
   private DaggerPublicComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_publicComponentType_FAST_INIT_MODE_test.DaggerPublicComponent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_publicComponentType_FAST_INIT_MODE_test.DaggerPublicComponent
index 71341f0..48c0f34 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_publicComponentType_FAST_INIT_MODE_test.DaggerPublicComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_publicComponentType_FAST_INIT_MODE_test.DaggerPublicComponent
@@ -12,7 +12,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class DaggerPublicComponent {
   private DaggerPublicComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_resolutionOrder_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_resolutionOrder_DEFAULT_MODE_test.DaggerTestComponent
index 6841e93..22771bb 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_resolutionOrder_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_resolutionOrder_DEFAULT_MODE_test.DaggerTestComponent
@@ -12,7 +12,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_resolutionOrder_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_resolutionOrder_FAST_INIT_MODE_test.DaggerTestComponent
index 6841e93..22771bb 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_resolutionOrder_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_resolutionOrder_FAST_INIT_MODE_test.DaggerTestComponent
@@ -12,7 +12,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_simpleComponentWithNesting_DEFAULT_MODE_test.DaggerOuterType_SimpleComponent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_simpleComponentWithNesting_DEFAULT_MODE_test.DaggerOuterType_SimpleComponent
index 37ea930..1a79810 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_simpleComponentWithNesting_DEFAULT_MODE_test.DaggerOuterType_SimpleComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_simpleComponentWithNesting_DEFAULT_MODE_test.DaggerOuterType_SimpleComponent
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerOuterType_SimpleComponent {
   private DaggerOuterType_SimpleComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_simpleComponentWithNesting_FAST_INIT_MODE_test.DaggerOuterType_SimpleComponent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_simpleComponentWithNesting_FAST_INIT_MODE_test.DaggerOuterType_SimpleComponent
index 37ea930..1a79810 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_simpleComponentWithNesting_FAST_INIT_MODE_test.DaggerOuterType_SimpleComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_simpleComponentWithNesting_FAST_INIT_MODE_test.DaggerOuterType_SimpleComponent
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerOuterType_SimpleComponent {
   private DaggerOuterType_SimpleComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_simpleComponent_DEFAULT_MODE_test.DaggerSimpleComponent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_simpleComponent_DEFAULT_MODE_test.DaggerSimpleComponent
index 9e46639..e1e3f64 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_simpleComponent_DEFAULT_MODE_test.DaggerSimpleComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_simpleComponent_DEFAULT_MODE_test.DaggerSimpleComponent
@@ -15,7 +15,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerSimpleComponent {
   private DaggerSimpleComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_simpleComponent_FAST_INIT_MODE_test.DaggerSimpleComponent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_simpleComponent_FAST_INIT_MODE_test.DaggerSimpleComponent
index d92a70e..094c1ff 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_simpleComponent_FAST_INIT_MODE_test.DaggerSimpleComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_simpleComponent_FAST_INIT_MODE_test.DaggerSimpleComponent
@@ -3,8 +3,8 @@
 import dagger.Lazy;
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DoubleCheck;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -15,7 +15,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerSimpleComponent {
   private DaggerSimpleComponent() {
@@ -65,7 +66,7 @@
     }
 
     @Override
-    public Provider<SomeInjectableType> someInjectableTypeProvider() {
+    public javax.inject.Provider<SomeInjectableType> someInjectableTypeProvider() {
       return someInjectableTypeProvider;
     }
 
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_simpleComponent_inheritedComponentMethodDep_DEFAULT_MODE_test.DaggerSimpleComponent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_simpleComponent_inheritedComponentMethodDep_DEFAULT_MODE_test.DaggerSimpleComponent
index 630073e..108b13d 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_simpleComponent_inheritedComponentMethodDep_DEFAULT_MODE_test.DaggerSimpleComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_simpleComponent_inheritedComponentMethodDep_DEFAULT_MODE_test.DaggerSimpleComponent
@@ -12,7 +12,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerSimpleComponent {
   private DaggerSimpleComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_simpleComponent_inheritedComponentMethodDep_FAST_INIT_MODE_test.DaggerSimpleComponent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_simpleComponent_inheritedComponentMethodDep_FAST_INIT_MODE_test.DaggerSimpleComponent
index 630073e..108b13d 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_simpleComponent_inheritedComponentMethodDep_FAST_INIT_MODE_test.DaggerSimpleComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_simpleComponent_inheritedComponentMethodDep_FAST_INIT_MODE_test.DaggerSimpleComponent
@@ -12,7 +12,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerSimpleComponent {
   private DaggerSimpleComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_simpleComponent_redundantComponentMethod_DEFAULT_MODE_test.DaggerSimpleComponent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_simpleComponent_redundantComponentMethod_DEFAULT_MODE_test.DaggerSimpleComponent
index 630073e..108b13d 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_simpleComponent_redundantComponentMethod_DEFAULT_MODE_test.DaggerSimpleComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_simpleComponent_redundantComponentMethod_DEFAULT_MODE_test.DaggerSimpleComponent
@@ -12,7 +12,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerSimpleComponent {
   private DaggerSimpleComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_simpleComponent_redundantComponentMethod_FAST_INIT_MODE_test.DaggerSimpleComponent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_simpleComponent_redundantComponentMethod_FAST_INIT_MODE_test.DaggerSimpleComponent
index 630073e..108b13d 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_simpleComponent_redundantComponentMethod_FAST_INIT_MODE_test.DaggerSimpleComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_simpleComponent_redundantComponentMethod_FAST_INIT_MODE_test.DaggerSimpleComponent
@@ -12,7 +12,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerSimpleComponent {
   private DaggerSimpleComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_subcomponentNotGeneratedIfNotUsedInGraph_DEFAULT_MODE_test.DaggerParent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_subcomponentNotGeneratedIfNotUsedInGraph_DEFAULT_MODE_test.DaggerParent
index 9447a47..c630533 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_subcomponentNotGeneratedIfNotUsedInGraph_DEFAULT_MODE_test.DaggerParent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_subcomponentNotGeneratedIfNotUsedInGraph_DEFAULT_MODE_test.DaggerParent
@@ -1,7 +1,6 @@
 package test;
 
 import dagger.internal.DaggerGenerated;
-import dagger.internal.Preconditions;
 import javax.annotation.processing.Generated;
 
 @DaggerGenerated
@@ -13,7 +12,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerParent {
   private DaggerParent() {
@@ -31,15 +31,6 @@
     private Builder() {
     }
 
-    /**
-     * @deprecated This module is declared, but an instance is not used in the component. This method is a no-op. For more, see https://dagger.dev/unused-modules.
-     */
-    @Deprecated
-    public Builder parentModule(ParentModule parentModule) {
-      Preconditions.checkNotNull(parentModule);
-      return this;
-    }
-
     public Parent build() {
       return new ParentImpl();
     }
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_subcomponentNotGeneratedIfNotUsedInGraph_FAST_INIT_MODE_test.DaggerParent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_subcomponentNotGeneratedIfNotUsedInGraph_FAST_INIT_MODE_test.DaggerParent
index 9447a47..c630533 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_subcomponentNotGeneratedIfNotUsedInGraph_FAST_INIT_MODE_test.DaggerParent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_subcomponentNotGeneratedIfNotUsedInGraph_FAST_INIT_MODE_test.DaggerParent
@@ -1,7 +1,6 @@
 package test;
 
 import dagger.internal.DaggerGenerated;
-import dagger.internal.Preconditions;
 import javax.annotation.processing.Generated;
 
 @DaggerGenerated
@@ -13,7 +12,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerParent {
   private DaggerParent() {
@@ -31,15 +31,6 @@
     private Builder() {
     }
 
-    /**
-     * @deprecated This module is declared, but an instance is not used in the component. This method is a no-op. For more, see https://dagger.dev/unused-modules.
-     */
-    @Deprecated
-    public Builder parentModule(ParentModule parentModule) {
-      Preconditions.checkNotNull(parentModule);
-      return this;
-    }
-
     public Parent build() {
       return new ParentImpl();
     }
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_transitiveModuleDeps_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_transitiveModuleDeps_DEFAULT_MODE_test.DaggerTestComponent
index ec93b6c..7b077e7 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_transitiveModuleDeps_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_transitiveModuleDeps_DEFAULT_MODE_test.DaggerTestComponent
@@ -1,7 +1,6 @@
 package test;
 
 import dagger.internal.DaggerGenerated;
-import dagger.internal.Preconditions;
 import javax.annotation.processing.Generated;
 
 @DaggerGenerated
@@ -13,7 +12,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -31,60 +31,6 @@
     private Builder() {
     }
 
-    /**
-     * @deprecated This module is declared, but an instance is not used in the component. This method is a no-op. For more, see https://dagger.dev/unused-modules.
-     */
-    @Deprecated
-    public Builder testModule(TestModule testModule) {
-      Preconditions.checkNotNull(testModule);
-      return this;
-    }
-
-    /**
-     * @deprecated This module is declared, but an instance is not used in the component. This method is a no-op. For more, see https://dagger.dev/unused-modules.
-     */
-    @Deprecated
-    public Builder parentTestIncluded(ParentTestIncluded parentTestIncluded) {
-      Preconditions.checkNotNull(parentTestIncluded);
-      return this;
-    }
-
-    /**
-     * @deprecated This module is declared, but an instance is not used in the component. This method is a no-op. For more, see https://dagger.dev/unused-modules.
-     */
-    @Deprecated
-    public Builder alwaysIncluded(AlwaysIncluded alwaysIncluded) {
-      Preconditions.checkNotNull(alwaysIncluded);
-      return this;
-    }
-
-    /**
-     * @deprecated This module is declared, but an instance is not used in the component. This method is a no-op. For more, see https://dagger.dev/unused-modules.
-     */
-    @Deprecated
-    public Builder depModule(DepModule depModule) {
-      Preconditions.checkNotNull(depModule);
-      return this;
-    }
-
-    /**
-     * @deprecated This module is declared, but an instance is not used in the component. This method is a no-op. For more, see https://dagger.dev/unused-modules.
-     */
-    @Deprecated
-    public Builder parentDepIncluded(ParentDepIncluded parentDepIncluded) {
-      Preconditions.checkNotNull(parentDepIncluded);
-      return this;
-    }
-
-    /**
-     * @deprecated This module is declared, but an instance is not used in the component. This method is a no-op. For more, see https://dagger.dev/unused-modules.
-     */
-    @Deprecated
-    public Builder refByDep(RefByDep refByDep) {
-      Preconditions.checkNotNull(refByDep);
-      return this;
-    }
-
     public TestComponent build() {
       return new TestComponentImpl();
     }
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_transitiveModuleDeps_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_transitiveModuleDeps_FAST_INIT_MODE_test.DaggerTestComponent
index ec93b6c..7b077e7 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_transitiveModuleDeps_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_transitiveModuleDeps_FAST_INIT_MODE_test.DaggerTestComponent
@@ -1,7 +1,6 @@
 package test;
 
 import dagger.internal.DaggerGenerated;
-import dagger.internal.Preconditions;
 import javax.annotation.processing.Generated;
 
 @DaggerGenerated
@@ -13,7 +12,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -31,60 +31,6 @@
     private Builder() {
     }
 
-    /**
-     * @deprecated This module is declared, but an instance is not used in the component. This method is a no-op. For more, see https://dagger.dev/unused-modules.
-     */
-    @Deprecated
-    public Builder testModule(TestModule testModule) {
-      Preconditions.checkNotNull(testModule);
-      return this;
-    }
-
-    /**
-     * @deprecated This module is declared, but an instance is not used in the component. This method is a no-op. For more, see https://dagger.dev/unused-modules.
-     */
-    @Deprecated
-    public Builder parentTestIncluded(ParentTestIncluded parentTestIncluded) {
-      Preconditions.checkNotNull(parentTestIncluded);
-      return this;
-    }
-
-    /**
-     * @deprecated This module is declared, but an instance is not used in the component. This method is a no-op. For more, see https://dagger.dev/unused-modules.
-     */
-    @Deprecated
-    public Builder alwaysIncluded(AlwaysIncluded alwaysIncluded) {
-      Preconditions.checkNotNull(alwaysIncluded);
-      return this;
-    }
-
-    /**
-     * @deprecated This module is declared, but an instance is not used in the component. This method is a no-op. For more, see https://dagger.dev/unused-modules.
-     */
-    @Deprecated
-    public Builder depModule(DepModule depModule) {
-      Preconditions.checkNotNull(depModule);
-      return this;
-    }
-
-    /**
-     * @deprecated This module is declared, but an instance is not used in the component. This method is a no-op. For more, see https://dagger.dev/unused-modules.
-     */
-    @Deprecated
-    public Builder parentDepIncluded(ParentDepIncluded parentDepIncluded) {
-      Preconditions.checkNotNull(parentDepIncluded);
-      return this;
-    }
-
-    /**
-     * @deprecated This module is declared, but an instance is not used in the component. This method is a no-op. For more, see https://dagger.dev/unused-modules.
-     */
-    @Deprecated
-    public Builder refByDep(RefByDep refByDep) {
-      Preconditions.checkNotNull(refByDep);
-      return this;
-    }
-
     public TestComponent build() {
       return new TestComponentImpl();
     }
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_unusedSubcomponents_dontResolveExtraBindingsInParentComponents_DEFAULT_MODE_test.DaggerParent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_unusedSubcomponents_dontResolveExtraBindingsInParentComponents_DEFAULT_MODE_test.DaggerParent
index 89764b9..9fcf3dc 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_unusedSubcomponents_dontResolveExtraBindingsInParentComponents_DEFAULT_MODE_test.DaggerParent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_unusedSubcomponents_dontResolveExtraBindingsInParentComponents_DEFAULT_MODE_test.DaggerParent
@@ -1,7 +1,6 @@
 package test;
 
 import dagger.internal.DaggerGenerated;
-import dagger.internal.Preconditions;
 import javax.annotation.processing.Generated;
 
 @DaggerGenerated
@@ -13,7 +12,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerParent {
   private DaggerParent() {
@@ -31,15 +31,6 @@
     private Builder() {
     }
 
-    /**
-     * @deprecated This module is declared, but an instance is not used in the component. This method is a no-op. For more, see https://dagger.dev/unused-modules.
-     */
-    @Deprecated
-    public Builder testModule(TestModule testModule) {
-      Preconditions.checkNotNull(testModule);
-      return this;
-    }
-
     public Parent build() {
       return new ParentImpl();
     }
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_unusedSubcomponents_dontResolveExtraBindingsInParentComponents_FAST_INIT_MODE_test.DaggerParent b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_unusedSubcomponents_dontResolveExtraBindingsInParentComponents_FAST_INIT_MODE_test.DaggerParent
index 89764b9..9fcf3dc 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_unusedSubcomponents_dontResolveExtraBindingsInParentComponents_FAST_INIT_MODE_test.DaggerParent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProcessorTest_unusedSubcomponents_dontResolveExtraBindingsInParentComponents_FAST_INIT_MODE_test.DaggerParent
@@ -1,7 +1,6 @@
 package test;
 
 import dagger.internal.DaggerGenerated;
-import dagger.internal.Preconditions;
 import javax.annotation.processing.Generated;
 
 @DaggerGenerated
@@ -13,7 +12,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerParent {
   private DaggerParent() {
@@ -31,15 +31,6 @@
     private Builder() {
     }
 
-    /**
-     * @deprecated This module is declared, but an instance is not used in the component. This method is a no-op. For more, see https://dagger.dev/unused-modules.
-     */
-    @Deprecated
-    public Builder testModule(TestModule testModule) {
-      Preconditions.checkNotNull(testModule);
-      return this;
-    }
-
     public Parent build() {
       return new ParentImpl();
     }
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProtectedTypeTest_componentAccessesProtectedType_succeeds_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentProtectedTypeTest_componentAccessesProtectedType_succeeds_DEFAULT_MODE_test.DaggerTestComponent
index 98c9ea7..a036546 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProtectedTypeTest_componentAccessesProtectedType_succeeds_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProtectedTypeTest_componentAccessesProtectedType_succeeds_DEFAULT_MODE_test.DaggerTestComponent
@@ -2,8 +2,8 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DoubleCheck;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 import test.sub.TestComponentBase_Dep_Factory;
 import test.sub.TestComponentBase_ProtectedType_Factory;
 
@@ -16,7 +16,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentProtectedTypeTest_componentAccessesProtectedType_succeeds_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentProtectedTypeTest_componentAccessesProtectedType_succeeds_FAST_INIT_MODE_test.DaggerTestComponent
index 441b713..7defcfc 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentProtectedTypeTest_componentAccessesProtectedType_succeeds_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentProtectedTypeTest_componentAccessesProtectedType_succeeds_FAST_INIT_MODE_test.DaggerTestComponent
@@ -2,8 +2,8 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DoubleCheck;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 import test.sub.TestComponentBase_Dep_Factory;
 import test.sub.TestComponentBase_ProtectedType_Factory;
 
@@ -16,7 +16,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_bindsInstance_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_bindsInstance_DEFAULT_MODE_test.DaggerTestComponent
index 0999a8b..bbe89b9 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_bindsInstance_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_bindsInstance_DEFAULT_MODE_test.DaggerTestComponent
@@ -14,7 +14,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_bindsInstance_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_bindsInstance_FAST_INIT_MODE_test.DaggerTestComponent
index 0999a8b..bbe89b9 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_bindsInstance_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_bindsInstance_FAST_INIT_MODE_test.DaggerTestComponent
@@ -14,7 +14,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_componentInstances_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_componentInstances_DEFAULT_MODE_test.DaggerTestComponent
index 7f50d88..98ba4b6 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_componentInstances_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_componentInstances_DEFAULT_MODE_test.DaggerTestComponent
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_componentInstances_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_componentInstances_FAST_INIT_MODE_test.DaggerTestComponent
index 7f50d88..98ba4b6 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_componentInstances_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_componentInstances_FAST_INIT_MODE_test.DaggerTestComponent
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_componentRequirementNeededInFactoryCreationOfSubcomponent_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_componentRequirementNeededInFactoryCreationOfSubcomponent_DEFAULT_MODE_test.DaggerTestComponent
index 78ff25e..9b39816 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_componentRequirementNeededInFactoryCreationOfSubcomponent_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_componentRequirementNeededInFactoryCreationOfSubcomponent_DEFAULT_MODE_test.DaggerTestComponent
@@ -2,10 +2,10 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.Preconditions;
+import dagger.internal.Provider;
 import dagger.internal.SetFactory;
 import java.util.Set;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -16,7 +16,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -72,7 +73,7 @@
     }
 
     @Override
-    public Provider<Object> dependsOnMultibinding() {
+    public javax.inject.Provider<Object> dependsOnMultibinding() {
       return reliesOnMultibindingProvider;
     }
   }
@@ -99,7 +100,7 @@
     }
 
     @Override
-    public Provider<Object> dependsOnMultibinding() {
+    public javax.inject.Provider<Object> dependsOnMultibinding() {
       return reliesOnMultibindingProvider;
     }
 
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_componentRequirementNeededInFactoryCreationOfSubcomponent_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_componentRequirementNeededInFactoryCreationOfSubcomponent_FAST_INIT_MODE_test.DaggerTestComponent
index 5eb16ad..94ebb33 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_componentRequirementNeededInFactoryCreationOfSubcomponent_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_componentRequirementNeededInFactoryCreationOfSubcomponent_FAST_INIT_MODE_test.DaggerTestComponent
@@ -3,9 +3,9 @@
 import com.google.common.collect.ImmutableSet;
 import dagger.internal.DaggerGenerated;
 import dagger.internal.Preconditions;
+import dagger.internal.Provider;
 import java.util.Set;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -16,7 +16,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -73,7 +74,7 @@
     }
 
     @Override
-    public Provider<Object> dependsOnMultibinding() {
+    public javax.inject.Provider<Object> dependsOnMultibinding() {
       return reliesOnMultibindingProvider;
     }
 
@@ -127,7 +128,7 @@
     }
 
     @Override
-    public Provider<Object> dependsOnMultibinding() {
+    public javax.inject.Provider<Object> dependsOnMultibinding() {
       return reliesOnMultibindingProvider;
     }
 
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_instanceModuleMethod_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_instanceModuleMethod_DEFAULT_MODE_test.DaggerTestComponent
index 36c3a11..99caa07 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_instanceModuleMethod_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_instanceModuleMethod_DEFAULT_MODE_test.DaggerTestComponent
@@ -15,7 +15,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_instanceModuleMethod_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_instanceModuleMethod_FAST_INIT_MODE_test.DaggerTestComponent
index 36c3a11..99caa07 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_instanceModuleMethod_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_instanceModuleMethod_FAST_INIT_MODE_test.DaggerTestComponent
@@ -15,7 +15,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentShardTest_testNewShardCreatedWithDependencies_DEFAULT_MODE_dagger.internal.codegen.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentShardTest_testNewShardCreatedWithDependencies_DEFAULT_MODE_dagger.internal.codegen.DaggerTestComponent
index d5a2af0..a2c9032 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentShardTest_testNewShardCreatedWithDependencies_DEFAULT_MODE_dagger.internal.codegen.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentShardTest_testNewShardCreatedWithDependencies_DEFAULT_MODE_dagger.internal.codegen.DaggerTestComponent
@@ -3,8 +3,8 @@
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DoubleCheck;
 import dagger.internal.Preconditions;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -15,7 +15,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -81,17 +82,17 @@
     }
 
     @Override
-    public Provider<Binding1> providerBinding1() {
+    public javax.inject.Provider<Binding1> providerBinding1() {
       return binding1Provider;
     }
 
     @Override
-    public Provider<Binding2> providerBinding2() {
+    public javax.inject.Provider<Binding2> providerBinding2() {
       return binding2Provider;
     }
 
     @Override
-    public Provider<Binding3> providerBinding3() {
+    public javax.inject.Provider<Binding3> providerBinding3() {
       return testComponentImpl.testComponentImplShard.binding3Provider;
     }
 
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentShardTest_testNewShardCreatedWithDependencies_FAST_INIT_MODE_dagger.internal.codegen.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentShardTest_testNewShardCreatedWithDependencies_FAST_INIT_MODE_dagger.internal.codegen.DaggerTestComponent
index e09bb44..5d58c6e 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentShardTest_testNewShardCreatedWithDependencies_FAST_INIT_MODE_dagger.internal.codegen.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentShardTest_testNewShardCreatedWithDependencies_FAST_INIT_MODE_dagger.internal.codegen.DaggerTestComponent
@@ -3,8 +3,8 @@
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DoubleCheck;
 import dagger.internal.Preconditions;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -15,7 +15,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -81,17 +82,17 @@
     }
 
     @Override
-    public Provider<Binding1> providerBinding1() {
+    public javax.inject.Provider<Binding1> providerBinding1() {
       return binding1Provider;
     }
 
     @Override
-    public Provider<Binding2> providerBinding2() {
+    public javax.inject.Provider<Binding2> providerBinding2() {
       return binding2Provider;
     }
 
     @Override
-    public Provider<Binding3> providerBinding3() {
+    public javax.inject.Provider<Binding3> providerBinding3() {
       return testComponentImpl.testComponentImplShard.binding3Provider;
     }
 
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentShardTest_testNewShardCreated_DEFAULT_MODE_dagger.internal.codegen.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentShardTest_testNewShardCreated_DEFAULT_MODE_dagger.internal.codegen.DaggerTestComponent
index de033d5..59a7cae 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentShardTest_testNewShardCreated_DEFAULT_MODE_dagger.internal.codegen.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentShardTest_testNewShardCreated_DEFAULT_MODE_dagger.internal.codegen.DaggerTestComponent
@@ -3,8 +3,8 @@
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DelegateFactory;
 import dagger.internal.DoubleCheck;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -15,7 +15,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -98,37 +99,37 @@
     }
 
     @Override
-    public Provider<Binding1> providerBinding1() {
+    public javax.inject.Provider<Binding1> providerBinding1() {
       return testComponentImpl.testComponentImplShard2.binding1Provider;
     }
 
     @Override
-    public Provider<Binding2> providerBinding2() {
+    public javax.inject.Provider<Binding2> providerBinding2() {
       return testComponentImpl.testComponentImplShard.binding2Provider;
     }
 
     @Override
-    public Provider<Binding3> providerBinding3() {
+    public javax.inject.Provider<Binding3> providerBinding3() {
       return testComponentImpl.testComponentImplShard.binding3Provider;
     }
 
     @Override
-    public Provider<Binding4> providerBinding4() {
+    public javax.inject.Provider<Binding4> providerBinding4() {
       return testComponentImpl.testComponentImplShard.binding4Provider;
     }
 
     @Override
-    public Provider<Binding5> providerBinding5() {
+    public javax.inject.Provider<Binding5> providerBinding5() {
       return testComponentImpl.testComponentImplShard.binding5Provider;
     }
 
     @Override
-    public Provider<Binding6> providerBinding6() {
+    public javax.inject.Provider<Binding6> providerBinding6() {
       return binding6Provider;
     }
 
     @Override
-    public Provider<Binding7> providerBinding7() {
+    public javax.inject.Provider<Binding7> providerBinding7() {
       return binding7Provider;
     }
   }
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentShardTest_testNewShardCreated_FAST_INIT_MODE_dagger.internal.codegen.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentShardTest_testNewShardCreated_FAST_INIT_MODE_dagger.internal.codegen.DaggerTestComponent
index 81056e2..9a84c85 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentShardTest_testNewShardCreated_FAST_INIT_MODE_dagger.internal.codegen.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentShardTest_testNewShardCreated_FAST_INIT_MODE_dagger.internal.codegen.DaggerTestComponent
@@ -3,8 +3,8 @@
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DelegateFactory;
 import dagger.internal.DoubleCheck;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -15,7 +15,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -98,37 +99,37 @@
     }
 
     @Override
-    public Provider<Binding1> providerBinding1() {
+    public javax.inject.Provider<Binding1> providerBinding1() {
       return testComponentImpl.testComponentImplShard2.binding1Provider;
     }
 
     @Override
-    public Provider<Binding2> providerBinding2() {
+    public javax.inject.Provider<Binding2> providerBinding2() {
       return testComponentImpl.testComponentImplShard.binding2Provider;
     }
 
     @Override
-    public Provider<Binding3> providerBinding3() {
+    public javax.inject.Provider<Binding3> providerBinding3() {
       return testComponentImpl.testComponentImplShard.binding3Provider;
     }
 
     @Override
-    public Provider<Binding4> providerBinding4() {
+    public javax.inject.Provider<Binding4> providerBinding4() {
       return testComponentImpl.testComponentImplShard.binding4Provider;
     }
 
     @Override
-    public Provider<Binding5> providerBinding5() {
+    public javax.inject.Provider<Binding5> providerBinding5() {
       return testComponentImpl.testComponentImplShard.binding5Provider;
     }
 
     @Override
-    public Provider<Binding6> providerBinding6() {
+    public javax.inject.Provider<Binding6> providerBinding6() {
       return binding6Provider;
     }
 
     @Override
-    public Provider<Binding7> providerBinding7() {
+    public javax.inject.Provider<Binding7> providerBinding7() {
       return binding7Provider;
     }
 
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentShardTest_testNewShardSubcomponentCreated_DEFAULT_MODE_dagger.internal.codegen.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentShardTest_testNewShardSubcomponentCreated_DEFAULT_MODE_dagger.internal.codegen.DaggerTestComponent
index 86b5db4..13f15e0 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentShardTest_testNewShardSubcomponentCreated_DEFAULT_MODE_dagger.internal.codegen.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentShardTest_testNewShardSubcomponentCreated_DEFAULT_MODE_dagger.internal.codegen.DaggerTestComponent
@@ -2,8 +2,8 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DoubleCheck;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -14,7 +14,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -77,17 +78,17 @@
     }
 
     @Override
-    public Provider<Binding1> providerBinding1() {
+    public javax.inject.Provider<Binding1> providerBinding1() {
       return binding1Provider;
     }
 
     @Override
-    public Provider<Binding2> providerBinding2() {
+    public javax.inject.Provider<Binding2> providerBinding2() {
       return binding2Provider;
     }
 
     @Override
-    public Provider<Binding3> providerBinding3() {
+    public javax.inject.Provider<Binding3> providerBinding3() {
       return testSubcomponentImpl.testSubcomponentImplShard.binding3Provider;
     }
   }
diff --git a/javatests/dagger/internal/codegen/goldens/ComponentShardTest_testNewShardSubcomponentCreated_FAST_INIT_MODE_dagger.internal.codegen.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentShardTest_testNewShardSubcomponentCreated_FAST_INIT_MODE_dagger.internal.codegen.DaggerTestComponent
index 5a675ba..f2a4aa6 100644
--- a/javatests/dagger/internal/codegen/goldens/ComponentShardTest_testNewShardSubcomponentCreated_FAST_INIT_MODE_dagger.internal.codegen.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/ComponentShardTest_testNewShardSubcomponentCreated_FAST_INIT_MODE_dagger.internal.codegen.DaggerTestComponent
@@ -2,8 +2,8 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DoubleCheck;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -14,7 +14,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -77,17 +78,17 @@
     }
 
     @Override
-    public Provider<Binding1> providerBinding1() {
+    public javax.inject.Provider<Binding1> providerBinding1() {
       return binding1Provider;
     }
 
     @Override
-    public Provider<Binding2> providerBinding2() {
+    public javax.inject.Provider<Binding2> providerBinding2() {
       return binding2Provider;
     }
 
     @Override
-    public Provider<Binding3> providerBinding3() {
+    public javax.inject.Provider<Binding3> providerBinding3() {
       return testSubcomponentImpl.testSubcomponentImplShard.binding3Provider;
     }
 
diff --git a/javatests/dagger/internal/codegen/goldens/DaggerProcessingOptionsTest_testCmdLineOptionEnabledPrecedesAnnotationDisabled_test.DaggerSimpleComponent b/javatests/dagger/internal/codegen/goldens/DaggerProcessingOptionsTest_testCmdLineOptionEnabledPrecedesAnnotationDisabled_test.DaggerSimpleComponent
index d92a70e..094c1ff 100644
--- a/javatests/dagger/internal/codegen/goldens/DaggerProcessingOptionsTest_testCmdLineOptionEnabledPrecedesAnnotationDisabled_test.DaggerSimpleComponent
+++ b/javatests/dagger/internal/codegen/goldens/DaggerProcessingOptionsTest_testCmdLineOptionEnabledPrecedesAnnotationDisabled_test.DaggerSimpleComponent
@@ -3,8 +3,8 @@
 import dagger.Lazy;
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DoubleCheck;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -15,7 +15,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerSimpleComponent {
   private DaggerSimpleComponent() {
@@ -65,7 +66,7 @@
     }
 
     @Override
-    public Provider<SomeInjectableType> someInjectableTypeProvider() {
+    public javax.inject.Provider<SomeInjectableType> someInjectableTypeProvider() {
       return someInjectableTypeProvider;
     }
 
diff --git a/javatests/dagger/internal/codegen/goldens/DaggerProcessingOptionsTest_testFastInitEnabledFromAnnotationSucceeded_test.DaggerSimpleComponent b/javatests/dagger/internal/codegen/goldens/DaggerProcessingOptionsTest_testFastInitEnabledFromAnnotationSucceeded_test.DaggerSimpleComponent
index d92a70e..094c1ff 100644
--- a/javatests/dagger/internal/codegen/goldens/DaggerProcessingOptionsTest_testFastInitEnabledFromAnnotationSucceeded_test.DaggerSimpleComponent
+++ b/javatests/dagger/internal/codegen/goldens/DaggerProcessingOptionsTest_testFastInitEnabledFromAnnotationSucceeded_test.DaggerSimpleComponent
@@ -3,8 +3,8 @@
 import dagger.Lazy;
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DoubleCheck;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -15,7 +15,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerSimpleComponent {
   private DaggerSimpleComponent() {
@@ -65,7 +66,7 @@
     }
 
     @Override
-    public Provider<SomeInjectableType> someInjectableTypeProvider() {
+    public javax.inject.Provider<SomeInjectableType> someInjectableTypeProvider() {
       return someInjectableTypeProvider;
     }
 
diff --git a/javatests/dagger/internal/codegen/goldens/DaggerProcessingOptionsTest_testFastInitaDisabledFromAnnotationSucceeded_test.DaggerSimpleComponent b/javatests/dagger/internal/codegen/goldens/DaggerProcessingOptionsTest_testFastInitaDisabledFromAnnotationSucceeded_test.DaggerSimpleComponent
index 9e46639..e1e3f64 100644
--- a/javatests/dagger/internal/codegen/goldens/DaggerProcessingOptionsTest_testFastInitaDisabledFromAnnotationSucceeded_test.DaggerSimpleComponent
+++ b/javatests/dagger/internal/codegen/goldens/DaggerProcessingOptionsTest_testFastInitaDisabledFromAnnotationSucceeded_test.DaggerSimpleComponent
@@ -15,7 +15,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerSimpleComponent {
   private DaggerSimpleComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_castNeeded_rawTypes_Provider_get_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_castNeeded_rawTypes_Provider_get_DEFAULT_MODE_test.DaggerTestComponent
index 87f55ab..0cf470e 100644
--- a/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_castNeeded_rawTypes_Provider_get_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_castNeeded_rawTypes_Provider_get_DEFAULT_MODE_test.DaggerTestComponent
@@ -2,8 +2,8 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DoubleCheck;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 import other.Subtype_Factory;
 import other.Supertype;
 
@@ -16,7 +16,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_castNeeded_rawTypes_Provider_get_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_castNeeded_rawTypes_Provider_get_FAST_INIT_MODE_test.DaggerTestComponent
index 06e4298..f7bd448 100644
--- a/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_castNeeded_rawTypes_Provider_get_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_castNeeded_rawTypes_Provider_get_FAST_INIT_MODE_test.DaggerTestComponent
@@ -2,8 +2,8 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DoubleCheck;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 import other.Subtype_Factory;
 import other.Supertype;
 
@@ -16,7 +16,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_castedToRawType_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_castedToRawType_DEFAULT_MODE_test.DaggerTestComponent
index 6bdd833..d5ebea6 100644
--- a/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_castedToRawType_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_castedToRawType_DEFAULT_MODE_test.DaggerTestComponent
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -46,7 +47,7 @@
 
     @Override
     public Provider<CharSequence> charSequence() {
-      return ((Provider) TestModule_ProvideStringFactory.create());
+      return ((dagger.internal.Provider) TestModule_ProvideStringFactory.create());
     }
 
     @Override
diff --git a/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_castedToRawType_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_castedToRawType_FAST_INIT_MODE_test.DaggerTestComponent
index f186b84..dda8836 100644
--- a/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_castedToRawType_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_castedToRawType_FAST_INIT_MODE_test.DaggerTestComponent
@@ -1,8 +1,8 @@
 package test;
 
 import dagger.internal.DaggerGenerated;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -53,7 +54,7 @@
     }
 
     @Override
-    public Provider<CharSequence> charSequence() {
+    public javax.inject.Provider<CharSequence> charSequence() {
       return ((Provider) provideStringProvider);
     }
 
@@ -63,7 +64,7 @@
     }
 
     @Override
-    public Provider<String> namedString() {
+    public javax.inject.Provider<String> namedString() {
       return provideStringProvider;
     }
 
diff --git a/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_doubleBinds_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_doubleBinds_DEFAULT_MODE_test.DaggerTestComponent
index 578eaf4..8a2c7de 100644
--- a/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_doubleBinds_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_doubleBinds_DEFAULT_MODE_test.DaggerTestComponent
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -46,12 +47,12 @@
 
     @Override
     public Provider<CharSequence> charSequence() {
-      return ((Provider) TestModule_ProvideStringFactory.create());
+      return ((dagger.internal.Provider) TestModule_ProvideStringFactory.create());
     }
 
     @Override
     public Provider<Object> object() {
-      return ((Provider) TestModule_ProvideStringFactory.create());
+      return ((dagger.internal.Provider) TestModule_ProvideStringFactory.create());
     }
   }
 }
diff --git a/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_doubleBinds_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_doubleBinds_FAST_INIT_MODE_test.DaggerTestComponent
index 310f8a1..5c9ce8a 100644
--- a/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_doubleBinds_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_doubleBinds_FAST_INIT_MODE_test.DaggerTestComponent
@@ -1,8 +1,8 @@
 package test;
 
 import dagger.internal.DaggerGenerated;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -53,12 +54,12 @@
     }
 
     @Override
-    public Provider<CharSequence> charSequence() {
+    public javax.inject.Provider<CharSequence> charSequence() {
       return ((Provider) provideStringProvider);
     }
 
     @Override
-    public Provider<Object> object() {
+    public javax.inject.Provider<Object> object() {
       return ((Provider) provideStringProvider);
     }
 
diff --git a/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_inlineFactoryOfInacessibleType_DEFAULT_MODE_test.DaggerRequestsSubtypeAsProvider b/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_inlineFactoryOfInacessibleType_DEFAULT_MODE_test.DaggerRequestsSubtypeAsProvider
index 193724a..a8ad72f 100644
--- a/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_inlineFactoryOfInacessibleType_DEFAULT_MODE_test.DaggerRequestsSubtypeAsProvider
+++ b/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_inlineFactoryOfInacessibleType_DEFAULT_MODE_test.DaggerRequestsSubtypeAsProvider
@@ -15,7 +15,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerRequestsSubtypeAsProvider {
   private DaggerRequestsSubtypeAsProvider() {
@@ -48,7 +49,7 @@
 
     @Override
     public Provider<Supertype> supertypeProvider() {
-      return ((Provider) Subtype_Factory.create());
+      return ((dagger.internal.Provider) Subtype_Factory.create());
     }
   }
 }
diff --git a/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_inlineFactoryOfInacessibleType_FAST_INIT_MODE_test.DaggerRequestsSubtypeAsProvider b/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_inlineFactoryOfInacessibleType_FAST_INIT_MODE_test.DaggerRequestsSubtypeAsProvider
index 0d3233a..6f6e32c 100644
--- a/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_inlineFactoryOfInacessibleType_FAST_INIT_MODE_test.DaggerRequestsSubtypeAsProvider
+++ b/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_inlineFactoryOfInacessibleType_FAST_INIT_MODE_test.DaggerRequestsSubtypeAsProvider
@@ -1,8 +1,8 @@
 package test;
 
 import dagger.internal.DaggerGenerated;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 import other.Subtype_Factory;
 import other.Supertype;
 
@@ -15,7 +15,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerRequestsSubtypeAsProvider {
   private DaggerRequestsSubtypeAsProvider() {
@@ -56,7 +57,7 @@
     }
 
     @Override
-    public Provider<Supertype> supertypeProvider() {
+    public javax.inject.Provider<Supertype> supertypeProvider() {
       return subtypeProvider;
     }
 
diff --git a/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_noCast_rawTypes_Provider_get_toInaccessibleType_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_noCast_rawTypes_Provider_get_toInaccessibleType_DEFAULT_MODE_test.DaggerTestComponent
index b1c1c2c..9e96fba 100644
--- a/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_noCast_rawTypes_Provider_get_toInaccessibleType_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_noCast_rawTypes_Provider_get_toInaccessibleType_DEFAULT_MODE_test.DaggerTestComponent
@@ -2,8 +2,8 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DoubleCheck;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 import other.Subtype_Factory;
 import other.UsesSupertype;
 import other.UsesSupertype_Factory;
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_noCast_rawTypes_Provider_get_toInaccessibleType_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_noCast_rawTypes_Provider_get_toInaccessibleType_FAST_INIT_MODE_test.DaggerTestComponent
index e076a1d..059eaab 100644
--- a/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_noCast_rawTypes_Provider_get_toInaccessibleType_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_noCast_rawTypes_Provider_get_toInaccessibleType_FAST_INIT_MODE_test.DaggerTestComponent
@@ -2,8 +2,8 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DoubleCheck;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 import other.Subtype_Factory;
 import other.UsesSupertype;
 import other.UsesSupertype_Factory;
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_providerWhenBindsScopeGreaterThanDependencyScope_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_providerWhenBindsScopeGreaterThanDependencyScope_DEFAULT_MODE_test.DaggerTestComponent
index 149a5fe..a8a4aad 100644
--- a/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_providerWhenBindsScopeGreaterThanDependencyScope_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_providerWhenBindsScopeGreaterThanDependencyScope_DEFAULT_MODE_test.DaggerTestComponent
@@ -2,9 +2,9 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DoubleCheck;
+import dagger.internal.Provider;
 import dagger.internal.SingleCheck;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -15,7 +15,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -58,7 +59,7 @@
     }
 
     @Override
-    public Provider<Object> object() {
+    public javax.inject.Provider<Object> object() {
       return bindStringProvider;
     }
   }
diff --git a/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_providerWhenBindsScopeGreaterThanDependencyScope_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_providerWhenBindsScopeGreaterThanDependencyScope_FAST_INIT_MODE_test.DaggerTestComponent
index 09600ed..40dcf73 100644
--- a/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_providerWhenBindsScopeGreaterThanDependencyScope_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_providerWhenBindsScopeGreaterThanDependencyScope_FAST_INIT_MODE_test.DaggerTestComponent
@@ -2,9 +2,9 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DoubleCheck;
+import dagger.internal.Provider;
 import dagger.internal.SingleCheck;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -15,7 +15,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -58,7 +59,7 @@
     }
 
     @Override
-    public Provider<Object> object() {
+    public javax.inject.Provider<Object> object() {
       return bindStringProvider;
     }
 
diff --git a/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_toDoubleCheck_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_toDoubleCheck_DEFAULT_MODE_test.DaggerTestComponent
index 61f28dd..4877c33 100644
--- a/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_toDoubleCheck_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_toDoubleCheck_DEFAULT_MODE_test.DaggerTestComponent
@@ -2,9 +2,9 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DoubleCheck;
+import dagger.internal.Provider;
 import dagger.internal.SingleCheck;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -15,7 +15,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_toDoubleCheck_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_toDoubleCheck_FAST_INIT_MODE_test.DaggerTestComponent
index 323f241..08c5844 100644
--- a/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_toDoubleCheck_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_toDoubleCheck_FAST_INIT_MODE_test.DaggerTestComponent
@@ -2,9 +2,9 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DoubleCheck;
+import dagger.internal.Provider;
 import dagger.internal.SingleCheck;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -15,7 +15,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_toSingleCheck_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_toSingleCheck_DEFAULT_MODE_test.DaggerTestComponent
index ccbf8fc..e04aae6 100644
--- a/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_toSingleCheck_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_toSingleCheck_DEFAULT_MODE_test.DaggerTestComponent
@@ -2,9 +2,9 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DoubleCheck;
+import dagger.internal.Provider;
 import dagger.internal.SingleCheck;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -15,7 +15,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_toSingleCheck_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_toSingleCheck_FAST_INIT_MODE_test.DaggerTestComponent
index 1b7c505..2ca627d 100644
--- a/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_toSingleCheck_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_toSingleCheck_FAST_INIT_MODE_test.DaggerTestComponent
@@ -2,9 +2,9 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DoubleCheck;
+import dagger.internal.Provider;
 import dagger.internal.SingleCheck;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -15,7 +15,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_toUnscoped_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_toUnscoped_DEFAULT_MODE_test.DaggerTestComponent
index 227bed0..e3d5bf6 100644
--- a/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_toUnscoped_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_toUnscoped_DEFAULT_MODE_test.DaggerTestComponent
@@ -2,9 +2,9 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DoubleCheck;
+import dagger.internal.Provider;
 import dagger.internal.SingleCheck;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -15,7 +15,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_toUnscoped_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_toUnscoped_FAST_INIT_MODE_test.DaggerTestComponent
index dea546e..93973b6 100644
--- a/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_toUnscoped_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/DelegateRequestRepresentationTest_toUnscoped_FAST_INIT_MODE_test.DaggerTestComponent
@@ -2,9 +2,9 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DoubleCheck;
+import dagger.internal.Provider;
 import dagger.internal.SingleCheck;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -15,7 +15,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ElidedFactoriesTest_scopedBinding_onlyUsedInSubcomponent_DEFAULT_MODE_test.DaggerSimpleComponent b/javatests/dagger/internal/codegen/goldens/ElidedFactoriesTest_scopedBinding_onlyUsedInSubcomponent_DEFAULT_MODE_test.DaggerSimpleComponent
index cb7a35d..416d9c2 100644
--- a/javatests/dagger/internal/codegen/goldens/ElidedFactoriesTest_scopedBinding_onlyUsedInSubcomponent_DEFAULT_MODE_test.DaggerSimpleComponent
+++ b/javatests/dagger/internal/codegen/goldens/ElidedFactoriesTest_scopedBinding_onlyUsedInSubcomponent_DEFAULT_MODE_test.DaggerSimpleComponent
@@ -2,8 +2,8 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DoubleCheck;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -14,7 +14,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerSimpleComponent {
   private DaggerSimpleComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ElidedFactoriesTest_scopedBinding_onlyUsedInSubcomponent_FAST_INIT_MODE_test.DaggerSimpleComponent b/javatests/dagger/internal/codegen/goldens/ElidedFactoriesTest_scopedBinding_onlyUsedInSubcomponent_FAST_INIT_MODE_test.DaggerSimpleComponent
index 94c174c..64762bd 100644
--- a/javatests/dagger/internal/codegen/goldens/ElidedFactoriesTest_scopedBinding_onlyUsedInSubcomponent_FAST_INIT_MODE_test.DaggerSimpleComponent
+++ b/javatests/dagger/internal/codegen/goldens/ElidedFactoriesTest_scopedBinding_onlyUsedInSubcomponent_FAST_INIT_MODE_test.DaggerSimpleComponent
@@ -2,8 +2,8 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DoubleCheck;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -14,7 +14,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerSimpleComponent {
   private DaggerSimpleComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ElidedFactoriesTest_simpleComponent_DEFAULT_MODE_test.DaggerSimpleComponent b/javatests/dagger/internal/codegen/goldens/ElidedFactoriesTest_simpleComponent_DEFAULT_MODE_test.DaggerSimpleComponent
index a5f9992..39dc9c5 100644
--- a/javatests/dagger/internal/codegen/goldens/ElidedFactoriesTest_simpleComponent_DEFAULT_MODE_test.DaggerSimpleComponent
+++ b/javatests/dagger/internal/codegen/goldens/ElidedFactoriesTest_simpleComponent_DEFAULT_MODE_test.DaggerSimpleComponent
@@ -12,7 +12,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerSimpleComponent {
   private DaggerSimpleComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ElidedFactoriesTest_simpleComponent_FAST_INIT_MODE_test.DaggerSimpleComponent b/javatests/dagger/internal/codegen/goldens/ElidedFactoriesTest_simpleComponent_FAST_INIT_MODE_test.DaggerSimpleComponent
index a5f9992..39dc9c5 100644
--- a/javatests/dagger/internal/codegen/goldens/ElidedFactoriesTest_simpleComponent_FAST_INIT_MODE_test.DaggerSimpleComponent
+++ b/javatests/dagger/internal/codegen/goldens/ElidedFactoriesTest_simpleComponent_FAST_INIT_MODE_test.DaggerSimpleComponent
@@ -12,7 +12,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerSimpleComponent {
   private DaggerSimpleComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ElidedFactoriesTest_simpleComponent_injectsProviderOf_dependsOnScoped_DEFAULT_MODE_test.DaggerSimpleComponent b/javatests/dagger/internal/codegen/goldens/ElidedFactoriesTest_simpleComponent_injectsProviderOf_dependsOnScoped_DEFAULT_MODE_test.DaggerSimpleComponent
index 32382c8..d11d1ab 100644
--- a/javatests/dagger/internal/codegen/goldens/ElidedFactoriesTest_simpleComponent_injectsProviderOf_dependsOnScoped_DEFAULT_MODE_test.DaggerSimpleComponent
+++ b/javatests/dagger/internal/codegen/goldens/ElidedFactoriesTest_simpleComponent_injectsProviderOf_dependsOnScoped_DEFAULT_MODE_test.DaggerSimpleComponent
@@ -2,8 +2,8 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DoubleCheck;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -14,7 +14,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerSimpleComponent {
   private DaggerSimpleComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ElidedFactoriesTest_simpleComponent_injectsProviderOf_dependsOnScoped_FAST_INIT_MODE_test.DaggerSimpleComponent b/javatests/dagger/internal/codegen/goldens/ElidedFactoriesTest_simpleComponent_injectsProviderOf_dependsOnScoped_FAST_INIT_MODE_test.DaggerSimpleComponent
index 381eeeb..acf83f2 100644
--- a/javatests/dagger/internal/codegen/goldens/ElidedFactoriesTest_simpleComponent_injectsProviderOf_dependsOnScoped_FAST_INIT_MODE_test.DaggerSimpleComponent
+++ b/javatests/dagger/internal/codegen/goldens/ElidedFactoriesTest_simpleComponent_injectsProviderOf_dependsOnScoped_FAST_INIT_MODE_test.DaggerSimpleComponent
@@ -2,8 +2,8 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DoubleCheck;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -14,7 +14,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerSimpleComponent {
   private DaggerSimpleComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/InaccessibleTypeBindsTest_inaccessibleTypeBoundInALoopScoped_DEFAULT_JAVA7_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/InaccessibleTypeBindsTest_inaccessibleTypeBoundInALoopScoped_DEFAULT_JAVA7_MODE_test.DaggerTestComponent
index 9e10117..e752840 100644
--- a/javatests/dagger/internal/codegen/goldens/InaccessibleTypeBindsTest_inaccessibleTypeBoundInALoopScoped_DEFAULT_JAVA7_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/InaccessibleTypeBindsTest_inaccessibleTypeBoundInALoopScoped_DEFAULT_JAVA7_MODE_test.DaggerTestComponent
@@ -3,8 +3,8 @@
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DelegateFactory;
 import dagger.internal.DoubleCheck;
+import dagger.internal.Provider;
 import javax.annotation.Generated;
-import javax.inject.Provider;
 import other.FooImpl_Factory;
 import other.OtherEntryPoint;
 import other.OtherEntryPoint_Factory;
@@ -18,7 +18,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -71,4 +72,4 @@
       return OtherEntryPoint_Factory.newInstance(fooImpl());
     }
   }
-}
\ No newline at end of file
+}
diff --git a/javatests/dagger/internal/codegen/goldens/InaccessibleTypeBindsTest_inaccessibleTypeBoundInALoopScoped_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/InaccessibleTypeBindsTest_inaccessibleTypeBoundInALoopScoped_DEFAULT_MODE_test.DaggerTestComponent
index 9c25066..7990079 100644
--- a/javatests/dagger/internal/codegen/goldens/InaccessibleTypeBindsTest_inaccessibleTypeBoundInALoopScoped_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/InaccessibleTypeBindsTest_inaccessibleTypeBoundInALoopScoped_DEFAULT_MODE_test.DaggerTestComponent
@@ -3,8 +3,8 @@
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DelegateFactory;
 import dagger.internal.DoubleCheck;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 import other.FooImpl_Factory;
 import other.OtherEntryPoint;
 import other.OtherEntryPoint_Factory;
@@ -18,7 +18,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/InaccessibleTypeBindsTest_inaccessibleTypeBoundInALoopScoped_FAST_INIT_JAVA7_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/InaccessibleTypeBindsTest_inaccessibleTypeBoundInALoopScoped_FAST_INIT_JAVA7_MODE_test.DaggerTestComponent
index 9642f33..bf80e63 100644
--- a/javatests/dagger/internal/codegen/goldens/InaccessibleTypeBindsTest_inaccessibleTypeBoundInALoopScoped_FAST_INIT_JAVA7_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/InaccessibleTypeBindsTest_inaccessibleTypeBoundInALoopScoped_FAST_INIT_JAVA7_MODE_test.DaggerTestComponent
@@ -3,8 +3,8 @@
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DelegateFactory;
 import dagger.internal.DoubleCheck;
+import dagger.internal.Provider;
 import javax.annotation.Generated;
-import javax.inject.Provider;
 import other.FooImpl_Factory;
 import other.OtherEntryPoint;
 import other.OtherEntryPoint_Factory;
@@ -18,7 +18,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -93,4 +94,4 @@
       }
     }
   }
-}
\ No newline at end of file
+}
diff --git a/javatests/dagger/internal/codegen/goldens/InaccessibleTypeBindsTest_inaccessibleTypeBoundInALoopScoped_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/InaccessibleTypeBindsTest_inaccessibleTypeBoundInALoopScoped_FAST_INIT_MODE_test.DaggerTestComponent
index a18b8a4..f92f558 100644
--- a/javatests/dagger/internal/codegen/goldens/InaccessibleTypeBindsTest_inaccessibleTypeBoundInALoopScoped_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/InaccessibleTypeBindsTest_inaccessibleTypeBoundInALoopScoped_FAST_INIT_MODE_test.DaggerTestComponent
@@ -3,8 +3,8 @@
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DelegateFactory;
 import dagger.internal.DoubleCheck;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 import other.FooImpl_Factory;
 import other.OtherEntryPoint;
 import other.OtherEntryPoint_Factory;
@@ -18,7 +18,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/InaccessibleTypeBindsTest_inaccessibleTypeBoundInALoop_DEFAULT_JAVA7_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/InaccessibleTypeBindsTest_inaccessibleTypeBoundInALoop_DEFAULT_JAVA7_MODE_test.DaggerTestComponent
index e377365..f13d94a 100644
--- a/javatests/dagger/internal/codegen/goldens/InaccessibleTypeBindsTest_inaccessibleTypeBoundInALoop_DEFAULT_JAVA7_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/InaccessibleTypeBindsTest_inaccessibleTypeBoundInALoop_DEFAULT_JAVA7_MODE_test.DaggerTestComponent
@@ -2,8 +2,8 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DelegateFactory;
+import dagger.internal.Provider;
 import javax.annotation.Generated;
-import javax.inject.Provider;
 import other.FooImpl_Factory;
 import other.OtherEntryPoint;
 import other.OtherEntryPoint_Factory;
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -67,4 +68,4 @@
       return OtherEntryPoint_Factory.newInstance(fooImpl());
     }
   }
-}
\ No newline at end of file
+}
diff --git a/javatests/dagger/internal/codegen/goldens/InaccessibleTypeBindsTest_inaccessibleTypeBoundInALoop_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/InaccessibleTypeBindsTest_inaccessibleTypeBoundInALoop_DEFAULT_MODE_test.DaggerTestComponent
index c1345ad..30be4f1 100644
--- a/javatests/dagger/internal/codegen/goldens/InaccessibleTypeBindsTest_inaccessibleTypeBoundInALoop_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/InaccessibleTypeBindsTest_inaccessibleTypeBoundInALoop_DEFAULT_MODE_test.DaggerTestComponent
@@ -2,8 +2,8 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DelegateFactory;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 import other.FooImpl_Factory;
 import other.OtherEntryPoint;
 import other.OtherEntryPoint_Factory;
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/InaccessibleTypeBindsTest_inaccessibleTypeBoundInALoop_FAST_INIT_JAVA7_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/InaccessibleTypeBindsTest_inaccessibleTypeBoundInALoop_FAST_INIT_JAVA7_MODE_test.DaggerTestComponent
index c6db8da..27a30fb 100644
--- a/javatests/dagger/internal/codegen/goldens/InaccessibleTypeBindsTest_inaccessibleTypeBoundInALoop_FAST_INIT_JAVA7_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/InaccessibleTypeBindsTest_inaccessibleTypeBoundInALoop_FAST_INIT_JAVA7_MODE_test.DaggerTestComponent
@@ -2,8 +2,8 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DelegateFactory;
+import dagger.internal.Provider;
 import javax.annotation.Generated;
-import javax.inject.Provider;
 import other.FooImpl_Factory;
 import other.OtherEntryPoint;
 import other.OtherEntryPoint_Factory;
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -89,4 +90,4 @@
       }
     }
   }
-}
\ No newline at end of file
+}
diff --git a/javatests/dagger/internal/codegen/goldens/InaccessibleTypeBindsTest_inaccessibleTypeBoundInALoop_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/InaccessibleTypeBindsTest_inaccessibleTypeBoundInALoop_FAST_INIT_MODE_test.DaggerTestComponent
index 8e2e959..7146c06 100644
--- a/javatests/dagger/internal/codegen/goldens/InaccessibleTypeBindsTest_inaccessibleTypeBoundInALoop_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/InaccessibleTypeBindsTest_inaccessibleTypeBoundInALoop_FAST_INIT_MODE_test.DaggerTestComponent
@@ -2,8 +2,8 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DelegateFactory;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 import other.FooImpl_Factory;
 import other.OtherEntryPoint;
 import other.OtherEntryPoint_Factory;
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/InaccessibleTypeBindsTest_scopedInaccessibleTypeBound_DEFAULT_JAVA7_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/InaccessibleTypeBindsTest_scopedInaccessibleTypeBound_DEFAULT_JAVA7_MODE_test.DaggerTestComponent
index d39656c..01ffe86 100644
--- a/javatests/dagger/internal/codegen/goldens/InaccessibleTypeBindsTest_scopedInaccessibleTypeBound_DEFAULT_JAVA7_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/InaccessibleTypeBindsTest_scopedInaccessibleTypeBound_DEFAULT_JAVA7_MODE_test.DaggerTestComponent
@@ -2,8 +2,8 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DoubleCheck;
+import dagger.internal.Provider;
 import javax.annotation.Generated;
-import javax.inject.Provider;
 import other.FooImpl_Factory;
 
 @DaggerGenerated
@@ -15,7 +15,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -59,4 +60,4 @@
       return bindProvider.get();
     }
   }
-}
\ No newline at end of file
+}
diff --git a/javatests/dagger/internal/codegen/goldens/InaccessibleTypeBindsTest_scopedInaccessibleTypeBound_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/InaccessibleTypeBindsTest_scopedInaccessibleTypeBound_DEFAULT_MODE_test.DaggerTestComponent
index 73dda53..ca51d3f 100644
--- a/javatests/dagger/internal/codegen/goldens/InaccessibleTypeBindsTest_scopedInaccessibleTypeBound_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/InaccessibleTypeBindsTest_scopedInaccessibleTypeBound_DEFAULT_MODE_test.DaggerTestComponent
@@ -2,8 +2,8 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DoubleCheck;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 import other.FooImpl_Factory;
 
 @DaggerGenerated
@@ -15,7 +15,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/InaccessibleTypeBindsTest_scopedInaccessibleTypeBound_FAST_INIT_JAVA7_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/InaccessibleTypeBindsTest_scopedInaccessibleTypeBound_FAST_INIT_JAVA7_MODE_test.DaggerTestComponent
index 7c0c68d..ce6bcdf 100644
--- a/javatests/dagger/internal/codegen/goldens/InaccessibleTypeBindsTest_scopedInaccessibleTypeBound_FAST_INIT_JAVA7_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/InaccessibleTypeBindsTest_scopedInaccessibleTypeBound_FAST_INIT_JAVA7_MODE_test.DaggerTestComponent
@@ -2,8 +2,8 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DoubleCheck;
+import dagger.internal.Provider;
 import javax.annotation.Generated;
-import javax.inject.Provider;
 import other.FooImpl_Factory;
 
 @DaggerGenerated
@@ -15,7 +15,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -85,4 +86,4 @@
       }
     }
   }
-}
\ No newline at end of file
+}
diff --git a/javatests/dagger/internal/codegen/goldens/InaccessibleTypeBindsTest_scopedInaccessibleTypeBound_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/InaccessibleTypeBindsTest_scopedInaccessibleTypeBound_FAST_INIT_MODE_test.DaggerTestComponent
index 84ae12f..c39381b 100644
--- a/javatests/dagger/internal/codegen/goldens/InaccessibleTypeBindsTest_scopedInaccessibleTypeBound_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/InaccessibleTypeBindsTest_scopedInaccessibleTypeBound_FAST_INIT_MODE_test.DaggerTestComponent
@@ -2,8 +2,8 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DoubleCheck;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 import other.FooImpl_Factory;
 
 @DaggerGenerated
@@ -15,7 +15,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_basicNameCollision_test.InjectConstructor_Factory b/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_basicNameCollision_test.InjectConstructor_Factory
index 00ee9af..8488aba 100644
--- a/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_basicNameCollision_test.InjectConstructor_Factory
+++ b/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_basicNameCollision_test.InjectConstructor_Factory
@@ -18,7 +18,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class InjectConstructor_Factory implements Factory<InjectConstructor> {
   private final Provider<other.pkg.Factory> factoryProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_boundedGenerics_test.GenericClass_Factory b/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_boundedGenerics_test.GenericClass_Factory
index 012d3d0..143d1ed 100644
--- a/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_boundedGenerics_test.GenericClass_Factory
+++ b/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_boundedGenerics_test.GenericClass_Factory
@@ -19,7 +19,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class GenericClass_Factory<A extends Number & Comparable<A>, B extends List<? extends String>, C extends List<? super String>> implements Factory<GenericClass<A, B, C>> {
   private final Provider<A> aProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_fieldAndMethodGenerics_test.GenericClass_Factory b/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_fieldAndMethodGenerics_test.GenericClass_Factory
index a3d5bf2..ab6d9ae 100644
--- a/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_fieldAndMethodGenerics_test.GenericClass_Factory
+++ b/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_fieldAndMethodGenerics_test.GenericClass_Factory
@@ -18,7 +18,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class GenericClass_Factory<A, B> implements Factory<GenericClass<A, B>> {
   private final Provider<A> aProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_genericClassWithNoDependencies_test.GenericClass_Factory b/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_genericClassWithNoDependencies_test.GenericClass_Factory
index d43e19f..95e0038 100644
--- a/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_genericClassWithNoDependencies_test.GenericClass_Factory
+++ b/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_genericClassWithNoDependencies_test.GenericClass_Factory
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class GenericClass_Factory<T> implements Factory<GenericClass<T>> {
   @Override
diff --git a/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_injectConstructorAndMembersInjection_test.AllInjections_Factory b/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_injectConstructorAndMembersInjection_test.AllInjections_Factory
index 71d791b..0c2475c 100644
--- a/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_injectConstructorAndMembersInjection_test.AllInjections_Factory
+++ b/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_injectConstructorAndMembersInjection_test.AllInjections_Factory
@@ -18,7 +18,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class AllInjections_Factory implements Factory<AllInjections> {
   private final Provider<String> sProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_injectConstructorOnGenericClass_test.GenericClass_Factory b/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_injectConstructorOnGenericClass_test.GenericClass_Factory
index 67d5808..6ac47e9 100644
--- a/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_injectConstructorOnGenericClass_test.GenericClass_Factory
+++ b/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_injectConstructorOnGenericClass_test.GenericClass_Factory
@@ -18,7 +18,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class GenericClass_Factory<T> implements Factory<GenericClass<T>> {
   private final Provider<T> tProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_injectConstructor_test.InjectConstructor_Factory b/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_injectConstructor_test.InjectConstructor_Factory
index bf20ec4..638815e 100644
--- a/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_injectConstructor_test.InjectConstructor_Factory
+++ b/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_injectConstructor_test.InjectConstructor_Factory
@@ -18,7 +18,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class InjectConstructor_Factory implements Factory<InjectConstructor> {
   private final Provider<String> sProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_multipleSameTypesWithGenericsAndQualifiersAndLazies_test.GenericClass_Factory b/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_multipleSameTypesWithGenericsAndQualifiersAndLazies_test.GenericClass_Factory
index bfc28d0..a5b93b8 100644
--- a/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_multipleSameTypesWithGenericsAndQualifiersAndLazies_test.GenericClass_Factory
+++ b/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_multipleSameTypesWithGenericsAndQualifiersAndLazies_test.GenericClass_Factory
@@ -20,7 +20,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class GenericClass_Factory<A, B> implements Factory<GenericClass<A, B>> {
   private final Provider<A> aProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_nestedNameCollision_test.InjectConstructor_Factory b/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_nestedNameCollision_test.InjectConstructor_Factory
index aba20ce..f3337a1 100644
--- a/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_nestedNameCollision_test.InjectConstructor_Factory
+++ b/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_nestedNameCollision_test.InjectConstructor_Factory
@@ -19,7 +19,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class InjectConstructor_Factory implements Factory<InjectConstructor> {
   private final Provider<Outer.Factory> factoryProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_noDeps_test.SimpleType_Factory b/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_noDeps_test.SimpleType_Factory
index 67f856c..41c6c72 100644
--- a/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_noDeps_test.SimpleType_Factory
+++ b/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_noDeps_test.SimpleType_Factory
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class SimpleType_Factory implements Factory<SimpleType> {
   @Override
diff --git a/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_samePackageNameCollision_test.InjectConstructor_Factory b/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_samePackageNameCollision_test.InjectConstructor_Factory
index 0e22f2d..f65c9c5 100644
--- a/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_samePackageNameCollision_test.InjectConstructor_Factory
+++ b/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_samePackageNameCollision_test.InjectConstructor_Factory
@@ -18,7 +18,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class InjectConstructor_Factory implements Factory<InjectConstructor> {
   private final Provider<other.pkg.CommonName> otherPackageProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_simpleComponentWithNesting_test.OuterType_A_Factory b/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_simpleComponentWithNesting_test.OuterType_A_Factory
index 371c716..424c614 100644
--- a/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_simpleComponentWithNesting_test.OuterType_A_Factory
+++ b/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_simpleComponentWithNesting_test.OuterType_A_Factory
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class OuterType_A_Factory implements Factory<OuterType.A> {
   @Override
diff --git a/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_testBaseClassQualifierMetadata_test.FooBase_Factory b/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_testBaseClassQualifierMetadata_test.FooBase_Factory
index e2b44b5..1f00f95 100644
--- a/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_testBaseClassQualifierMetadata_test.FooBase_Factory
+++ b/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_testBaseClassQualifierMetadata_test.FooBase_Factory
@@ -18,7 +18,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class FooBase_Factory implements Factory<FooBase> {
   private final Provider<Integer> iProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_testBaseClassQualifierMetadata_test.FooBase_MembersInjector b/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_testBaseClassQualifierMetadata_test.FooBase_MembersInjector
index e93005b..5e865ff 100644
--- a/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_testBaseClassQualifierMetadata_test.FooBase_MembersInjector
+++ b/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_testBaseClassQualifierMetadata_test.FooBase_MembersInjector
@@ -20,7 +20,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class FooBase_MembersInjector implements MembersInjector<FooBase> {
   private final Provider<String> injectFieldProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_testBaseClassQualifierMetadata_test.Foo_Factory b/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_testBaseClassQualifierMetadata_test.Foo_Factory
index 69bc962..48d9102 100644
--- a/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_testBaseClassQualifierMetadata_test.Foo_Factory
+++ b/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_testBaseClassQualifierMetadata_test.Foo_Factory
@@ -18,7 +18,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class Foo_Factory implements Factory<Foo> {
   private final Provider<Integer> iProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_testBaseClassQualifierMetadata_test.Foo_MembersInjector b/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_testBaseClassQualifierMetadata_test.Foo_MembersInjector
index 36d5b1d..7485836 100644
--- a/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_testBaseClassQualifierMetadata_test.Foo_MembersInjector
+++ b/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_testBaseClassQualifierMetadata_test.Foo_MembersInjector
@@ -20,7 +20,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class Foo_MembersInjector implements MembersInjector<Foo> {
   private final Provider<String> injectFieldProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_testComplexQualifierMetadata_test.SomeBinding_Factory b/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_testComplexQualifierMetadata_test.SomeBinding_Factory
index 9a4b6e6..2d100f6 100644
--- a/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_testComplexQualifierMetadata_test.SomeBinding_Factory
+++ b/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_testComplexQualifierMetadata_test.SomeBinding_Factory
@@ -21,7 +21,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class SomeBinding_Factory implements Factory<SomeBinding> {
   private final Provider<String> str1Provider;
diff --git a/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_testComplexQualifierMetadata_test.SomeBinding_MembersInjector b/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_testComplexQualifierMetadata_test.SomeBinding_MembersInjector
index a30a9df..a5707af 100644
--- a/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_testComplexQualifierMetadata_test.SomeBinding_MembersInjector
+++ b/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_testComplexQualifierMetadata_test.SomeBinding_MembersInjector
@@ -20,7 +20,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class SomeBinding_MembersInjector implements MembersInjector<SomeBinding> {
   private final Provider<String> injectFieldProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_testQualifierMetadata_test.SomeBinding_Factory b/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_testQualifierMetadata_test.SomeBinding_Factory
index f830866..40690b3 100644
--- a/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_testQualifierMetadata_test.SomeBinding_Factory
+++ b/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_testQualifierMetadata_test.SomeBinding_Factory
@@ -18,7 +18,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class SomeBinding_Factory implements Factory<SomeBinding> {
   private final Provider<Double> dProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_testQualifierMetadata_test.SomeBinding_MembersInjector b/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_testQualifierMetadata_test.SomeBinding_MembersInjector
index f17203d..a8ca780 100644
--- a/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_testQualifierMetadata_test.SomeBinding_MembersInjector
+++ b/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_testQualifierMetadata_test.SomeBinding_MembersInjector
@@ -20,7 +20,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class SomeBinding_MembersInjector implements MembersInjector<SomeBinding> {
   private final Provider<String> injectFieldProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_testScopedMetadataWithCustomScope_test.ScopedBinding_Factory b/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_testScopedMetadataWithCustomScope_test.ScopedBinding_Factory
index 8220ee6..d949bdd 100644
--- a/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_testScopedMetadataWithCustomScope_test.ScopedBinding_Factory
+++ b/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_testScopedMetadataWithCustomScope_test.ScopedBinding_Factory
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class ScopedBinding_Factory implements Factory<ScopedBinding> {
   @Override
diff --git a/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_testScopedMetadata_test.ScopedBinding_Factory b/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_testScopedMetadata_test.ScopedBinding_Factory
index 871fe75..5682bb0 100644
--- a/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_testScopedMetadata_test.ScopedBinding_Factory
+++ b/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_testScopedMetadata_test.ScopedBinding_Factory
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class ScopedBinding_Factory implements Factory<ScopedBinding> {
   @Override
diff --git a/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_twoGenericTypes_test.GenericClass_Factory b/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_twoGenericTypes_test.GenericClass_Factory
index 39e73da..116df17 100644
--- a/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_twoGenericTypes_test.GenericClass_Factory
+++ b/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_twoGenericTypes_test.GenericClass_Factory
@@ -18,7 +18,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class GenericClass_Factory<A, B> implements Factory<GenericClass<A, B>> {
   private final Provider<A> aProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_wildcardDependency_test.InjectConstructor_Factory b/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_wildcardDependency_test.InjectConstructor_Factory
index d5758e7..681a4b6 100644
--- a/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_wildcardDependency_test.InjectConstructor_Factory
+++ b/javatests/dagger/internal/codegen/goldens/InjectConstructorFactoryGeneratorTest_wildcardDependency_test.InjectConstructor_Factory
@@ -19,7 +19,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class InjectConstructor_Factory implements Factory<InjectConstructor> {
   private final Provider<List<?>> objectsProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/LazyClassKeyMapBindingComponentProcessorTest_mapBindingsWithInaccessibleKeys_DEFAULT_MODE_mapkeys.MapModule_ClassKeyMapKey b/javatests/dagger/internal/codegen/goldens/LazyClassKeyMapBindingComponentProcessorTest_mapBindingsWithInaccessibleKeys_DEFAULT_MODE_mapkeys.MapModule_ClassKeyMapKey
new file mode 100644
index 0000000..63a07ab
--- /dev/null
+++ b/javatests/dagger/internal/codegen/goldens/LazyClassKeyMapBindingComponentProcessorTest_mapBindingsWithInaccessibleKeys_DEFAULT_MODE_mapkeys.MapModule_ClassKeyMapKey
@@ -0,0 +1,30 @@
+package mapkeys;
+
+import dagger.internal.DaggerGenerated;
+import dagger.internal.KeepFieldType;
+import javax.annotation.processing.Generated;
+
+@DaggerGenerated
+@Generated(
+    value = "dagger.internal.codegen.ComponentProcessor",
+    comments = "https://dagger.dev"
+)
+@SuppressWarnings({
+    "unchecked",
+    "rawtypes",
+    "KotlinInternal",
+    "KotlinInternalInJava",
+    "cast"
+})
+public final class MapModule_ClassKeyMapKey {
+  @KeepFieldType
+  MapKeys.Inaccessible className;
+
+  private MapModule_ClassKeyMapKey() {
+  }
+
+  public static Class<?> create() {
+    return MapKeys.Inaccessible.class;
+  }
+}
+
diff --git a/javatests/dagger/internal/codegen/goldens/LazyClassKeyMapBindingComponentProcessorTest_mapBindingsWithInaccessibleKeys_DEFAULT_MODE_mapkeys.MapModule_ComplexKeyWithInaccessibleAnnotationValueMapKey b/javatests/dagger/internal/codegen/goldens/LazyClassKeyMapBindingComponentProcessorTest_mapBindingsWithInaccessibleKeys_DEFAULT_MODE_mapkeys.MapModule_ComplexKeyWithInaccessibleAnnotationValueMapKey
new file mode 100644
index 0000000..3e00ffd
--- /dev/null
+++ b/javatests/dagger/internal/codegen/goldens/LazyClassKeyMapBindingComponentProcessorTest_mapBindingsWithInaccessibleKeys_DEFAULT_MODE_mapkeys.MapModule_ComplexKeyWithInaccessibleAnnotationValueMapKey
@@ -0,0 +1,26 @@
+package mapkeys;
+
+import dagger.internal.DaggerGenerated;
+import javax.annotation.processing.Generated;
+
+@DaggerGenerated
+@Generated(
+    value = "dagger.internal.codegen.ComponentProcessor",
+    comments = "https://dagger.dev"
+)
+@SuppressWarnings({
+    "unchecked",
+    "rawtypes",
+    "KotlinInternal",
+    "KotlinInternalInJava",
+    "cast"
+})
+public final class MapModule_ComplexKeyWithInaccessibleAnnotationValueMapKey {
+  private MapModule_ComplexKeyWithInaccessibleAnnotationValueMapKey() {
+  }
+
+  public static MapKeys.ComplexKey create() {
+    return MapKeys_ComplexKeyCreator.createComplexKey(new Class[] {String.class}, String.class, MapKeys_ComplexKeyCreator.createLazyClassKey(MapKeys.Inaccessible.class));
+  }
+}
+
diff --git a/javatests/dagger/internal/codegen/goldens/LazyClassKeyMapBindingComponentProcessorTest_mapBindingsWithInaccessibleKeys_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/LazyClassKeyMapBindingComponentProcessorTest_mapBindingsWithInaccessibleKeys_DEFAULT_MODE_test.DaggerTestComponent
new file mode 100644
index 0000000..eff6a40
--- /dev/null
+++ b/javatests/dagger/internal/codegen/goldens/LazyClassKeyMapBindingComponentProcessorTest_mapBindingsWithInaccessibleKeys_DEFAULT_MODE_test.DaggerTestComponent
@@ -0,0 +1,99 @@
+package test;
+
+import com.google.common.collect.ImmutableMap;
+import dagger.internal.DaggerGenerated;
+import dagger.internal.IdentifierNameString;
+import dagger.internal.LazyClassKeyMap;
+import dagger.internal.MapFactory;
+import dagger.internal.Provider;
+import java.util.Map;
+import javax.annotation.processing.Generated;
+import mapkeys.MapKeys;
+import mapkeys.MapModule;
+import mapkeys.MapModule_ClassKeyFactory;
+import mapkeys.MapModule_ComplexKeyWithInaccessibleAnnotationValueFactory;
+import mapkeys.MapModule_ComplexKeyWithInaccessibleAnnotationValueMapKey;
+import mapkeys.MapModule_ComplexKeyWithInaccessibleArrayValueFactory;
+import mapkeys.MapModule_ComplexKeyWithInaccessibleArrayValueMapKey;
+import mapkeys.MapModule_ComplexKeyWithInaccessibleValueFactory;
+import mapkeys.MapModule_ComplexKeyWithInaccessibleValueMapKey;
+
+@DaggerGenerated
+@Generated(
+    value = "dagger.internal.codegen.ComponentProcessor",
+    comments = "https://dagger.dev"
+)
+@SuppressWarnings({
+    "unchecked",
+    "rawtypes",
+    "KotlinInternal",
+    "KotlinInternalInJava",
+    "cast"
+})
+final class DaggerTestComponent {
+  private DaggerTestComponent() {
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public static TestComponent create() {
+    return new Builder().build();
+  }
+
+  static final class Builder {
+    private Builder() {
+    }
+
+    public TestComponent build() {
+      return new TestComponentImpl();
+    }
+  }
+
+  private static final class TestComponentImpl implements TestComponent {
+    private final TestComponentImpl testComponentImpl = this;
+
+    private Provider<Map<Class<?>, Integer>> mapOfClassOfAndIntegerProvider;
+
+    private Provider<Map<MapKeys.ComplexKey, Integer>> mapOfComplexKeyAndIntegerProvider;
+
+    private TestComponentImpl() {
+
+      initialize();
+
+    }
+
+    @SuppressWarnings("unchecked")
+    private void initialize() {
+      this.mapOfClassOfAndIntegerProvider = LazyClassKeyMap.Factory.<Integer>of(MapFactory.<String, Integer>builder(1).put(LazyClassKeyProvider.mapkeys_MapKeys_Inaccessible, MapModule_ClassKeyFactory.create()).build());
+      this.mapOfComplexKeyAndIntegerProvider = MapFactory.<MapKeys.ComplexKey, Integer>builder(3).put(MapModule_ComplexKeyWithInaccessibleValueMapKey.create(), MapModule_ComplexKeyWithInaccessibleValueFactory.create()).put(MapModule_ComplexKeyWithInaccessibleArrayValueMapKey.create(), MapModule_ComplexKeyWithInaccessibleArrayValueFactory.create()).put(MapModule_ComplexKeyWithInaccessibleAnnotationValueMapKey.create(), MapModule_ComplexKeyWithInaccessibleAnnotationValueFactory.create()).build();
+    }
+
+    @Override
+    public Map<Class<?>, Integer> classKey() {
+      return LazyClassKeyMap.<Integer>of(ImmutableMap.<String, Integer>of(LazyClassKeyProvider.mapkeys_MapKeys_Inaccessible, MapModule.classKey()));
+    }
+
+    @Override
+    public javax.inject.Provider<Map<Class<?>, Integer>> classKeyProvider() {
+      return mapOfClassOfAndIntegerProvider;
+    }
+
+    @Override
+    public Map<MapKeys.ComplexKey, Integer> complexKey() {
+      return ImmutableMap.<MapKeys.ComplexKey, Integer>of(MapModule_ComplexKeyWithInaccessibleValueMapKey.create(), MapModule.complexKeyWithInaccessibleValue(), MapModule_ComplexKeyWithInaccessibleArrayValueMapKey.create(), MapModule.complexKeyWithInaccessibleArrayValue(), MapModule_ComplexKeyWithInaccessibleAnnotationValueMapKey.create(), MapModule.complexKeyWithInaccessibleAnnotationValue());
+    }
+
+    @Override
+    public javax.inject.Provider<Map<MapKeys.ComplexKey, Integer>> complexKeyProvider() {
+      return mapOfComplexKeyAndIntegerProvider;
+    }
+
+    @IdentifierNameString
+    private static final class LazyClassKeyProvider {
+      static String mapkeys_MapKeys_Inaccessible = "mapkeys.MapKeys$Inaccessible";
+    }
+  }
+}
+
diff --git a/javatests/dagger/internal/codegen/goldens/LazyClassKeyMapBindingComponentProcessorTest_mapBindingsWithInaccessibleKeys_FAST_INIT_MODE_mapkeys.MapModule_ClassKeyMapKey b/javatests/dagger/internal/codegen/goldens/LazyClassKeyMapBindingComponentProcessorTest_mapBindingsWithInaccessibleKeys_FAST_INIT_MODE_mapkeys.MapModule_ClassKeyMapKey
new file mode 100644
index 0000000..63a07ab
--- /dev/null
+++ b/javatests/dagger/internal/codegen/goldens/LazyClassKeyMapBindingComponentProcessorTest_mapBindingsWithInaccessibleKeys_FAST_INIT_MODE_mapkeys.MapModule_ClassKeyMapKey
@@ -0,0 +1,30 @@
+package mapkeys;
+
+import dagger.internal.DaggerGenerated;
+import dagger.internal.KeepFieldType;
+import javax.annotation.processing.Generated;
+
+@DaggerGenerated
+@Generated(
+    value = "dagger.internal.codegen.ComponentProcessor",
+    comments = "https://dagger.dev"
+)
+@SuppressWarnings({
+    "unchecked",
+    "rawtypes",
+    "KotlinInternal",
+    "KotlinInternalInJava",
+    "cast"
+})
+public final class MapModule_ClassKeyMapKey {
+  @KeepFieldType
+  MapKeys.Inaccessible className;
+
+  private MapModule_ClassKeyMapKey() {
+  }
+
+  public static Class<?> create() {
+    return MapKeys.Inaccessible.class;
+  }
+}
+
diff --git a/javatests/dagger/internal/codegen/goldens/LazyClassKeyMapBindingComponentProcessorTest_mapBindingsWithInaccessibleKeys_FAST_INIT_MODE_mapkeys.MapModule_ComplexKeyWithInaccessibleAnnotationValueMapKey b/javatests/dagger/internal/codegen/goldens/LazyClassKeyMapBindingComponentProcessorTest_mapBindingsWithInaccessibleKeys_FAST_INIT_MODE_mapkeys.MapModule_ComplexKeyWithInaccessibleAnnotationValueMapKey
new file mode 100644
index 0000000..3e00ffd
--- /dev/null
+++ b/javatests/dagger/internal/codegen/goldens/LazyClassKeyMapBindingComponentProcessorTest_mapBindingsWithInaccessibleKeys_FAST_INIT_MODE_mapkeys.MapModule_ComplexKeyWithInaccessibleAnnotationValueMapKey
@@ -0,0 +1,26 @@
+package mapkeys;
+
+import dagger.internal.DaggerGenerated;
+import javax.annotation.processing.Generated;
+
+@DaggerGenerated
+@Generated(
+    value = "dagger.internal.codegen.ComponentProcessor",
+    comments = "https://dagger.dev"
+)
+@SuppressWarnings({
+    "unchecked",
+    "rawtypes",
+    "KotlinInternal",
+    "KotlinInternalInJava",
+    "cast"
+})
+public final class MapModule_ComplexKeyWithInaccessibleAnnotationValueMapKey {
+  private MapModule_ComplexKeyWithInaccessibleAnnotationValueMapKey() {
+  }
+
+  public static MapKeys.ComplexKey create() {
+    return MapKeys_ComplexKeyCreator.createComplexKey(new Class[] {String.class}, String.class, MapKeys_ComplexKeyCreator.createLazyClassKey(MapKeys.Inaccessible.class));
+  }
+}
+
diff --git a/javatests/dagger/internal/codegen/goldens/LazyClassKeyMapBindingComponentProcessorTest_mapBindingsWithInaccessibleKeys_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/LazyClassKeyMapBindingComponentProcessorTest_mapBindingsWithInaccessibleKeys_FAST_INIT_MODE_test.DaggerTestComponent
new file mode 100644
index 0000000..478b010
--- /dev/null
+++ b/javatests/dagger/internal/codegen/goldens/LazyClassKeyMapBindingComponentProcessorTest_mapBindingsWithInaccessibleKeys_FAST_INIT_MODE_test.DaggerTestComponent
@@ -0,0 +1,119 @@
+package test;
+
+import com.google.common.collect.ImmutableMap;
+import dagger.internal.DaggerGenerated;
+import dagger.internal.IdentifierNameString;
+import dagger.internal.LazyClassKeyMap;
+import dagger.internal.Provider;
+import java.util.Map;
+import javax.annotation.processing.Generated;
+import mapkeys.MapKeys;
+import mapkeys.MapModule;
+import mapkeys.MapModule_ComplexKeyWithInaccessibleAnnotationValueMapKey;
+import mapkeys.MapModule_ComplexKeyWithInaccessibleArrayValueMapKey;
+import mapkeys.MapModule_ComplexKeyWithInaccessibleValueMapKey;
+
+@DaggerGenerated
+@Generated(
+    value = "dagger.internal.codegen.ComponentProcessor",
+    comments = "https://dagger.dev"
+)
+@SuppressWarnings({
+    "unchecked",
+    "rawtypes",
+    "KotlinInternal",
+    "KotlinInternalInJava",
+    "cast"
+})
+final class DaggerTestComponent {
+  private DaggerTestComponent() {
+  }
+
+  public static Builder builder() {
+    return new Builder();
+  }
+
+  public static TestComponent create() {
+    return new Builder().build();
+  }
+
+  static final class Builder {
+    private Builder() {
+    }
+
+    public TestComponent build() {
+      return new TestComponentImpl();
+    }
+  }
+
+  private static final class TestComponentImpl implements TestComponent {
+    private final TestComponentImpl testComponentImpl = this;
+
+    private Provider<Map<Class<?>, Integer>> mapOfClassOfAndIntegerProvider;
+
+    private Provider<Map<MapKeys.ComplexKey, Integer>> mapOfComplexKeyAndIntegerProvider;
+
+    private TestComponentImpl() {
+
+      initialize();
+
+    }
+
+    @SuppressWarnings("unchecked")
+    private void initialize() {
+      this.mapOfClassOfAndIntegerProvider = new SwitchingProvider<>(testComponentImpl, 0);
+      this.mapOfComplexKeyAndIntegerProvider = new SwitchingProvider<>(testComponentImpl, 1);
+    }
+
+    @Override
+    public Map<Class<?>, Integer> classKey() {
+      return mapOfClassOfAndIntegerProvider.get();
+    }
+
+    @Override
+    public javax.inject.Provider<Map<Class<?>, Integer>> classKeyProvider() {
+      return mapOfClassOfAndIntegerProvider;
+    }
+
+    @Override
+    public Map<MapKeys.ComplexKey, Integer> complexKey() {
+      return mapOfComplexKeyAndIntegerProvider.get();
+    }
+
+    @Override
+    public javax.inject.Provider<Map<MapKeys.ComplexKey, Integer>> complexKeyProvider() {
+      return mapOfComplexKeyAndIntegerProvider;
+    }
+
+    private static final class SwitchingProvider<T> implements Provider<T> {
+      private final TestComponentImpl testComponentImpl;
+
+      private final int id;
+
+      SwitchingProvider(TestComponentImpl testComponentImpl, int id) {
+        this.testComponentImpl = testComponentImpl;
+        this.id = id;
+      }
+
+      @SuppressWarnings("unchecked")
+      @Override
+      public T get() {
+        switch (id) {
+          case 0: // java.util.Map<java.lang.Class<?>,java.lang.Integer> 
+          return (T) LazyClassKeyMap.<Integer>of(ImmutableMap.<String, Integer>of(LazyClassKeyProvider.mapkeys_MapKeys_Inaccessible, MapModule.classKey()));
+
+          case 1: // java.util.Map<mapkeys.MapKeys.ComplexKey,java.lang.Integer> 
+          return (T) ImmutableMap.<MapKeys.ComplexKey, Integer>of(MapModule_ComplexKeyWithInaccessibleValueMapKey.create(), MapModule.complexKeyWithInaccessibleValue(), MapModule_ComplexKeyWithInaccessibleArrayValueMapKey.create(), MapModule.complexKeyWithInaccessibleArrayValue(), MapModule_ComplexKeyWithInaccessibleAnnotationValueMapKey.create(), MapModule.complexKeyWithInaccessibleAnnotationValue());
+
+          default: throw new AssertionError(id);
+        }
+      }
+    }
+
+    @IdentifierNameString
+    private static final class LazyClassKeyProvider {
+      static String mapkeys_MapKeys_Inaccessible = "mapkeys.MapKeys$Inaccessible";
+    }
+  }
+}
+
diff --git a/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_injectMapWithoutMapBinding_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_injectMapWithoutMapBinding_DEFAULT_MODE_test.DaggerTestComponent
index 227404c..b348b61 100644
--- a/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_injectMapWithoutMapBinding_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_injectMapWithoutMapBinding_DEFAULT_MODE_test.DaggerTestComponent
@@ -14,7 +14,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_injectMapWithoutMapBinding_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_injectMapWithoutMapBinding_FAST_INIT_MODE_test.DaggerTestComponent
index 227404c..b348b61 100644
--- a/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_injectMapWithoutMapBinding_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_injectMapWithoutMapBinding_FAST_INIT_MODE_test.DaggerTestComponent
@@ -14,7 +14,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithEnumKey_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithEnumKey_DEFAULT_MODE_test.DaggerTestComponent
index 88153bc..dbffedd 100644
--- a/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithEnumKey_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithEnumKey_DEFAULT_MODE_test.DaggerTestComponent
@@ -3,9 +3,9 @@
 import dagger.internal.DaggerGenerated;
 import dagger.internal.MapProviderFactory;
 import dagger.internal.Preconditions;
+import dagger.internal.Provider;
 import java.util.Map;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -16,7 +16,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -66,7 +67,7 @@
 
     private Provider<Handler> provideLoginHandlerProvider;
 
-    private Provider<Map<PathEnum, Provider<Handler>>> mapOfPathEnumAndProviderOfHandlerProvider;
+    private Provider mapOfPathEnumAndProviderOfHandlerProvider;
 
     private TestComponentImpl(MapModuleOne mapModuleOneParam, MapModuleTwo mapModuleTwoParam) {
 
@@ -83,7 +84,7 @@
     }
 
     @Override
-    public Provider<Map<PathEnum, Provider<Handler>>> dispatcher() {
+    public javax.inject.Provider<Map<PathEnum, javax.inject.Provider<Handler>>> dispatcher() {
       return mapOfPathEnumAndProviderOfHandlerProvider;
     }
   }
diff --git a/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithEnumKey_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithEnumKey_FAST_INIT_MODE_test.DaggerTestComponent
index ac0e74e..54f6250 100644
--- a/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithEnumKey_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithEnumKey_FAST_INIT_MODE_test.DaggerTestComponent
@@ -3,9 +3,9 @@
 import com.google.common.collect.ImmutableMap;
 import dagger.internal.DaggerGenerated;
 import dagger.internal.Preconditions;
+import dagger.internal.Provider;
 import java.util.Map;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -16,7 +16,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -70,7 +71,7 @@
 
     private Provider<Handler> provideLoginHandlerProvider;
 
-    private Provider<Map<PathEnum, Provider<Handler>>> mapOfPathEnumAndProviderOfHandlerProvider;
+    private Provider mapOfPathEnumAndProviderOfHandlerProvider;
 
     private TestComponentImpl(MapModuleOne mapModuleOneParam, MapModuleTwo mapModuleTwoParam) {
       this.mapModuleOne = mapModuleOneParam;
@@ -88,7 +89,7 @@
     }
 
     @Override
-    public Provider<Map<PathEnum, Provider<Handler>>> dispatcher() {
+    public javax.inject.Provider<Map<PathEnum, javax.inject.Provider<Handler>>> dispatcher() {
       return mapOfPathEnumAndProviderOfHandlerProvider;
     }
 
@@ -107,7 +108,7 @@
       public T get() {
         switch (id) {
           case 0: // java.util.Map<test.PathEnum,javax.inject.Provider<test.Handler>> 
-          return (T) ImmutableMap.<PathEnum, Provider<Handler>>of(PathEnum.ADMIN, testComponentImpl.provideAdminHandlerProvider, PathEnum.LOGIN, testComponentImpl.provideLoginHandlerProvider);
+          return (T) ImmutableMap.<PathEnum, javax.inject.Provider<Handler>>of(PathEnum.ADMIN, testComponentImpl.provideAdminHandlerProvider, PathEnum.LOGIN, testComponentImpl.provideLoginHandlerProvider);
 
           case 1: // java.util.Map<test.PathEnum,javax.inject.Provider<test.Handler>> test.MapModuleOne#provideAdminHandler 
           return (T) MapModuleOne_ProvideAdminHandlerFactory.provideAdminHandler(testComponentImpl.mapModuleOne);
diff --git a/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithInaccessibleKeys_DEFAULT_MODE_mapkeys.MapModule_ClassKeyMapKey b/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithInaccessibleKeys_DEFAULT_MODE_mapkeys.MapModule_ClassKeyMapKey
index 252d007..209220e 100644
--- a/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithInaccessibleKeys_DEFAULT_MODE_mapkeys.MapModule_ClassKeyMapKey
+++ b/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithInaccessibleKeys_DEFAULT_MODE_mapkeys.MapModule_ClassKeyMapKey
@@ -12,7 +12,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class MapModule_ClassKeyMapKey {
   private MapModule_ClassKeyMapKey() {
diff --git a/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithInaccessibleKeys_DEFAULT_MODE_mapkeys.MapModule_ComplexKeyWithInaccessibleAnnotationValueMapKey b/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithInaccessibleKeys_DEFAULT_MODE_mapkeys.MapModule_ComplexKeyWithInaccessibleAnnotationValueMapKey
index 34cbcba..f65280b 100644
--- a/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithInaccessibleKeys_DEFAULT_MODE_mapkeys.MapModule_ComplexKeyWithInaccessibleAnnotationValueMapKey
+++ b/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithInaccessibleKeys_DEFAULT_MODE_mapkeys.MapModule_ComplexKeyWithInaccessibleAnnotationValueMapKey
@@ -12,7 +12,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class MapModule_ComplexKeyWithInaccessibleAnnotationValueMapKey {
   private MapModule_ComplexKeyWithInaccessibleAnnotationValueMapKey() {
diff --git a/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithInaccessibleKeys_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithInaccessibleKeys_DEFAULT_MODE_test.DaggerTestComponent
index 1d9618d..2b35d46 100644
--- a/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithInaccessibleKeys_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithInaccessibleKeys_DEFAULT_MODE_test.DaggerTestComponent
@@ -3,9 +3,9 @@
 import com.google.common.collect.ImmutableMap;
 import dagger.internal.DaggerGenerated;
 import dagger.internal.MapFactory;
+import dagger.internal.Provider;
 import java.util.Map;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 import mapkeys.MapKeys;
 import mapkeys.MapModule;
 import mapkeys.MapModule_ClassKeyFactory;
@@ -28,7 +28,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -84,7 +85,7 @@
     }
 
     @Override
-    public Provider<Map<Class<?>, Integer>> classKeyProvider() {
+    public javax.inject.Provider<Map<Class<?>, Integer>> classKeyProvider() {
       return mapOfClassOfAndIntegerProvider;
     }
 
@@ -94,7 +95,7 @@
     }
 
     @Override
-    public Provider<Object> inaccessibleEnumProvider() {
+    public javax.inject.Provider<Object> inaccessibleEnumProvider() {
       return mapOfPackagePrivateEnumAndIntegerProvider;
     }
 
@@ -104,7 +105,7 @@
     }
 
     @Override
-    public Provider<Map<MapKeys.ComplexKey, Integer>> complexKeyProvider() {
+    public javax.inject.Provider<Map<MapKeys.ComplexKey, Integer>> complexKeyProvider() {
       return mapOfComplexKeyAndIntegerProvider;
     }
   }
diff --git a/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithInaccessibleKeys_FAST_INIT_MODE_mapkeys.MapModule_ClassKeyMapKey b/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithInaccessibleKeys_FAST_INIT_MODE_mapkeys.MapModule_ClassKeyMapKey
index 252d007..209220e 100644
--- a/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithInaccessibleKeys_FAST_INIT_MODE_mapkeys.MapModule_ClassKeyMapKey
+++ b/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithInaccessibleKeys_FAST_INIT_MODE_mapkeys.MapModule_ClassKeyMapKey
@@ -12,7 +12,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class MapModule_ClassKeyMapKey {
   private MapModule_ClassKeyMapKey() {
diff --git a/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithInaccessibleKeys_FAST_INIT_MODE_mapkeys.MapModule_ComplexKeyWithInaccessibleAnnotationValueMapKey b/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithInaccessibleKeys_FAST_INIT_MODE_mapkeys.MapModule_ComplexKeyWithInaccessibleAnnotationValueMapKey
index 34cbcba..f65280b 100644
--- a/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithInaccessibleKeys_FAST_INIT_MODE_mapkeys.MapModule_ComplexKeyWithInaccessibleAnnotationValueMapKey
+++ b/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithInaccessibleKeys_FAST_INIT_MODE_mapkeys.MapModule_ComplexKeyWithInaccessibleAnnotationValueMapKey
@@ -12,7 +12,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class MapModule_ComplexKeyWithInaccessibleAnnotationValueMapKey {
   private MapModule_ComplexKeyWithInaccessibleAnnotationValueMapKey() {
diff --git a/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithInaccessibleKeys_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithInaccessibleKeys_FAST_INIT_MODE_test.DaggerTestComponent
index 1d9618d..2b35d46 100644
--- a/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithInaccessibleKeys_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithInaccessibleKeys_FAST_INIT_MODE_test.DaggerTestComponent
@@ -3,9 +3,9 @@
 import com.google.common.collect.ImmutableMap;
 import dagger.internal.DaggerGenerated;
 import dagger.internal.MapFactory;
+import dagger.internal.Provider;
 import java.util.Map;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 import mapkeys.MapKeys;
 import mapkeys.MapModule;
 import mapkeys.MapModule_ClassKeyFactory;
@@ -28,7 +28,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -84,7 +85,7 @@
     }
 
     @Override
-    public Provider<Map<Class<?>, Integer>> classKeyProvider() {
+    public javax.inject.Provider<Map<Class<?>, Integer>> classKeyProvider() {
       return mapOfClassOfAndIntegerProvider;
     }
 
@@ -94,7 +95,7 @@
     }
 
     @Override
-    public Provider<Object> inaccessibleEnumProvider() {
+    public javax.inject.Provider<Object> inaccessibleEnumProvider() {
       return mapOfPackagePrivateEnumAndIntegerProvider;
     }
 
@@ -104,7 +105,7 @@
     }
 
     @Override
-    public Provider<Map<MapKeys.ComplexKey, Integer>> complexKeyProvider() {
+    public javax.inject.Provider<Map<MapKeys.ComplexKey, Integer>> complexKeyProvider() {
       return mapOfComplexKeyAndIntegerProvider;
     }
   }
diff --git a/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithNonProviderValue_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithNonProviderValue_DEFAULT_MODE_test.DaggerTestComponent
index b2e7cf5..e2d93ec 100644
--- a/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithNonProviderValue_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithNonProviderValue_DEFAULT_MODE_test.DaggerTestComponent
@@ -3,9 +3,9 @@
 import dagger.internal.DaggerGenerated;
 import dagger.internal.MapFactory;
 import dagger.internal.Preconditions;
+import dagger.internal.Provider;
 import java.util.Map;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -16,7 +16,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -83,7 +84,7 @@
     }
 
     @Override
-    public Provider<Map<PathEnum, Handler>> dispatcher() {
+    public javax.inject.Provider<Map<PathEnum, Handler>> dispatcher() {
       return mapOfPathEnumAndHandlerProvider;
     }
   }
diff --git a/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithNonProviderValue_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithNonProviderValue_FAST_INIT_MODE_test.DaggerTestComponent
index 4e898ed..c3f0578 100644
--- a/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithNonProviderValue_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithNonProviderValue_FAST_INIT_MODE_test.DaggerTestComponent
@@ -3,9 +3,9 @@
 import com.google.common.collect.ImmutableMap;
 import dagger.internal.DaggerGenerated;
 import dagger.internal.Preconditions;
+import dagger.internal.Provider;
 import java.util.Map;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -16,7 +16,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -82,7 +83,7 @@
     }
 
     @Override
-    public Provider<Map<PathEnum, Handler>> dispatcher() {
+    public javax.inject.Provider<Map<PathEnum, Handler>> dispatcher() {
       return mapOfPathEnumAndHandlerProvider;
     }
 
diff --git a/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithStringKey_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithStringKey_DEFAULT_MODE_test.DaggerTestComponent
index 0b463f5..cd24892 100644
--- a/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithStringKey_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithStringKey_DEFAULT_MODE_test.DaggerTestComponent
@@ -3,9 +3,9 @@
 import dagger.internal.DaggerGenerated;
 import dagger.internal.MapProviderFactory;
 import dagger.internal.Preconditions;
+import dagger.internal.Provider;
 import java.util.Map;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -16,7 +16,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -66,7 +67,7 @@
 
     private Provider<Handler> provideLoginHandlerProvider;
 
-    private Provider<Map<String, Provider<Handler>>> mapOfStringAndProviderOfHandlerProvider;
+    private Provider mapOfStringAndProviderOfHandlerProvider;
 
     private TestComponentImpl(MapModuleOne mapModuleOneParam, MapModuleTwo mapModuleTwoParam) {
 
@@ -83,7 +84,7 @@
     }
 
     @Override
-    public Provider<Map<String, Provider<Handler>>> dispatcher() {
+    public javax.inject.Provider<Map<String, javax.inject.Provider<Handler>>> dispatcher() {
       return mapOfStringAndProviderOfHandlerProvider;
     }
   }
diff --git a/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithStringKey_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithStringKey_FAST_INIT_MODE_test.DaggerTestComponent
index 65513bb..47a7d8b 100644
--- a/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithStringKey_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithStringKey_FAST_INIT_MODE_test.DaggerTestComponent
@@ -3,9 +3,9 @@
 import com.google.common.collect.ImmutableMap;
 import dagger.internal.DaggerGenerated;
 import dagger.internal.Preconditions;
+import dagger.internal.Provider;
 import java.util.Map;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -16,7 +16,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -70,7 +71,7 @@
 
     private Provider<Handler> provideLoginHandlerProvider;
 
-    private Provider<Map<String, Provider<Handler>>> mapOfStringAndProviderOfHandlerProvider;
+    private Provider mapOfStringAndProviderOfHandlerProvider;
 
     private TestComponentImpl(MapModuleOne mapModuleOneParam, MapModuleTwo mapModuleTwoParam) {
       this.mapModuleOne = mapModuleOneParam;
@@ -88,7 +89,7 @@
     }
 
     @Override
-    public Provider<Map<String, Provider<Handler>>> dispatcher() {
+    public javax.inject.Provider<Map<String, javax.inject.Provider<Handler>>> dispatcher() {
       return mapOfStringAndProviderOfHandlerProvider;
     }
 
@@ -107,7 +108,7 @@
       public T get() {
         switch (id) {
           case 0: // java.util.Map<java.lang.String,javax.inject.Provider<test.Handler>> 
-          return (T) ImmutableMap.<String, Provider<Handler>>of("Admin", testComponentImpl.provideAdminHandlerProvider, "Login", testComponentImpl.provideLoginHandlerProvider);
+          return (T) ImmutableMap.<String, javax.inject.Provider<Handler>>of("Admin", testComponentImpl.provideAdminHandlerProvider, "Login", testComponentImpl.provideLoginHandlerProvider);
 
           case 1: // java.util.Map<java.lang.String,javax.inject.Provider<test.Handler>> test.MapModuleOne#provideAdminHandler 
           return (T) MapModuleOne_ProvideAdminHandlerFactory.provideAdminHandler(testComponentImpl.mapModuleOne);
diff --git a/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithWrappedKey_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithWrappedKey_DEFAULT_MODE_test.DaggerTestComponent
index 47847a7..bbba316 100644
--- a/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithWrappedKey_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithWrappedKey_DEFAULT_MODE_test.DaggerTestComponent
@@ -3,9 +3,9 @@
 import dagger.internal.DaggerGenerated;
 import dagger.internal.MapProviderFactory;
 import dagger.internal.Preconditions;
+import dagger.internal.Provider;
 import java.util.Map;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -16,7 +16,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -66,7 +67,7 @@
 
     private Provider<Handler> provideLoginHandlerProvider;
 
-    private Provider<Map<WrappedClassKey, Provider<Handler>>> mapOfWrappedClassKeyAndProviderOfHandlerProvider;
+    private Provider mapOfWrappedClassKeyAndProviderOfHandlerProvider;
 
     private TestComponentImpl(MapModuleOne mapModuleOneParam, MapModuleTwo mapModuleTwoParam) {
 
@@ -83,7 +84,8 @@
     }
 
     @Override
-    public Provider<Map<WrappedClassKey, Provider<Handler>>> dispatcher() {
+    public javax.inject.Provider<Map<WrappedClassKey, javax.inject.Provider<Handler>>> dispatcher(
+        ) {
       return mapOfWrappedClassKeyAndProviderOfHandlerProvider;
     }
   }
diff --git a/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithWrappedKey_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithWrappedKey_FAST_INIT_MODE_test.DaggerTestComponent
index 3180571..d057b50 100644
--- a/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithWrappedKey_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/MapBindingComponentProcessorTest_mapBindingsWithWrappedKey_FAST_INIT_MODE_test.DaggerTestComponent
@@ -3,9 +3,9 @@
 import com.google.common.collect.ImmutableMap;
 import dagger.internal.DaggerGenerated;
 import dagger.internal.Preconditions;
+import dagger.internal.Provider;
 import java.util.Map;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -16,7 +16,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -70,7 +71,7 @@
 
     private Provider<Handler> provideLoginHandlerProvider;
 
-    private Provider<Map<WrappedClassKey, Provider<Handler>>> mapOfWrappedClassKeyAndProviderOfHandlerProvider;
+    private Provider mapOfWrappedClassKeyAndProviderOfHandlerProvider;
 
     private TestComponentImpl(MapModuleOne mapModuleOneParam, MapModuleTwo mapModuleTwoParam) {
       this.mapModuleOne = mapModuleOneParam;
@@ -88,7 +89,8 @@
     }
 
     @Override
-    public Provider<Map<WrappedClassKey, Provider<Handler>>> dispatcher() {
+    public javax.inject.Provider<Map<WrappedClassKey, javax.inject.Provider<Handler>>> dispatcher(
+        ) {
       return mapOfWrappedClassKeyAndProviderOfHandlerProvider;
     }
 
@@ -107,7 +109,7 @@
       public T get() {
         switch (id) {
           case 0: // java.util.Map<test.WrappedClassKey,javax.inject.Provider<test.Handler>> 
-          return (T) ImmutableMap.<WrappedClassKey, Provider<Handler>>of(WrappedClassKeyCreator.createWrappedClassKey(Integer.class), testComponentImpl.provideAdminHandlerProvider, WrappedClassKeyCreator.createWrappedClassKey(Long.class), testComponentImpl.provideLoginHandlerProvider);
+          return (T) ImmutableMap.<WrappedClassKey, javax.inject.Provider<Handler>>of(WrappedClassKeyCreator.createWrappedClassKey(Integer.class), testComponentImpl.provideAdminHandlerProvider, WrappedClassKeyCreator.createWrappedClassKey(Long.class), testComponentImpl.provideLoginHandlerProvider);
 
           case 1: // java.util.Map<test.WrappedClassKey,javax.inject.Provider<test.Handler>> test.MapModuleOne#provideAdminHandler 
           return (T) MapModuleOne_ProvideAdminHandlerFactory.provideAdminHandler(testComponentImpl.mapModuleOne);
diff --git a/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationTest_inaccessible_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationTest_inaccessible_DEFAULT_MODE_test.DaggerTestComponent
index 390f13a..37bbf79 100644
--- a/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationTest_inaccessible_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationTest_inaccessible_DEFAULT_MODE_test.DaggerTestComponent
@@ -16,7 +16,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationTest_inaccessible_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationTest_inaccessible_FAST_INIT_MODE_test.DaggerTestComponent
index 390f13a..37bbf79 100644
--- a/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationTest_inaccessible_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationTest_inaccessible_FAST_INIT_MODE_test.DaggerTestComponent
@@ -16,7 +16,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationTest_mapBindings_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationTest_mapBindings_DEFAULT_MODE_test.DaggerTestComponent
index 79ac59f..f47f081 100644
--- a/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationTest_mapBindings_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationTest_mapBindings_DEFAULT_MODE_test.DaggerTestComponent
@@ -16,7 +16,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationTest_mapBindings_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationTest_mapBindings_FAST_INIT_MODE_test.DaggerTestComponent
index 0010e58..0acd7f1 100644
--- a/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationTest_mapBindings_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationTest_mapBindings_FAST_INIT_MODE_test.DaggerTestComponent
@@ -2,10 +2,10 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.MapBuilder;
+import dagger.internal.Provider;
 import java.util.Collections;
 import java.util.Map;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -16,7 +16,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -70,8 +71,8 @@
     }
 
     @Override
-    public Map<String, Provider<String>> providerStrings() {
-      return Collections.<String, Provider<String>>emptyMap();
+    public Map<String, javax.inject.Provider<String>> providerStrings() {
+      return Collections.<String, javax.inject.Provider<String>>emptyMap();
     }
 
     @Override
@@ -80,8 +81,8 @@
     }
 
     @Override
-    public Map<Integer, Provider<Integer>> providerInts() {
-      return Collections.<Integer, Provider<Integer>>singletonMap(0, provideIntProvider);
+    public Map<Integer, javax.inject.Provider<Integer>> providerInts() {
+      return Collections.<Integer, javax.inject.Provider<Integer>>singletonMap(0, provideIntProvider);
     }
 
     @Override
@@ -90,8 +91,8 @@
     }
 
     @Override
-    public Map<Long, Provider<Long>> providerLongs() {
-      return MapBuilder.<Long, Provider<Long>>newMapBuilder(3).put(0L, provideLong0Provider).put(1L, provideLong1Provider).put(2L, provideLong2Provider).build();
+    public Map<Long, javax.inject.Provider<Long>> providerLongs() {
+      return MapBuilder.<Long, javax.inject.Provider<Long>>newMapBuilder(3).put(0L, provideLong0Provider).put(1L, provideLong1Provider).put(2L, provideLong2Provider).build();
     }
 
     private static final class SwitchingProvider<T> implements Provider<T> {
diff --git a/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationTest_productionComponents_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationTest_productionComponents_DEFAULT_MODE_test.DaggerTestComponent
index 635667f..8ae5d82 100644
--- a/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationTest_productionComponents_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationTest_productionComponents_DEFAULT_MODE_test.DaggerTestComponent
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationTest_productionComponents_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationTest_productionComponents_FAST_INIT_MODE_test.DaggerTestComponent
index 635667f..8ae5d82 100644
--- a/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationTest_productionComponents_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationTest_productionComponents_FAST_INIT_MODE_test.DaggerTestComponent
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationTest_subcomponentOmitsInheritedBindings_DEFAULT_MODE_test.DaggerParent b/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationTest_subcomponentOmitsInheritedBindings_DEFAULT_MODE_test.DaggerParent
index e9f21dd..f4f6564 100644
--- a/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationTest_subcomponentOmitsInheritedBindings_DEFAULT_MODE_test.DaggerParent
+++ b/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationTest_subcomponentOmitsInheritedBindings_DEFAULT_MODE_test.DaggerParent
@@ -15,7 +15,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerParent {
   private DaggerParent() {
diff --git a/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationTest_subcomponentOmitsInheritedBindings_FAST_INIT_MODE_test.DaggerParent b/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationTest_subcomponentOmitsInheritedBindings_FAST_INIT_MODE_test.DaggerParent
index e9f21dd..f4f6564 100644
--- a/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationTest_subcomponentOmitsInheritedBindings_FAST_INIT_MODE_test.DaggerParent
+++ b/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationTest_subcomponentOmitsInheritedBindings_FAST_INIT_MODE_test.DaggerParent
@@ -15,7 +15,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerParent {
   private DaggerParent() {
diff --git a/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationWithGuavaTest_inaccessible_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationWithGuavaTest_inaccessible_DEFAULT_MODE_test.DaggerTestComponent
index 1f1d76a..24c5619 100644
--- a/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationWithGuavaTest_inaccessible_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationWithGuavaTest_inaccessible_DEFAULT_MODE_test.DaggerTestComponent
@@ -16,7 +16,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationWithGuavaTest_inaccessible_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationWithGuavaTest_inaccessible_FAST_INIT_MODE_test.DaggerTestComponent
index 1f1d76a..24c5619 100644
--- a/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationWithGuavaTest_inaccessible_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationWithGuavaTest_inaccessible_FAST_INIT_MODE_test.DaggerTestComponent
@@ -16,7 +16,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationWithGuavaTest_mapBindings_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationWithGuavaTest_mapBindings_DEFAULT_MODE_test.DaggerTestComponent
index e6f96d5..5520281 100644
--- a/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationWithGuavaTest_mapBindings_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationWithGuavaTest_mapBindings_DEFAULT_MODE_test.DaggerTestComponent
@@ -15,7 +15,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationWithGuavaTest_mapBindings_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationWithGuavaTest_mapBindings_FAST_INIT_MODE_test.DaggerTestComponent
index e99a963..12346c8 100644
--- a/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationWithGuavaTest_mapBindings_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationWithGuavaTest_mapBindings_FAST_INIT_MODE_test.DaggerTestComponent
@@ -2,9 +2,9 @@
 
 import com.google.common.collect.ImmutableMap;
 import dagger.internal.DaggerGenerated;
+import dagger.internal.Provider;
 import java.util.Map;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -15,7 +15,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -69,8 +70,8 @@
     }
 
     @Override
-    public Map<Long, Provider<Long>> providerLongs() {
-      return ImmutableMap.<Long, Provider<Long>>builderWithExpectedSize(6).put(0L, testComponentImpl.provideLong0Provider).put(1L, testComponentImpl.provideLong1Provider).put(2L, testComponentImpl.provideLong2Provider).put(3L, provideLong3Provider).put(4L, provideLong4Provider).put(5L, provideLong5Provider).build();
+    public Map<Long, javax.inject.Provider<Long>> providerLongs() {
+      return ImmutableMap.<Long, javax.inject.Provider<Long>>builderWithExpectedSize(6).put(0L, testComponentImpl.provideLong0Provider).put(1L, testComponentImpl.provideLong1Provider).put(2L, testComponentImpl.provideLong2Provider).put(3L, provideLong3Provider).put(4L, provideLong4Provider).put(5L, provideLong5Provider).build();
     }
 
     private static final class SwitchingProvider<T> implements Provider<T> {
@@ -136,8 +137,8 @@
     }
 
     @Override
-    public Map<String, Provider<String>> providerStrings() {
-      return ImmutableMap.<String, Provider<String>>of();
+    public Map<String, javax.inject.Provider<String>> providerStrings() {
+      return ImmutableMap.<String, javax.inject.Provider<String>>of();
     }
 
     @Override
@@ -146,8 +147,8 @@
     }
 
     @Override
-    public Map<Integer, Provider<Integer>> providerInts() {
-      return ImmutableMap.<Integer, Provider<Integer>>of(0, provideIntProvider);
+    public Map<Integer, javax.inject.Provider<Integer>> providerInts() {
+      return ImmutableMap.<Integer, javax.inject.Provider<Integer>>of(0, provideIntProvider);
     }
 
     @Override
@@ -156,8 +157,8 @@
     }
 
     @Override
-    public Map<Long, Provider<Long>> providerLongs() {
-      return ImmutableMap.<Long, Provider<Long>>of(0L, provideLong0Provider, 1L, provideLong1Provider, 2L, provideLong2Provider);
+    public Map<Long, javax.inject.Provider<Long>> providerLongs() {
+      return ImmutableMap.<Long, javax.inject.Provider<Long>>of(0L, provideLong0Provider, 1L, provideLong1Provider, 2L, provideLong2Provider);
     }
 
     @Override
diff --git a/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationWithGuavaTest_productionComponents_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationWithGuavaTest_productionComponents_DEFAULT_MODE_test.DaggerTestComponent
index 26b3dfd..dc29708 100644
--- a/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationWithGuavaTest_productionComponents_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationWithGuavaTest_productionComponents_DEFAULT_MODE_test.DaggerTestComponent
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationWithGuavaTest_productionComponents_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationWithGuavaTest_productionComponents_FAST_INIT_MODE_test.DaggerTestComponent
index 26b3dfd..dc29708 100644
--- a/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationWithGuavaTest_productionComponents_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationWithGuavaTest_productionComponents_FAST_INIT_MODE_test.DaggerTestComponent
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationWithGuavaTest_subcomponentOmitsInheritedBindings_DEFAULT_MODE_test.DaggerParent b/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationWithGuavaTest_subcomponentOmitsInheritedBindings_DEFAULT_MODE_test.DaggerParent
index eb76470..0ac6e9f 100644
--- a/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationWithGuavaTest_subcomponentOmitsInheritedBindings_DEFAULT_MODE_test.DaggerParent
+++ b/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationWithGuavaTest_subcomponentOmitsInheritedBindings_DEFAULT_MODE_test.DaggerParent
@@ -15,7 +15,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerParent {
   private DaggerParent() {
diff --git a/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationWithGuavaTest_subcomponentOmitsInheritedBindings_FAST_INIT_MODE_test.DaggerParent b/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationWithGuavaTest_subcomponentOmitsInheritedBindings_FAST_INIT_MODE_test.DaggerParent
index eb76470..0ac6e9f 100644
--- a/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationWithGuavaTest_subcomponentOmitsInheritedBindings_FAST_INIT_MODE_test.DaggerParent
+++ b/javatests/dagger/internal/codegen/goldens/MapRequestRepresentationWithGuavaTest_subcomponentOmitsInheritedBindings_FAST_INIT_MODE_test.DaggerParent
@@ -15,7 +15,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerParent {
   private DaggerParent() {
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_accessibility_DEFAULT_MODE_other.Inaccessible_MembersInjector b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_accessibility_DEFAULT_MODE_other.Inaccessible_MembersInjector
index 0bf65b2..cc45f79 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_accessibility_DEFAULT_MODE_other.Inaccessible_MembersInjector
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_accessibility_DEFAULT_MODE_other.Inaccessible_MembersInjector
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class Inaccessible_MembersInjector implements MembersInjector<Inaccessible> {
   private final Provider<Foo> fooProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_accessibility_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_accessibility_DEFAULT_MODE_test.DaggerTestComponent
index 4ecf3f5..5f232b1 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_accessibility_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_accessibility_DEFAULT_MODE_test.DaggerTestComponent
@@ -18,7 +18,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_accessibility_FAST_INIT_MODE_other.Inaccessible_MembersInjector b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_accessibility_FAST_INIT_MODE_other.Inaccessible_MembersInjector
index 0bf65b2..cc45f79 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_accessibility_FAST_INIT_MODE_other.Inaccessible_MembersInjector
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_accessibility_FAST_INIT_MODE_other.Inaccessible_MembersInjector
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class Inaccessible_MembersInjector implements MembersInjector<Inaccessible> {
   private final Provider<Foo> fooProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_accessibility_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_accessibility_FAST_INIT_MODE_test.DaggerTestComponent
index 4ecf3f5..5f232b1 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_accessibility_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_accessibility_FAST_INIT_MODE_test.DaggerTestComponent
@@ -18,7 +18,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_accessibleRawType_ofInaccessibleType_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_accessibleRawType_ofInaccessibleType_DEFAULT_MODE_test.DaggerTestComponent
index 5cb03e8..c17dea0 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_accessibleRawType_ofInaccessibleType_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_accessibleRawType_ofInaccessibleType_DEFAULT_MODE_test.DaggerTestComponent
@@ -3,11 +3,9 @@
 import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DoubleCheck;
-import dagger.internal.Preconditions;
+import dagger.internal.Provider;
 import java.util.List;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
-import other.InaccessiblesModule;
 import other.InaccessiblesModule_InaccessiblesFactory;
 import other.UsesInaccessibles;
 import other.UsesInaccessibles_Factory;
@@ -22,7 +20,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -40,15 +39,6 @@
     private Builder() {
     }
 
-    /**
-     * @deprecated This module is declared, but an instance is not used in the component. This method is a no-op. For more, see https://dagger.dev/unused-modules.
-     */
-    @Deprecated
-    public Builder inaccessiblesModule(InaccessiblesModule inaccessiblesModule) {
-      Preconditions.checkNotNull(inaccessiblesModule);
-      return this;
-    }
-
     public TestComponent build() {
       return new TestComponentImpl();
     }
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_accessibleRawType_ofInaccessibleType_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_accessibleRawType_ofInaccessibleType_FAST_INIT_MODE_test.DaggerTestComponent
index 02230a6..854a429 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_accessibleRawType_ofInaccessibleType_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_accessibleRawType_ofInaccessibleType_FAST_INIT_MODE_test.DaggerTestComponent
@@ -3,11 +3,9 @@
 import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DoubleCheck;
-import dagger.internal.Preconditions;
+import dagger.internal.Provider;
 import java.util.List;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
-import other.InaccessiblesModule;
 import other.InaccessiblesModule_InaccessiblesFactory;
 import other.UsesInaccessibles;
 import other.UsesInaccessibles_Factory;
@@ -22,7 +20,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -40,15 +39,6 @@
     private Builder() {
     }
 
-    /**
-     * @deprecated This module is declared, but an instance is not used in the component. This method is a no-op. For more, see https://dagger.dev/unused-modules.
-     */
-    @Deprecated
-    public Builder inaccessiblesModule(InaccessiblesModule inaccessiblesModule) {
-      Preconditions.checkNotNull(inaccessiblesModule);
-      return this;
-    }
-
     public TestComponent build() {
       return new TestComponentImpl();
     }
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_componentWithNestingAndGeneratedType_DEFAULT_MODE_test.OuterType_B_MembersInjector b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_componentWithNestingAndGeneratedType_DEFAULT_MODE_test.OuterType_B_MembersInjector
index 72b876e..5b4932f 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_componentWithNestingAndGeneratedType_DEFAULT_MODE_test.OuterType_B_MembersInjector
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_componentWithNestingAndGeneratedType_DEFAULT_MODE_test.OuterType_B_MembersInjector
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class OuterType_B_MembersInjector implements MembersInjector<OuterType.B> {
   private final Provider<OuterType.A> aProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_componentWithNestingAndGeneratedType_FAST_INIT_MODE_test.OuterType_B_MembersInjector b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_componentWithNestingAndGeneratedType_FAST_INIT_MODE_test.OuterType_B_MembersInjector
index 72b876e..5b4932f 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_componentWithNestingAndGeneratedType_FAST_INIT_MODE_test.OuterType_B_MembersInjector
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_componentWithNestingAndGeneratedType_FAST_INIT_MODE_test.OuterType_B_MembersInjector
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class OuterType_B_MembersInjector implements MembersInjector<OuterType.B> {
   private final Provider<OuterType.A> aProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_fieldAndMethodGenerics_DEFAULT_MODE_test.GenericClass_MembersInjector b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_fieldAndMethodGenerics_DEFAULT_MODE_test.GenericClass_MembersInjector
index e3a7035..70415a8 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_fieldAndMethodGenerics_DEFAULT_MODE_test.GenericClass_MembersInjector
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_fieldAndMethodGenerics_DEFAULT_MODE_test.GenericClass_MembersInjector
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class GenericClass_MembersInjector<A, B> implements MembersInjector<GenericClass<A, B>> {
   private final Provider<A> aProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_fieldAndMethodGenerics_FAST_INIT_MODE_test.GenericClass_MembersInjector b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_fieldAndMethodGenerics_FAST_INIT_MODE_test.GenericClass_MembersInjector
index e3a7035..70415a8 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_fieldAndMethodGenerics_FAST_INIT_MODE_test.GenericClass_MembersInjector
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_fieldAndMethodGenerics_FAST_INIT_MODE_test.GenericClass_MembersInjector
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class GenericClass_MembersInjector<A, B> implements MembersInjector<GenericClass<A, B>> {
   private final Provider<A> aProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_fieldInjectionForShadowedMember_DEFAULT_MODE_test.Child_MembersInjector b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_fieldInjectionForShadowedMember_DEFAULT_MODE_test.Child_MembersInjector
index 36f5651..2f69706 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_fieldInjectionForShadowedMember_DEFAULT_MODE_test.Child_MembersInjector
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_fieldInjectionForShadowedMember_DEFAULT_MODE_test.Child_MembersInjector
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class Child_MembersInjector implements MembersInjector<Child> {
   private final Provider<Foo> objectProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_fieldInjectionForShadowedMember_FAST_INIT_MODE_test.Child_MembersInjector b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_fieldInjectionForShadowedMember_FAST_INIT_MODE_test.Child_MembersInjector
index 36f5651..2f69706 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_fieldInjectionForShadowedMember_FAST_INIT_MODE_test.Child_MembersInjector
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_fieldInjectionForShadowedMember_FAST_INIT_MODE_test.Child_MembersInjector
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class Child_MembersInjector implements MembersInjector<Child> {
   private final Provider<Foo> objectProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_fieldInjectionWithQualifier_DEFAULT_MODE_test.FieldInjectionWithQualifier_MembersInjector b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_fieldInjectionWithQualifier_DEFAULT_MODE_test.FieldInjectionWithQualifier_MembersInjector
index 7d5b277..46faeb8 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_fieldInjectionWithQualifier_DEFAULT_MODE_test.FieldInjectionWithQualifier_MembersInjector
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_fieldInjectionWithQualifier_DEFAULT_MODE_test.FieldInjectionWithQualifier_MembersInjector
@@ -18,7 +18,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class FieldInjectionWithQualifier_MembersInjector implements MembersInjector<FieldInjectionWithQualifier> {
   private final Provider<String> aProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_fieldInjectionWithQualifier_FAST_INIT_MODE_test.FieldInjectionWithQualifier_MembersInjector b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_fieldInjectionWithQualifier_FAST_INIT_MODE_test.FieldInjectionWithQualifier_MembersInjector
index 7d5b277..46faeb8 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_fieldInjectionWithQualifier_FAST_INIT_MODE_test.FieldInjectionWithQualifier_MembersInjector
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_fieldInjectionWithQualifier_FAST_INIT_MODE_test.FieldInjectionWithQualifier_MembersInjector
@@ -18,7 +18,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class FieldInjectionWithQualifier_MembersInjector implements MembersInjector<FieldInjectionWithQualifier> {
   private final Provider<String> aProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_fieldInjection_DEFAULT_MODE_test.FieldInjection_MembersInjector b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_fieldInjection_DEFAULT_MODE_test.FieldInjection_MembersInjector
index 7c3425a..b0af865 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_fieldInjection_DEFAULT_MODE_test.FieldInjection_MembersInjector
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_fieldInjection_DEFAULT_MODE_test.FieldInjection_MembersInjector
@@ -19,7 +19,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class FieldInjection_MembersInjector implements MembersInjector<FieldInjection> {
   private final Provider<String> stringProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_fieldInjection_FAST_INIT_MODE_test.FieldInjection_MembersInjector b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_fieldInjection_FAST_INIT_MODE_test.FieldInjection_MembersInjector
index 7c3425a..b0af865 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_fieldInjection_FAST_INIT_MODE_test.FieldInjection_MembersInjector
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_fieldInjection_FAST_INIT_MODE_test.FieldInjection_MembersInjector
@@ -19,7 +19,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class FieldInjection_MembersInjector implements MembersInjector<FieldInjection> {
   private final Provider<String> stringProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_injectConstructorAndMembersInjection_DEFAULT_MODE_test.AllInjections_MembersInjector b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_injectConstructorAndMembersInjection_DEFAULT_MODE_test.AllInjections_MembersInjector
index 479cf07..0c67f59 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_injectConstructorAndMembersInjection_DEFAULT_MODE_test.AllInjections_MembersInjector
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_injectConstructorAndMembersInjection_DEFAULT_MODE_test.AllInjections_MembersInjector
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class AllInjections_MembersInjector implements MembersInjector<AllInjections> {
   private final Provider<String> sProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_injectConstructorAndMembersInjection_FAST_INIT_MODE_test.AllInjections_MembersInjector b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_injectConstructorAndMembersInjection_FAST_INIT_MODE_test.AllInjections_MembersInjector
index 479cf07..0c67f59 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_injectConstructorAndMembersInjection_FAST_INIT_MODE_test.AllInjections_MembersInjector
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_injectConstructorAndMembersInjection_FAST_INIT_MODE_test.AllInjections_MembersInjector
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class AllInjections_MembersInjector implements MembersInjector<AllInjections> {
   private final Provider<String> sProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_injectsPrimitive_DEFAULT_MODE_test.InjectedType_Factory b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_injectsPrimitive_DEFAULT_MODE_test.InjectedType_Factory
index 8851616..b63c408 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_injectsPrimitive_DEFAULT_MODE_test.InjectedType_Factory
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_injectsPrimitive_DEFAULT_MODE_test.InjectedType_Factory
@@ -18,7 +18,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class InjectedType_Factory implements Factory<InjectedType> {
   private final Provider<Integer> primitiveIntProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_injectsPrimitive_DEFAULT_MODE_test.InjectedType_MembersInjector b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_injectsPrimitive_DEFAULT_MODE_test.InjectedType_MembersInjector
index 91f6586..f288697 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_injectsPrimitive_DEFAULT_MODE_test.InjectedType_MembersInjector
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_injectsPrimitive_DEFAULT_MODE_test.InjectedType_MembersInjector
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class InjectedType_MembersInjector implements MembersInjector<InjectedType> {
   private final Provider<Integer> primitiveIntProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_injectsPrimitive_FAST_INIT_MODE_test.InjectedType_Factory b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_injectsPrimitive_FAST_INIT_MODE_test.InjectedType_Factory
index 8851616..b63c408 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_injectsPrimitive_FAST_INIT_MODE_test.InjectedType_Factory
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_injectsPrimitive_FAST_INIT_MODE_test.InjectedType_Factory
@@ -18,7 +18,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class InjectedType_Factory implements Factory<InjectedType> {
   private final Provider<Integer> primitiveIntProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_injectsPrimitive_FAST_INIT_MODE_test.InjectedType_MembersInjector b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_injectsPrimitive_FAST_INIT_MODE_test.InjectedType_MembersInjector
index 91f6586..f288697 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_injectsPrimitive_FAST_INIT_MODE_test.InjectedType_MembersInjector
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_injectsPrimitive_FAST_INIT_MODE_test.InjectedType_MembersInjector
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class InjectedType_MembersInjector implements MembersInjector<InjectedType> {
   private final Provider<Integer> primitiveIntProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_methodInjection_DEFAULT_MODE_test.MethodInjection_MembersInjector b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_methodInjection_DEFAULT_MODE_test.MethodInjection_MembersInjector
index 3fcbb90..9d11248 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_methodInjection_DEFAULT_MODE_test.MethodInjection_MembersInjector
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_methodInjection_DEFAULT_MODE_test.MethodInjection_MembersInjector
@@ -18,7 +18,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class MethodInjection_MembersInjector implements MembersInjector<MethodInjection> {
   private final Provider<String> stringProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_methodInjection_FAST_INIT_MODE_test.MethodInjection_MembersInjector b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_methodInjection_FAST_INIT_MODE_test.MethodInjection_MembersInjector
index 3fcbb90..9d11248 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_methodInjection_FAST_INIT_MODE_test.MethodInjection_MembersInjector
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_methodInjection_FAST_INIT_MODE_test.MethodInjection_MembersInjector
@@ -18,7 +18,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class MethodInjection_MembersInjector implements MembersInjector<MethodInjection> {
   private final Provider<String> stringProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_middleClassNoFieldInjection_DEFAULT_MODE_test.A_MembersInjector b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_middleClassNoFieldInjection_DEFAULT_MODE_test.A_MembersInjector
index f06dabe..86589c7 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_middleClassNoFieldInjection_DEFAULT_MODE_test.A_MembersInjector
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_middleClassNoFieldInjection_DEFAULT_MODE_test.A_MembersInjector
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class A_MembersInjector implements MembersInjector<A> {
   private final Provider<String> valueCProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_middleClassNoFieldInjection_DEFAULT_MODE_test.C_MembersInjector b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_middleClassNoFieldInjection_DEFAULT_MODE_test.C_MembersInjector
index 1b862a7..9c18178 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_middleClassNoFieldInjection_DEFAULT_MODE_test.C_MembersInjector
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_middleClassNoFieldInjection_DEFAULT_MODE_test.C_MembersInjector
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class C_MembersInjector implements MembersInjector<C> {
   private final Provider<String> valueCProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_middleClassNoFieldInjection_FAST_INIT_MODE_test.A_MembersInjector b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_middleClassNoFieldInjection_FAST_INIT_MODE_test.A_MembersInjector
index f06dabe..86589c7 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_middleClassNoFieldInjection_FAST_INIT_MODE_test.A_MembersInjector
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_middleClassNoFieldInjection_FAST_INIT_MODE_test.A_MembersInjector
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class A_MembersInjector implements MembersInjector<A> {
   private final Provider<String> valueCProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_middleClassNoFieldInjection_FAST_INIT_MODE_test.C_MembersInjector b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_middleClassNoFieldInjection_FAST_INIT_MODE_test.C_MembersInjector
index 1b862a7..9c18178 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_middleClassNoFieldInjection_FAST_INIT_MODE_test.C_MembersInjector
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_middleClassNoFieldInjection_FAST_INIT_MODE_test.C_MembersInjector
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class C_MembersInjector implements MembersInjector<C> {
   private final Provider<String> valueCProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_mixedMemberInjection_DEFAULT_MODE_test.MixedMemberInjection_MembersInjector b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_mixedMemberInjection_DEFAULT_MODE_test.MixedMemberInjection_MembersInjector
index e12de5c..ba590b8 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_mixedMemberInjection_DEFAULT_MODE_test.MixedMemberInjection_MembersInjector
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_mixedMemberInjection_DEFAULT_MODE_test.MixedMemberInjection_MembersInjector
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class MixedMemberInjection_MembersInjector implements MembersInjector<MixedMemberInjection> {
   private final Provider<String> stringProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_mixedMemberInjection_FAST_INIT_MODE_test.MixedMemberInjection_MembersInjector b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_mixedMemberInjection_FAST_INIT_MODE_test.MixedMemberInjection_MembersInjector
index e12de5c..ba590b8 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_mixedMemberInjection_FAST_INIT_MODE_test.MixedMemberInjection_MembersInjector
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_mixedMemberInjection_FAST_INIT_MODE_test.MixedMemberInjection_MembersInjector
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class MixedMemberInjection_MembersInjector implements MembersInjector<MixedMemberInjection> {
   private final Provider<String> stringProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_parentClass_injectedMembersInSupertype_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_parentClass_injectedMembersInSupertype_DEFAULT_MODE_test.DaggerTestComponent
index 2bcafb9..88e7fa5 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_parentClass_injectedMembersInSupertype_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_parentClass_injectedMembersInSupertype_DEFAULT_MODE_test.DaggerTestComponent
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_parentClass_injectedMembersInSupertype_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_parentClass_injectedMembersInSupertype_FAST_INIT_MODE_test.DaggerTestComponent
index 2bcafb9..88e7fa5 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_parentClass_injectedMembersInSupertype_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_parentClass_injectedMembersInSupertype_FAST_INIT_MODE_test.DaggerTestComponent
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_parentClass_noInjectedMembers_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_parentClass_noInjectedMembers_DEFAULT_MODE_test.DaggerTestComponent
index 9549f7b..c4c4b07 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_parentClass_noInjectedMembers_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_parentClass_noInjectedMembers_DEFAULT_MODE_test.DaggerTestComponent
@@ -12,7 +12,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_parentClass_noInjectedMembers_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_parentClass_noInjectedMembers_FAST_INIT_MODE_test.DaggerTestComponent
index 9549f7b..c4c4b07 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_parentClass_noInjectedMembers_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_parentClass_noInjectedMembers_FAST_INIT_MODE_test.DaggerTestComponent
@@ -12,7 +12,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_publicSupertypeHiddenSubtype_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_publicSupertypeHiddenSubtype_DEFAULT_MODE_test.DaggerTestComponent
index 560506b..04a4131 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_publicSupertypeHiddenSubtype_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_publicSupertypeHiddenSubtype_DEFAULT_MODE_test.DaggerTestComponent
@@ -19,7 +19,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_publicSupertypeHiddenSubtype_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_publicSupertypeHiddenSubtype_FAST_INIT_MODE_test.DaggerTestComponent
index 560506b..04a4131 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_publicSupertypeHiddenSubtype_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_publicSupertypeHiddenSubtype_FAST_INIT_MODE_test.DaggerTestComponent
@@ -19,7 +19,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_simpleComponentWithNesting_DEFAULT_MODE_test.OuterType_B_MembersInjector b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_simpleComponentWithNesting_DEFAULT_MODE_test.OuterType_B_MembersInjector
index 72b876e..5b4932f 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_simpleComponentWithNesting_DEFAULT_MODE_test.OuterType_B_MembersInjector
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_simpleComponentWithNesting_DEFAULT_MODE_test.OuterType_B_MembersInjector
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class OuterType_B_MembersInjector implements MembersInjector<OuterType.B> {
   private final Provider<OuterType.A> aProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_simpleComponentWithNesting_FAST_INIT_MODE_test.OuterType_B_MembersInjector b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_simpleComponentWithNesting_FAST_INIT_MODE_test.OuterType_B_MembersInjector
index 72b876e..5b4932f 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_simpleComponentWithNesting_FAST_INIT_MODE_test.OuterType_B_MembersInjector
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_simpleComponentWithNesting_FAST_INIT_MODE_test.OuterType_B_MembersInjector
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class OuterType_B_MembersInjector implements MembersInjector<OuterType.B> {
   private final Provider<OuterType.A> aProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_subclassedGenericMembersInjectors_DEFAULT_MODE_test.Child_MembersInjector b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_subclassedGenericMembersInjectors_DEFAULT_MODE_test.Child_MembersInjector
index 19d0335..6040966 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_subclassedGenericMembersInjectors_DEFAULT_MODE_test.Child_MembersInjector
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_subclassedGenericMembersInjectors_DEFAULT_MODE_test.Child_MembersInjector
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class Child_MembersInjector<T> implements MembersInjector<Child<T>> {
   private final Provider<T> xProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_subclassedGenericMembersInjectors_FAST_INIT_MODE_test.Child_MembersInjector b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_subclassedGenericMembersInjectors_FAST_INIT_MODE_test.Child_MembersInjector
index 19d0335..6040966 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_subclassedGenericMembersInjectors_FAST_INIT_MODE_test.Child_MembersInjector
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_subclassedGenericMembersInjectors_FAST_INIT_MODE_test.Child_MembersInjector
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class Child_MembersInjector<T> implements MembersInjector<Child<T>> {
   private final Provider<T> xProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_supertypeMembersInjection_DEFAULT_MODE_test.B_MembersInjector b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_supertypeMembersInjection_DEFAULT_MODE_test.B_MembersInjector
index 0489970..01f787b 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_supertypeMembersInjection_DEFAULT_MODE_test.B_MembersInjector
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_supertypeMembersInjection_DEFAULT_MODE_test.B_MembersInjector
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class B_MembersInjector implements MembersInjector<B> {
   private final Provider<String> sProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_supertypeMembersInjection_FAST_INIT_MODE_test.B_MembersInjector b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_supertypeMembersInjection_FAST_INIT_MODE_test.B_MembersInjector
index 0489970..01f787b 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_supertypeMembersInjection_FAST_INIT_MODE_test.B_MembersInjector
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_supertypeMembersInjection_FAST_INIT_MODE_test.B_MembersInjector
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class B_MembersInjector implements MembersInjector<B> {
   private final Provider<String> sProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_testConstructorInjectedFieldInjection_DEFAULT_MODE_test.A_MembersInjector b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_testConstructorInjectedFieldInjection_DEFAULT_MODE_test.A_MembersInjector
index 5db62ea..f126251 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_testConstructorInjectedFieldInjection_DEFAULT_MODE_test.A_MembersInjector
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_testConstructorInjectedFieldInjection_DEFAULT_MODE_test.A_MembersInjector
@@ -16,7 +16,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class A_MembersInjector implements MembersInjector<A> {
   private final Provider<String> valueBProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_testConstructorInjectedFieldInjection_DEFAULT_MODE_test.B_MembersInjector b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_testConstructorInjectedFieldInjection_DEFAULT_MODE_test.B_MembersInjector
index 6a81851..192947e 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_testConstructorInjectedFieldInjection_DEFAULT_MODE_test.B_MembersInjector
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_testConstructorInjectedFieldInjection_DEFAULT_MODE_test.B_MembersInjector
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class B_MembersInjector implements MembersInjector<B> {
   private final Provider<String> valueBProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_testConstructorInjectedFieldInjection_FAST_INIT_MODE_test.A_MembersInjector b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_testConstructorInjectedFieldInjection_FAST_INIT_MODE_test.A_MembersInjector
index 5db62ea..f126251 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_testConstructorInjectedFieldInjection_FAST_INIT_MODE_test.A_MembersInjector
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_testConstructorInjectedFieldInjection_FAST_INIT_MODE_test.A_MembersInjector
@@ -16,7 +16,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class A_MembersInjector implements MembersInjector<A> {
   private final Provider<String> valueBProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_testConstructorInjectedFieldInjection_FAST_INIT_MODE_test.B_MembersInjector b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_testConstructorInjectedFieldInjection_FAST_INIT_MODE_test.B_MembersInjector
index 6a81851..192947e 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_testConstructorInjectedFieldInjection_FAST_INIT_MODE_test.B_MembersInjector
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_testConstructorInjectedFieldInjection_FAST_INIT_MODE_test.B_MembersInjector
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class B_MembersInjector implements MembersInjector<B> {
   private final Provider<String> valueBProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_testMembersInjectionBindingExistsInParentComponent_DEFAULT_MODE_test.DaggerMyComponent b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_testMembersInjectionBindingExistsInParentComponent_DEFAULT_MODE_test.DaggerMyComponent
index c20059f..c563a1a 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_testMembersInjectionBindingExistsInParentComponent_DEFAULT_MODE_test.DaggerMyComponent
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_testMembersInjectionBindingExistsInParentComponent_DEFAULT_MODE_test.DaggerMyComponent
@@ -15,7 +15,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class DaggerMyComponent {
   private DaggerMyComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_testMembersInjectionBindingExistsInParentComponent_FAST_INIT_MODE_test.DaggerMyComponent b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_testMembersInjectionBindingExistsInParentComponent_FAST_INIT_MODE_test.DaggerMyComponent
index c20059f..c563a1a 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_testMembersInjectionBindingExistsInParentComponent_FAST_INIT_MODE_test.DaggerMyComponent
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_testMembersInjectionBindingExistsInParentComponent_FAST_INIT_MODE_test.DaggerMyComponent
@@ -15,7 +15,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class DaggerMyComponent {
   private DaggerMyComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_testMembersInjectionBindingSharesInjectMethodsWithProvisionBinding_DEFAULT_MODE_test.DaggerMyComponent b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_testMembersInjectionBindingSharesInjectMethodsWithProvisionBinding_DEFAULT_MODE_test.DaggerMyComponent
index a352ab6..72140b3 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_testMembersInjectionBindingSharesInjectMethodsWithProvisionBinding_DEFAULT_MODE_test.DaggerMyComponent
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_testMembersInjectionBindingSharesInjectMethodsWithProvisionBinding_DEFAULT_MODE_test.DaggerMyComponent
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class DaggerMyComponent {
   private DaggerMyComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_testMembersInjectionBindingSharesInjectMethodsWithProvisionBinding_FAST_INIT_MODE_test.DaggerMyComponent b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_testMembersInjectionBindingSharesInjectMethodsWithProvisionBinding_FAST_INIT_MODE_test.DaggerMyComponent
index a352ab6..72140b3 100644
--- a/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_testMembersInjectionBindingSharesInjectMethodsWithProvisionBinding_FAST_INIT_MODE_test.DaggerMyComponent
+++ b/javatests/dagger/internal/codegen/goldens/MembersInjectionTest_testMembersInjectionBindingSharesInjectMethodsWithProvisionBinding_FAST_INIT_MODE_test.DaggerMyComponent
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class DaggerMyComponent {
   private DaggerMyComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_genericSubclassedModule_test.ChildIntegerModule_ProvideIntegerFactory b/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_genericSubclassedModule_test.ChildIntegerModule_ProvideIntegerFactory
index 622314a..8b9a451 100644
--- a/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_genericSubclassedModule_test.ChildIntegerModule_ProvideIntegerFactory
+++ b/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_genericSubclassedModule_test.ChildIntegerModule_ProvideIntegerFactory
@@ -18,7 +18,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class ChildIntegerModule_ProvideIntegerFactory implements Factory<Integer> {
   private final ChildIntegerModule module;
diff --git a/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_genericSubclassedModule_test.ChildNumberModule_ProvideNumberFactory b/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_genericSubclassedModule_test.ChildNumberModule_ProvideNumberFactory
index b906749..d662cc6 100644
--- a/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_genericSubclassedModule_test.ChildNumberModule_ProvideNumberFactory
+++ b/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_genericSubclassedModule_test.ChildNumberModule_ProvideNumberFactory
@@ -18,7 +18,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class ChildNumberModule_ProvideNumberFactory implements Factory<Number> {
   private final ChildNumberModule module;
diff --git a/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_genericSubclassedModule_test.ParentModule_ProvideBElementFactory b/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_genericSubclassedModule_test.ParentModule_ProvideBElementFactory
index 967f5f2..d669e2a 100644
--- a/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_genericSubclassedModule_test.ParentModule_ProvideBElementFactory
+++ b/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_genericSubclassedModule_test.ParentModule_ProvideBElementFactory
@@ -19,7 +19,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class ParentModule_ProvideBElementFactory<A extends CharSequence, B, C extends Number & Comparable<C>> implements Factory<B> {
   private final ParentModule<A, B, C> module;
diff --git a/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_genericSubclassedModule_test.ParentModule_ProvideBEntryFactory b/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_genericSubclassedModule_test.ParentModule_ProvideBEntryFactory
index d518c05..35052f4 100644
--- a/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_genericSubclassedModule_test.ParentModule_ProvideBEntryFactory
+++ b/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_genericSubclassedModule_test.ParentModule_ProvideBEntryFactory
@@ -19,7 +19,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class ParentModule_ProvideBEntryFactory<A extends CharSequence, B, C extends Number & Comparable<C>> implements Factory<B> {
   private final ParentModule<A, B, C> module;
diff --git a/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_genericSubclassedModule_test.ParentModule_ProvideListBFactory b/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_genericSubclassedModule_test.ParentModule_ProvideListBFactory
index 405bdda..a36bf26 100644
--- a/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_genericSubclassedModule_test.ParentModule_ProvideListBFactory
+++ b/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_genericSubclassedModule_test.ParentModule_ProvideListBFactory
@@ -20,7 +20,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class ParentModule_ProvideListBFactory<A extends CharSequence, B, C extends Number & Comparable<C>> implements Factory<List<B>> {
   private final ParentModule<A, B, C> module;
diff --git a/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_multipleProvidesMethods_test.TestModule_ProvideObjectsFactory b/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_multipleProvidesMethods_test.TestModule_ProvideObjectsFactory
index d0147f7..63ae5bf 100644
--- a/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_multipleProvidesMethods_test.TestModule_ProvideObjectsFactory
+++ b/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_multipleProvidesMethods_test.TestModule_ProvideObjectsFactory
@@ -24,7 +24,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class TestModule_ProvideObjectsFactory implements Factory<List<Object>> {
   private final TestModule module;
diff --git a/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_nullableProvides_test.TestModule_ProvideStringFactory b/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_nullableProvides_test.TestModule_ProvideStringFactory
index cbc4dc1..8e3b1cd 100644
--- a/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_nullableProvides_test.TestModule_ProvideStringFactory
+++ b/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_nullableProvides_test.TestModule_ProvideStringFactory
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class TestModule_ProvideStringFactory implements Factory<String> {
   private final TestModule module;
diff --git a/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_parameterizedModuleWithStaticProvidesMethodOfGenericType_test.ParameterizedModule_ProvideMapStringNumberFactory b/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_parameterizedModuleWithStaticProvidesMethodOfGenericType_test.ParameterizedModule_ProvideMapStringNumberFactory
index 397def8..9185ad3 100644
--- a/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_parameterizedModuleWithStaticProvidesMethodOfGenericType_test.ParameterizedModule_ProvideMapStringNumberFactory
+++ b/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_parameterizedModuleWithStaticProvidesMethodOfGenericType_test.ParameterizedModule_ProvideMapStringNumberFactory
@@ -19,7 +19,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class ParameterizedModule_ProvideMapStringNumberFactory implements Factory<Map<String, Number>> {
   @Override
diff --git a/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_parameterizedModuleWithStaticProvidesMethodOfGenericType_test.ParameterizedModule_ProvideNonGenericTypeFactory b/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_parameterizedModuleWithStaticProvidesMethodOfGenericType_test.ParameterizedModule_ProvideNonGenericTypeFactory
index c5a0f30..29bea60 100644
--- a/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_parameterizedModuleWithStaticProvidesMethodOfGenericType_test.ParameterizedModule_ProvideNonGenericTypeFactory
+++ b/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_parameterizedModuleWithStaticProvidesMethodOfGenericType_test.ParameterizedModule_ProvideNonGenericTypeFactory
@@ -18,7 +18,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class ParameterizedModule_ProvideNonGenericTypeFactory implements Factory<Object> {
   @Override
diff --git a/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_parameterizedModuleWithStaticProvidesMethodOfGenericType_test.ParameterizedModule_ProvideNonGenericTypeWithDepsFactory b/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_parameterizedModuleWithStaticProvidesMethodOfGenericType_test.ParameterizedModule_ProvideNonGenericTypeWithDepsFactory
index 019f5f2..4f91376 100644
--- a/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_parameterizedModuleWithStaticProvidesMethodOfGenericType_test.ParameterizedModule_ProvideNonGenericTypeWithDepsFactory
+++ b/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_parameterizedModuleWithStaticProvidesMethodOfGenericType_test.ParameterizedModule_ProvideNonGenericTypeWithDepsFactory
@@ -19,7 +19,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class ParameterizedModule_ProvideNonGenericTypeWithDepsFactory implements Factory<String> {
   private final Provider<Object> oProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_providesSetElementWildcard_test.TestModule_ProvideWildcardListFactory b/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_providesSetElementWildcard_test.TestModule_ProvideWildcardListFactory
index bb66ad3..6fabfaa 100644
--- a/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_providesSetElementWildcard_test.TestModule_ProvideWildcardListFactory
+++ b/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_providesSetElementWildcard_test.TestModule_ProvideWildcardListFactory
@@ -19,7 +19,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class TestModule_ProvideWildcardListFactory implements Factory<List<List<?>>> {
   private final TestModule module;
diff --git a/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_providesSetElement_test.TestModule_ProvideStringFactory b/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_providesSetElement_test.TestModule_ProvideStringFactory
index 835bb72..6675a41 100644
--- a/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_providesSetElement_test.TestModule_ProvideStringFactory
+++ b/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_providesSetElement_test.TestModule_ProvideStringFactory
@@ -18,7 +18,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class TestModule_ProvideStringFactory implements Factory<String> {
   private final TestModule module;
diff --git a/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_providesSetValues_test.TestModule_ProvideStringsFactory b/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_providesSetValues_test.TestModule_ProvideStringsFactory
index 459a1a8..240620f 100644
--- a/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_providesSetValues_test.TestModule_ProvideStringsFactory
+++ b/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_providesSetValues_test.TestModule_ProvideStringsFactory
@@ -19,7 +19,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class TestModule_ProvideStringsFactory implements Factory<Set<String>> {
   private final TestModule module;
diff --git a/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_proxyMethodsConflictWithOtherFactoryMethods_test.TestModule_CreateFactory b/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_proxyMethodsConflictWithOtherFactoryMethods_test.TestModule_CreateFactory
index 061a827..9250da8 100644
--- a/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_proxyMethodsConflictWithOtherFactoryMethods_test.TestModule_CreateFactory
+++ b/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_proxyMethodsConflictWithOtherFactoryMethods_test.TestModule_CreateFactory
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class TestModule_CreateFactory implements Factory<Boolean> {
   @Override
diff --git a/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_proxyMethodsConflictWithOtherFactoryMethods_test.TestModule_GetFactory b/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_proxyMethodsConflictWithOtherFactoryMethods_test.TestModule_GetFactory
index 7d9d3c5..52eb228 100644
--- a/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_proxyMethodsConflictWithOtherFactoryMethods_test.TestModule_GetFactory
+++ b/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_proxyMethodsConflictWithOtherFactoryMethods_test.TestModule_GetFactory
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class TestModule_GetFactory implements Factory<Integer> {
   @Override
diff --git a/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_singleProvidesMethodNoArgs_disableNullable_test.TestModule_ProvideStringFactory b/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_singleProvidesMethodNoArgs_disableNullable_test.TestModule_ProvideStringFactory
index 4515d0a..9755887 100644
--- a/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_singleProvidesMethodNoArgs_disableNullable_test.TestModule_ProvideStringFactory
+++ b/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_singleProvidesMethodNoArgs_disableNullable_test.TestModule_ProvideStringFactory
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class TestModule_ProvideStringFactory implements Factory<String> {
   private final TestModule module;
diff --git a/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_singleProvidesMethodNoArgs_test.TestModule_ProvideStringFactory b/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_singleProvidesMethodNoArgs_test.TestModule_ProvideStringFactory
index 835bb72..6675a41 100644
--- a/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_singleProvidesMethodNoArgs_test.TestModule_ProvideStringFactory
+++ b/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_singleProvidesMethodNoArgs_test.TestModule_ProvideStringFactory
@@ -18,7 +18,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class TestModule_ProvideStringFactory implements Factory<String> {
   private final TestModule module;
diff --git a/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_testQualifierMetadataOnProvides_test.MyModule_ProvideStringFactory b/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_testQualifierMetadataOnProvides_test.MyModule_ProvideStringFactory
index 64da8b3..e62e7b9 100644
--- a/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_testQualifierMetadataOnProvides_test.MyModule_ProvideStringFactory
+++ b/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_testQualifierMetadataOnProvides_test.MyModule_ProvideStringFactory
@@ -22,7 +22,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class MyModule_ProvideStringFactory implements Factory<String> {
   private final Provider<Integer> iProvider;
diff --git a/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_testScopeMetadataWithCustomScope_test.MyModule_ProvideStringFactory b/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_testScopeMetadataWithCustomScope_test.MyModule_ProvideStringFactory
index d9b71ef..8ec360d 100644
--- a/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_testScopeMetadataWithCustomScope_test.MyModule_ProvideStringFactory
+++ b/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_testScopeMetadataWithCustomScope_test.MyModule_ProvideStringFactory
@@ -18,7 +18,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class MyModule_ProvideStringFactory implements Factory<String> {
   @Override
diff --git a/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_testScopedMetadataOnNonStaticProvides_test.MyModule_ProvideStringFactory b/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_testScopedMetadataOnNonStaticProvides_test.MyModule_ProvideStringFactory
index bd6c237..e5a04c5 100644
--- a/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_testScopedMetadataOnNonStaticProvides_test.MyModule_ProvideStringFactory
+++ b/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_testScopedMetadataOnNonStaticProvides_test.MyModule_ProvideStringFactory
@@ -18,7 +18,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class MyModule_ProvideStringFactory implements Factory<String> {
   private final MyModule module;
diff --git a/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_testScopedMetadataOnStaticProvides_test.MyModule_ProvideStringFactory b/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_testScopedMetadataOnStaticProvides_test.MyModule_ProvideStringFactory
index 591f9ac..b88b3e3 100644
--- a/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_testScopedMetadataOnStaticProvides_test.MyModule_ProvideStringFactory
+++ b/javatests/dagger/internal/codegen/goldens/ModuleFactoryGeneratorTest_testScopedMetadataOnStaticProvides_test.MyModule_ProvideStringFactory
@@ -18,7 +18,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class MyModule_ProvideStringFactory implements Factory<String> {
   @Override
diff --git a/javatests/dagger/internal/codegen/goldens/OptionalBindingRequestFulfillmentTest_inlinedOptionalBindings_DEFAULT_JAVA7_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/OptionalBindingRequestFulfillmentTest_inlinedOptionalBindings_DEFAULT_JAVA7_MODE_test.DaggerTestComponent
index 3f21b64..37c1bb8 100644
--- a/javatests/dagger/internal/codegen/goldens/OptionalBindingRequestFulfillmentTest_inlinedOptionalBindings_DEFAULT_JAVA7_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/OptionalBindingRequestFulfillmentTest_inlinedOptionalBindings_DEFAULT_JAVA7_MODE_test.DaggerTestComponent
@@ -3,7 +3,6 @@
 import com.google.common.base.Optional;
 import dagger.Lazy;
 import dagger.internal.DaggerGenerated;
-import dagger.internal.Preconditions;
 import dagger.internal.ProviderOfLazy;
 import javax.annotation.Generated;
 import javax.inject.Provider;
@@ -20,7 +19,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -38,15 +38,6 @@
     private Builder() {
     }
 
-    /**
-     * @deprecated This module is declared, but an instance is not used in the component. This method is a no-op. For more, see https://dagger.dev/unused-modules.
-     */
-    @Deprecated
-    public Builder maybeModule(Maybe.MaybeModule maybeModule) {
-      Preconditions.checkNotNull(maybeModule);
-      return this;
-    }
-
     public TestComponent build() {
       return new TestComponentImpl();
     }
@@ -67,7 +58,7 @@
 
     @Override
     public Optional<Provider<Lazy<Maybe>>> providerOfLazyOfMaybe() {
-      return Optional.of(ProviderOfLazy.create(Maybe_MaybeModule_ProvideMaybeFactory.create()));
+      return (Optional) Optional.of(ProviderOfLazy.create(Maybe_MaybeModule_ProvideMaybeFactory.create()));
     }
 
     @Override
@@ -77,7 +68,7 @@
 
     @Override
     public Optional<Provider<Lazy<DefinitelyNot>>> providerOfLazyOfDefinitelyNot() {
-      return Optional.<Provider<Lazy<DefinitelyNot>>>absent();
+      return (Optional) Optional.<Provider<Lazy<DefinitelyNot>>>absent();
     }
   }
 }
diff --git a/javatests/dagger/internal/codegen/goldens/OptionalBindingRequestFulfillmentTest_inlinedOptionalBindings_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/OptionalBindingRequestFulfillmentTest_inlinedOptionalBindings_DEFAULT_MODE_test.DaggerTestComponent
index 72d51f3..0884286 100644
--- a/javatests/dagger/internal/codegen/goldens/OptionalBindingRequestFulfillmentTest_inlinedOptionalBindings_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/OptionalBindingRequestFulfillmentTest_inlinedOptionalBindings_DEFAULT_MODE_test.DaggerTestComponent
@@ -3,7 +3,6 @@
 import com.google.common.base.Optional;
 import dagger.Lazy;
 import dagger.internal.DaggerGenerated;
-import dagger.internal.Preconditions;
 import dagger.internal.ProviderOfLazy;
 import javax.annotation.processing.Generated;
 import javax.inject.Provider;
@@ -20,7 +19,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -38,15 +38,6 @@
     private Builder() {
     }
 
-    /**
-     * @deprecated This module is declared, but an instance is not used in the component. This method is a no-op. For more, see https://dagger.dev/unused-modules.
-     */
-    @Deprecated
-    public Builder maybeModule(Maybe.MaybeModule maybeModule) {
-      Preconditions.checkNotNull(maybeModule);
-      return this;
-    }
-
     public TestComponent build() {
       return new TestComponentImpl();
     }
diff --git a/javatests/dagger/internal/codegen/goldens/OptionalBindingRequestFulfillmentTest_inlinedOptionalBindings_FAST_INIT_JAVA7_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/OptionalBindingRequestFulfillmentTest_inlinedOptionalBindings_FAST_INIT_JAVA7_MODE_test.DaggerTestComponent
index f99b125..f1ab214 100644
--- a/javatests/dagger/internal/codegen/goldens/OptionalBindingRequestFulfillmentTest_inlinedOptionalBindings_FAST_INIT_JAVA7_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/OptionalBindingRequestFulfillmentTest_inlinedOptionalBindings_FAST_INIT_JAVA7_MODE_test.DaggerTestComponent
@@ -3,10 +3,9 @@
 import com.google.common.base.Optional;
 import dagger.Lazy;
 import dagger.internal.DaggerGenerated;
-import dagger.internal.Preconditions;
+import dagger.internal.Provider;
 import dagger.internal.ProviderOfLazy;
 import javax.annotation.Generated;
-import javax.inject.Provider;
 import other.DefinitelyNot;
 import other.Maybe;
 import other.Maybe_MaybeModule_ProvideMaybeFactory;
@@ -20,7 +19,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -38,15 +38,6 @@
     private Builder() {
     }
 
-    /**
-     * @deprecated This module is declared, but an instance is not used in the component. This method is a no-op. For more, see https://dagger.dev/unused-modules.
-     */
-    @Deprecated
-    public Builder maybeModule(Maybe.MaybeModule maybeModule) {
-      Preconditions.checkNotNull(maybeModule);
-      return this;
-    }
-
     public TestComponent build() {
       return new TestComponentImpl();
     }
@@ -74,8 +65,8 @@
     }
 
     @Override
-    public Optional<Provider<Lazy<Maybe>>> providerOfLazyOfMaybe() {
-      return Optional.of(ProviderOfLazy.create(provideMaybeProvider));
+    public Optional<javax.inject.Provider<Lazy<Maybe>>> providerOfLazyOfMaybe() {
+      return (Optional) Optional.of(ProviderOfLazy.create(provideMaybeProvider));
     }
 
     @Override
@@ -84,8 +75,8 @@
     }
 
     @Override
-    public Optional<Provider<Lazy<DefinitelyNot>>> providerOfLazyOfDefinitelyNot() {
-      return Optional.<Provider<Lazy<DefinitelyNot>>>absent();
+    public Optional<javax.inject.Provider<Lazy<DefinitelyNot>>> providerOfLazyOfDefinitelyNot() {
+      return (Optional) Optional.<javax.inject.Provider<Lazy<DefinitelyNot>>>absent();
     }
 
     private static final class SwitchingProvider<T> implements Provider<T> {
diff --git a/javatests/dagger/internal/codegen/goldens/OptionalBindingRequestFulfillmentTest_inlinedOptionalBindings_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/OptionalBindingRequestFulfillmentTest_inlinedOptionalBindings_FAST_INIT_MODE_test.DaggerTestComponent
index 5d44063..83b8f81 100644
--- a/javatests/dagger/internal/codegen/goldens/OptionalBindingRequestFulfillmentTest_inlinedOptionalBindings_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/OptionalBindingRequestFulfillmentTest_inlinedOptionalBindings_FAST_INIT_MODE_test.DaggerTestComponent
@@ -3,10 +3,9 @@
 import com.google.common.base.Optional;
 import dagger.Lazy;
 import dagger.internal.DaggerGenerated;
-import dagger.internal.Preconditions;
+import dagger.internal.Provider;
 import dagger.internal.ProviderOfLazy;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 import other.DefinitelyNot;
 import other.Maybe;
 import other.Maybe_MaybeModule_ProvideMaybeFactory;
@@ -20,7 +19,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -38,15 +38,6 @@
     private Builder() {
     }
 
-    /**
-     * @deprecated This module is declared, but an instance is not used in the component. This method is a no-op. For more, see https://dagger.dev/unused-modules.
-     */
-    @Deprecated
-    public Builder maybeModule(Maybe.MaybeModule maybeModule) {
-      Preconditions.checkNotNull(maybeModule);
-      return this;
-    }
-
     public TestComponent build() {
       return new TestComponentImpl();
     }
@@ -74,7 +65,7 @@
     }
 
     @Override
-    public Optional<Provider<Lazy<Maybe>>> providerOfLazyOfMaybe() {
+    public Optional<javax.inject.Provider<Lazy<Maybe>>> providerOfLazyOfMaybe() {
       return Optional.of(ProviderOfLazy.create(provideMaybeProvider));
     }
 
@@ -84,7 +75,7 @@
     }
 
     @Override
-    public Optional<Provider<Lazy<DefinitelyNot>>> providerOfLazyOfDefinitelyNot() {
+    public Optional<javax.inject.Provider<Lazy<DefinitelyNot>>> providerOfLazyOfDefinitelyNot() {
       return Optional.absent();
     }
 
diff --git a/javatests/dagger/internal/codegen/goldens/OptionalBindingRequestFulfillmentTest_requestForFuture_DEFAULT_JAVA7_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/OptionalBindingRequestFulfillmentTest_requestForFuture_DEFAULT_JAVA7_MODE_test.DaggerTestComponent
index 7325da9..9d278cb 100644
--- a/javatests/dagger/internal/codegen/goldens/OptionalBindingRequestFulfillmentTest_requestForFuture_DEFAULT_JAVA7_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/OptionalBindingRequestFulfillmentTest_requestForFuture_DEFAULT_JAVA7_MODE_test.DaggerTestComponent
@@ -4,7 +4,6 @@
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 import dagger.internal.DaggerGenerated;
-import dagger.internal.Preconditions;
 import dagger.producers.internal.CancellationListener;
 import javax.annotation.Generated;
 import other.DefinitelyNot;
@@ -20,7 +19,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -38,15 +38,6 @@
     private Builder() {
     }
 
-    /**
-     * @deprecated This module is declared, but an instance is not used in the component. This method is a no-op. For more, see https://dagger.dev/unused-modules.
-     */
-    @Deprecated
-    public Builder maybeModule(Maybe.MaybeModule maybeModule) {
-      Preconditions.checkNotNull(maybeModule);
-      return this;
-    }
-
     public TestComponent build() {
       return new TestComponentImpl();
     }
diff --git a/javatests/dagger/internal/codegen/goldens/OptionalBindingRequestFulfillmentTest_requestForFuture_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/OptionalBindingRequestFulfillmentTest_requestForFuture_DEFAULT_MODE_test.DaggerTestComponent
index 0e2bb0f..e6e1d5a 100644
--- a/javatests/dagger/internal/codegen/goldens/OptionalBindingRequestFulfillmentTest_requestForFuture_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/OptionalBindingRequestFulfillmentTest_requestForFuture_DEFAULT_MODE_test.DaggerTestComponent
@@ -4,7 +4,6 @@
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 import dagger.internal.DaggerGenerated;
-import dagger.internal.Preconditions;
 import dagger.producers.internal.CancellationListener;
 import javax.annotation.processing.Generated;
 import other.DefinitelyNot;
@@ -20,7 +19,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -38,15 +38,6 @@
     private Builder() {
     }
 
-    /**
-     * @deprecated This module is declared, but an instance is not used in the component. This method is a no-op. For more, see https://dagger.dev/unused-modules.
-     */
-    @Deprecated
-    public Builder maybeModule(Maybe.MaybeModule maybeModule) {
-      Preconditions.checkNotNull(maybeModule);
-      return this;
-    }
-
     public TestComponent build() {
       return new TestComponentImpl();
     }
diff --git a/javatests/dagger/internal/codegen/goldens/OptionalBindingRequestFulfillmentTest_requestForFuture_FAST_INIT_JAVA7_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/OptionalBindingRequestFulfillmentTest_requestForFuture_FAST_INIT_JAVA7_MODE_test.DaggerTestComponent
index 7325da9..9d278cb 100644
--- a/javatests/dagger/internal/codegen/goldens/OptionalBindingRequestFulfillmentTest_requestForFuture_FAST_INIT_JAVA7_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/OptionalBindingRequestFulfillmentTest_requestForFuture_FAST_INIT_JAVA7_MODE_test.DaggerTestComponent
@@ -4,7 +4,6 @@
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 import dagger.internal.DaggerGenerated;
-import dagger.internal.Preconditions;
 import dagger.producers.internal.CancellationListener;
 import javax.annotation.Generated;
 import other.DefinitelyNot;
@@ -20,7 +19,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -38,15 +38,6 @@
     private Builder() {
     }
 
-    /**
-     * @deprecated This module is declared, but an instance is not used in the component. This method is a no-op. For more, see https://dagger.dev/unused-modules.
-     */
-    @Deprecated
-    public Builder maybeModule(Maybe.MaybeModule maybeModule) {
-      Preconditions.checkNotNull(maybeModule);
-      return this;
-    }
-
     public TestComponent build() {
       return new TestComponentImpl();
     }
diff --git a/javatests/dagger/internal/codegen/goldens/OptionalBindingRequestFulfillmentTest_requestForFuture_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/OptionalBindingRequestFulfillmentTest_requestForFuture_FAST_INIT_MODE_test.DaggerTestComponent
index 0e2bb0f..e6e1d5a 100644
--- a/javatests/dagger/internal/codegen/goldens/OptionalBindingRequestFulfillmentTest_requestForFuture_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/OptionalBindingRequestFulfillmentTest_requestForFuture_FAST_INIT_MODE_test.DaggerTestComponent
@@ -4,7 +4,6 @@
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 import dagger.internal.DaggerGenerated;
-import dagger.internal.Preconditions;
 import dagger.producers.internal.CancellationListener;
 import javax.annotation.processing.Generated;
 import other.DefinitelyNot;
@@ -20,7 +19,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -38,15 +38,6 @@
     private Builder() {
     }
 
-    /**
-     * @deprecated This module is declared, but an instance is not used in the component. This method is a no-op. For more, see https://dagger.dev/unused-modules.
-     */
-    @Deprecated
-    public Builder maybeModule(Maybe.MaybeModule maybeModule) {
-      Preconditions.checkNotNull(maybeModule);
-      return this;
-    }
-
     public TestComponent build() {
       return new TestComponentImpl();
     }
diff --git a/javatests/dagger/internal/codegen/goldens/ProducerModuleFactoryGeneratorTest_singleProducesMethodNoArgsFutureWithProducerName_test.TestModule_ProduceStringFactory b/javatests/dagger/internal/codegen/goldens/ProducerModuleFactoryGeneratorTest_singleProducesMethodNoArgsFutureWithProducerName_test.TestModule_ProduceStringFactory
index bf59a06..048cdc8 100644
--- a/javatests/dagger/internal/codegen/goldens/ProducerModuleFactoryGeneratorTest_singleProducesMethodNoArgsFutureWithProducerName_test.TestModule_ProduceStringFactory
+++ b/javatests/dagger/internal/codegen/goldens/ProducerModuleFactoryGeneratorTest_singleProducesMethodNoArgsFutureWithProducerName_test.TestModule_ProduceStringFactory
@@ -20,7 +20,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class TestModule_ProduceStringFactory extends AbstractProducesMethodProducer<Void, String> {
   private final TestModule module;
diff --git a/javatests/dagger/internal/codegen/goldens/ProducerModuleFactoryGeneratorTest_singleProducesMethodNoArgsFuture_test.TestModule_ProduceStringFactory b/javatests/dagger/internal/codegen/goldens/ProducerModuleFactoryGeneratorTest_singleProducesMethodNoArgsFuture_test.TestModule_ProduceStringFactory
index cf94c2d..248ceb1 100644
--- a/javatests/dagger/internal/codegen/goldens/ProducerModuleFactoryGeneratorTest_singleProducesMethodNoArgsFuture_test.TestModule_ProduceStringFactory
+++ b/javatests/dagger/internal/codegen/goldens/ProducerModuleFactoryGeneratorTest_singleProducesMethodNoArgsFuture_test.TestModule_ProduceStringFactory
@@ -20,7 +20,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 public final class TestModule_ProduceStringFactory extends AbstractProducesMethodProducer<Void, String> {
   private final TestModule module;
diff --git a/javatests/dagger/internal/codegen/goldens/ProductionComponentProcessorTest_productionScope_injectConstructor_DEFAULT_MODE_test.DaggerParent b/javatests/dagger/internal/codegen/goldens/ProductionComponentProcessorTest_productionScope_injectConstructor_DEFAULT_MODE_test.DaggerParent
index 11af50c..3b72cd4 100644
--- a/javatests/dagger/internal/codegen/goldens/ProductionComponentProcessorTest_productionScope_injectConstructor_DEFAULT_MODE_test.DaggerParent
+++ b/javatests/dagger/internal/codegen/goldens/ProductionComponentProcessorTest_productionScope_injectConstructor_DEFAULT_MODE_test.DaggerParent
@@ -2,9 +2,9 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DoubleCheck;
+import dagger.internal.Provider;
 import dagger.producers.internal.CancellationListener;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -15,7 +15,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerParent {
   private DaggerParent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ProductionComponentProcessorTest_productionScope_injectConstructor_FAST_INIT_MODE_test.DaggerParent b/javatests/dagger/internal/codegen/goldens/ProductionComponentProcessorTest_productionScope_injectConstructor_FAST_INIT_MODE_test.DaggerParent
index 5d0b797..ab89bab 100644
--- a/javatests/dagger/internal/codegen/goldens/ProductionComponentProcessorTest_productionScope_injectConstructor_FAST_INIT_MODE_test.DaggerParent
+++ b/javatests/dagger/internal/codegen/goldens/ProductionComponentProcessorTest_productionScope_injectConstructor_FAST_INIT_MODE_test.DaggerParent
@@ -2,9 +2,9 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DoubleCheck;
+import dagger.internal.Provider;
 import dagger.producers.internal.CancellationListener;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -15,7 +15,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerParent {
   private DaggerParent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ProductionComponentProcessorTest_simpleComponent_DEFAULT_MODE_test.DaggerTestClass_SimpleComponent b/javatests/dagger/internal/codegen/goldens/ProductionComponentProcessorTest_simpleComponent_DEFAULT_MODE_test.DaggerTestClass_SimpleComponent
index d55cd37..6146004 100644
--- a/javatests/dagger/internal/codegen/goldens/ProductionComponentProcessorTest_simpleComponent_DEFAULT_MODE_test.DaggerTestClass_SimpleComponent
+++ b/javatests/dagger/internal/codegen/goldens/ProductionComponentProcessorTest_simpleComponent_DEFAULT_MODE_test.DaggerTestClass_SimpleComponent
@@ -5,6 +5,7 @@
 import dagger.internal.DoubleCheck;
 import dagger.internal.InstanceFactory;
 import dagger.internal.Preconditions;
+import dagger.internal.Provider;
 import dagger.internal.SetFactory;
 import dagger.producers.Producer;
 import dagger.producers.internal.CancellationListener;
@@ -12,7 +13,6 @@
 import dagger.producers.monitoring.ProductionComponentMonitor;
 import java.util.concurrent.Executor;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -23,7 +23,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestClass_SimpleComponent {
   private DaggerTestClass_SimpleComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/ProductionComponentProcessorTest_simpleComponent_FAST_INIT_MODE_test.DaggerTestClass_SimpleComponent b/javatests/dagger/internal/codegen/goldens/ProductionComponentProcessorTest_simpleComponent_FAST_INIT_MODE_test.DaggerTestClass_SimpleComponent
index 9ad6e6f..c5df7dc 100644
--- a/javatests/dagger/internal/codegen/goldens/ProductionComponentProcessorTest_simpleComponent_FAST_INIT_MODE_test.DaggerTestClass_SimpleComponent
+++ b/javatests/dagger/internal/codegen/goldens/ProductionComponentProcessorTest_simpleComponent_FAST_INIT_MODE_test.DaggerTestClass_SimpleComponent
@@ -5,6 +5,7 @@
 import dagger.internal.DoubleCheck;
 import dagger.internal.InstanceFactory;
 import dagger.internal.Preconditions;
+import dagger.internal.Provider;
 import dagger.internal.SetFactory;
 import dagger.producers.Producer;
 import dagger.producers.internal.CancellationListener;
@@ -12,7 +13,6 @@
 import dagger.producers.monitoring.ProductionComponentMonitor;
 import java.util.concurrent.Executor;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -23,7 +23,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestClass_SimpleComponent {
   private DaggerTestClass_SimpleComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentTest_inaccessible_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentTest_inaccessible_DEFAULT_MODE_test.DaggerTestComponent
index 7d85952..988302c 100644
--- a/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentTest_inaccessible_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentTest_inaccessible_DEFAULT_MODE_test.DaggerTestComponent
@@ -18,7 +18,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentTest_inaccessible_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentTest_inaccessible_FAST_INIT_MODE_test.DaggerTestComponent
index 7d85952..988302c 100644
--- a/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentTest_inaccessible_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentTest_inaccessible_FAST_INIT_MODE_test.DaggerTestComponent
@@ -18,7 +18,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentTest_productionComponents_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentTest_productionComponents_DEFAULT_MODE_test.DaggerTestComponent
index d174c1f..f56f0e6 100644
--- a/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentTest_productionComponents_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentTest_productionComponents_DEFAULT_MODE_test.DaggerTestComponent
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentTest_productionComponents_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentTest_productionComponents_FAST_INIT_MODE_test.DaggerTestComponent
index d174c1f..f56f0e6 100644
--- a/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentTest_productionComponents_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentTest_productionComponents_FAST_INIT_MODE_test.DaggerTestComponent
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentTest_setBindings_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentTest_setBindings_DEFAULT_MODE_test.DaggerTestComponent
index 829486b..e69fffe 100644
--- a/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentTest_setBindings_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentTest_setBindings_DEFAULT_MODE_test.DaggerTestComponent
@@ -1,7 +1,6 @@
 package test;
 
 import dagger.internal.DaggerGenerated;
-import dagger.internal.Preconditions;
 import dagger.internal.SetBuilder;
 import java.util.Collections;
 import java.util.Set;
@@ -16,7 +15,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -34,15 +34,6 @@
     private Builder() {
     }
 
-    /**
-     * @deprecated This module is declared, but an instance is not used in the component. This method is a no-op. For more, see https://dagger.dev/unused-modules.
-     */
-    @Deprecated
-    public Builder setModule(SetModule setModule) {
-      Preconditions.checkNotNull(setModule);
-      return this;
-    }
-
     public TestComponent build() {
       return new TestComponentImpl();
     }
diff --git a/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentTest_setBindings_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentTest_setBindings_FAST_INIT_MODE_test.DaggerTestComponent
index 829486b..e69fffe 100644
--- a/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentTest_setBindings_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentTest_setBindings_FAST_INIT_MODE_test.DaggerTestComponent
@@ -1,7 +1,6 @@
 package test;
 
 import dagger.internal.DaggerGenerated;
-import dagger.internal.Preconditions;
 import dagger.internal.SetBuilder;
 import java.util.Collections;
 import java.util.Set;
@@ -16,7 +15,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -34,15 +34,6 @@
     private Builder() {
     }
 
-    /**
-     * @deprecated This module is declared, but an instance is not used in the component. This method is a no-op. For more, see https://dagger.dev/unused-modules.
-     */
-    @Deprecated
-    public Builder setModule(SetModule setModule) {
-      Preconditions.checkNotNull(setModule);
-      return this;
-    }
-
     public TestComponent build() {
       return new TestComponentImpl();
     }
diff --git a/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentTest_subcomponentOmitsInheritedBindings_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentTest_subcomponentOmitsInheritedBindings_DEFAULT_MODE_test.DaggerTestComponent
index 24b2d56..2ffdfd2 100644
--- a/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentTest_subcomponentOmitsInheritedBindings_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentTest_subcomponentOmitsInheritedBindings_DEFAULT_MODE_test.DaggerTestComponent
@@ -1,7 +1,6 @@
 package test;
 
 import dagger.internal.DaggerGenerated;
-import dagger.internal.Preconditions;
 import java.util.Collections;
 import java.util.Set;
 import javax.annotation.processing.Generated;
@@ -15,7 +14,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerParent {
   private DaggerParent() {
@@ -33,15 +33,6 @@
     private Builder() {
     }
 
-    /**
-     * @deprecated This module is declared, but an instance is not used in the component. This method is a no-op. For more, see https://dagger.dev/unused-modules.
-     */
-    @Deprecated
-    public Builder parentModule(ParentModule parentModule) {
-      Preconditions.checkNotNull(parentModule);
-      return this;
-    }
-
     public Parent build() {
       return new ParentImpl();
     }
diff --git a/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentTest_subcomponentOmitsInheritedBindings_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentTest_subcomponentOmitsInheritedBindings_FAST_INIT_MODE_test.DaggerTestComponent
index 24b2d56..2ffdfd2 100644
--- a/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentTest_subcomponentOmitsInheritedBindings_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentTest_subcomponentOmitsInheritedBindings_FAST_INIT_MODE_test.DaggerTestComponent
@@ -1,7 +1,6 @@
 package test;
 
 import dagger.internal.DaggerGenerated;
-import dagger.internal.Preconditions;
 import java.util.Collections;
 import java.util.Set;
 import javax.annotation.processing.Generated;
@@ -15,7 +14,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerParent {
   private DaggerParent() {
@@ -33,15 +33,6 @@
     private Builder() {
     }
 
-    /**
-     * @deprecated This module is declared, but an instance is not used in the component. This method is a no-op. For more, see https://dagger.dev/unused-modules.
-     */
-    @Deprecated
-    public Builder parentModule(ParentModule parentModule) {
-      Preconditions.checkNotNull(parentModule);
-      return this;
-    }
-
     public Parent build() {
       return new ParentImpl();
     }
diff --git a/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentWithGuavaTest_inaccessible_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentWithGuavaTest_inaccessible_DEFAULT_MODE_test.DaggerTestComponent
index fb9fffb..1d16978 100644
--- a/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentWithGuavaTest_inaccessible_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentWithGuavaTest_inaccessible_DEFAULT_MODE_test.DaggerTestComponent
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentWithGuavaTest_inaccessible_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentWithGuavaTest_inaccessible_FAST_INIT_MODE_test.DaggerTestComponent
index fb9fffb..1d16978 100644
--- a/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentWithGuavaTest_inaccessible_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentWithGuavaTest_inaccessible_FAST_INIT_MODE_test.DaggerTestComponent
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentWithGuavaTest_productionComponents_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentWithGuavaTest_productionComponents_DEFAULT_MODE_test.DaggerTestComponent
index 5df3e4d..a6836ce 100644
--- a/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentWithGuavaTest_productionComponents_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentWithGuavaTest_productionComponents_DEFAULT_MODE_test.DaggerTestComponent
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentWithGuavaTest_productionComponents_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentWithGuavaTest_productionComponents_FAST_INIT_MODE_test.DaggerTestComponent
index 5df3e4d..a6836ce 100644
--- a/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentWithGuavaTest_productionComponents_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentWithGuavaTest_productionComponents_FAST_INIT_MODE_test.DaggerTestComponent
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentWithGuavaTest_setBindings_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentWithGuavaTest_setBindings_DEFAULT_MODE_test.DaggerTestComponent
index ef08309..e2ff2df 100644
--- a/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentWithGuavaTest_setBindings_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentWithGuavaTest_setBindings_DEFAULT_MODE_test.DaggerTestComponent
@@ -2,7 +2,6 @@
 
 import com.google.common.collect.ImmutableSet;
 import dagger.internal.DaggerGenerated;
-import dagger.internal.Preconditions;
 import java.util.Set;
 import javax.annotation.processing.Generated;
 
@@ -15,7 +14,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -33,15 +33,6 @@
     private Builder() {
     }
 
-    /**
-     * @deprecated This module is declared, but an instance is not used in the component. This method is a no-op. For more, see https://dagger.dev/unused-modules.
-     */
-    @Deprecated
-    public Builder setModule(SetModule setModule) {
-      Preconditions.checkNotNull(setModule);
-      return this;
-    }
-
     public TestComponent build() {
       return new TestComponentImpl();
     }
diff --git a/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentWithGuavaTest_setBindings_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentWithGuavaTest_setBindings_FAST_INIT_MODE_test.DaggerTestComponent
index ef08309..e2ff2df 100644
--- a/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentWithGuavaTest_setBindings_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentWithGuavaTest_setBindings_FAST_INIT_MODE_test.DaggerTestComponent
@@ -2,7 +2,6 @@
 
 import com.google.common.collect.ImmutableSet;
 import dagger.internal.DaggerGenerated;
-import dagger.internal.Preconditions;
 import java.util.Set;
 import javax.annotation.processing.Generated;
 
@@ -15,7 +14,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -33,15 +33,6 @@
     private Builder() {
     }
 
-    /**
-     * @deprecated This module is declared, but an instance is not used in the component. This method is a no-op. For more, see https://dagger.dev/unused-modules.
-     */
-    @Deprecated
-    public Builder setModule(SetModule setModule) {
-      Preconditions.checkNotNull(setModule);
-      return this;
-    }
-
     public TestComponent build() {
       return new TestComponentImpl();
     }
diff --git a/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentWithGuavaTest_subcomponentOmitsInheritedBindings_DEFAULT_MODE_test.DaggerParent b/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentWithGuavaTest_subcomponentOmitsInheritedBindings_DEFAULT_MODE_test.DaggerParent
index 36e87af..9b03019 100644
--- a/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentWithGuavaTest_subcomponentOmitsInheritedBindings_DEFAULT_MODE_test.DaggerParent
+++ b/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentWithGuavaTest_subcomponentOmitsInheritedBindings_DEFAULT_MODE_test.DaggerParent
@@ -2,7 +2,6 @@
 
 import com.google.common.collect.ImmutableSet;
 import dagger.internal.DaggerGenerated;
-import dagger.internal.Preconditions;
 import java.util.Set;
 import javax.annotation.processing.Generated;
 
@@ -15,7 +14,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerParent {
   private DaggerParent() {
@@ -33,15 +33,6 @@
     private Builder() {
     }
 
-    /**
-     * @deprecated This module is declared, but an instance is not used in the component. This method is a no-op. For more, see https://dagger.dev/unused-modules.
-     */
-    @Deprecated
-    public Builder parentModule(ParentModule parentModule) {
-      Preconditions.checkNotNull(parentModule);
-      return this;
-    }
-
     public Parent build() {
       return new ParentImpl();
     }
diff --git a/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentWithGuavaTest_subcomponentOmitsInheritedBindings_FAST_INIT_MODE_test.DaggerParent b/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentWithGuavaTest_subcomponentOmitsInheritedBindings_FAST_INIT_MODE_test.DaggerParent
index 36e87af..9b03019 100644
--- a/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentWithGuavaTest_subcomponentOmitsInheritedBindings_FAST_INIT_MODE_test.DaggerParent
+++ b/javatests/dagger/internal/codegen/goldens/SetBindingRequestFulfillmentWithGuavaTest_subcomponentOmitsInheritedBindings_FAST_INIT_MODE_test.DaggerParent
@@ -2,7 +2,6 @@
 
 import com.google.common.collect.ImmutableSet;
 import dagger.internal.DaggerGenerated;
-import dagger.internal.Preconditions;
 import java.util.Set;
 import javax.annotation.processing.Generated;
 
@@ -15,7 +14,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerParent {
   private DaggerParent() {
@@ -33,15 +33,6 @@
     private Builder() {
     }
 
-    /**
-     * @deprecated This module is declared, but an instance is not used in the component. This method is a no-op. For more, see https://dagger.dev/unused-modules.
-     */
-    @Deprecated
-    public Builder parentModule(ParentModule parentModule) {
-      Preconditions.checkNotNull(parentModule);
-      return this;
-    }
-
     public Parent build() {
       return new ParentImpl();
     }
diff --git a/javatests/dagger/internal/codegen/goldens/SubcomponentCreatorRequestFulfillmentTest_testInlinedSubcomponentCreators_componentMethod_compilerMode=DEFAULT_MODE, creatorKind=dagger.Subcomponent.Builder_test.DaggerC b/javatests/dagger/internal/codegen/goldens/SubcomponentCreatorRequestFulfillmentTest_testInlinedSubcomponentCreators_componentMethod_compilerMode=DEFAULT_MODE, creatorKind=dagger.Subcomponent.Builder_test.DaggerC
index cac6863..a2352f6 100644
--- a/javatests/dagger/internal/codegen/goldens/SubcomponentCreatorRequestFulfillmentTest_testInlinedSubcomponentCreators_componentMethod_compilerMode=DEFAULT_MODE, creatorKind=dagger.Subcomponent.Builder_test.DaggerC
+++ b/javatests/dagger/internal/codegen/goldens/SubcomponentCreatorRequestFulfillmentTest_testInlinedSubcomponentCreators_componentMethod_compilerMode=DEFAULT_MODE, creatorKind=dagger.Subcomponent.Builder_test.DaggerC
@@ -12,7 +12,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerC {
   private DaggerC() {
diff --git a/javatests/dagger/internal/codegen/goldens/SubcomponentCreatorRequestFulfillmentTest_testInlinedSubcomponentCreators_componentMethod_compilerMode=DEFAULT_MODE, creatorKind=dagger.Subcomponent.Factory_test.DaggerC b/javatests/dagger/internal/codegen/goldens/SubcomponentCreatorRequestFulfillmentTest_testInlinedSubcomponentCreators_componentMethod_compilerMode=DEFAULT_MODE, creatorKind=dagger.Subcomponent.Factory_test.DaggerC
index bb85c82..a0c7080 100644
--- a/javatests/dagger/internal/codegen/goldens/SubcomponentCreatorRequestFulfillmentTest_testInlinedSubcomponentCreators_componentMethod_compilerMode=DEFAULT_MODE, creatorKind=dagger.Subcomponent.Factory_test.DaggerC
+++ b/javatests/dagger/internal/codegen/goldens/SubcomponentCreatorRequestFulfillmentTest_testInlinedSubcomponentCreators_componentMethod_compilerMode=DEFAULT_MODE, creatorKind=dagger.Subcomponent.Factory_test.DaggerC
@@ -12,7 +12,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerC {
   private DaggerC() {
diff --git a/javatests/dagger/internal/codegen/goldens/SubcomponentCreatorRequestFulfillmentTest_testInlinedSubcomponentCreators_componentMethod_compilerMode=FAST_INIT_MODE, creatorKind=dagger.Subcomponent.Builder_test.DaggerC b/javatests/dagger/internal/codegen/goldens/SubcomponentCreatorRequestFulfillmentTest_testInlinedSubcomponentCreators_componentMethod_compilerMode=FAST_INIT_MODE, creatorKind=dagger.Subcomponent.Builder_test.DaggerC
index cac6863..a2352f6 100644
--- a/javatests/dagger/internal/codegen/goldens/SubcomponentCreatorRequestFulfillmentTest_testInlinedSubcomponentCreators_componentMethod_compilerMode=FAST_INIT_MODE, creatorKind=dagger.Subcomponent.Builder_test.DaggerC
+++ b/javatests/dagger/internal/codegen/goldens/SubcomponentCreatorRequestFulfillmentTest_testInlinedSubcomponentCreators_componentMethod_compilerMode=FAST_INIT_MODE, creatorKind=dagger.Subcomponent.Builder_test.DaggerC
@@ -12,7 +12,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerC {
   private DaggerC() {
diff --git a/javatests/dagger/internal/codegen/goldens/SubcomponentCreatorRequestFulfillmentTest_testInlinedSubcomponentCreators_componentMethod_compilerMode=FAST_INIT_MODE, creatorKind=dagger.Subcomponent.Factory_test.DaggerC b/javatests/dagger/internal/codegen/goldens/SubcomponentCreatorRequestFulfillmentTest_testInlinedSubcomponentCreators_componentMethod_compilerMode=FAST_INIT_MODE, creatorKind=dagger.Subcomponent.Factory_test.DaggerC
index bb85c82..a0c7080 100644
--- a/javatests/dagger/internal/codegen/goldens/SubcomponentCreatorRequestFulfillmentTest_testInlinedSubcomponentCreators_componentMethod_compilerMode=FAST_INIT_MODE, creatorKind=dagger.Subcomponent.Factory_test.DaggerC
+++ b/javatests/dagger/internal/codegen/goldens/SubcomponentCreatorRequestFulfillmentTest_testInlinedSubcomponentCreators_componentMethod_compilerMode=FAST_INIT_MODE, creatorKind=dagger.Subcomponent.Factory_test.DaggerC
@@ -12,7 +12,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerC {
   private DaggerC() {
diff --git a/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_delegateFactoryNotCreatedForSubcomponentWhenProviderExistsInParent_DEFAULT_MODE_test.DaggerParentComponent b/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_delegateFactoryNotCreatedForSubcomponentWhenProviderExistsInParent_DEFAULT_MODE_test.DaggerParentComponent
index b05b85f..3a24c10 100644
--- a/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_delegateFactoryNotCreatedForSubcomponentWhenProviderExistsInParent_DEFAULT_MODE_test.DaggerParentComponent
+++ b/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_delegateFactoryNotCreatedForSubcomponentWhenProviderExistsInParent_DEFAULT_MODE_test.DaggerParentComponent
@@ -3,8 +3,8 @@
 import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DoubleCheck;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -15,7 +15,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerParentComponent {
   private DaggerParentComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_delegateFactoryNotCreatedForSubcomponentWhenProviderExistsInParent_FAST_INIT_MODE_test.DaggerParentComponent b/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_delegateFactoryNotCreatedForSubcomponentWhenProviderExistsInParent_FAST_INIT_MODE_test.DaggerParentComponent
index 6311a20..4cbe543 100644
--- a/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_delegateFactoryNotCreatedForSubcomponentWhenProviderExistsInParent_FAST_INIT_MODE_test.DaggerParentComponent
+++ b/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_delegateFactoryNotCreatedForSubcomponentWhenProviderExistsInParent_FAST_INIT_MODE_test.DaggerParentComponent
@@ -3,8 +3,8 @@
 import com.google.errorprone.annotations.CanIgnoreReturnValue;
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DoubleCheck;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -15,7 +15,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerParentComponent {
   private DaggerParentComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_multipleSubcomponentsWithSameSimpleNamesCanExistInSameComponent_DEFAULT_MODE_test.DaggerParentComponent b/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_multipleSubcomponentsWithSameSimpleNamesCanExistInSameComponent_DEFAULT_MODE_test.DaggerParentComponent
index 5e80c36..245871b 100644
--- a/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_multipleSubcomponentsWithSameSimpleNamesCanExistInSameComponent_DEFAULT_MODE_test.DaggerParentComponent
+++ b/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_multipleSubcomponentsWithSameSimpleNamesCanExistInSameComponent_DEFAULT_MODE_test.DaggerParentComponent
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerParentComponent {
   private DaggerParentComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_multipleSubcomponentsWithSameSimpleNamesCanExistInSameComponent_FAST_INIT_MODE_test.DaggerParentComponent b/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_multipleSubcomponentsWithSameSimpleNamesCanExistInSameComponent_FAST_INIT_MODE_test.DaggerParentComponent
index 5e80c36..245871b 100644
--- a/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_multipleSubcomponentsWithSameSimpleNamesCanExistInSameComponent_FAST_INIT_MODE_test.DaggerParentComponent
+++ b/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_multipleSubcomponentsWithSameSimpleNamesCanExistInSameComponent_FAST_INIT_MODE_test.DaggerParentComponent
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerParentComponent {
   private DaggerParentComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_subcomponentBuilderNamesShouldNotConflict_DEFAULT_MODE_test.DaggerC b/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_subcomponentBuilderNamesShouldNotConflict_DEFAULT_MODE_test.DaggerC
index ad51478..c866218 100644
--- a/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_subcomponentBuilderNamesShouldNotConflict_DEFAULT_MODE_test.DaggerC
+++ b/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_subcomponentBuilderNamesShouldNotConflict_DEFAULT_MODE_test.DaggerC
@@ -12,7 +12,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerC {
   private DaggerC() {
diff --git a/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_subcomponentBuilderNamesShouldNotConflict_FAST_INIT_MODE_test.DaggerC b/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_subcomponentBuilderNamesShouldNotConflict_FAST_INIT_MODE_test.DaggerC
index ad51478..c866218 100644
--- a/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_subcomponentBuilderNamesShouldNotConflict_FAST_INIT_MODE_test.DaggerC
+++ b/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_subcomponentBuilderNamesShouldNotConflict_FAST_INIT_MODE_test.DaggerC
@@ -12,7 +12,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerC {
   private DaggerC() {
diff --git a/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_subcomponentImplNameUsesFullyQualifiedClassNameIfNecessary_DEFAULT_MODE_test.DaggerParentComponent b/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_subcomponentImplNameUsesFullyQualifiedClassNameIfNecessary_DEFAULT_MODE_test.DaggerParentComponent
index fc75681..a778a05 100644
--- a/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_subcomponentImplNameUsesFullyQualifiedClassNameIfNecessary_DEFAULT_MODE_test.DaggerParentComponent
+++ b/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_subcomponentImplNameUsesFullyQualifiedClassNameIfNecessary_DEFAULT_MODE_test.DaggerParentComponent
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerParentComponent {
   private DaggerParentComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_subcomponentImplNameUsesFullyQualifiedClassNameIfNecessary_FAST_INIT_MODE_test.DaggerParentComponent b/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_subcomponentImplNameUsesFullyQualifiedClassNameIfNecessary_FAST_INIT_MODE_test.DaggerParentComponent
index fc75681..a778a05 100644
--- a/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_subcomponentImplNameUsesFullyQualifiedClassNameIfNecessary_FAST_INIT_MODE_test.DaggerParentComponent
+++ b/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_subcomponentImplNameUsesFullyQualifiedClassNameIfNecessary_FAST_INIT_MODE_test.DaggerParentComponent
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerParentComponent {
   private DaggerParentComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_subcomponentNamesShouldNotConflictWithParent_DEFAULT_MODE_test.DaggerC b/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_subcomponentNamesShouldNotConflictWithParent_DEFAULT_MODE_test.DaggerC
index 69f480f..e2c98e3 100644
--- a/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_subcomponentNamesShouldNotConflictWithParent_DEFAULT_MODE_test.DaggerC
+++ b/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_subcomponentNamesShouldNotConflictWithParent_DEFAULT_MODE_test.DaggerC
@@ -12,7 +12,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerC {
   private DaggerC() {
diff --git a/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_subcomponentNamesShouldNotConflictWithParent_FAST_INIT_MODE_test.DaggerC b/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_subcomponentNamesShouldNotConflictWithParent_FAST_INIT_MODE_test.DaggerC
index 69f480f..e2c98e3 100644
--- a/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_subcomponentNamesShouldNotConflictWithParent_FAST_INIT_MODE_test.DaggerC
+++ b/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_subcomponentNamesShouldNotConflictWithParent_FAST_INIT_MODE_test.DaggerC
@@ -12,7 +12,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerC {
   private DaggerC() {
diff --git a/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_subcomponentSimpleNamesDisambiguatedInRoot_DEFAULT_MODE_DaggerParentComponent b/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_subcomponentSimpleNamesDisambiguatedInRoot_DEFAULT_MODE_DaggerParentComponent
index 33e45bf..7b47466 100644
--- a/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_subcomponentSimpleNamesDisambiguatedInRoot_DEFAULT_MODE_DaggerParentComponent
+++ b/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_subcomponentSimpleNamesDisambiguatedInRoot_DEFAULT_MODE_DaggerParentComponent
@@ -10,7 +10,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerParentComponent {
   private DaggerParentComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_subcomponentSimpleNamesDisambiguatedInRoot_FAST_INIT_MODE_DaggerParentComponent b/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_subcomponentSimpleNamesDisambiguatedInRoot_FAST_INIT_MODE_DaggerParentComponent
index 33e45bf..7b47466 100644
--- a/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_subcomponentSimpleNamesDisambiguatedInRoot_FAST_INIT_MODE_DaggerParentComponent
+++ b/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_subcomponentSimpleNamesDisambiguatedInRoot_FAST_INIT_MODE_DaggerParentComponent
@@ -10,7 +10,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerParentComponent {
   private DaggerParentComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_subcomponentSimpleNamesDisambiguated_DEFAULT_MODE_test.DaggerParentComponent b/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_subcomponentSimpleNamesDisambiguated_DEFAULT_MODE_test.DaggerParentComponent
index 9f50fa9..6a9942d 100644
--- a/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_subcomponentSimpleNamesDisambiguated_DEFAULT_MODE_test.DaggerParentComponent
+++ b/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_subcomponentSimpleNamesDisambiguated_DEFAULT_MODE_test.DaggerParentComponent
@@ -12,7 +12,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerParentComponent {
   private DaggerParentComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_subcomponentSimpleNamesDisambiguated_FAST_INIT_MODE_test.DaggerParentComponent b/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_subcomponentSimpleNamesDisambiguated_FAST_INIT_MODE_test.DaggerParentComponent
index 9f50fa9..6a9942d 100644
--- a/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_subcomponentSimpleNamesDisambiguated_FAST_INIT_MODE_test.DaggerParentComponent
+++ b/javatests/dagger/internal/codegen/goldens/SubcomponentValidationTest_subcomponentSimpleNamesDisambiguated_FAST_INIT_MODE_test.DaggerParentComponent
@@ -12,7 +12,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerParentComponent {
   private DaggerParentComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/SwitchingProviderTest_emptyMultibindings_avoidSwitchProviders_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/SwitchingProviderTest_emptyMultibindings_avoidSwitchProviders_DEFAULT_MODE_test.DaggerTestComponent
index 7b26af1..0ac7a6d 100644
--- a/javatests/dagger/internal/codegen/goldens/SwitchingProviderTest_emptyMultibindings_avoidSwitchProviders_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/SwitchingProviderTest_emptyMultibindings_avoidSwitchProviders_DEFAULT_MODE_test.DaggerTestComponent
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/SwitchingProviderTest_emptyMultibindings_avoidSwitchProviders_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/SwitchingProviderTest_emptyMultibindings_avoidSwitchProviders_FAST_INIT_MODE_test.DaggerTestComponent
index 7b26af1..0ac7a6d 100644
--- a/javatests/dagger/internal/codegen/goldens/SwitchingProviderTest_emptyMultibindings_avoidSwitchProviders_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/SwitchingProviderTest_emptyMultibindings_avoidSwitchProviders_FAST_INIT_MODE_test.DaggerTestComponent
@@ -17,7 +17,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/SwitchingProviderTest_memberInjectors_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/SwitchingProviderTest_memberInjectors_DEFAULT_MODE_test.DaggerTestComponent
index e0230e0..db768e1 100644
--- a/javatests/dagger/internal/codegen/goldens/SwitchingProviderTest_memberInjectors_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/SwitchingProviderTest_memberInjectors_DEFAULT_MODE_test.DaggerTestComponent
@@ -4,8 +4,8 @@
 import dagger.internal.DaggerGenerated;
 import dagger.internal.InstanceFactory;
 import dagger.internal.MembersInjectors;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -16,7 +16,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -56,7 +57,7 @@
     }
 
     @Override
-    public Provider<MembersInjector<Foo>> providerOfMembersInjector() {
+    public javax.inject.Provider<MembersInjector<Foo>> providerOfMembersInjector() {
       return fooMembersInjectorProvider;
     }
   }
diff --git a/javatests/dagger/internal/codegen/goldens/SwitchingProviderTest_memberInjectors_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/SwitchingProviderTest_memberInjectors_FAST_INIT_MODE_test.DaggerTestComponent
index e0230e0..db768e1 100644
--- a/javatests/dagger/internal/codegen/goldens/SwitchingProviderTest_memberInjectors_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/SwitchingProviderTest_memberInjectors_FAST_INIT_MODE_test.DaggerTestComponent
@@ -4,8 +4,8 @@
 import dagger.internal.DaggerGenerated;
 import dagger.internal.InstanceFactory;
 import dagger.internal.MembersInjectors;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -16,7 +16,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -56,7 +57,7 @@
     }
 
     @Override
-    public Provider<MembersInjector<Foo>> providerOfMembersInjector() {
+    public javax.inject.Provider<MembersInjector<Foo>> providerOfMembersInjector() {
       return fooMembersInjectorProvider;
     }
   }
diff --git a/javatests/dagger/internal/codegen/goldens/SwitchingProviderTest_optionals_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/SwitchingProviderTest_optionals_DEFAULT_MODE_test.DaggerTestComponent
index 904fb4a..c474dc4 100644
--- a/javatests/dagger/internal/codegen/goldens/SwitchingProviderTest_optionals_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/SwitchingProviderTest_optionals_DEFAULT_MODE_test.DaggerTestComponent
@@ -3,9 +3,9 @@
 import dagger.internal.DaggerGenerated;
 import dagger.internal.InstanceFactory;
 import dagger.internal.Preconditions;
+import dagger.internal.Provider;
 import java.util.Optional;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -16,7 +16,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   /**
@@ -94,12 +95,12 @@
     }
 
     @Override
-    public Provider<Optional<Present>> providerOfOptionalOfPresent() {
+    public javax.inject.Provider<Optional<Present>> providerOfOptionalOfPresent() {
       return optionalOfPresentProvider;
     }
 
     @Override
-    public Provider<Optional<Absent>> providerOfOptionalOfAbsent() {
+    public javax.inject.Provider<Optional<Absent>> providerOfOptionalOfAbsent() {
       return optionalOfAbsentProvider;
     }
   }
diff --git a/javatests/dagger/internal/codegen/goldens/SwitchingProviderTest_optionals_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/SwitchingProviderTest_optionals_FAST_INIT_MODE_test.DaggerTestComponent
index 1e46fde..54d032d 100644
--- a/javatests/dagger/internal/codegen/goldens/SwitchingProviderTest_optionals_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/SwitchingProviderTest_optionals_FAST_INIT_MODE_test.DaggerTestComponent
@@ -2,9 +2,9 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.InstanceFactory;
+import dagger.internal.Provider;
 import java.util.Optional;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -15,7 +15,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   /**
@@ -73,12 +74,12 @@
     }
 
     @Override
-    public Provider<Optional<Present>> providerOfOptionalOfPresent() {
+    public javax.inject.Provider<Optional<Present>> providerOfOptionalOfPresent() {
       return optionalOfPresentProvider;
     }
 
     @Override
-    public Provider<Optional<Absent>> providerOfOptionalOfAbsent() {
+    public javax.inject.Provider<Optional<Absent>> providerOfOptionalOfAbsent() {
       return optionalOfAbsentProvider;
     }
 
diff --git a/javatests/dagger/internal/codegen/goldens/SwitchingProviderTest_scopedBinds_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/SwitchingProviderTest_scopedBinds_DEFAULT_MODE_test.DaggerTestComponent
index d3f68be..ab66d4e 100644
--- a/javatests/dagger/internal/codegen/goldens/SwitchingProviderTest_scopedBinds_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/SwitchingProviderTest_scopedBinds_DEFAULT_MODE_test.DaggerTestComponent
@@ -2,8 +2,8 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DoubleCheck;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -14,7 +14,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -54,12 +55,12 @@
     }
 
     @Override
-    public Provider<Object> objectProvider() {
+    public javax.inject.Provider<Object> objectProvider() {
       return ((Provider) cProvider);
     }
 
     @Override
-    public Provider<CharSequence> charSequenceProvider() {
+    public javax.inject.Provider<CharSequence> charSequenceProvider() {
       return cProvider;
     }
   }
diff --git a/javatests/dagger/internal/codegen/goldens/SwitchingProviderTest_scopedBinds_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/SwitchingProviderTest_scopedBinds_FAST_INIT_MODE_test.DaggerTestComponent
index 440def0..0a7cdb2 100644
--- a/javatests/dagger/internal/codegen/goldens/SwitchingProviderTest_scopedBinds_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/SwitchingProviderTest_scopedBinds_FAST_INIT_MODE_test.DaggerTestComponent
@@ -2,8 +2,8 @@
 
 import dagger.internal.DaggerGenerated;
 import dagger.internal.DoubleCheck;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -14,7 +14,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -57,12 +58,12 @@
     }
 
     @Override
-    public Provider<Object> objectProvider() {
+    public javax.inject.Provider<Object> objectProvider() {
       return ((Provider) cProvider);
     }
 
     @Override
-    public Provider<CharSequence> charSequenceProvider() {
+    public javax.inject.Provider<CharSequence> charSequenceProvider() {
       return cProvider;
     }
 
diff --git a/javatests/dagger/internal/codegen/goldens/SwitchingProviderTest_switchingProviderTest_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/SwitchingProviderTest_switchingProviderTest_DEFAULT_MODE_test.DaggerTestComponent
index c04beef..ade9e53 100644
--- a/javatests/dagger/internal/codegen/goldens/SwitchingProviderTest_switchingProviderTest_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/SwitchingProviderTest_switchingProviderTest_DEFAULT_MODE_test.DaggerTestComponent
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
diff --git a/javatests/dagger/internal/codegen/goldens/SwitchingProviderTest_switchingProviderTest_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/SwitchingProviderTest_switchingProviderTest_FAST_INIT_MODE_test.DaggerTestComponent
index c2bcf91..e225c47 100644
--- a/javatests/dagger/internal/codegen/goldens/SwitchingProviderTest_switchingProviderTest_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/SwitchingProviderTest_switchingProviderTest_FAST_INIT_MODE_test.DaggerTestComponent
@@ -1,8 +1,8 @@
 package test;
 
 import dagger.internal.DaggerGenerated;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -358,507 +359,507 @@
     }
 
     @Override
-    public Provider<Binding0> getBinding0Provider() {
+    public javax.inject.Provider<Binding0> getBinding0Provider() {
       return binding0Provider;
     }
 
     @Override
-    public Provider<Binding1> getBinding1Provider() {
+    public javax.inject.Provider<Binding1> getBinding1Provider() {
       return binding1Provider;
     }
 
     @Override
-    public Provider<Binding2> getBinding2Provider() {
+    public javax.inject.Provider<Binding2> getBinding2Provider() {
       return binding2Provider;
     }
 
     @Override
-    public Provider<Binding3> getBinding3Provider() {
+    public javax.inject.Provider<Binding3> getBinding3Provider() {
       return binding3Provider;
     }
 
     @Override
-    public Provider<Binding4> getBinding4Provider() {
+    public javax.inject.Provider<Binding4> getBinding4Provider() {
       return binding4Provider;
     }
 
     @Override
-    public Provider<Binding5> getBinding5Provider() {
+    public javax.inject.Provider<Binding5> getBinding5Provider() {
       return binding5Provider;
     }
 
     @Override
-    public Provider<Binding6> getBinding6Provider() {
+    public javax.inject.Provider<Binding6> getBinding6Provider() {
       return binding6Provider;
     }
 
     @Override
-    public Provider<Binding7> getBinding7Provider() {
+    public javax.inject.Provider<Binding7> getBinding7Provider() {
       return binding7Provider;
     }
 
     @Override
-    public Provider<Binding8> getBinding8Provider() {
+    public javax.inject.Provider<Binding8> getBinding8Provider() {
       return binding8Provider;
     }
 
     @Override
-    public Provider<Binding9> getBinding9Provider() {
+    public javax.inject.Provider<Binding9> getBinding9Provider() {
       return binding9Provider;
     }
 
     @Override
-    public Provider<Binding10> getBinding10Provider() {
+    public javax.inject.Provider<Binding10> getBinding10Provider() {
       return binding10Provider;
     }
 
     @Override
-    public Provider<Binding11> getBinding11Provider() {
+    public javax.inject.Provider<Binding11> getBinding11Provider() {
       return binding11Provider;
     }
 
     @Override
-    public Provider<Binding12> getBinding12Provider() {
+    public javax.inject.Provider<Binding12> getBinding12Provider() {
       return binding12Provider;
     }
 
     @Override
-    public Provider<Binding13> getBinding13Provider() {
+    public javax.inject.Provider<Binding13> getBinding13Provider() {
       return binding13Provider;
     }
 
     @Override
-    public Provider<Binding14> getBinding14Provider() {
+    public javax.inject.Provider<Binding14> getBinding14Provider() {
       return binding14Provider;
     }
 
     @Override
-    public Provider<Binding15> getBinding15Provider() {
+    public javax.inject.Provider<Binding15> getBinding15Provider() {
       return binding15Provider;
     }
 
     @Override
-    public Provider<Binding16> getBinding16Provider() {
+    public javax.inject.Provider<Binding16> getBinding16Provider() {
       return binding16Provider;
     }
 
     @Override
-    public Provider<Binding17> getBinding17Provider() {
+    public javax.inject.Provider<Binding17> getBinding17Provider() {
       return binding17Provider;
     }
 
     @Override
-    public Provider<Binding18> getBinding18Provider() {
+    public javax.inject.Provider<Binding18> getBinding18Provider() {
       return binding18Provider;
     }
 
     @Override
-    public Provider<Binding19> getBinding19Provider() {
+    public javax.inject.Provider<Binding19> getBinding19Provider() {
       return binding19Provider;
     }
 
     @Override
-    public Provider<Binding20> getBinding20Provider() {
+    public javax.inject.Provider<Binding20> getBinding20Provider() {
       return binding20Provider;
     }
 
     @Override
-    public Provider<Binding21> getBinding21Provider() {
+    public javax.inject.Provider<Binding21> getBinding21Provider() {
       return binding21Provider;
     }
 
     @Override
-    public Provider<Binding22> getBinding22Provider() {
+    public javax.inject.Provider<Binding22> getBinding22Provider() {
       return binding22Provider;
     }
 
     @Override
-    public Provider<Binding23> getBinding23Provider() {
+    public javax.inject.Provider<Binding23> getBinding23Provider() {
       return binding23Provider;
     }
 
     @Override
-    public Provider<Binding24> getBinding24Provider() {
+    public javax.inject.Provider<Binding24> getBinding24Provider() {
       return binding24Provider;
     }
 
     @Override
-    public Provider<Binding25> getBinding25Provider() {
+    public javax.inject.Provider<Binding25> getBinding25Provider() {
       return binding25Provider;
     }
 
     @Override
-    public Provider<Binding26> getBinding26Provider() {
+    public javax.inject.Provider<Binding26> getBinding26Provider() {
       return binding26Provider;
     }
 
     @Override
-    public Provider<Binding27> getBinding27Provider() {
+    public javax.inject.Provider<Binding27> getBinding27Provider() {
       return binding27Provider;
     }
 
     @Override
-    public Provider<Binding28> getBinding28Provider() {
+    public javax.inject.Provider<Binding28> getBinding28Provider() {
       return binding28Provider;
     }
 
     @Override
-    public Provider<Binding29> getBinding29Provider() {
+    public javax.inject.Provider<Binding29> getBinding29Provider() {
       return binding29Provider;
     }
 
     @Override
-    public Provider<Binding30> getBinding30Provider() {
+    public javax.inject.Provider<Binding30> getBinding30Provider() {
       return binding30Provider;
     }
 
     @Override
-    public Provider<Binding31> getBinding31Provider() {
+    public javax.inject.Provider<Binding31> getBinding31Provider() {
       return binding31Provider;
     }
 
     @Override
-    public Provider<Binding32> getBinding32Provider() {
+    public javax.inject.Provider<Binding32> getBinding32Provider() {
       return binding32Provider;
     }
 
     @Override
-    public Provider<Binding33> getBinding33Provider() {
+    public javax.inject.Provider<Binding33> getBinding33Provider() {
       return binding33Provider;
     }
 
     @Override
-    public Provider<Binding34> getBinding34Provider() {
+    public javax.inject.Provider<Binding34> getBinding34Provider() {
       return binding34Provider;
     }
 
     @Override
-    public Provider<Binding35> getBinding35Provider() {
+    public javax.inject.Provider<Binding35> getBinding35Provider() {
       return binding35Provider;
     }
 
     @Override
-    public Provider<Binding36> getBinding36Provider() {
+    public javax.inject.Provider<Binding36> getBinding36Provider() {
       return binding36Provider;
     }
 
     @Override
-    public Provider<Binding37> getBinding37Provider() {
+    public javax.inject.Provider<Binding37> getBinding37Provider() {
       return binding37Provider;
     }
 
     @Override
-    public Provider<Binding38> getBinding38Provider() {
+    public javax.inject.Provider<Binding38> getBinding38Provider() {
       return binding38Provider;
     }
 
     @Override
-    public Provider<Binding39> getBinding39Provider() {
+    public javax.inject.Provider<Binding39> getBinding39Provider() {
       return binding39Provider;
     }
 
     @Override
-    public Provider<Binding40> getBinding40Provider() {
+    public javax.inject.Provider<Binding40> getBinding40Provider() {
       return binding40Provider;
     }
 
     @Override
-    public Provider<Binding41> getBinding41Provider() {
+    public javax.inject.Provider<Binding41> getBinding41Provider() {
       return binding41Provider;
     }
 
     @Override
-    public Provider<Binding42> getBinding42Provider() {
+    public javax.inject.Provider<Binding42> getBinding42Provider() {
       return binding42Provider;
     }
 
     @Override
-    public Provider<Binding43> getBinding43Provider() {
+    public javax.inject.Provider<Binding43> getBinding43Provider() {
       return binding43Provider;
     }
 
     @Override
-    public Provider<Binding44> getBinding44Provider() {
+    public javax.inject.Provider<Binding44> getBinding44Provider() {
       return binding44Provider;
     }
 
     @Override
-    public Provider<Binding45> getBinding45Provider() {
+    public javax.inject.Provider<Binding45> getBinding45Provider() {
       return binding45Provider;
     }
 
     @Override
-    public Provider<Binding46> getBinding46Provider() {
+    public javax.inject.Provider<Binding46> getBinding46Provider() {
       return binding46Provider;
     }
 
     @Override
-    public Provider<Binding47> getBinding47Provider() {
+    public javax.inject.Provider<Binding47> getBinding47Provider() {
       return binding47Provider;
     }
 
     @Override
-    public Provider<Binding48> getBinding48Provider() {
+    public javax.inject.Provider<Binding48> getBinding48Provider() {
       return binding48Provider;
     }
 
     @Override
-    public Provider<Binding49> getBinding49Provider() {
+    public javax.inject.Provider<Binding49> getBinding49Provider() {
       return binding49Provider;
     }
 
     @Override
-    public Provider<Binding50> getBinding50Provider() {
+    public javax.inject.Provider<Binding50> getBinding50Provider() {
       return binding50Provider;
     }
 
     @Override
-    public Provider<Binding51> getBinding51Provider() {
+    public javax.inject.Provider<Binding51> getBinding51Provider() {
       return binding51Provider;
     }
 
     @Override
-    public Provider<Binding52> getBinding52Provider() {
+    public javax.inject.Provider<Binding52> getBinding52Provider() {
       return binding52Provider;
     }
 
     @Override
-    public Provider<Binding53> getBinding53Provider() {
+    public javax.inject.Provider<Binding53> getBinding53Provider() {
       return binding53Provider;
     }
 
     @Override
-    public Provider<Binding54> getBinding54Provider() {
+    public javax.inject.Provider<Binding54> getBinding54Provider() {
       return binding54Provider;
     }
 
     @Override
-    public Provider<Binding55> getBinding55Provider() {
+    public javax.inject.Provider<Binding55> getBinding55Provider() {
       return binding55Provider;
     }
 
     @Override
-    public Provider<Binding56> getBinding56Provider() {
+    public javax.inject.Provider<Binding56> getBinding56Provider() {
       return binding56Provider;
     }
 
     @Override
-    public Provider<Binding57> getBinding57Provider() {
+    public javax.inject.Provider<Binding57> getBinding57Provider() {
       return binding57Provider;
     }
 
     @Override
-    public Provider<Binding58> getBinding58Provider() {
+    public javax.inject.Provider<Binding58> getBinding58Provider() {
       return binding58Provider;
     }
 
     @Override
-    public Provider<Binding59> getBinding59Provider() {
+    public javax.inject.Provider<Binding59> getBinding59Provider() {
       return binding59Provider;
     }
 
     @Override
-    public Provider<Binding60> getBinding60Provider() {
+    public javax.inject.Provider<Binding60> getBinding60Provider() {
       return binding60Provider;
     }
 
     @Override
-    public Provider<Binding61> getBinding61Provider() {
+    public javax.inject.Provider<Binding61> getBinding61Provider() {
       return binding61Provider;
     }
 
     @Override
-    public Provider<Binding62> getBinding62Provider() {
+    public javax.inject.Provider<Binding62> getBinding62Provider() {
       return binding62Provider;
     }
 
     @Override
-    public Provider<Binding63> getBinding63Provider() {
+    public javax.inject.Provider<Binding63> getBinding63Provider() {
       return binding63Provider;
     }
 
     @Override
-    public Provider<Binding64> getBinding64Provider() {
+    public javax.inject.Provider<Binding64> getBinding64Provider() {
       return binding64Provider;
     }
 
     @Override
-    public Provider<Binding65> getBinding65Provider() {
+    public javax.inject.Provider<Binding65> getBinding65Provider() {
       return binding65Provider;
     }
 
     @Override
-    public Provider<Binding66> getBinding66Provider() {
+    public javax.inject.Provider<Binding66> getBinding66Provider() {
       return binding66Provider;
     }
 
     @Override
-    public Provider<Binding67> getBinding67Provider() {
+    public javax.inject.Provider<Binding67> getBinding67Provider() {
       return binding67Provider;
     }
 
     @Override
-    public Provider<Binding68> getBinding68Provider() {
+    public javax.inject.Provider<Binding68> getBinding68Provider() {
       return binding68Provider;
     }
 
     @Override
-    public Provider<Binding69> getBinding69Provider() {
+    public javax.inject.Provider<Binding69> getBinding69Provider() {
       return binding69Provider;
     }
 
     @Override
-    public Provider<Binding70> getBinding70Provider() {
+    public javax.inject.Provider<Binding70> getBinding70Provider() {
       return binding70Provider;
     }
 
     @Override
-    public Provider<Binding71> getBinding71Provider() {
+    public javax.inject.Provider<Binding71> getBinding71Provider() {
       return binding71Provider;
     }
 
     @Override
-    public Provider<Binding72> getBinding72Provider() {
+    public javax.inject.Provider<Binding72> getBinding72Provider() {
       return binding72Provider;
     }
 
     @Override
-    public Provider<Binding73> getBinding73Provider() {
+    public javax.inject.Provider<Binding73> getBinding73Provider() {
       return binding73Provider;
     }
 
     @Override
-    public Provider<Binding74> getBinding74Provider() {
+    public javax.inject.Provider<Binding74> getBinding74Provider() {
       return binding74Provider;
     }
 
     @Override
-    public Provider<Binding75> getBinding75Provider() {
+    public javax.inject.Provider<Binding75> getBinding75Provider() {
       return binding75Provider;
     }
 
     @Override
-    public Provider<Binding76> getBinding76Provider() {
+    public javax.inject.Provider<Binding76> getBinding76Provider() {
       return binding76Provider;
     }
 
     @Override
-    public Provider<Binding77> getBinding77Provider() {
+    public javax.inject.Provider<Binding77> getBinding77Provider() {
       return binding77Provider;
     }
 
     @Override
-    public Provider<Binding78> getBinding78Provider() {
+    public javax.inject.Provider<Binding78> getBinding78Provider() {
       return binding78Provider;
     }
 
     @Override
-    public Provider<Binding79> getBinding79Provider() {
+    public javax.inject.Provider<Binding79> getBinding79Provider() {
       return binding79Provider;
     }
 
     @Override
-    public Provider<Binding80> getBinding80Provider() {
+    public javax.inject.Provider<Binding80> getBinding80Provider() {
       return binding80Provider;
     }
 
     @Override
-    public Provider<Binding81> getBinding81Provider() {
+    public javax.inject.Provider<Binding81> getBinding81Provider() {
       return binding81Provider;
     }
 
     @Override
-    public Provider<Binding82> getBinding82Provider() {
+    public javax.inject.Provider<Binding82> getBinding82Provider() {
       return binding82Provider;
     }
 
     @Override
-    public Provider<Binding83> getBinding83Provider() {
+    public javax.inject.Provider<Binding83> getBinding83Provider() {
       return binding83Provider;
     }
 
     @Override
-    public Provider<Binding84> getBinding84Provider() {
+    public javax.inject.Provider<Binding84> getBinding84Provider() {
       return binding84Provider;
     }
 
     @Override
-    public Provider<Binding85> getBinding85Provider() {
+    public javax.inject.Provider<Binding85> getBinding85Provider() {
       return binding85Provider;
     }
 
     @Override
-    public Provider<Binding86> getBinding86Provider() {
+    public javax.inject.Provider<Binding86> getBinding86Provider() {
       return binding86Provider;
     }
 
     @Override
-    public Provider<Binding87> getBinding87Provider() {
+    public javax.inject.Provider<Binding87> getBinding87Provider() {
       return binding87Provider;
     }
 
     @Override
-    public Provider<Binding88> getBinding88Provider() {
+    public javax.inject.Provider<Binding88> getBinding88Provider() {
       return binding88Provider;
     }
 
     @Override
-    public Provider<Binding89> getBinding89Provider() {
+    public javax.inject.Provider<Binding89> getBinding89Provider() {
       return binding89Provider;
     }
 
     @Override
-    public Provider<Binding90> getBinding90Provider() {
+    public javax.inject.Provider<Binding90> getBinding90Provider() {
       return binding90Provider;
     }
 
     @Override
-    public Provider<Binding91> getBinding91Provider() {
+    public javax.inject.Provider<Binding91> getBinding91Provider() {
       return binding91Provider;
     }
 
     @Override
-    public Provider<Binding92> getBinding92Provider() {
+    public javax.inject.Provider<Binding92> getBinding92Provider() {
       return binding92Provider;
     }
 
     @Override
-    public Provider<Binding93> getBinding93Provider() {
+    public javax.inject.Provider<Binding93> getBinding93Provider() {
       return binding93Provider;
     }
 
     @Override
-    public Provider<Binding94> getBinding94Provider() {
+    public javax.inject.Provider<Binding94> getBinding94Provider() {
       return binding94Provider;
     }
 
     @Override
-    public Provider<Binding95> getBinding95Provider() {
+    public javax.inject.Provider<Binding95> getBinding95Provider() {
       return binding95Provider;
     }
 
     @Override
-    public Provider<Binding96> getBinding96Provider() {
+    public javax.inject.Provider<Binding96> getBinding96Provider() {
       return binding96Provider;
     }
 
     @Override
-    public Provider<Binding97> getBinding97Provider() {
+    public javax.inject.Provider<Binding97> getBinding97Provider() {
       return binding97Provider;
     }
 
     @Override
-    public Provider<Binding98> getBinding98Provider() {
+    public javax.inject.Provider<Binding98> getBinding98Provider() {
       return binding98Provider;
     }
 
     @Override
-    public Provider<Binding99> getBinding99Provider() {
+    public javax.inject.Provider<Binding99> getBinding99Provider() {
       return binding99Provider;
     }
 
     @Override
-    public Provider<Binding100> getBinding100Provider() {
+    public javax.inject.Provider<Binding100> getBinding100Provider() {
       return binding100Provider;
     }
 
diff --git a/javatests/dagger/internal/codegen/goldens/SwitchingProviderTest_unscopedBinds_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/SwitchingProviderTest_unscopedBinds_DEFAULT_MODE_test.DaggerTestComponent
index 00679b4..b2933ae 100644
--- a/javatests/dagger/internal/codegen/goldens/SwitchingProviderTest_unscopedBinds_DEFAULT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/SwitchingProviderTest_unscopedBinds_DEFAULT_MODE_test.DaggerTestComponent
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -46,12 +47,12 @@
 
     @Override
     public Provider<Object> objectProvider() {
-      return ((Provider) TestModule_SFactory.create());
+      return ((dagger.internal.Provider) TestModule_SFactory.create());
     }
 
     @Override
     public Provider<CharSequence> charSequenceProvider() {
-      return ((Provider) TestModule_SFactory.create());
+      return ((dagger.internal.Provider) TestModule_SFactory.create());
     }
   }
 }
diff --git a/javatests/dagger/internal/codegen/goldens/SwitchingProviderTest_unscopedBinds_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/SwitchingProviderTest_unscopedBinds_FAST_INIT_MODE_test.DaggerTestComponent
index 2970ba6..eef5afc 100644
--- a/javatests/dagger/internal/codegen/goldens/SwitchingProviderTest_unscopedBinds_FAST_INIT_MODE_test.DaggerTestComponent
+++ b/javatests/dagger/internal/codegen/goldens/SwitchingProviderTest_unscopedBinds_FAST_INIT_MODE_test.DaggerTestComponent
@@ -1,8 +1,8 @@
 package test;
 
 import dagger.internal.DaggerGenerated;
+import dagger.internal.Provider;
 import javax.annotation.processing.Generated;
-import javax.inject.Provider;
 
 @DaggerGenerated
 @Generated(
@@ -13,7 +13,8 @@
     "unchecked",
     "rawtypes",
     "KotlinInternal",
-    "KotlinInternalInJava"
+    "KotlinInternalInJava",
+    "cast"
 })
 final class DaggerTestComponent {
   private DaggerTestComponent() {
@@ -53,12 +54,12 @@
     }
 
     @Override
-    public Provider<Object> objectProvider() {
+    public javax.inject.Provider<Object> objectProvider() {
       return ((Provider) sProvider);
     }
 
     @Override
-    public Provider<CharSequence> charSequenceProvider() {
+    public javax.inject.Provider<CharSequence> charSequenceProvider() {
       return ((Provider) sProvider);
     }
 
diff --git a/javatests/dagger/internal/codegen/kotlin/KspComponentProcessorTest.java b/javatests/dagger/internal/codegen/kotlin/KspComponentProcessorTest.java
index cc4f5a1..20a57f1 100644
--- a/javatests/dagger/internal/codegen/kotlin/KspComponentProcessorTest.java
+++ b/javatests/dagger/internal/codegen/kotlin/KspComponentProcessorTest.java
@@ -57,7 +57,8 @@
                         "    \"unchecked\",",
                         "    \"rawtypes\",",
                         "    \"KotlinInternal\",",
-                        "    \"KotlinInternalInJava\"",
+                        "    \"KotlinInternalInJava\",",
+                        "    \"cast\"",
                         "})",
                         "public final class DaggerMyComponent {",
                         "  private DaggerMyComponent() {",
@@ -160,7 +161,8 @@
                         "    \"unchecked\",",
                         "    \"rawtypes\",",
                         "    \"KotlinInternal\",",
-                        "    \"KotlinInternalInJava\"",
+                        "    \"KotlinInternalInJava\",",
+                        "    \"cast\"",
                         "})",
                         "public final class DaggerMyComponent {",
                         "  private DaggerMyComponent() {",
@@ -230,8 +232,8 @@
                         "package test;",
                         "",
                         "import dagger.internal.DaggerGenerated;",
+                        "import dagger.internal.Provider;",
                         "import javax.annotation.processing.Generated;",
-                        "import javax.inject.Provider;",
                         "",
                         "@DaggerGenerated",
                         "@Generated(",
@@ -242,7 +244,8 @@
                         "    \"unchecked\",",
                         "    \"rawtypes\",",
                         "    \"KotlinInternal\",",
-                        "    \"KotlinInternalInJava\"",
+                        "    \"KotlinInternalInJava\",",
+                        "    \"cast\"",
                         "})",
                         "public final class DaggerMyComponent {",
                         "  private DaggerMyComponent() {",
@@ -283,7 +286,7 @@
                         "    }",
                         "",
                         "    @Override",
-                        "    public Provider<Foo> foo() {",
+                        "    public javax.inject.Provider<Foo> foo() {",
                         "      return fooProvider;",
                         "    }",
                         "  }",
@@ -342,7 +345,8 @@
                         "    \"unchecked\",",
                         "    \"rawtypes\",",
                         "    \"KotlinInternal\",",
-                        "    \"KotlinInternalInJava\"",
+                        "    \"KotlinInternalInJava\",",
+                        "    \"cast\"",
                         "})",
                         "public final class DaggerMyComponent {",
                         "  private DaggerMyComponent() {",
@@ -448,7 +452,8 @@
                         "    \"unchecked\",",
                         "    \"rawtypes\",",
                         "    \"KotlinInternal\",",
-                        "    \"KotlinInternalInJava\"",
+                        "    \"KotlinInternalInJava\",",
+                        "    \"cast\"",
                         "})",
                         "public final class DaggerMyComponent {",
                         "  private DaggerMyComponent() {",
@@ -560,7 +565,8 @@
                         "    \"unchecked\",",
                         "    \"rawtypes\",",
                         "    \"KotlinInternal\",",
-                        "    \"KotlinInternalInJava\"",
+                        "    \"KotlinInternalInJava\",",
+                        "    \"cast\"",
                         "})",
                         "public final class DaggerMyComponent {",
                         "  private DaggerMyComponent() {",
diff --git a/javatests/dagger/producers/BUILD b/javatests/dagger/producers/BUILD
index 0253799..6c76856 100644
--- a/javatests/dagger/producers/BUILD
+++ b/javatests/dagger/producers/BUILD
@@ -31,6 +31,7 @@
     functional = 0,
     javacopts = JAVA_RELEASE_MIN + DOCLINT_REFERENCES + DOCLINT_HTML_AND_SYNTAX,
     deps = [
+        "//java/dagger:core",
         "//java/dagger/producers",
         "//third_party/java/guava:testlib",
         "//third_party/java/guava/collect",
diff --git a/javatests/dagger/producers/internal/AbstractProducesMethodProducerTest.java b/javatests/dagger/producers/internal/AbstractProducesMethodProducerTest.java
index af13504..0b32d71 100644
--- a/javatests/dagger/producers/internal/AbstractProducesMethodProducerTest.java
+++ b/javatests/dagger/producers/internal/AbstractProducesMethodProducerTest.java
@@ -28,13 +28,13 @@
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.MoreExecutors;
 import com.google.common.util.concurrent.SettableFuture;
+import dagger.internal.Provider;
 import dagger.producers.Producer;
 import dagger.producers.monitoring.ProducerMonitor;
 import dagger.producers.monitoring.ProducerToken;
 import dagger.producers.monitoring.ProductionComponentMonitor;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executor;
-import javax.inject.Provider;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/javatests/dagger/producers/internal/ProducersTest.java b/javatests/dagger/producers/internal/ProducersTest.java
index 1cfe121..5b2d9c1 100644
--- a/javatests/dagger/producers/internal/ProducersTest.java
+++ b/javatests/dagger/producers/internal/ProducersTest.java
@@ -23,12 +23,12 @@
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.SettableFuture;
+import dagger.internal.Provider;
 import dagger.producers.Produced;
 import dagger.producers.Producer;
 import java.util.Set;
 import java.util.concurrent.CancellationException;
 import java.util.concurrent.ExecutionException;
-import javax.inject.Provider;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
diff --git a/test_defs.bzl b/test_defs.bzl
index 467f4e9..3b13626 100644
--- a/test_defs.bzl
+++ b/test_defs.bzl
@@ -31,7 +31,6 @@
     "Shards": ["-Adagger.keysPerComponentShard=2"],
     "FastInit": ["-Adagger.fastInit=enabled"],
     "FastInit_Shards": ["-Adagger.fastInit=enabled", "-Adagger.keysPerComponentShard=2"],
-    "IgnoreProvisionKeyWildcards": ["-Adagger.ignoreProvisionKeyWildcards=enabled"],
 }
 
 def GenKtLibrary(
@@ -51,6 +50,7 @@
         deps = deps,
         gen_library_deps = gen_library_deps,
         test_only_deps = None,
+        shard_count = None,
         plugins = plugins,
         javacopts = javacopts,
         functional = functional,
@@ -65,6 +65,7 @@
         test_only_deps = None,
         plugins = None,
         javacopts = None,
+        shard_count = None,
         functional = True,
         require_jdk7_syntax = True):
     _GenTestsWithVariants(
@@ -77,6 +78,7 @@
         test_only_deps = test_only_deps,
         plugins = plugins,
         javacopts = javacopts,
+        shard_count = shard_count,
         functional = functional,
         require_jdk7_syntax = require_jdk7_syntax,
     )
@@ -102,6 +104,7 @@
         test_only_deps = None,
         plugins = plugins,
         javacopts = javacopts,
+        shard_count = None,
         functional = functional,
         require_jdk7_syntax = require_jdk7_syntax,
     )
@@ -114,6 +117,7 @@
         test_only_deps = None,
         plugins = None,
         javacopts = None,
+        shard_count = None,
         functional = True,
         require_jdk7_syntax = True):
     if any([src for src in srcs if src.endswith(".kt")]):
@@ -128,6 +132,7 @@
         test_only_deps = test_only_deps,
         plugins = plugins,
         javacopts = javacopts,
+        shard_count = shard_count,
         functional = functional,
         require_jdk7_syntax = require_jdk7_syntax,
     )
@@ -139,6 +144,7 @@
         test_only_deps = None,
         plugins = None,
         javacopts = None,
+        shard_count = None,
         functional = True,
         require_jdk7_syntax = True,
         manifest_values = None):
@@ -153,6 +159,7 @@
         test_only_deps = test_only_deps,
         plugins = plugins,
         javacopts = javacopts,
+        shard_count = shard_count,
         functional = functional,
         require_jdk7_syntax = require_jdk7_syntax,
         test_kwargs = {"manifest_values": manifest_values},
@@ -168,6 +175,7 @@
         test_only_deps,
         plugins,
         javacopts,
+        shard_count,
         functional,
         require_jdk7_syntax,
         test_kwargs = None):
@@ -243,6 +251,7 @@
                     deps = test_deps + variant_deps,
                     plugins = plugins,
                     javacopts = javacopts + variant_javacopts,
+                    shard_count = shard_count,
                     jvm_flags = jvm_flags,
                     functional = functional,
                     test_kwargs = test_kwargs,
@@ -292,6 +301,7 @@
         deps,
         plugins,
         javacopts,
+        shard_count,
         jvm_flags,
         functional,
         test_kwargs):
@@ -320,6 +330,7 @@
         jvm_flags = jvm_flags,
         plugins = plugins,
         tags = tags,
+        shard_count = shard_count,
         test_class = test_class,
         deps = deps,
         **test_kwargs_with_javacopts
diff --git a/third_party/java/jspecify_annotations/BUILD b/third_party/java/jspecify_annotations/BUILD
new file mode 100644
index 0000000..cb72082
--- /dev/null
+++ b/third_party/java/jspecify_annotations/BUILD
@@ -0,0 +1,22 @@
+# Copyright (C) 2023 The Dagger Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# BUILD rules for https://github.com/square/javapoet
+
+package(default_visibility = ["//:src"])
+
+alias(
+    name = "jspecify_annotations",
+    actual = "@maven//:org_jspecify_jspecify",
+)
diff --git a/tools/bazel.rc b/tools/bazel.rc
new file mode 100644
index 0000000..2707c1c
--- /dev/null
+++ b/tools/bazel.rc
@@ -0,0 +1,11 @@
+# Global bazelrc file (see https://bazel.build/run/bazelrc#global-bazelrc)
+
+# Note: This flag is required to prevent actions from clashing with each when
+# reading/writing tmp files. Without this flag we get errors like:
+#
+#  Error: Cannot use file /tmp/hsperfdata_runner/12 because it is locked by
+#         another process
+#
+# This flag will be enabled by default in Bazel 7.0.0, but for now we enable it
+# manually. For more details: https://github.com/bazelbuild/bazel/issues/3236.
+build --incompatible_sandbox_hermetic_tmp
\ No newline at end of file
diff --git a/tools/maven.bzl b/tools/maven.bzl
index bc76386..4fba1a5 100644
--- a/tools/maven.bzl
+++ b/tools/maven.bzl
@@ -15,10 +15,10 @@
 """Macros to simplify generating maven files.
 """
 
+load("@google_bazel_common//tools/jarjar:jarjar.bzl", "jarjar_library")
+load("@google_bazel_common//tools/javadoc:javadoc.bzl", "javadoc_library")
 load("@google_bazel_common//tools/maven:pom_file.bzl", default_pom_file = "pom_file")
 load(":maven_info.bzl", "MavenInfo", "collect_maven_info")
-load("@google_bazel_common//tools/javadoc:javadoc.bzl", "javadoc_library")
-load("@google_bazel_common//tools/jarjar:jarjar.bzl", "jarjar_library")
 
 SHADED_MAVEN_DEPS = [
     "com.google.auto:auto-common",
@@ -66,6 +66,8 @@
         shaded_deps = None,
         manifest = None,
         lint_deps = None,
+        proguard_and_r8_specs = None,
+        r8_specs = None,
         proguard_specs = None):
     _gen_maven_artifact(
         name,
@@ -85,6 +87,8 @@
         shaded_deps,
         manifest,
         lint_deps,
+        proguard_and_r8_specs,
+        r8_specs,
         proguard_specs
     )
 
@@ -106,6 +110,8 @@
         shaded_deps,
         manifest,
         lint_deps,
+        proguard_and_r8_specs,
+        r8_specs,
         proguard_specs):
     """Generates the files required for a maven artifact.
 
@@ -140,7 +146,12 @@
       shaded_deps: The shaded deps for the jarjar.
       manifest: The AndroidManifest.xml to bundle in when packaing an 'aar'.
       lint_deps: The lint targets to be bundled in when packaging an 'aar'.
-      proguard_specs: The proguard spec files to be bundled in when packaging an 'aar'
+      proguard_and_r8_specs: The proguard spec files to be bundled in when
+                             packaging an 'aar', which will be applied in
+                             both r8 and proguard.
+      r8_specs: The proguard spec files to be used only for r8 when packaging an 'jar'.
+      proguard_specs: The proguard spec files to be used only for proguard not r8 when
+                           packaging an 'jar'.
     """
 
     _validate_maven_deps(
@@ -189,11 +200,11 @@
         else:
             lint_jar_name = None
 
-        if proguard_specs:
+        if proguard_and_r8_specs:
             # Concatenate all proguard rules since an aar only contains a single proguard.txt
             native.genrule(
                 name = name + "-proguard",
-                srcs = proguard_specs,
+                srcs = proguard_and_r8_specs,
                 outs = [name + "-proguard.txt"],
                 cmd = "cat $(SRCS) > $@",
             )
@@ -217,12 +228,46 @@
             cmd = "cp $< $@",
         )
     else:
+        # (TODO/322873492) add support for passing in general proguard rule.
+        if r8_specs:
+            # Concatenate all r8 rules.
+            native.genrule(
+                name = name + "-r8",
+                srcs = r8_specs,
+                outs = [name + "-r8.txt"],
+                cmd = "cat $(SRCS) > $@",
+            )
+            r8_file = name + "-r8.txt"
+        else:
+            r8_file = None
+
+        if proguard_specs:
+            # Concatenate all proguard only rules.
+            native.genrule(
+                name = name + "-proguard-only",
+                srcs = proguard_specs,
+                outs = [name + "-proguard-only.txt"],
+                cmd = "cat $(SRCS) > $@",
+            )
+            proguard_only_file = name + "-proguard-only.txt"
+        else:
+            proguard_only_file = None
+
         jarjar_library(
-            name = name,
+            name = name + "-classes",
             testonly = testonly,
             jars = artifact_targets + shaded_deps,
             merge_meta_inf_files = merge_meta_inf_files,
         )
+        jar_name = name + "-classes.jar"
+
+        # Include r8 and proguard rules to dagger jar if there is one.
+        _package_r8_and_proguard_rule(
+            name = name,
+            artifactJar = jar_name,
+            r8Spec = r8_file,
+            proguardSpec = proguard_only_file,
+        )
 
     jarjar_library(
         name = name + "-src",
@@ -405,3 +450,58 @@
         "aar": "%{name}.aar",
     },
 )
+
+def _package_r8_and_proguard_rule_impl(ctx):
+    inputs = [ctx.file.artifactJar]
+    if ctx.file.r8Spec:
+        inputs.append(ctx.file.r8Spec)
+    if ctx.file.proguardSpec:
+        inputs.append(ctx.file.proguardSpec)
+    ctx.actions.run_shell(
+        inputs = inputs,
+        outputs = [ctx.outputs.jar],
+        command = """
+            TMPDIR="$(mktemp -d)"
+            cp {artifactJar} $TMPDIR/artifact.jar
+            if [[ -a {r8Spec} ]]; then
+                mkdir -p META-INF/com.android.tools/r8
+                cp {r8Spec} META-INF/com.android.tools/r8/r8.pro
+                jar uf $TMPDIR/artifact.jar META-INF/
+            fi
+            if [[ -a {proguardSpec} ]]; then
+                mkdir -p META-INF/com.android.tools/proguard
+                cp {proguardSpec} META-INF/com.android.tools/proguard/proguard.pro
+                jar uf $TMPDIR/artifact.jar META-INF/
+            fi
+            cp $TMPDIR/artifact.jar {outputFile}
+            """.format(
+            artifactJar = ctx.file.artifactJar.path,
+            r8Spec = ctx.file.r8Spec.path if ctx.file.r8Spec else "none",
+            proguardSpec = ctx.file.proguardSpec.path if ctx.file.proguardSpec else "none",
+            outputFile = ctx.outputs.jar.path,
+        ),
+    )
+
+_package_r8_and_proguard_rule = rule(
+    implementation = _package_r8_and_proguard_rule_impl,
+    attrs = {
+        "artifactJar": attr.label(
+            doc = "The library artifact jar to be updated.",
+            allow_single_file = True,
+            mandatory = True,
+        ),
+        "r8Spec": attr.label(
+            doc = "The r8.txt file to be merged with the artifact jar",
+            allow_single_file = True,
+            mandatory = False,
+        ),
+        "proguardSpec": attr.label(
+            doc = "The proguard-only.txt file to be merged with the artifact jar",
+            allow_single_file = True,
+            mandatory = False,
+        ),
+    },
+    outputs = {
+        "jar": "%{name}.jar",
+    },
+)
diff --git a/util/cleanup-github-caches.py b/util/cleanup-github-caches.py
new file mode 100755
index 0000000..41e4ede
--- /dev/null
+++ b/util/cleanup-github-caches.py
@@ -0,0 +1,142 @@
+"""Cleans out the GitHub Actions cache by deleting obsolete caches.
+
+   Usage:
+   python cleanup-github-caches.py
+"""
+
+import collections
+import datetime
+import json
+import os
+import re
+import subprocess
+import sys
+
+
+def main(argv):
+  if len(argv) > 1:
+    raise ValueError('Expected no arguments: {}'.format(argv))
+
+  # Group caches by their Git reference, e.g "refs/pull/3968/merge"
+  caches_by_ref = collections.defaultdict(list)
+  for cache in get_caches():
+    caches_by_ref[cache['ref']].append(cache)
+
+  # Caclulate caches that should be deleted.
+  caches_to_delete = []
+  for ref, caches in caches_by_ref.items():
+    # If the pull request is already "closed", then delete all caches.
+    if (ref != 'refs/heads/master' and ref != 'master'):
+      match = re.findall(r'refs/pull/(\d+)/merge', ref)
+      if match:
+        pull_request_number = match[0]
+        pull_request = get_pull_request(pull_request_number)
+        if pull_request['state'] == 'closed':
+          caches_to_delete += caches
+          continue
+      else:
+        raise ValueError('Could not find pull request number:', ref)
+
+    # Check for caches with the same key prefix and delete the older caches.
+    caches_by_key = {}
+    for cache in caches:
+      key_prefix = re.findall('(.*)-.*', cache['key'])[0]
+      if key_prefix in caches_by_key:
+        prev_cache = caches_by_key[key_prefix]
+        if (get_created_at(cache) > get_created_at(prev_cache)):
+          caches_to_delete.append(prev_cache)
+          caches_by_key[key_prefix] = cache
+        else:
+          caches_to_delete.append(cache)
+      else:
+        caches_by_key[key_prefix] = cache
+
+  for cache in caches_to_delete:
+    print('Deleting cache ({}): {}'.format(cache['ref'], cache['key']))
+    print(delete_cache(cache))
+
+
+def get_created_at(cache):
+  created_at = cache['created_at'].split('.')[0]
+  # GitHub changed its date format so support both the old and new format for
+  # now.
+  for date_format in ('%Y-%m-%dT%H:%M:%SZ', '%Y-%m-%dT%H:%M:%S'):
+    try:
+      return datetime.datetime.strptime(created_at, date_format)
+    except ValueError:
+      pass
+  raise ValueError('no valid date format found: "%s"' % created_at)
+
+
+def delete_cache(cache):
+  # pylint: disable=line-too-long
+  """Deletes the given cache from GitHub Actions.
+
+  See https://docs.github.com/en/rest/actions/cache?apiVersion=2022-11-28#delete-a-github-actions-cache-for-a-repository-using-a-cache-id
+
+  Args:
+    cache: The cache to delete.
+
+  Returns:
+    The response of the api call.
+  """
+  return call_github_api(
+      """-X DELETE \
+      https://api.github.com/repos/google/dagger/actions/caches/{0}
+      """.format(cache['id'])
+  )
+
+
+def get_caches():
+  # pylint: disable=line-too-long
+  """Gets the list of existing caches from GitHub Actions.
+
+  See https://docs.github.com/en/rest/actions/cache?apiVersion=2022-11-28#list-github-actions-caches-for-a-repository
+
+  Returns:
+    The list of existing caches.
+  """
+  result = call_github_api(
+      'https://api.github.com/repos/google/dagger/actions/caches'
+  )
+  return json.loads(result)['actions_caches']
+
+
+def get_pull_request(pr_number):
+  # pylint: disable=line-too-long
+  """Gets the pull request with given number from GitHub Actions.
+
+  See https://docs.github.com/en/rest/pulls/pulls?apiVersion=2022-11-28#get-a-pull-request
+
+  Args:
+    pr_number: The pull request number used to get the pull request.
+
+  Returns:
+    The pull request.
+  """
+  result = call_github_api(
+      'https://api.github.com/repos/google/dagger/pulls/{0}'.format(pr_number)
+  )
+  return json.loads(result)
+
+
+def call_github_api(endpoint):
+  auth_cmd = ''
+  if 'GITHUB_TOKEN' in os.environ:
+    token = os.environ.get('GITHUB_TOKEN')
+    auth_cmd = '-H "Authorization: Bearer {0}"'.format(token)
+  cmd = """curl -L \
+      {auth_cmd} \
+      -H \"Accept: application/vnd.github+json\" \
+      -H \"X-GitHub-Api-Version: 2022-11-28\" \
+      {endpoint}""".format(auth_cmd=auth_cmd, endpoint=endpoint)
+  return subprocess.run(
+      [cmd],
+      check=True,
+      shell=True,
+      capture_output=True
+  ).stdout.decode('utf-8')
+
+
+if __name__ == '__main__':
+  main(sys.argv)
diff --git a/util/deploy-dagger.sh b/util/deploy-dagger.sh
index 9249b91..b0b68a8 100755
--- a/util/deploy-dagger.sh
+++ b/util/deploy-dagger.sh
@@ -37,10 +37,10 @@
 
 _deploy \
   "" \
-  java/dagger/libcore.jar \
+  java/dagger/artifact.jar \
   java/dagger/pom.xml \
-  java/dagger/libcore-src.jar \
-  java/dagger/core-javadoc.jar \
+  java/dagger/artifact-src.jar \
+  java/dagger/artifact-javadoc.jar \
   "dagger"
 
 _deploy \
@@ -52,7 +52,7 @@
   ""
 
 _deploy \
-  "com.google.auto.common,dagger.spi.shaded.auto.common;androidx.room.compiler,dagger.spi.shaded.androidx.room.compiler;kotlinx.metadata,dagger.spi.shaded.kotlinx.metadata;androidx.room,dagger.spi.shaded.androidx.room" \
+  "com.google.auto.common,dagger.spi.internal.shaded.auto.common;androidx.room.compiler,dagger.spi.internal.shaded.androidx.room.compiler;kotlinx.metadata,dagger.spi.internal.shaded.kotlinx.metadata;androidx.room,dagger.spi.internal.shaded.androidx.room" \
   java/dagger/internal/codegen/artifact.jar \
   java/dagger/internal/codegen/pom.xml \
   java/dagger/internal/codegen/artifact-src.jar \
@@ -68,7 +68,7 @@
   ""
 
 _deploy \
-  "com.google.auto.common,dagger.spi.shaded.auto.common;androidx.room.compiler,dagger.spi.shaded.androidx.room.compiler;kotlinx.metadata,dagger.spi.shaded.kotlinx.metadata;androidx.room,dagger.spi.shaded.androidx.room" \
+  "com.google.auto.common,dagger.spi.internal.shaded.auto.common;androidx.room.compiler,dagger.spi.internal.shaded.androidx.room.compiler;kotlinx.metadata,dagger.spi.internal.shaded.kotlinx.metadata;androidx.room,dagger.spi.internal.shaded.androidx.room" \
   java/dagger/spi/artifact.jar \
   java/dagger/spi/pom.xml \
   java/dagger/spi/artifact-src.jar \
@@ -77,10 +77,10 @@
 
 _deploy \
   "" \
-  java/dagger/android/android.aar \
+  java/dagger/android/artifact.aar \
   java/dagger/android/pom.xml \
-  java/dagger/android/libandroid-src.jar \
-  java/dagger/android/android-javadoc.jar \
+  java/dagger/android/artifact-src.jar \
+  java/dagger/android/artifact-javadoc.jar \
   ""
 
 _deploy \
@@ -93,10 +93,10 @@
 
 _deploy \
   "" \
-  java/dagger/android/support/support.aar \
+  java/dagger/android/support/artifact.aar \
   java/dagger/android/support/pom.xml \
-  java/dagger/android/support/libsupport-src.jar \
-  java/dagger/android/support/support-javadoc.jar \
+  java/dagger/android/support/artifact-src.jar \
+  java/dagger/android/support/artifact-javadoc.jar \
   ""
 
 _deploy \
@@ -108,11 +108,11 @@
   ""
 
 _deploy \
-  "" \
-  shaded_android_processor.jar \
+  "com.google.auto.common,dagger.spi.internal.shaded.auto.common;androidx.room.compiler,dagger.spi.internal.shaded.androidx.room.compiler;kotlinx.metadata,dagger.spi.internal.shaded.kotlinx.metadata;androidx.room,dagger.spi.internal.shaded.androidx.room" \
+  java/dagger/android/processor/artifact.jar \
   java/dagger/android/processor/pom.xml \
-  java/dagger/android/processor/libprocessor-src.jar \
-  java/dagger/android/processor/processor-javadoc.jar \
+  java/dagger/android/processor/artifact-src.jar \
+  java/dagger/android/processor/artifact-javadoc.jar \
   ""
 
 _deploy \
diff --git a/util/deploy-hilt-gradle-plugin.sh b/util/deploy-hilt-gradle-plugin.sh
index 72ff939..698b0c9 100755
--- a/util/deploy-hilt-gradle-plugin.sh
+++ b/util/deploy-hilt-gradle-plugin.sh
@@ -12,8 +12,8 @@
   local plugindir=java/dagger/hilt/android/plugin
   ./$plugindir/gradlew -p $plugindir --no-daemon clean \
     publishAllPublicationsToMavenRepository -PPublishVersion="$VERSION_NAME"
-  local outdir=$plugindir/main/build/repo/com/google/dagger/hilt-android-gradle-plugin/$VERSION_NAME
-  local markerOutDir=$plugindir/main/build/repo/com/google/dagger/hilt/android/com.google.dagger.hilt.android.gradle.plugin/$VERSION_NAME
+  local outdir=$plugindir/main/buildOut/repo/com/google/dagger/hilt-android-gradle-plugin/$VERSION_NAME
+  local markerOutDir=$plugindir/main/buildOut/repo/com/google/dagger/hilt/android/com.google.dagger.hilt.android.gradle.plugin/$VERSION_NAME
   # When building '-SNAPSHOT' versions in gradle, the filenames replaces
   # '-SNAPSHOT' with timestamps, so we need to disambiguate by finding each file
   # to deploy. See: https://stackoverflow.com/questions/54182823/
diff --git a/util/deploy-hilt.sh b/util/deploy-hilt.sh
index cdf4b6b..81b384c 100755
--- a/util/deploy-hilt.sh
+++ b/util/deploy-hilt.sh
@@ -52,7 +52,7 @@
   ""
 
 _deploy \
-  "com.google.auto.common,dagger.spi.shaded.auto.common;androidx.room.compiler,dagger.spi.shaded.androidx.room.compiler;kotlinx.metadata,dagger.spi.shaded.kotlinx.metadata;androidx.room,dagger.spi.shaded.androidx.room" \
+  "com.google.auto.common,dagger.spi.internal.shaded.auto.common;androidx.room.compiler,dagger.spi.internal.shaded.androidx.room.compiler;kotlinx.metadata,dagger.spi.internal.shaded.kotlinx.metadata;androidx.room,dagger.spi.internal.shaded.androidx.room" \
   java/dagger/hilt/processor/artifact.jar \
   java/dagger/hilt/processor/pom.xml \
   java/dagger/hilt/processor/artifact-src.jar \
@@ -60,7 +60,7 @@
   ""
 
 _deploy \
-  "com.google.auto.common,dagger.spi.shaded.auto.common;androidx.room.compiler,dagger.spi.shaded.androidx.room.compiler;kotlinx.metadata,dagger.spi.shaded.kotlinx.metadata;androidx.room,dagger.spi.shaded.androidx.room" \
+  "com.google.auto.common,dagger.spi.internal.shaded.auto.common;androidx.room.compiler,dagger.spi.internal.shaded.androidx.room.compiler;kotlinx.metadata,dagger.spi.internal.shaded.kotlinx.metadata;androidx.room,dagger.spi.internal.shaded.androidx.room" \
   java/dagger/hilt/android/processor/artifact.jar \
   java/dagger/hilt/android/processor/pom.xml \
   java/dagger/hilt/android/processor/artifact-src.jar \
diff --git a/util/run-local-emulator-tests.sh b/util/run-local-emulator-tests.sh
index 30b31be..733f637 100755
--- a/util/run-local-emulator-tests.sh
+++ b/util/run-local-emulator-tests.sh
@@ -8,6 +8,9 @@
 readonly GRADLE_PROJECTS=(
     "javatests/artifacts/hilt-android/simple"
     "javatests/artifacts/hilt-android/simpleKotlin"
+    "javatests/artifacts/hilt-android/viewmodel"
+    "javatests/artifacts/hilt-android/lazyclasskey"
+    "javatests/artifacts/dagger/lazyclasskey"
 )
 for project in "${GRADLE_PROJECTS[@]}"; do
     echo "Running gradle Android emulator tests for $project"
diff --git a/util/run-local-gradle-android-tests.sh b/util/run-local-gradle-android-tests.sh
index 0b3a5f5..9ae56f8 100755
--- a/util/run-local-gradle-android-tests.sh
+++ b/util/run-local-gradle-android-tests.sh
@@ -9,18 +9,33 @@
     "javatests/artifacts/dagger-android/simple"
     "javatests/artifacts/hilt-android/simple"
 )
-for project in "${JAVA_ANDROID_GRADLE_PROJECTS[@]}"; do
-    echo "Running gradle tests for $project with AGP $AGP_VERSION_INPUT"
-    AGP_VERSION=$AGP_VERSION_INPUT ./$project/gradlew -p $project assembleDebug $COMMON_GRADLE_ARGS
-    AGP_VERSION=$AGP_VERSION_INPUT ./$project/gradlew -p $project testDebug --continue $COMMON_GRADLE_ARGS
-done
-
 readonly KOTLIN_ANDROID_GRADLE_PROJECTS=(
     "javatests/artifacts/hilt-android/simpleKotlin"
 )
-for project in "${KOTLIN_ANDROID_GRADLE_PROJECTS[@]}"; do
-    echo "Running gradle tests for $project with AGP $AGP_VERSION_INPUT"
-    AGP_VERSION=$AGP_VERSION_INPUT ./$project/gradlew -p $project assembleDebug $COMMON_GRADLE_ARGS
-    AGP_VERSION=$AGP_VERSION_INPUT ./$project/gradlew -p $project testWithKaptDebugUnitTest --continue $COMMON_GRADLE_ARGS
-    AGP_VERSION=$AGP_VERSION_INPUT ./$project/gradlew -p $project testWithKspDebugUnitTest --continue $COMMON_GRADLE_ARGS
-done
+if [[ $AGP_VERSION_INPUT == "7.0.0" || $AGP_VERSION_INPUT == "7.1.2" ]]
+then
+  for project in "${JAVA_ANDROID_GRADLE_PROJECTS[@]}"; do
+      echo "Running gradle tests for $project with AGP $AGP_VERSION_INPUT"
+      AGP_VERSION=$AGP_VERSION_INPUT ./$project/gradlew -p $project assembleDebug $COMMON_GRADLE_ARGS
+      AGP_VERSION=$AGP_VERSION_INPUT ./$project/gradlew -p $project testDebug --continue $COMMON_GRADLE_ARGS
+  done
+
+  for project in "${KOTLIN_ANDROID_GRADLE_PROJECTS[@]}"; do
+      echo "Running gradle tests for $project with AGP $AGP_VERSION_INPUT"
+      AGP_VERSION=$AGP_VERSION_INPUT ./$project/gradlew -p $project assembleDebug $COMMON_GRADLE_ARGS
+      AGP_VERSION=$AGP_VERSION_INPUT ./$project/gradlew -p $project testWithKaptDebugUnitTest --continue $COMMON_GRADLE_ARGS
+      AGP_VERSION=$AGP_VERSION_INPUT ./$project/gradlew -p $project testWithKspDebugUnitTest --continue $COMMON_GRADLE_ARGS
+  done
+fi
+
+readonly JAVA_ANDROID_GRADLE_JDK17_PROJECTS=(
+    "javatests/artifacts/dagger-android-ksp"
+)
+if [[ $AGP_VERSION_INPUT == "8.1.0" ]]
+then
+  for project in "${JAVA_ANDROID_GRADLE_JDK17_PROJECTS[@]}"; do
+      echo "Running gradle tests for $project with AGP $AGP_VERSION_INPUT"
+      AGP_VERSION=$AGP_VERSION_INPUT ./$project/gradlew -p $project assembleDebug $COMMON_GRADLE_ARGS
+      AGP_VERSION=$AGP_VERSION_INPUT ./$project/gradlew -p $project testDebug --continue $COMMON_GRADLE_ARGS
+  done
+fi
diff --git a/util/run-local-tests.sh b/util/run-local-tests.sh
index 4e81e5f..2603346 100755
--- a/util/run-local-tests.sh
+++ b/util/run-local-tests.sh
@@ -19,4 +19,4 @@
 util/run-local-gradle-android-tests.sh "7.0.0"
 util/run-local-gradle-android-tests.sh "7.1.2"
 
-
+# TODO: this script is not up-to-date with Dagger github actions