diff --git a/src/main/java/com/android/tools/metalava/AnnotationsMerger.kt b/src/main/java/com/android/tools/metalava/AnnotationsMerger.kt
index 795d99eba61947220d871b1c242803b38232e8b0..76d430d61207d99750541ffda78e42a2b6bfdd72 100644
--- a/src/main/java/com/android/tools/metalava/AnnotationsMerger.kt
+++ b/src/main/java/com/android/tools/metalava/AnnotationsMerger.kt
@@ -56,11 +56,16 @@ import com.android.tools.metalava.model.ClassItem
 import com.android.tools.metalava.model.Codebase
 import com.android.tools.metalava.model.DefaultAnnotationItem
 import com.android.tools.metalava.model.DefaultAnnotationValue
+import com.android.tools.metalava.model.FieldItem
 import com.android.tools.metalava.model.Item
 import com.android.tools.metalava.model.MethodItem
+import com.android.tools.metalava.model.ModifierList
+import com.android.tools.metalava.model.ParameterItem
+import com.android.tools.metalava.model.TypeItem
 import com.android.tools.metalava.model.parseDocument
 import com.android.tools.metalava.model.psi.PsiAnnotationItem
 import com.android.tools.metalava.model.psi.PsiBasedCodebase
+import com.android.tools.metalava.model.psi.PsiTypeItem
 import com.android.tools.metalava.model.visitors.ApiVisitor
 import com.google.common.io.ByteStreams
 import com.google.common.io.Closeables
@@ -240,32 +245,70 @@ class AnnotationsMerger(
             override fun compare(old: Item, new: Item) {
                 val newModifiers = new.modifiers
                 for (annotation in old.modifiers.annotations()) {
-                    var addAnnotation = false
-                    if (annotation.isNullnessAnnotation()) {
-                        if (!newModifiers.hasNullnessInfo()) {
-                            addAnnotation = true
-                        }
-                    } else {
-                        // TODO: Check for other incompatibilities than nullness?
-                        val qualifiedName = annotation.qualifiedName() ?: continue
-                        if (newModifiers.findAnnotation(qualifiedName) == null) {
-                            addAnnotation = true
-                        }
+                    mergeAnnotation(annotation, newModifiers, new)
+                }
+            }
+
+            private fun mergeAnnotation(
+                annotation: AnnotationItem,
+                newModifiers: ModifierList,
+                new: Item
+            ) {
+                var addAnnotation = false
+                if (annotation.isNullnessAnnotation()) {
+                    if (!newModifiers.hasNullnessInfo()) {
+                        addAnnotation = true
                     }
+                } else {
+                    // TODO: Check for other incompatibilities than nullness?
+                    val qualifiedName = annotation.qualifiedName() ?: return
+                    if (newModifiers.findAnnotation(qualifiedName) == null) {
+                        addAnnotation = true
+                    }
+                }
 
-                    if (addAnnotation) {
-                        // Don't map annotation names - this would turn newly non null back into non null
-                        new.mutableModifiers().addAnnotation(
-                            new.codebase.createAnnotation(
-                                annotation.toSource(),
-                                new,
-                                mapName = false
-                            )
+                if (addAnnotation) {
+                    // Don't map annotation names - this would turn newly non null back into non null
+                    new.mutableModifiers().addAnnotation(
+                        new.codebase.createAnnotation(
+                            annotation.toSource(),
+                            new,
+                            mapName = false
                         )
+                    )
+                }
+            }
+
+            override fun compare(old: ParameterItem, new: ParameterItem) {
+                mergeTypeAnnotations(old.type(), new)
+            }
+
+            override fun compare(old: FieldItem, new: FieldItem) {
+                mergeTypeAnnotations(old.type(), new)
+            }
+
+            override fun compare(old: MethodItem, new: MethodItem) {
+                mergeTypeAnnotations(old.returnType(), new)
+            }
+
+            // Merge in type annotations
+            private fun mergeTypeAnnotations(
+                typeItem: TypeItem?,
+                new: Item
+            ) {
+                typeItem ?: return
+                val type = (typeItem as? PsiTypeItem)?.psiType ?: return
+                val typeAnnotations = type.annotations
+                if (typeAnnotations.isNotEmpty()) {
+                    for (annotation in typeAnnotations) {
+                        val codebase = new.codebase as PsiBasedCodebase
+                        val annotationItem = PsiAnnotationItem.create(codebase, annotation)
+                        mergeAnnotation(annotationItem, new.modifiers, new)
                     }
                 }
             }
         }
+
         CodebaseComparator().compare(
             visitor, externalCodebase, codebase, ApiPredicate()
         )
diff --git a/src/main/java/com/android/tools/metalava/model/psi/PsiTypeItem.kt b/src/main/java/com/android/tools/metalava/model/psi/PsiTypeItem.kt
index 306770a675fbde386b4780bf60a18384a403973f..507731483f1b5c997a3185b01b54593792aaef5d 100644
--- a/src/main/java/com/android/tools/metalava/model/psi/PsiTypeItem.kt
+++ b/src/main/java/com/android/tools/metalava/model/psi/PsiTypeItem.kt
@@ -56,7 +56,7 @@ import com.intellij.psi.util.TypeConversionUtil
 import org.jetbrains.kotlin.asJava.elements.KtLightTypeParameter
 
 /** Represents a type backed by PSI */
-class PsiTypeItem private constructor(private val codebase: PsiBasedCodebase, private val psiType: PsiType) : TypeItem {
+class PsiTypeItem private constructor(private val codebase: PsiBasedCodebase, val psiType: PsiType) : TypeItem {
     private var toString: String? = null
     private var toAnnotatedString: String? = null
     private var toInnerAnnotatedString: String? = null
diff --git a/src/test/java/com/android/tools/metalava/AnnotationsMergerTest.kt b/src/test/java/com/android/tools/metalava/AnnotationsMergerTest.kt
index cc7eb68c3c8845c98f32e019078176867b691b9d..f1d6a12b9ae8bbc1251567ad8d921c18c9986c15 100644
--- a/src/test/java/com/android/tools/metalava/AnnotationsMergerTest.kt
+++ b/src/test/java/com/android/tools/metalava/AnnotationsMergerTest.kt
@@ -211,24 +211,70 @@ class AnnotationsMergerTest : DriverTest() {
     }
 
     @Test
-    fun `Merge inclusion annotations from Java stub files`() {
+    fun `Merge type use qualifier annotations from Java stub files`() {
+        // See b/123223339
         check(
-            warnings = "src/test/pkg/Example.java:6: error: @test.annotation.Show APIs must also be marked @hide: method test.pkg.Example.cShown() [UnhiddenSystemApi]",
             sourceFiles = *arrayOf(
                 java(
                     """
                 package test.pkg;
 
-                public interface Example {
-                    void aNotAnnotated();
-                    void bHidden();
-                    void cShown();
+                public class Test {
+                    private Test() { }
+                    public void foo(Object... args) { }
                 }
+                """
+                ),
+                libcoreNonNullSource,
+                libcoreNullableSource
+            ),
+            compatibilityMode = false,
+            outputKotlinStyleNulls = false,
+            omitCommonPackages = false,
+            mergeJavaStubAnnotations = """
+                package test.pkg;
 
-                public interface HiddenExample {
-                    void method();
+                public class Test {
+                    public void foo(java.lang.@libcore.util.Nullable Object @libcore.util.NonNull ... args) { throw new RuntimeException("Stub!"); }
                 }
-                """
+                """,
+            api = """
+                package test.pkg {
+                  public class Test {
+                    method public void foo(@androidx.annotation.NonNull java.lang.Object...);
+                  }
+                }
+                """,
+            extraArguments = arrayOf(ARG_HIDE_PACKAGE, "libcore.util")
+        )
+    }
+
+    @Test
+    fun `Merge inclusion annotations from Java stub files`() {
+        check(
+            warnings = "src/test/pkg/Example.annotated.java:6: error: @test.annotation.Show APIs must also be marked @hide: method test.pkg.Example.cShown() [UnhiddenSystemApi]",
+            sourceFiles = *arrayOf(
+                java(
+                    "src/test/pkg/Example.annotated.java",
+                    """
+                    package test.pkg;
+
+                    public interface Example {
+                        void aNotAnnotated();
+                        void bHidden();
+                        void cShown();
+                    }
+                    """
+                ),
+                java(
+                    "src/test/pkg/HiddenExample.annotated.java",
+                    """
+                    package test.pkg;
+
+                    public interface HiddenExample {
+                        void method();
+                    }
+                    """
                 )
             ),
             compatibilityMode = false,
@@ -267,14 +313,15 @@ class AnnotationsMergerTest : DriverTest() {
         check(
             sourceFiles = *arrayOf(
                 java(
+                    "src/test/pkg/Example.annotated.java",
                     """
-                package test.pkg;
+                    package test.pkg;
 
-                public interface Example {
-                    void aNotAnnotated();
-                    void bShown();
-                }
-                """
+                    public interface Example {
+                        void aNotAnnotated();
+                        void bShown();
+                    }
+                    """
                 )
             ),
             compatibilityMode = false,
diff --git a/src/test/java/com/android/tools/metalava/DriverTest.kt b/src/test/java/com/android/tools/metalava/DriverTest.kt
index 533e58f8d1690d6cdf2d644e490fb8139499bdae..e54df8105f49f68edb3208ffcce5903ae69be7c4 100644
--- a/src/test/java/com/android/tools/metalava/DriverTest.kt
+++ b/src/test/java/com/android/tools/metalava/DriverTest.kt
@@ -1902,6 +1902,10 @@ abstract class DriverTest {
             }
         }
 
+        fun java(to: String, @Language("JAVA") source: String): LintDetectorTest.TestFile {
+            return TestFiles.java(to, source.trimIndent())
+        }
+
         fun java(@Language("JAVA") source: String): LintDetectorTest.TestFile {
             return TestFiles.java(source.trimIndent())
         }