[Draft] Jspecify: support type use annotations
diff --git a/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/JavaValueParameterImpl.java b/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/JavaValueParameterImpl.java
index cca1813..6aaaa89 100644
--- a/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/JavaValueParameterImpl.java
+++ b/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/JavaValueParameterImpl.java
@@ -67,6 +67,7 @@
     @NotNull
     @Override
     public Collection<JavaAnnotation> getAnnotations() {
+        // here there is a problem
         return JavaElementUtil.getRegularAndExternalAnnotations(this);
     }
 
diff --git a/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/classFiles/Annotations.kt b/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/classFiles/Annotations.kt
index e1ac5a9..e9f8bd8 100644
--- a/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/classFiles/Annotations.kt
+++ b/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/classFiles/Annotations.kt
@@ -17,6 +17,7 @@
 package org.jetbrains.kotlin.load.java.structure.impl.classFiles
 
 import org.jetbrains.kotlin.load.java.structure.*
+import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryJavaAnnotation.Companion.translatePath
 import org.jetbrains.kotlin.name.ClassId
 import org.jetbrains.kotlin.name.FqName
 import org.jetbrains.kotlin.name.Name
@@ -25,11 +26,11 @@
 import java.lang.reflect.Array
 
 internal class AnnotationsAndParameterCollectorMethodVisitor(
-        private val member: BinaryJavaMethodBase,
-        private val context: ClassifierResolutionContext,
-        private val signatureParser: BinaryClassSignatureParser,
-        private val parametersToSkipNumber: Int,
-        private val parametersCountInMethodDesc: Int
+    private val member: BinaryJavaMethodBase,
+    private val context: ClassifierResolutionContext,
+    private val signatureParser: BinaryClassSignatureParser,
+    private val parametersToSkipNumber: Int,
+    private val parametersCountInMethodDesc: Int
 ) : MethodVisitor(ASM_API_VERSION_FOR_CLASS_READING) {
     private var parameterIndex = 0
 
@@ -57,8 +58,8 @@
 
     override fun visitAnnotation(desc: String, visible: Boolean) =
             BinaryJavaAnnotation.addAnnotation(
-                    member.annotations as MutableCollection<JavaAnnotation>,
-                    desc, context, signatureParser
+                member.annotations as MutableCollection<JavaAnnotation>,
+                desc, context, signatureParser
             )
 
     @Suppress("NOTHING_TO_OVERRIDE")
@@ -77,15 +78,75 @@
         if (index < 0) return null
 
         val annotations =
-                member.valueParameters[index].annotations as MutableCollection<JavaAnnotation>?
+            member.valueParameters[index].annotations as MutableCollection<JavaAnnotation>?
                 ?: return null
 
         return BinaryJavaAnnotation.addAnnotation(annotations, desc, context, signatureParser)
     }
 
     override fun visitTypeAnnotation(typeRef: Int, typePath: TypePath?, desc: String, visible: Boolean): AnnotationVisitor? {
-        // TODO: support annotations on type arguments
-        if (typePath != null) return null
+        if (typePath != null) {
+            val typeReference = TypeReference(typeRef)
+            val translatedPath = translatePath(typePath)
+
+            when (typeReference.sort) {
+                TypeReference.METHOD_RETURN -> {
+                    var baseType = member.safeAs<BinaryJavaMethod>()?.returnType ?: return null
+
+                    for (element in translatedPath) {
+                        when (element.first) {
+                            PathElementType.TYPE_ARGUMENT -> {
+                                if (baseType is JavaClassifierType) {
+                                    baseType = baseType.typeArguments[element.second!!]!!
+                                }
+                            }
+                            PathElementType.WILDCARD_BOUND -> {
+                                if (baseType is JavaWildcardType) {
+                                    baseType = baseType.bound!!
+                                }
+                            }
+                            PathElementType.ARRAY_ELEMENT -> {
+                                if (baseType is JavaArrayType) {
+                                    baseType = baseType.componentType
+                                }
+                            }
+                        }
+                    }
+
+                    return BinaryJavaAnnotation.addTypeAnnotation(baseType, desc, context, signatureParser)
+                }
+
+                TypeReference.METHOD_FORMAL_PARAMETER -> {
+                    var baseType = member.valueParameters[typeReference.formalParameterIndex].type
+
+                    for (element in translatedPath) {
+                        when (element.first) {
+                            PathElementType.TYPE_ARGUMENT -> {
+                                if (baseType is JavaClassifierType) {
+                                    baseType = baseType.typeArguments[element.second!!]!!
+                                }
+                            }
+                            PathElementType.WILDCARD_BOUND -> {
+                                if (baseType is JavaWildcardType) {
+                                    baseType = baseType.bound!!
+                                }
+                            }
+                            PathElementType.ARRAY_ELEMENT -> {
+                                if (baseType is JavaArrayType) {
+                                    baseType = baseType.componentType
+                                }
+                            }
+                        }
+                    }
+
+                    return BinaryJavaAnnotation.addTypeAnnotation(
+                        baseType,
+                        desc, context, signatureParser
+                    )
+                }
+            }
+            return null
+        }
 
         val typeReference = TypeReference(typeRef)
 
@@ -94,29 +155,105 @@
                 BinaryJavaAnnotation.addTypeAnnotation(it, desc, context, signatureParser)
             }
 
+            TypeReference.METHOD_TYPE_PARAMETER -> {
+                BinaryJavaAnnotation.addTypeAnnotation(
+                    member.typeParameters[typeReference.typeParameterIndex],
+                    desc, context, signatureParser
+                )
+            }
+
             TypeReference.METHOD_FORMAL_PARAMETER ->
-                    BinaryJavaAnnotation.addTypeAnnotation(
-                            member.valueParameters[typeReference.formalParameterIndex].type,
-                            desc, context, signatureParser
-                    )
+                BinaryJavaAnnotation.addTypeAnnotation(
+                    member.valueParameters[typeReference.formalParameterIndex].type,
+                    desc, context, signatureParser
+                )
 
             else -> null
         }
     }
+
+    enum class PathElementType { ARRAY_ELEMENT, WILDCARD_BOUND, ENCLOSING_CLASS, TYPE_ARGUMENT }
+
+//    private fun translatePath(path: TypePath?): ByteArray? {
+//        var typeText: String = myTypeInfo.text
+//        var arrayLevel: Int = myTypeInfo.arrayCount + if (myTypeInfo.isEllipsis) 1 else 0
+//        var qualifiedName = PsiNameHelper.getQualifiedClassName(typeText, false)
+//        var depth: Int = myFirstPassData.getInnerDepth(qualifiedName)
+//        var atWildcard = false
+//        if (path == null) {
+//            if (depth == 0 || arrayLevel > 0) {
+//                return ArrayUtil.EMPTY_BYTE_ARRAY
+//            }
+//            val result = ByteArray(depth)
+//            Arrays.fill(result, TypeAnnotationContainer.Collector.ENCLOSING_CLASS)
+//            return result
+//        }
+//        val result = ByteArrayOutputStream()
+//        val length = path.length
+//        for (i in 0 until length) {
+//            val step = path.getStep(i).toByte()
+//            when (step) {
+//                TypePath.INNER_TYPE -> {
+//                    if (depth == 0) return null
+//                    depth--
+//                }
+//                TypePath.ARRAY_ELEMENT -> {
+//                    if (arrayLevel <= 0 || atWildcard) return null
+//                    arrayLevel--
+//                    result.write(TypeAnnotationContainer.Collector.ARRAY_ELEMENT)
+//                }
+//                TypePath.WILDCARD_BOUND -> {
+//                    if (!atWildcard) return null
+//                    atWildcard = false
+//                    result.write(TypeAnnotationContainer.Collector.WILDCARD_BOUND)
+//                }
+//                TypePath.TYPE_ARGUMENT -> {
+//                    if (atWildcard || arrayLevel > 0) return null
+//                    while (depth-- > 0) {
+//                        result.write(TypeAnnotationContainer.Collector.ENCLOSING_CLASS)
+//                        typeText = PsiNameHelper.getOuterClassReference(typeText)
+//                    }
+//                    val argumentIndex = path.getStepArgument(i)
+//                    val arguments = PsiNameHelper.getClassParametersText(typeText)
+//                    if (argumentIndex >= arguments.size) return null
+//                    val argument = TypeInfo.fromString(arguments[argumentIndex], false)
+//                    arrayLevel = argument.arrayCount.toInt()
+//                    typeText = argument.text
+//                    if (typeText.startsWith("? extends ")) {
+//                        typeText = typeText.substring("? extends ".length)
+//                        atWildcard = true
+//                    } else if (typeText.startsWith("? super ")) {
+//                        typeText = typeText.substring("? super ".length)
+//                        atWildcard = true
+//                    }
+//                    qualifiedName = PsiNameHelper.getQualifiedClassName(typeText, false)
+//                    depth = myFirstPassData.getInnerDepth(qualifiedName)
+//                    result.write(TypeAnnotationContainer.Collector.TYPE_ARGUMENT)
+//                    result.write(argumentIndex)
+//                }
+//            }
+//        }
+//        if (!atWildcard && arrayLevel == 0) {
+//            while (depth-- > 0) {
+//                result.write(TypeAnnotationContainer.Collector.ENCLOSING_CLASS)
+//            }
+//        }
+//        return result.toByteArray()
+//    }
 }
 
 class BinaryJavaAnnotation private constructor(
-        desc: String,
-        private val context: ClassifierResolutionContext,
-        override val arguments: Collection<JavaAnnotationArgument>
+    desc: String,
+    private val context: ClassifierResolutionContext,
+    override val arguments: Collection<JavaAnnotationArgument>
 ) : JavaAnnotation {
 
     companion object {
 
         fun createAnnotationAndVisitor(
-                desc: String,
-                context: ClassifierResolutionContext,
-                signatureParser: BinaryClassSignatureParser
+            desc: String,
+            context: ClassifierResolutionContext,
+            signatureParser: BinaryClassSignatureParser
         ): Pair<JavaAnnotation, AnnotationVisitor> {
             val arguments = mutableListOf<JavaAnnotationArgument>()
             val annotation = BinaryJavaAnnotation(desc, context, arguments)
@@ -125,10 +262,10 @@
         }
 
         fun addAnnotation(
-                annotations: MutableCollection<JavaAnnotation>,
-                desc: String,
-                context: ClassifierResolutionContext,
-                signatureParser: BinaryClassSignatureParser
+            annotations: MutableCollection<JavaAnnotation>,
+            desc: String,
+            context: ClassifierResolutionContext,
+            signatureParser: BinaryClassSignatureParser
         ): AnnotationVisitor {
             val (javaAnnotation, annotationVisitor) = createAnnotationAndVisitor(desc, context, signatureParser)
             annotations.add(javaAnnotation)
@@ -137,18 +274,61 @@
         }
 
         fun addTypeAnnotation(
-                type: JavaType,
-                desc: String,
-                context: ClassifierResolutionContext,
-                signatureParser: BinaryClassSignatureParser
+            type: JavaType,
+            desc: String,
+            context: ClassifierResolutionContext,
+            signatureParser: BinaryClassSignatureParser
         ): AnnotationVisitor? {
-            type as? PlainJavaClassifierType ?: return null
+            return when (type) {
+                is PlainJavaClassifierType -> {
+                    val (javaAnnotation, annotationVisitor) = createAnnotationAndVisitor(desc, context, signatureParser)
+                    type.addAnnotation(javaAnnotation)
+                    annotationVisitor
+                }
+                is PlainJavaArrayType -> {
+                    val (javaAnnotation, annotationVisitor) = createAnnotationAndVisitor(desc, context, signatureParser)
+                    type.addAnnotation(javaAnnotation)
+                    annotationVisitor
+                }
+                else -> null
+            }
+        }
+
+        fun addTypeAnnotation(
+            type: JavaTypeParameter,
+            desc: String,
+            context: ClassifierResolutionContext,
+            signatureParser: BinaryClassSignatureParser
+        ): AnnotationVisitor? {
+            if (type !is BinaryJavaTypeParameter) return null
 
             val (javaAnnotation, annotationVisitor) = createAnnotationAndVisitor(desc, context, signatureParser)
             type.addAnnotation(javaAnnotation)
 
             return annotationVisitor
         }
+
+        internal fun translatePath(path: TypePath): List<Pair<AnnotationsAndParameterCollectorMethodVisitor.PathElementType, Int?>> {
+            val length = path.length
+            val list = mutableListOf<Pair<AnnotationsAndParameterCollectorMethodVisitor.PathElementType, Int?>>()
+            for (i in 0 until length) {
+                when (path.getStep(i)) {
+                    TypePath.INNER_TYPE -> {
+                        continue
+                    }
+                    TypePath.ARRAY_ELEMENT -> {
+                        list.add(AnnotationsAndParameterCollectorMethodVisitor.PathElementType.ARRAY_ELEMENT to null)
+                    }
+                    TypePath.WILDCARD_BOUND -> {
+                        list.add(AnnotationsAndParameterCollectorMethodVisitor.PathElementType.WILDCARD_BOUND to null)
+                    }
+                    TypePath.TYPE_ARGUMENT -> {
+                        list.add(AnnotationsAndParameterCollectorMethodVisitor.PathElementType.TYPE_ARGUMENT to path.getStepArgument(i))
+                    }
+                }
+            }
+            return list
+        }
     }
 
     private val classifierResolutionResult by lazy(LazyThreadSafetyMode.NONE) {
@@ -224,37 +404,37 @@
 }
 
 class PlainJavaLiteralAnnotationArgument(
-        name: String?,
-        override val value: Any?
+    name: String?,
+    override val value: Any?
 ) : PlainJavaAnnotationArgument(name), JavaLiteralAnnotationArgument
 
 class PlainJavaClassObjectAnnotationArgument(
-        name: String?,
-        private val type: Type,
-        private val signatureParser: BinaryClassSignatureParser,
-        private val context: ClassifierResolutionContext
+    name: String?,
+    private val type: Type,
+    private val signatureParser: BinaryClassSignatureParser,
+    private val context: ClassifierResolutionContext
 ) : PlainJavaAnnotationArgument(name), JavaClassObjectAnnotationArgument {
     override fun getReferencedType() = signatureParser.mapAsmType(type, context)
 }
 
 class PlainJavaArrayAnnotationArgument(
-        name: String?,
-        private val elements: List<JavaAnnotationArgument>
+    name: String?,
+    private val elements: List<JavaAnnotationArgument>
 ) : PlainJavaAnnotationArgument(name), JavaArrayAnnotationArgument {
     override fun getElements(): List<JavaAnnotationArgument> = elements
 }
 
 class PlainJavaAnnotationAsAnnotationArgument(
-        name: String?,
-        private val annotation: JavaAnnotation
+    name: String?,
+    private val annotation: JavaAnnotation
 ) : PlainJavaAnnotationArgument(name), JavaAnnotationAsAnnotationArgument {
     override fun getAnnotation() = annotation
 }
 
 class PlainJavaEnumValueAnnotationArgument(
-        name: String?,
-        override val enumClassId: ClassId,
-        entryName: String
+    name: String?,
+    override val enumClassId: ClassId,
+    entryName: String
 ) : PlainJavaAnnotationArgument(name), JavaEnumValueAnnotationArgument {
     override val entryName = Name.identifier(entryName)
 }
diff --git a/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/classFiles/BinaryJavaClass.kt b/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/classFiles/BinaryJavaClass.kt
index 243a4b4..c1b2c26 100644
--- a/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/classFiles/BinaryJavaClass.kt
+++ b/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/classFiles/BinaryJavaClass.kt
@@ -67,6 +67,49 @@
 
     override fun isFromSourceCodeInScope(scope: SearchScope): Boolean = false
 
+    override fun visitTypeAnnotation(typeRef: Int, typePath: TypePath?, descriptor: String?, visible: Boolean): AnnotationVisitor? {
+        val typeReference = TypeReference(typeRef)
+        if (descriptor == null)
+            return null
+
+        return when (typeReference.sort) {
+            TypeReference.CLASS_TYPE_PARAMETER -> {
+                BinaryJavaAnnotation.addTypeAnnotation(
+                    typeParameters[typeReference.typeParameterIndex],
+                    descriptor, context, signatureParser
+                )
+            }
+            TypeReference.CLASS_TYPE_PARAMETER_BOUND -> {
+                val isThereImplicitObjectUpperBound =
+                    typeParameters[typeReference.typeParameterIndex].upperBounds.none { it.classifierQualifiedName == "java.lang.Object" } &&
+                            typeParameters[typeReference.typeParameterIndex].upperBounds.none {
+                                (it.classifier as? BinaryJavaClass)?.constructors?.size != 0
+                            }
+                val typeParameterBoundIndex =
+                    if (isThereImplicitObjectUpperBound) typeReference.typeParameterBoundIndex - 1 else typeReference.typeParameterBoundIndex
+                val bound = typeParameters[typeReference.typeParameterIndex].upperBounds.toList()[typeParameterBoundIndex]
+
+                if (typePath == null) {
+                    BinaryJavaAnnotation.addTypeAnnotation(bound, descriptor, context, signatureParser)
+                } else {
+                    val translatedPath = BinaryJavaAnnotation.translatePath(typePath)
+                    var baseType = bound
+
+                    for (element in translatedPath) {
+                        when (element.first) {
+                            AnnotationsAndParameterCollectorMethodVisitor.PathElementType.TYPE_ARGUMENT -> {
+                                baseType = (baseType.typeArguments[element.second!!] as JavaClassifierType?)!!
+                            }
+                        }
+                    }
+
+                    return BinaryJavaAnnotation.addTypeAnnotation(baseType, descriptor, context, signatureParser)
+                }
+            }
+            else -> null
+        }
+    }
+
     override fun visitEnd() {
         methods.trimToSize()
         fields.trimToSize()
diff --git a/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/classFiles/Other.kt b/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/classFiles/Other.kt
index 72fc2c3..0adcbce 100644
--- a/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/classFiles/Other.kt
+++ b/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/classFiles/Other.kt
@@ -42,9 +42,18 @@
         override val name: Name,
         override val upperBounds: Collection<JavaClassifierType>
 ) : JavaTypeParameter {
-    // TODO: support annotations on type parameters
-    override val annotations get() = emptyList<JavaAnnotation>()
-    override fun findAnnotation(fqName: FqName) = null
+    override val annotations get() = _annotations
+    override fun findAnnotation(fqName: FqName) = annotations.find { it.classId?.asSingleFqName() == fqName }
+
+    private var _annotations = emptyList<JavaAnnotation>()
+
+    internal fun addAnnotation(annotation: JavaAnnotation) {
+        if (_annotations.isEmpty()) {
+            _annotations = SmartList()
+        }
+
+        (_annotations as MutableList).add(annotation)
+    }
 
     override val isDeprecatedInJavaDoc get() = false
 }
diff --git a/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/classFiles/Types.kt b/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/classFiles/Types.kt
index 9c17f03..3d2522c 100644
--- a/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/classFiles/Types.kt
+++ b/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/classFiles/Types.kt
@@ -24,14 +24,29 @@
 
 // They are only used for java class files, but potentially may be used in other cases
 // It would be better to call them like JavaSomeTypeImpl, but these names are already occupied by the PSI based types
-internal class PlainJavaArrayType(override val componentType: JavaType) : JavaArrayType
+internal class PlainJavaArrayType(override val componentType: JavaType) : JavaArrayType {
+    private var _annotations = emptyList<JavaAnnotation>()
+    override val annotations get() = _annotations
+
+    override fun findAnnotation(fqName: FqName) = annotations.find { it.classId?.asSingleFqName() == fqName }
+    override val isDeprecatedInJavaDoc = false
+
+    internal fun addAnnotation(annotation: JavaAnnotation) {
+        if (_annotations.isEmpty()) {
+            _annotations = SmartList()
+        }
+
+        (_annotations as MutableList).add(annotation)
+    }
+}
+
 internal class PlainJavaWildcardType(override val bound: JavaType?, override val isExtends: Boolean) : JavaWildcardType
 internal class PlainJavaPrimitiveType(override val type: PrimitiveType?) : JavaPrimitiveType
 
 internal class PlainJavaClassifierType(
-        // calculation of classifier and canonicalText
-        classifierComputation: () -> ClassifierResolutionContext.Result,
-        override val typeArguments: List<JavaType>
+    // calculation of classifier and canonicalText
+    classifierComputation: () -> ClassifierResolutionContext.Result,
+    override val typeArguments: List<JavaType>
 ) : JavaClassifierType {
     private val classifierResolverResult by lazy(LazyThreadSafetyMode.NONE, classifierComputation)
 
diff --git a/compiler/testData/loadJava/compiledJava/ArrayTypeVariance.java b/compiler/testData/loadJava/compiledJava/ArrayTypeVariance.java
index 512559a..695c5b8 100644
--- a/compiler/testData/loadJava/compiledJava/ArrayTypeVariance.java
+++ b/compiler/testData/loadJava/compiledJava/ArrayTypeVariance.java
@@ -1,7 +1,16 @@
 package test;
 
+import java.lang.annotation.*;
+
 public final class ArrayTypeVariance {
-    public final Object[] toArray(Object[] p0) {
+    @Documented
+    @Retention(RetentionPolicy.CLASS)
+    @Target(ElementType.TYPE_USE)
+    public @interface NotNull {}
+
+    class Foo<T> {}
+
+    public final Object[] toArray(Foo<@NotNull Integer> p0) {
         throw new UnsupportedOperationException();
     }
 }
diff --git a/compiler/testData/loadJava/compiledJava/ArrayTypeVariance.txt b/compiler/testData/loadJava/compiledJava/ArrayTypeVariance.txt
index f4f7754..21f75e9 100644
--- a/compiler/testData/loadJava/compiledJava/ArrayTypeVariance.txt
+++ b/compiler/testData/loadJava/compiledJava/ArrayTypeVariance.txt
@@ -2,5 +2,13 @@
 
 public final class ArrayTypeVariance {
     public constructor ArrayTypeVariance()
-    public final fun toArray(/*0*/ p0: kotlin.Array<(out) kotlin.Any!>!): kotlin.Array<(out) kotlin.Any!>!
+    public final fun toArray(/*0*/ p0: test.ArrayTypeVariance.Foo<@test.ArrayTypeVariance.NotNull kotlin.Int!>!): kotlin.Array<(out) kotlin.Any!>!
+
+    public/*package*/ open inner class Foo</*0*/ T : kotlin.Any!> {
+        public/*package*/ constructor Foo</*0*/ T : kotlin.Any!>()
+    }
+
+    @kotlin.annotation.MustBeDocumented @kotlin.annotation.Retention(value = AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE}) public final annotation class NotNull : kotlin.Annotation {
+        public constructor NotNull()
+    }
 }
diff --git a/compiler/testData/loadJava/compiledJava/annotations/AnnotatedParameterInInnerClassConstructor.java b/compiler/testData/loadJava/compiledJava/annotations/AnnotatedParameterInInnerClassConstructor.java
index 226906b..569715f 100644
--- a/compiler/testData/loadJava/compiledJava/annotations/AnnotatedParameterInInnerClassConstructor.java
+++ b/compiler/testData/loadJava/compiledJava/annotations/AnnotatedParameterInInnerClassConstructor.java
@@ -1,16 +1,18 @@
+// SKIP_IN_FIR_TEST
+// SKIP_IN_RUNTIME_TEST
 package test;
 
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
 class AnnotatedParameterInInnerClassConstructor {
 
+    @Target(ElementType.TYPE_USE)
     public @interface Anno {
-        String value();
     }
 
-    class Inner {
-        Inner(@Anno("a") String a , @Anno("b")  String b) {}
+    class InnerGeneric<T, K> {
     }
 
-    class InnerGeneric<T> {
-        InnerGeneric(@Anno("a") String a , @Anno("b")  String b) {}
-    }
+    Integer foo(InnerGeneric<@Anno String, InnerGeneric<String, @Anno InnerGeneric<@Anno String, String>>> a) { return 11; }
 }
\ No newline at end of file
diff --git a/compiler/testData/loadJava/compiledJava/annotations/AnnotatedParameterInInnerClassConstructor.txt b/compiler/testData/loadJava/compiledJava/annotations/AnnotatedParameterInInnerClassConstructor.txt
index 87fbeac..f3b9210 100644
--- a/compiler/testData/loadJava/compiledJava/annotations/AnnotatedParameterInInnerClassConstructor.txt
+++ b/compiler/testData/loadJava/compiledJava/annotations/AnnotatedParameterInInnerClassConstructor.txt
@@ -2,17 +2,13 @@
 
 public/*package*/ open class AnnotatedParameterInInnerClassConstructor {
     public/*package*/ constructor AnnotatedParameterInInnerClassConstructor()
+    public/*package*/ open fun foo(/*0*/ p0: test.AnnotatedParameterInInnerClassConstructor.InnerGeneric<@test.AnnotatedParameterInInnerClassConstructor.Anno kotlin.String!, test.AnnotatedParameterInInnerClassConstructor.InnerGeneric<kotlin.String!, @test.AnnotatedParameterInInnerClassConstructor.Anno test.AnnotatedParameterInInnerClassConstructor.InnerGeneric<@test.AnnotatedParameterInInnerClassConstructor.Anno kotlin.String!, kotlin.String!>!>!>!): kotlin.Int!
 
-    public final annotation class Anno : kotlin.Annotation {
-        public constructor Anno(/*0*/ value: kotlin.String)
-        public final val value: kotlin.String
+    @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE}) public final annotation class Anno : kotlin.Annotation {
+        public constructor Anno()
     }
 
-    public/*package*/ open inner class Inner {
-        public/*package*/ constructor Inner(/*0*/ @test.AnnotatedParameterInInnerClassConstructor.Anno(value = "a") p0: kotlin.String!, /*1*/ @test.AnnotatedParameterInInnerClassConstructor.Anno(value = "b") p1: kotlin.String!)
-    }
-
-    public/*package*/ open inner class InnerGeneric</*0*/ T : kotlin.Any!> {
-        public/*package*/ constructor InnerGeneric</*0*/ T : kotlin.Any!>(/*0*/ @test.AnnotatedParameterInInnerClassConstructor.Anno(value = "a") p0: kotlin.String!, /*1*/ @test.AnnotatedParameterInInnerClassConstructor.Anno(value = "b") p1: kotlin.String!)
+    public/*package*/ open inner class InnerGeneric</*0*/ T : kotlin.Any!, /*1*/ K : kotlin.Any!> {
+        public/*package*/ constructor InnerGeneric</*0*/ T : kotlin.Any!, /*1*/ K : kotlin.Any!>()
     }
 }
diff --git a/compiler/testData/loadJava/compiledJava/annotations/AnnotatedTypeInInnerClassConstructor.java b/compiler/testData/loadJava/compiledJava/annotations/AnnotatedTypeInInnerClassConstructor.java
index a26065f..9e1f783b 100644
--- a/compiler/testData/loadJava/compiledJava/annotations/AnnotatedTypeInInnerClassConstructor.java
+++ b/compiler/testData/loadJava/compiledJava/annotations/AnnotatedTypeInInnerClassConstructor.java
@@ -9,14 +9,10 @@
 
     @Target(ElementType.TYPE_USE)
     public @interface Anno {
-        String value();
-    }
-
-    class Inner {
-        Inner(@Anno("a") String a , @Anno("b")  String b) {}
     }
 
     class InnerGeneric<T> {
-        InnerGeneric(@Anno("a") String a , @Anno("b")  String b) {}
     }
+
+    @Anno Integer foo(@Anno InnerGeneric<@Anno String> a) { return 11; }
 }
\ No newline at end of file
diff --git a/compiler/testData/loadJava/compiledJava/annotations/AnnotatedTypeInInnerClassConstructor.txt b/compiler/testData/loadJava/compiledJava/annotations/AnnotatedTypeInInnerClassConstructor.txt
index d55b0ca..88b9e8c 100644
--- a/compiler/testData/loadJava/compiledJava/annotations/AnnotatedTypeInInnerClassConstructor.txt
+++ b/compiler/testData/loadJava/compiledJava/annotations/AnnotatedTypeInInnerClassConstructor.txt
@@ -2,17 +2,13 @@
 
 public/*package*/ open class AnnotatedParameterInInnerClassConstructor {
     public/*package*/ constructor AnnotatedParameterInInnerClassConstructor()
+    public/*package*/ open fun foo(/*0*/ p0: @test.AnnotatedParameterInInnerClassConstructor.Anno test.AnnotatedParameterInInnerClassConstructor.InnerGeneric<@test.AnnotatedParameterInInnerClassConstructor.Anno kotlin.String!>!): @test.AnnotatedParameterInInnerClassConstructor.Anno kotlin.Int!
 
     @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE}) public final annotation class Anno : kotlin.Annotation {
-        public constructor Anno(/*0*/ value: kotlin.String)
-        public final val value: kotlin.String
-    }
-
-    public/*package*/ open inner class Inner {
-        public/*package*/ constructor Inner(/*0*/ p0: @test.AnnotatedParameterInInnerClassConstructor.Anno(value = "a") kotlin.String!, /*1*/ p1: @test.AnnotatedParameterInInnerClassConstructor.Anno(value = "b") kotlin.String!)
+        public constructor Anno()
     }
 
     public/*package*/ open inner class InnerGeneric</*0*/ T : kotlin.Any!> {
-        public/*package*/ constructor InnerGeneric</*0*/ T : kotlin.Any!>(/*0*/ p0: @test.AnnotatedParameterInInnerClassConstructor.Anno(value = "a") kotlin.String!, /*1*/ p1: @test.AnnotatedParameterInInnerClassConstructor.Anno(value = "b") kotlin.String!)
+        public/*package*/ constructor InnerGeneric</*0*/ T : kotlin.Any!>()
     }
 }
diff --git a/compiler/testData/loadJava8/compiledJava/TypeAnnotations.java b/compiler/testData/loadJava8/compiledJava/TypeAnnotations.java
deleted file mode 100644
index c62ead6..0000000
--- a/compiler/testData/loadJava8/compiledJava/TypeAnnotations.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package test;
-
-import java.lang.annotation.*;
-public class TypeAnnotations {
-    @Target(ElementType.TYPE_USE)
-    @interface A {
-        String value() default "";
-    }
-
-    interface G<T> {
-    }
-
-    interface G2<A, B> {
-    }
-
-    // Currently annotations on type parameters and arguments are not loaded from compiled code because of IDEA-153093
-    // Once it will be fixed check if KT-11454 is ready to be resolved
-    public interface MyClass<TT> {
-        void f(G<@A String> p);
-
-        void f(G2<@A String, @A("abc") Integer> p);
-    }
-}
diff --git a/compiler/testData/loadJava8/compiledJava/TypeParameterAnnotations.java b/compiler/testData/loadJava8/compiledJava/TypeParameterAnnotations.java
deleted file mode 100644
index 55dbc0b..0000000
--- a/compiler/testData/loadJava8/compiledJava/TypeParameterAnnotations.java
+++ /dev/null
@@ -1,16 +0,0 @@
-// JAVAC_EXPECTED_FILE
-package test;
-
-import java.lang.annotation.*;
-public class TypeParameterAnnotations {
-    @Target(ElementType.TYPE_PARAMETER)
-    public @interface A {
-        String value() default "";
-    }
-
-    // Currently annotations on type parameters and arguments are not loaded from compiled code because of IDEA-153093
-    // Once it will be fixed check if KT-11454 is ready to be resolved
-    public interface G<@A T> {
-        <@A("abc") R> void foo(R r);
-    }
-}
diff --git a/compiler/testData/loadJava8/compiledJava/TypeParameterAnnotations.javac.txt b/compiler/testData/loadJava8/compiledJava/TypeParameterAnnotations.javac.txt
deleted file mode 100644
index e78e875..0000000
--- a/compiler/testData/loadJava8/compiledJava/TypeParameterAnnotations.javac.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-package test
-
-public open class TypeParameterAnnotations {
-    public constructor TypeParameterAnnotations()
-
-    @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE_PARAMETER}) public final annotation class A : kotlin.Annotation {
-        public constructor A(/*0*/ value: kotlin.String = ...)
-        public final val value: kotlin.String
-    }
-
-    public interface G</*0*/ @test.TypeParameterAnnotations.A T : kotlin.Any!> {
-        public abstract fun </*0*/ @test.TypeParameterAnnotations.A(value = "abc") R : kotlin.Any!> foo(/*0*/ p0: R!): kotlin.Unit
-    }
-}
diff --git a/compiler/testData/loadJava8/compiledJava/TypeParameterAnnotations.runtime.txt b/compiler/testData/loadJava8/compiledJava/TypeParameterAnnotations.runtime.txt
deleted file mode 100644
index 98273e8..0000000
--- a/compiler/testData/loadJava8/compiledJava/TypeParameterAnnotations.runtime.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-package test
-
-public open class TypeParameterAnnotations {
-    public constructor TypeParameterAnnotations()
-
-    @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE_PARAMETER}) @kotlin.annotation.Retention(value = ...) public final annotation class A : kotlin.Annotation {
-        public final val value: kotlin.String
-            public final fun <get-value>(): kotlin.String
-    }
-
-    public interface G</*0*/ @test.TypeParameterAnnotations.A(value = "") T : kotlin.Any!> {
-        public abstract fun </*0*/ @test.TypeParameterAnnotations.A(value = "abc") R : kotlin.Any!> foo(/*0*/ R!): kotlin.Unit
-    }
-}
diff --git a/compiler/testData/loadJava8/compiledJava/TypeParameterAnnotations.txt b/compiler/testData/loadJava8/compiledJava/TypeParameterAnnotations.txt
deleted file mode 100644
index 1be3aa4..0000000
--- a/compiler/testData/loadJava8/compiledJava/TypeParameterAnnotations.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-package test
-
-public open class TypeParameterAnnotations {
-    public constructor TypeParameterAnnotations()
-
-    @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE_PARAMETER}) public final annotation class A : kotlin.Annotation {
-        public constructor A(/*0*/ value: kotlin.String = ...)
-        public final val value: kotlin.String
-    }
-
-    public interface G</*0*/ T : kotlin.Any!> {
-        public abstract fun </*0*/ R : kotlin.Any!> foo(/*0*/ p0: R!): kotlin.Unit
-    }
-}
diff --git a/compiler/testData/loadJava8/compiledJava/typeParameterAnnotations/Basic.java b/compiler/testData/loadJava8/compiledJava/typeParameterAnnotations/Basic.java
new file mode 100644
index 0000000..3cee927c2
--- /dev/null
+++ b/compiler/testData/loadJava8/compiledJava/typeParameterAnnotations/Basic.java
@@ -0,0 +1,14 @@
+// JAVAC_EXPECTED_FILE
+package test;
+
+import java.lang.annotation.*;
+public class Basic {
+    @Target(ElementType.TYPE_PARAMETER)
+    public @interface A {
+        String value() default "";
+    }
+
+    public interface G<@A T> {
+        <@A("abc") R> void foo(R r);
+    }
+}
diff --git a/compiler/testData/loadJava8/compiledJava/typeParameterAnnotations/Basic.javac.txt b/compiler/testData/loadJava8/compiledJava/typeParameterAnnotations/Basic.javac.txt
new file mode 100644
index 0000000..900f301
--- /dev/null
+++ b/compiler/testData/loadJava8/compiledJava/typeParameterAnnotations/Basic.javac.txt
@@ -0,0 +1,14 @@
+package test
+
+public open class Basic {
+    public constructor Basic()
+
+    @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE_PARAMETER}) public final annotation class A : kotlin.Annotation {
+        public constructor A(/*0*/ value: kotlin.String = ...)
+        public final val value: kotlin.String
+    }
+
+    public interface G</*0*/ @test.Basic.A T : kotlin.Any!> {
+        public abstract fun </*0*/ @test.Basic.A(value = "abc") R : kotlin.Any!> foo(/*0*/ p0: R!): kotlin.Unit
+    }
+}
diff --git a/compiler/testData/loadJava8/compiledJava/typeParameterAnnotations/Basic.runtime.txt b/compiler/testData/loadJava8/compiledJava/typeParameterAnnotations/Basic.runtime.txt
new file mode 100644
index 0000000..2a256fb
--- /dev/null
+++ b/compiler/testData/loadJava8/compiledJava/typeParameterAnnotations/Basic.runtime.txt
@@ -0,0 +1,14 @@
+package test
+
+public open class Basic {
+    public constructor Basic()
+
+    @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE_PARAMETER}) @kotlin.annotation.Retention(value = ...) public final annotation class A : kotlin.Annotation {
+        public final val value: kotlin.String
+            public final fun <get-value>(): kotlin.String
+    }
+
+    public interface G</*0*/ @test.Basic.A(value = "") T : kotlin.Any!> {
+        public abstract fun </*0*/ @test.Basic.A(value = "abc") R : kotlin.Any!> foo(/*0*/ R!): kotlin.Unit
+    }
+}
diff --git a/compiler/testData/loadJava8/compiledJava/typeParameterAnnotations/Basic.txt b/compiler/testData/loadJava8/compiledJava/typeParameterAnnotations/Basic.txt
new file mode 100644
index 0000000..900f301
--- /dev/null
+++ b/compiler/testData/loadJava8/compiledJava/typeParameterAnnotations/Basic.txt
@@ -0,0 +1,14 @@
+package test
+
+public open class Basic {
+    public constructor Basic()
+
+    @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE_PARAMETER}) public final annotation class A : kotlin.Annotation {
+        public constructor A(/*0*/ value: kotlin.String = ...)
+        public final val value: kotlin.String
+    }
+
+    public interface G</*0*/ @test.Basic.A T : kotlin.Any!> {
+        public abstract fun </*0*/ @test.Basic.A(value = "abc") R : kotlin.Any!> foo(/*0*/ p0: R!): kotlin.Unit
+    }
+}
diff --git a/compiler/testData/loadJava8/sourceJava/TypeAnnotations.java b/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/Basic.java
similarity index 90%
rename from compiler/testData/loadJava8/sourceJava/TypeAnnotations.java
rename to compiler/testData/loadJava8/compiledJava/typeUseAnnotations/Basic.java
index cffa9f4..e2309da 100644
--- a/compiler/testData/loadJava8/sourceJava/TypeAnnotations.java
+++ b/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/Basic.java
@@ -1,7 +1,7 @@
 package test;
 
 import java.lang.annotation.*;
-public class TypeAnnotations {
+public class Basic {
     @Target(ElementType.TYPE_USE)
     @interface A {
         String value() default "";
diff --git a/compiler/testData/loadJava8/compiledJava/TypeAnnotations.txt b/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/Basic.txt
similarity index 62%
copy from compiler/testData/loadJava8/compiledJava/TypeAnnotations.txt
copy to compiler/testData/loadJava8/compiledJava/typeUseAnnotations/Basic.txt
index 9fa9870..b5181c5 100644
--- a/compiler/testData/loadJava8/compiledJava/TypeAnnotations.txt
+++ b/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/Basic.txt
@@ -1,7 +1,7 @@
 package test
 
-public open class TypeAnnotations {
-    public constructor TypeAnnotations()
+public open class Basic {
+    public constructor Basic()
 
     @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE}) public/*package*/ final annotation class A : kotlin.Annotation {
         public/*package*/ constructor A(/*0*/ value: kotlin.String = ...)
@@ -15,7 +15,7 @@
     }
 
     public interface MyClass</*0*/ TT : kotlin.Any!> {
-        public abstract fun f(/*0*/ p0: test.TypeAnnotations.G2<kotlin.String!, kotlin.Int!>!): kotlin.Unit
-        public abstract fun f(/*0*/ p0: test.TypeAnnotations.G<kotlin.String!>!): kotlin.Unit
+        public abstract fun f(/*0*/ p0: test.Basic.G2<@test.Basic.A kotlin.String!, @test.Basic.A(value = "abc") kotlin.Int!>!): kotlin.Unit
+        public abstract fun f(/*0*/ p0: test.Basic.G<@test.Basic.A kotlin.String!>!): kotlin.Unit
     }
 }
diff --git a/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/ClassTypeParameterUpperBounds.java b/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/ClassTypeParameterUpperBounds.java
new file mode 100644
index 0000000..815198b
--- /dev/null
+++ b/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/ClassTypeParameterUpperBounds.java
@@ -0,0 +1,26 @@
+// JAVAC_EXPECTED_FILE
+
+package test;
+
+import java.lang.annotation.*;
+
+public class ClassTypeParameterUpperBounds {
+    @Target(ElementType.TYPE_USE)
+    @interface Anno {
+        String value() default "";
+    }
+
+    interface I1 {}
+    interface I2<T> {}
+    interface I3<T> {}
+
+    interface G1<T extends @Anno Object> { }
+    class G2<A, B extends @Anno Integer> { }
+    interface G3<A, B extends Object & @Anno I1> { }
+    class G4<A extends @Anno B, B> { }
+    interface G5<A, B extends @Anno A> { }
+    class G6<A extends @Anno I1, B, C, D extends @Anno E, E, F> { }
+    interface G7<A extends Object & I2<@Anno Integer> & @Anno I3<String>> { }
+    //class G8<A extends Object, B extends I3<@Anno A> & @Anno I2<A>> { }
+    // TODO: class My extends Foo<@Nullable String> {}
+}
diff --git a/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/ClassTypeParameterUpperBounds.txt b/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/ClassTypeParameterUpperBounds.txt
new file mode 100644
index 0000000..da2335a
--- /dev/null
+++ b/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/ClassTypeParameterUpperBounds.txt
@@ -0,0 +1,43 @@
+package test
+
+public open class ClassTypeParameterUpperBounds {
+    public constructor ClassTypeParameterUpperBounds()
+
+    @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE}) public/*package*/ final annotation class Anno : kotlin.Annotation {
+        public/*package*/ constructor Anno(/*0*/ value: kotlin.String = ...)
+        public final val value: kotlin.String
+    }
+
+    public/*package*/ interface G1</*0*/ T : @test.ClassTypeParameterUpperBounds.Anno kotlin.Any!> {
+    }
+
+    public/*package*/ open inner class G2</*0*/ A : kotlin.Any!, /*1*/ B : @test.ClassTypeParameterUpperBounds.Anno kotlin.Int!> {
+        public/*package*/ constructor G2</*0*/ A : kotlin.Any!, /*1*/ B : @test.ClassTypeParameterUpperBounds.Anno kotlin.Int!>()
+    }
+
+    public/*package*/ interface G3</*0*/ A : kotlin.Any!, /*1*/ B : kotlin.Any!> where B : @test.ClassTypeParameterUpperBounds.Anno test.ClassTypeParameterUpperBounds.I1! {
+    }
+
+    public/*package*/ open inner class G4</*0*/ A : @test.ClassTypeParameterUpperBounds.Anno B!, /*1*/ B : kotlin.Any!> {
+        public/*package*/ constructor G4</*0*/ A : @test.ClassTypeParameterUpperBounds.Anno B!, /*1*/ B : kotlin.Any!>()
+    }
+
+    public/*package*/ interface G5</*0*/ A : kotlin.Any!, /*1*/ B : @test.ClassTypeParameterUpperBounds.Anno A!> {
+    }
+
+    public/*package*/ open inner class G6</*0*/ A : @test.ClassTypeParameterUpperBounds.Anno test.ClassTypeParameterUpperBounds.I1!, /*1*/ B : kotlin.Any!, /*2*/ C : kotlin.Any!, /*3*/ D : @test.ClassTypeParameterUpperBounds.Anno E!, /*4*/ E : kotlin.Any!, /*5*/ F : kotlin.Any!> {
+        public/*package*/ constructor G6</*0*/ A : @test.ClassTypeParameterUpperBounds.Anno test.ClassTypeParameterUpperBounds.I1!, /*1*/ B : kotlin.Any!, /*2*/ C : kotlin.Any!, /*3*/ D : @test.ClassTypeParameterUpperBounds.Anno E!, /*4*/ E : kotlin.Any!, /*5*/ F : kotlin.Any!>()
+    }
+
+    public/*package*/ interface G7</*0*/ A : kotlin.Any!> where A : test.ClassTypeParameterUpperBounds.I2<@test.ClassTypeParameterUpperBounds.Anno kotlin.Int!>!, A : @test.ClassTypeParameterUpperBounds.Anno test.ClassTypeParameterUpperBounds.I3<kotlin.String!>! {
+    }
+
+    public/*package*/ interface I1 {
+    }
+
+    public/*package*/ interface I2</*0*/ T : kotlin.Any!> {
+    }
+
+    public/*package*/ interface I3</*0*/ T : kotlin.Any!> {
+    }
+}
diff --git a/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/ReturnType.java b/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/ReturnType.java
new file mode 100644
index 0000000..59dab81
--- /dev/null
+++ b/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/ReturnType.java
@@ -0,0 +1,38 @@
+// JAVAC_EXPECTED_FILE
+
+package test;
+
+import java.lang.annotation.*;
+
+@Target(ElementType.TYPE_USE)
+@interface A {
+    String value() default "";
+}
+
+interface ReturnType {
+    interface G0 { }
+    interface G1<T> { }
+    interface G2<A, B> { }
+
+    //// simplpe type arguments
+    //G1<@A G0> f0();
+    //G1<G1<G1<G1<@A G0>>>> f1();
+    //G1<@A String> f2();
+    //G2<@A String, G2<@A("abc") Integer, G2<@A("abc") G2<Integer, @A Integer>, @A("abc") Integer>>> f3();
+    //
+    //// wildcards
+    //G1<? extends @A G0> f4();
+    //G1<G1<G1<G1<? extends @A G0>>>> f5();
+    //G1<? extends @A String> f6();
+    //G2<? extends @A String, G2<? extends @A("abc") Integer, G2<? extends @A("abc") G2<Integer, ? extends @A Integer>, ? extends @A("abc") Integer>>> f7();
+    //
+    //G1<? super @A G0> f8();
+    //G1<G1<G1<G1<? super @A G0>>>> f9();
+    //G1<? super @A String> f10();
+    //G2<? super @A String, G2<? super @A("abc") Integer, G2<? super @A("abc") G2<Integer, ? super @A Integer>, ? super @A("abc") Integer>>> f11();
+    //
+    //G2<? super @A String, G2<? extends @A("abc") Integer, G2<? extends @A("abc") G2<Integer, ? super @A Integer>, ? extends @A("abc") Integer>>> f12();
+
+    //G1<int @A []> f13();
+    void f20(@A String ... x);
+}
diff --git a/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/ReturnType.txt b/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/ReturnType.txt
new file mode 100644
index 0000000..f595f6a
--- /dev/null
+++ b/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/ReturnType.txt
@@ -0,0 +1,31 @@
+package test
+
+@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE}) public/*package*/ final annotation class A : kotlin.Annotation {
+    public/*package*/ constructor A(/*0*/ value: kotlin.String = ...)
+    public final val value: kotlin.String
+}
+
+public/*package*/ interface ReturnType {
+    public abstract fun f0(): test.ReturnType.G1<@test.A test.ReturnType.G0!>!
+    public abstract fun f1(): test.ReturnType.G1<test.ReturnType.G1<test.ReturnType.G1<test.ReturnType.G1<@test.A test.ReturnType.G0!>!>!>!>!
+    public abstract fun f10(): test.ReturnType.G1<in @test.A kotlin.String!>!
+    public abstract fun f11(): test.ReturnType.G2<in @test.A kotlin.String!, test.ReturnType.G2<in @test.A kotlin.Int!, test.ReturnType.G2<in @test.A test.ReturnType.G2<kotlin.Int!, in @test.A kotlin.Int!>!, in @test.A kotlin.Int!>!>!>!
+    public abstract fun f12(): test.ReturnType.G2<in @test.A kotlin.String!, test.ReturnType.G2<out @test.A kotlin.Int!, test.ReturnType.G2<out @test.A test.ReturnType.G2<kotlin.Int!, in @test.A kotlin.Int!>!, out @test.A kotlin.Int!>!>!>!
+    public abstract fun f2(): test.ReturnType.G1<@test.A kotlin.String!>!
+    public abstract fun f3(): test.ReturnType.G2<@test.A kotlin.String!, test.ReturnType.G2<@test.A kotlin.Int!, test.ReturnType.G2<@test.A test.ReturnType.G2<kotlin.Int!, @test.A kotlin.Int!>!, @test.A kotlin.Int!>!>!>!
+    public abstract fun f4(): test.ReturnType.G1<out @test.A test.ReturnType.G0!>!
+    public abstract fun f5(): test.ReturnType.G1<test.ReturnType.G1<test.ReturnType.G1<test.ReturnType.G1<out @test.A test.ReturnType.G0!>!>!>!>!
+    public abstract fun f6(): test.ReturnType.G1<out @test.A kotlin.String!>!
+    public abstract fun f7(): test.ReturnType.G2<out @test.A kotlin.String!, test.ReturnType.G2<out @test.A kotlin.Int!, test.ReturnType.G2<out @test.A test.ReturnType.G2<kotlin.Int!, out @test.A kotlin.Int!>!, out @test.A kotlin.Int!>!>!>!
+    public abstract fun f8(): test.ReturnType.G1<in @test.A test.ReturnType.G0!>!
+    public abstract fun f9(): test.ReturnType.G1<test.ReturnType.G1<test.ReturnType.G1<test.ReturnType.G1<in @test.A test.ReturnType.G0!>!>!>!>!
+
+    public interface G0 {
+    }
+
+    public interface G1</*0*/ T : kotlin.Any!> {
+    }
+
+    public interface G2</*0*/ A : kotlin.Any!, /*1*/ B : kotlin.Any!> {
+    }
+}
diff --git a/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/ValueArguments.java b/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/ValueArguments.java
new file mode 100644
index 0000000..d9df2ca
--- /dev/null
+++ b/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/ValueArguments.java
@@ -0,0 +1,21 @@
+// JAVAC_EXPECTED_FILE
+
+package test;
+
+import java.lang.annotation.*;
+
+interface TypeAnnotations {
+    @Target(ElementType.TYPE_USE)
+    @interface Anno {
+        String value() default "";
+    }
+
+    interface G0 { }
+    interface G1<T> { }
+    interface G2<A, B> { }
+
+    void f0(G1<@Anno G0> p);
+    void f1(G1<G1<G1<G1<@Anno G0>>>> p);
+    void f2(G1<@Anno String> p);
+    void f3(G2<@Anno String, G2<@Anno("abc") Integer, G2<@Anno("abc") G2<Integer, @Anno Integer>, @Anno("abc") Integer>>> p);
+}
diff --git a/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/ValueArguments.txt b/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/ValueArguments.txt
new file mode 100644
index 0000000..67e0adf
--- /dev/null
+++ b/compiler/testData/loadJava8/compiledJava/typeUseAnnotations/ValueArguments.txt
@@ -0,0 +1,22 @@
+package test
+
+public/*package*/ interface TypeAnnotations {
+    public abstract fun f0(/*0*/ p0: test.TypeAnnotations.G1<@test.TypeAnnotations.Anno test.TypeAnnotations.G0!>!): kotlin.Unit
+    public abstract fun f1(/*0*/ p0: test.TypeAnnotations.G1<test.TypeAnnotations.G1<test.TypeAnnotations.G1<test.TypeAnnotations.G1<@test.TypeAnnotations.Anno test.TypeAnnotations.G0!>!>!>!>!): kotlin.Unit
+    public abstract fun f2(/*0*/ p0: test.TypeAnnotations.G1<@test.TypeAnnotations.Anno kotlin.String!>!): kotlin.Unit
+    public abstract fun f3(/*0*/ p0: test.TypeAnnotations.G2<@test.TypeAnnotations.Anno kotlin.String!, test.TypeAnnotations.G2<@test.TypeAnnotations.Anno(value = "abc") kotlin.Int!, test.TypeAnnotations.G2<@test.TypeAnnotations.Anno(value = "abc") test.TypeAnnotations.G2<kotlin.Int!, @test.TypeAnnotations.Anno kotlin.Int!>!, @test.TypeAnnotations.Anno(value = "abc") kotlin.Int!>!>!>!): kotlin.Unit
+
+    @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE}) public final annotation class Anno : kotlin.Annotation {
+        public constructor Anno(/*0*/ value: kotlin.String = ...)
+        public final val value: kotlin.String
+    }
+
+    public interface G0 {
+    }
+
+    public interface G1</*0*/ T : kotlin.Any!> {
+    }
+
+    public interface G2</*0*/ A : kotlin.Any!, /*1*/ B : kotlin.Any!> {
+    }
+}
diff --git a/compiler/testData/loadJava8/sourceJava/TypeAnnotations.txt b/compiler/testData/loadJava8/sourceJava/TypeAnnotations.txt
deleted file mode 100644
index d5160b8..0000000
--- a/compiler/testData/loadJava8/sourceJava/TypeAnnotations.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-package test
-
-public open class TypeAnnotations {
-    public constructor TypeAnnotations()
-
-    @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE}) public/*package*/ final annotation class A : kotlin.Annotation {
-        public/*package*/ constructor A(/*0*/ value: kotlin.String = ...)
-        public final val value: kotlin.String
-    }
-
-    public/*package*/ interface G</*0*/ T : kotlin.Any!> {
-    }
-
-    public/*package*/ interface G2</*0*/ A : kotlin.Any!, /*1*/ B : kotlin.Any!> {
-    }
-
-    public interface MyClass</*0*/ TT : kotlin.Any!> {
-        public abstract fun f(/*0*/ p: test.TypeAnnotations.G2<@test.TypeAnnotations.A kotlin.String!, @test.TypeAnnotations.A(value = "abc") kotlin.Int!>!): kotlin.Unit
-        public abstract fun f(/*0*/ p: test.TypeAnnotations.G<@test.TypeAnnotations.A kotlin.String!>!): kotlin.Unit
-    }
-}
diff --git a/compiler/testData/loadJava8/sourceJava/typeParameterAnnotations/Basic.java b/compiler/testData/loadJava8/sourceJava/typeParameterAnnotations/Basic.java
new file mode 100644
index 0000000..c5bf43a
--- /dev/null
+++ b/compiler/testData/loadJava8/sourceJava/typeParameterAnnotations/Basic.java
@@ -0,0 +1,35 @@
+// JAVAC_EXPECTED_FILE
+
+package test;
+
+import java.lang.annotation.*;
+
+@Target(ElementType.TYPE_USE)
+@interface A {
+    String value() default "";
+}
+
+interface Basic {
+    interface G0 { }
+    interface G1<T> { }
+    interface G2<A, B> { }
+
+    // simplpe type arguments
+    G1<@A G0> f0();
+    G1<G1<G1<G1<@A G0>>>> f1();
+    G1<@A String> f2();
+    G2<@A String, G2<@A("abc") Integer, G2<@A("abc") G2<Integer, @A Integer>, @A("abc") Integer>>> f3();
+
+    // wildcards
+    G1<? extends @A G0> f4();
+    G1<G1<G1<G1<? extends @A G0>>>> f5();
+    G1<? extends @A String> f6();
+    G2<? extends @A String, G2<? extends @A("abc") Integer, G2<? extends @A("abc") G2<Integer, ? extends @A Integer>, ? extends @A("abc") Integer>>> f7();
+
+    G1<? super @A G0> f8();
+    G1<G1<G1<G1<? super @A G0>>>> f9();
+    G1<? super @A String> f10();
+    G2<? super @A String, G2<? super @A("abc") Integer, G2<? super @A("abc") G2<Integer, ? super @A Integer>, ? super @A("abc") Integer>>> f11();
+
+    G2<? super @A String, G2<? extends @A("abc") Integer, G2<? extends @A("abc") G2<Integer, ? super @A Integer>, ? extends @A("abc") Integer>>> f12();
+}
diff --git a/compiler/testData/loadJava8/sourceJava/typeParameterAnnotations/Basic.javac.txt b/compiler/testData/loadJava8/sourceJava/typeParameterAnnotations/Basic.javac.txt
new file mode 100644
index 0000000..a988765
--- /dev/null
+++ b/compiler/testData/loadJava8/sourceJava/typeParameterAnnotations/Basic.javac.txt
@@ -0,0 +1,14 @@
+package test
+
+public open class Basic {
+    public constructor Basic()
+
+    @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE_PARAMETER}) public final annotation class A : kotlin.Annotation {
+        public constructor A(/*0*/ value: kotlin.String = ...)
+        public final val value: kotlin.String
+    }
+
+    public interface G</*0*/ @test.Basic.A T : kotlin.Any!> {
+        public abstract fun </*0*/ @test.Basic.A(value = "abc") R : kotlin.Any!> foo(/*0*/ r: R!): kotlin.Unit
+    }
+}
diff --git a/compiler/testData/loadJava8/sourceJava/typeParameterAnnotations/Basic.runtime.txt b/compiler/testData/loadJava8/sourceJava/typeParameterAnnotations/Basic.runtime.txt
new file mode 100644
index 0000000..2a256fb
--- /dev/null
+++ b/compiler/testData/loadJava8/sourceJava/typeParameterAnnotations/Basic.runtime.txt
@@ -0,0 +1,14 @@
+package test
+
+public open class Basic {
+    public constructor Basic()
+
+    @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE_PARAMETER}) @kotlin.annotation.Retention(value = ...) public final annotation class A : kotlin.Annotation {
+        public final val value: kotlin.String
+            public final fun <get-value>(): kotlin.String
+    }
+
+    public interface G</*0*/ @test.Basic.A(value = "") T : kotlin.Any!> {
+        public abstract fun </*0*/ @test.Basic.A(value = "abc") R : kotlin.Any!> foo(/*0*/ R!): kotlin.Unit
+    }
+}
diff --git a/compiler/testData/loadJava8/sourceJava/typeParameterAnnotations/Basic.txt b/compiler/testData/loadJava8/sourceJava/typeParameterAnnotations/Basic.txt
new file mode 100644
index 0000000..d615eb2
--- /dev/null
+++ b/compiler/testData/loadJava8/sourceJava/typeParameterAnnotations/Basic.txt
@@ -0,0 +1,14 @@
+package test
+
+public/*package*/ interface Basic {
+    public abstract fun f8(): test.Basic.G1<in test.Basic.G0!>!
+
+    public interface G0 {
+    }
+
+    public interface G1</*0*/ T : kotlin.Any!> {
+    }
+
+    public interface G2</*0*/ A : kotlin.Any!, /*1*/ B : kotlin.Any!> {
+    }
+}
diff --git a/compiler/testData/loadJava8/sourceJava/TypeAnnotations.java b/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/Basic.java
similarity index 90%
copy from compiler/testData/loadJava8/sourceJava/TypeAnnotations.java
copy to compiler/testData/loadJava8/sourceJava/typeUseAnnotations/Basic.java
index cffa9f4..e2309da 100644
--- a/compiler/testData/loadJava8/sourceJava/TypeAnnotations.java
+++ b/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/Basic.java
@@ -1,7 +1,7 @@
 package test;
 
 import java.lang.annotation.*;
-public class TypeAnnotations {
+public class Basic {
     @Target(ElementType.TYPE_USE)
     @interface A {
         String value() default "";
diff --git a/compiler/testData/loadJava8/compiledJava/TypeAnnotations.txt b/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/Basic.txt
similarity index 62%
rename from compiler/testData/loadJava8/compiledJava/TypeAnnotations.txt
rename to compiler/testData/loadJava8/sourceJava/typeUseAnnotations/Basic.txt
index 9fa9870..ce0f47c 100644
--- a/compiler/testData/loadJava8/compiledJava/TypeAnnotations.txt
+++ b/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/Basic.txt
@@ -1,7 +1,7 @@
 package test
 
-public open class TypeAnnotations {
-    public constructor TypeAnnotations()
+public open class Basic {
+    public constructor Basic()
 
     @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE}) public/*package*/ final annotation class A : kotlin.Annotation {
         public/*package*/ constructor A(/*0*/ value: kotlin.String = ...)
@@ -15,7 +15,7 @@
     }
 
     public interface MyClass</*0*/ TT : kotlin.Any!> {
-        public abstract fun f(/*0*/ p0: test.TypeAnnotations.G2<kotlin.String!, kotlin.Int!>!): kotlin.Unit
-        public abstract fun f(/*0*/ p0: test.TypeAnnotations.G<kotlin.String!>!): kotlin.Unit
+        public abstract fun f(/*0*/ p: test.Basic.G2<@test.Basic.A kotlin.String!, @test.Basic.A(value = "abc") kotlin.Int!>!): kotlin.Unit
+        public abstract fun f(/*0*/ p: test.Basic.G<@test.Basic.A kotlin.String!>!): kotlin.Unit
     }
 }
diff --git a/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/ClassTypeParameterUpperBounds.java b/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/ClassTypeParameterUpperBounds.java
new file mode 100644
index 0000000..815198b
--- /dev/null
+++ b/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/ClassTypeParameterUpperBounds.java
@@ -0,0 +1,26 @@
+// JAVAC_EXPECTED_FILE
+
+package test;
+
+import java.lang.annotation.*;
+
+public class ClassTypeParameterUpperBounds {
+    @Target(ElementType.TYPE_USE)
+    @interface Anno {
+        String value() default "";
+    }
+
+    interface I1 {}
+    interface I2<T> {}
+    interface I3<T> {}
+
+    interface G1<T extends @Anno Object> { }
+    class G2<A, B extends @Anno Integer> { }
+    interface G3<A, B extends Object & @Anno I1> { }
+    class G4<A extends @Anno B, B> { }
+    interface G5<A, B extends @Anno A> { }
+    class G6<A extends @Anno I1, B, C, D extends @Anno E, E, F> { }
+    interface G7<A extends Object & I2<@Anno Integer> & @Anno I3<String>> { }
+    //class G8<A extends Object, B extends I3<@Anno A> & @Anno I2<A>> { }
+    // TODO: class My extends Foo<@Nullable String> {}
+}
diff --git a/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/ClassTypeParameterUpperBounds.javac.txt b/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/ClassTypeParameterUpperBounds.javac.txt
new file mode 100644
index 0000000..da2335a
--- /dev/null
+++ b/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/ClassTypeParameterUpperBounds.javac.txt
@@ -0,0 +1,43 @@
+package test
+
+public open class ClassTypeParameterUpperBounds {
+    public constructor ClassTypeParameterUpperBounds()
+
+    @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE}) public/*package*/ final annotation class Anno : kotlin.Annotation {
+        public/*package*/ constructor Anno(/*0*/ value: kotlin.String = ...)
+        public final val value: kotlin.String
+    }
+
+    public/*package*/ interface G1</*0*/ T : @test.ClassTypeParameterUpperBounds.Anno kotlin.Any!> {
+    }
+
+    public/*package*/ open inner class G2</*0*/ A : kotlin.Any!, /*1*/ B : @test.ClassTypeParameterUpperBounds.Anno kotlin.Int!> {
+        public/*package*/ constructor G2</*0*/ A : kotlin.Any!, /*1*/ B : @test.ClassTypeParameterUpperBounds.Anno kotlin.Int!>()
+    }
+
+    public/*package*/ interface G3</*0*/ A : kotlin.Any!, /*1*/ B : kotlin.Any!> where B : @test.ClassTypeParameterUpperBounds.Anno test.ClassTypeParameterUpperBounds.I1! {
+    }
+
+    public/*package*/ open inner class G4</*0*/ A : @test.ClassTypeParameterUpperBounds.Anno B!, /*1*/ B : kotlin.Any!> {
+        public/*package*/ constructor G4</*0*/ A : @test.ClassTypeParameterUpperBounds.Anno B!, /*1*/ B : kotlin.Any!>()
+    }
+
+    public/*package*/ interface G5</*0*/ A : kotlin.Any!, /*1*/ B : @test.ClassTypeParameterUpperBounds.Anno A!> {
+    }
+
+    public/*package*/ open inner class G6</*0*/ A : @test.ClassTypeParameterUpperBounds.Anno test.ClassTypeParameterUpperBounds.I1!, /*1*/ B : kotlin.Any!, /*2*/ C : kotlin.Any!, /*3*/ D : @test.ClassTypeParameterUpperBounds.Anno E!, /*4*/ E : kotlin.Any!, /*5*/ F : kotlin.Any!> {
+        public/*package*/ constructor G6</*0*/ A : @test.ClassTypeParameterUpperBounds.Anno test.ClassTypeParameterUpperBounds.I1!, /*1*/ B : kotlin.Any!, /*2*/ C : kotlin.Any!, /*3*/ D : @test.ClassTypeParameterUpperBounds.Anno E!, /*4*/ E : kotlin.Any!, /*5*/ F : kotlin.Any!>()
+    }
+
+    public/*package*/ interface G7</*0*/ A : kotlin.Any!> where A : test.ClassTypeParameterUpperBounds.I2<@test.ClassTypeParameterUpperBounds.Anno kotlin.Int!>!, A : @test.ClassTypeParameterUpperBounds.Anno test.ClassTypeParameterUpperBounds.I3<kotlin.String!>! {
+    }
+
+    public/*package*/ interface I1 {
+    }
+
+    public/*package*/ interface I2</*0*/ T : kotlin.Any!> {
+    }
+
+    public/*package*/ interface I3</*0*/ T : kotlin.Any!> {
+    }
+}
diff --git a/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/ClassTypeParameterUpperBounds.txt b/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/ClassTypeParameterUpperBounds.txt
new file mode 100644
index 0000000..da2335a
--- /dev/null
+++ b/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/ClassTypeParameterUpperBounds.txt
@@ -0,0 +1,43 @@
+package test
+
+public open class ClassTypeParameterUpperBounds {
+    public constructor ClassTypeParameterUpperBounds()
+
+    @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE}) public/*package*/ final annotation class Anno : kotlin.Annotation {
+        public/*package*/ constructor Anno(/*0*/ value: kotlin.String = ...)
+        public final val value: kotlin.String
+    }
+
+    public/*package*/ interface G1</*0*/ T : @test.ClassTypeParameterUpperBounds.Anno kotlin.Any!> {
+    }
+
+    public/*package*/ open inner class G2</*0*/ A : kotlin.Any!, /*1*/ B : @test.ClassTypeParameterUpperBounds.Anno kotlin.Int!> {
+        public/*package*/ constructor G2</*0*/ A : kotlin.Any!, /*1*/ B : @test.ClassTypeParameterUpperBounds.Anno kotlin.Int!>()
+    }
+
+    public/*package*/ interface G3</*0*/ A : kotlin.Any!, /*1*/ B : kotlin.Any!> where B : @test.ClassTypeParameterUpperBounds.Anno test.ClassTypeParameterUpperBounds.I1! {
+    }
+
+    public/*package*/ open inner class G4</*0*/ A : @test.ClassTypeParameterUpperBounds.Anno B!, /*1*/ B : kotlin.Any!> {
+        public/*package*/ constructor G4</*0*/ A : @test.ClassTypeParameterUpperBounds.Anno B!, /*1*/ B : kotlin.Any!>()
+    }
+
+    public/*package*/ interface G5</*0*/ A : kotlin.Any!, /*1*/ B : @test.ClassTypeParameterUpperBounds.Anno A!> {
+    }
+
+    public/*package*/ open inner class G6</*0*/ A : @test.ClassTypeParameterUpperBounds.Anno test.ClassTypeParameterUpperBounds.I1!, /*1*/ B : kotlin.Any!, /*2*/ C : kotlin.Any!, /*3*/ D : @test.ClassTypeParameterUpperBounds.Anno E!, /*4*/ E : kotlin.Any!, /*5*/ F : kotlin.Any!> {
+        public/*package*/ constructor G6</*0*/ A : @test.ClassTypeParameterUpperBounds.Anno test.ClassTypeParameterUpperBounds.I1!, /*1*/ B : kotlin.Any!, /*2*/ C : kotlin.Any!, /*3*/ D : @test.ClassTypeParameterUpperBounds.Anno E!, /*4*/ E : kotlin.Any!, /*5*/ F : kotlin.Any!>()
+    }
+
+    public/*package*/ interface G7</*0*/ A : kotlin.Any!> where A : test.ClassTypeParameterUpperBounds.I2<@test.ClassTypeParameterUpperBounds.Anno kotlin.Int!>!, A : @test.ClassTypeParameterUpperBounds.Anno test.ClassTypeParameterUpperBounds.I3<kotlin.String!>! {
+    }
+
+    public/*package*/ interface I1 {
+    }
+
+    public/*package*/ interface I2</*0*/ T : kotlin.Any!> {
+    }
+
+    public/*package*/ interface I3</*0*/ T : kotlin.Any!> {
+    }
+}
diff --git a/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/ReturnType.java b/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/ReturnType.java
new file mode 100644
index 0000000..bc3acfb
--- /dev/null
+++ b/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/ReturnType.java
@@ -0,0 +1,26 @@
+// JAVAC_EXPECTED_FILE
+
+package test;
+
+import java.lang.annotation.*;
+
+interface ReturnType {
+    @Target(ElementType.TYPE_USE)
+    @interface Anno {
+        String value() default "";
+    }
+
+    interface G0 { }
+    interface G1<T> { }
+    interface G2<A, B> { }
+
+    // simplpe type arguments
+    //G1<@Anno G0> f0();
+    //G1<G1<G1<G1<@Anno G0>>>> f1();
+    //G1<@Anno String> f2();
+    //G2<@Anno String, G2<@Anno("abc") Integer, G2<@Anno("abc") G2<Integer, @Anno Integer>, @Anno("abc") Integer>>> f3();
+
+    //G1<String @Anno []> f13();
+
+    void f20(@Anno String ... x);
+}
diff --git a/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/ReturnType.javac.txt b/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/ReturnType.javac.txt
new file mode 100644
index 0000000..e662ae5
--- /dev/null
+++ b/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/ReturnType.javac.txt
@@ -0,0 +1,19 @@
+package test
+
+public/*package*/ interface TypeAnnotations {
+    public abstract fun f3(): test.TypeAnnotations.G1<out @test.TypeAnnotations.Anno kotlin.String!>!
+
+    @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE}) public final annotation class Anno : kotlin.Annotation {
+        public constructor Anno(/*0*/ value: kotlin.String = ...)
+        public final val value: kotlin.String
+    }
+
+    public interface G0 {
+    }
+
+    public interface G1</*0*/ T : kotlin.Any!> {
+    }
+
+    public interface G2</*0*/ A : kotlin.Any!, /*1*/ B : kotlin.Any!> {
+    }
+}
diff --git a/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/ReturnType.txt b/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/ReturnType.txt
new file mode 100644
index 0000000..1742848
--- /dev/null
+++ b/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/ReturnType.txt
@@ -0,0 +1,22 @@
+package test
+
+public/*package*/ interface TypeAnnotations {
+    public abstract fun f0(): test.TypeAnnotations.G1<@test.TypeAnnotations.Anno test.TypeAnnotations.G0!>!
+    public abstract fun f1(): test.TypeAnnotations.G1<test.TypeAnnotations.G1<test.TypeAnnotations.G1<test.TypeAnnotations.G1<@test.TypeAnnotations.Anno test.TypeAnnotations.G0!>!>!>!>!
+    public abstract fun f2(): test.TypeAnnotations.G1<@test.TypeAnnotations.Anno kotlin.String!>!
+    public abstract fun f3(): test.TypeAnnotations.G2<@test.TypeAnnotations.Anno kotlin.String!, test.TypeAnnotations.G2<@test.TypeAnnotations.Anno kotlin.Int!, test.TypeAnnotations.G2<@test.TypeAnnotations.Anno test.TypeAnnotations.G2<kotlin.Int!, @test.TypeAnnotations.Anno kotlin.Int!>!, @test.TypeAnnotations.Anno kotlin.Int!>!>!>!
+
+    @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE}) public final annotation class Anno : kotlin.Annotation {
+        public constructor Anno(/*0*/ value: kotlin.String = ...)
+        public final val value: kotlin.String
+    }
+
+    public interface G0 {
+    }
+
+    public interface G1</*0*/ T : kotlin.Any!> {
+    }
+
+    public interface G2</*0*/ A : kotlin.Any!, /*1*/ B : kotlin.Any!> {
+    }
+}
diff --git a/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/ValueArguments.java b/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/ValueArguments.java
new file mode 100644
index 0000000..7087069
--- /dev/null
+++ b/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/ValueArguments.java
@@ -0,0 +1,21 @@
+// JAVAC_EXPECTED_FILE
+
+package test;
+
+import java.lang.annotation.*;
+
+class ValueArguments {
+    @Target(ElementType.TYPE_USE)
+    @interface Anno {
+        String value() default "";
+    }
+
+    interface G0 { }
+    interface G1<T> { }
+    interface G2<A, B> { }
+
+    void f0(G1<@Anno G0> p);
+    void f1(G1<G1<G1<G1<@Anno G0>>>> p);
+    void f2(G1<@Anno String> p);
+    void f3(G2<@Anno String, G2<@Anno("abc") Integer, G2<@Anno("abc") G2<Integer, @Anno Integer>, @Anno("abc") Integer>>> p);
+}
diff --git a/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/ValueArguments.javac.txt b/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/ValueArguments.javac.txt
new file mode 100644
index 0000000..60fe3a9
--- /dev/null
+++ b/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/ValueArguments.javac.txt
@@ -0,0 +1,22 @@
+package test
+
+public/*package*/ interface TypeAnnotations {
+    public abstract fun f0(/*0*/ p: test.TypeAnnotations.G1<@test.TypeAnnotations.Anno test.TypeAnnotations.G0!>!): kotlin.Unit
+    public abstract fun f1(/*0*/ p: test.TypeAnnotations.G1<test.TypeAnnotations.G1<test.TypeAnnotations.G1<test.TypeAnnotations.G1<@test.TypeAnnotations.Anno test.TypeAnnotations.G0!>!>!>!>!): kotlin.Unit
+    public abstract fun f2(/*0*/ p: test.TypeAnnotations.G1<@test.TypeAnnotations.Anno kotlin.String!>!): kotlin.Unit
+    public abstract fun f3(/*0*/ p: test.TypeAnnotations.G2<@test.TypeAnnotations.Anno kotlin.String!, test.TypeAnnotations.G2<@test.TypeAnnotations.Anno(value = "abc") kotlin.Int!, test.TypeAnnotations.G2<@test.TypeAnnotations.Anno(value = "abc") test.TypeAnnotations.G2<kotlin.Int!, @test.TypeAnnotations.Anno kotlin.Int!>!, @test.TypeAnnotations.Anno(value = "abc") kotlin.Int!>!>!>!): kotlin.Unit
+
+    @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE}) public final annotation class Anno : kotlin.Annotation {
+        public constructor Anno(/*0*/ value: kotlin.String = ...)
+        public final val value: kotlin.String
+    }
+
+    public interface G0 {
+    }
+
+    public interface G1</*0*/ T : kotlin.Any!> {
+    }
+
+    public interface G2</*0*/ A : kotlin.Any!, /*1*/ B : kotlin.Any!> {
+    }
+}
diff --git a/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/ValueArguments.txt b/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/ValueArguments.txt
new file mode 100644
index 0000000..67e0adf
--- /dev/null
+++ b/compiler/testData/loadJava8/sourceJava/typeUseAnnotations/ValueArguments.txt
@@ -0,0 +1,22 @@
+package test
+
+public/*package*/ interface TypeAnnotations {
+    public abstract fun f0(/*0*/ p0: test.TypeAnnotations.G1<@test.TypeAnnotations.Anno test.TypeAnnotations.G0!>!): kotlin.Unit
+    public abstract fun f1(/*0*/ p0: test.TypeAnnotations.G1<test.TypeAnnotations.G1<test.TypeAnnotations.G1<test.TypeAnnotations.G1<@test.TypeAnnotations.Anno test.TypeAnnotations.G0!>!>!>!>!): kotlin.Unit
+    public abstract fun f2(/*0*/ p0: test.TypeAnnotations.G1<@test.TypeAnnotations.Anno kotlin.String!>!): kotlin.Unit
+    public abstract fun f3(/*0*/ p0: test.TypeAnnotations.G2<@test.TypeAnnotations.Anno kotlin.String!, test.TypeAnnotations.G2<@test.TypeAnnotations.Anno(value = "abc") kotlin.Int!, test.TypeAnnotations.G2<@test.TypeAnnotations.Anno(value = "abc") test.TypeAnnotations.G2<kotlin.Int!, @test.TypeAnnotations.Anno kotlin.Int!>!, @test.TypeAnnotations.Anno(value = "abc") kotlin.Int!>!>!>!): kotlin.Unit
+
+    @kotlin.annotation.Target(allowedTargets = {AnnotationTarget.TYPE}) public final annotation class Anno : kotlin.Annotation {
+        public constructor Anno(/*0*/ value: kotlin.String = ...)
+        public final val value: kotlin.String
+    }
+
+    public interface G0 {
+    }
+
+    public interface G1</*0*/ T : kotlin.Any!> {
+    }
+
+    public interface G2</*0*/ A : kotlin.Any!, /*1*/ B : kotlin.Any!> {
+    }
+}
diff --git a/compiler/tests-java8/tests/org/jetbrains/kotlin/jvm/compiler/LoadJava8TestGenerated.java b/compiler/tests-java8/tests/org/jetbrains/kotlin/jvm/compiler/LoadJava8TestGenerated.java
index 2a94ab3..e32de4f 100644
--- a/compiler/tests-java8/tests/org/jetbrains/kotlin/jvm/compiler/LoadJava8TestGenerated.java
+++ b/compiler/tests-java8/tests/org/jetbrains/kotlin/jvm/compiler/LoadJava8TestGenerated.java
@@ -45,14 +45,55 @@
             runTest("compiler/testData/loadJava8/compiledJava/ParameterNames.java");
         }
 
-        @TestMetadata("TypeAnnotations.java")
-        public void testTypeAnnotations() throws Exception {
-            runTest("compiler/testData/loadJava8/compiledJava/TypeAnnotations.java");
+        @TestMetadata("compiler/testData/loadJava8/compiledJava/typeParameterAnnotations")
+        @TestDataPath("$PROJECT_ROOT")
+        @RunWith(JUnit3RunnerWithInners.class)
+        public static class TypeParameterAnnotations extends AbstractLoadJava8Test {
+            private void runTest(String testDataFilePath) throws Exception {
+                KotlinTestUtils.runTest(this::doTestCompiledJava, this, testDataFilePath);
+            }
+
+            public void testAllFilesPresentInTypeParameterAnnotations() throws Exception {
+                KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/loadJava8/compiledJava/typeParameterAnnotations"), Pattern.compile("^(.+)\\.java$"), null, true);
+            }
+
+            @TestMetadata("Basic.java")
+            public void testBasic() throws Exception {
+                runTest("compiler/testData/loadJava8/compiledJava/typeParameterAnnotations/Basic.java");
+            }
         }
 
-        @TestMetadata("TypeParameterAnnotations.java")
-        public void testTypeParameterAnnotations() throws Exception {
-            runTest("compiler/testData/loadJava8/compiledJava/TypeParameterAnnotations.java");
+        @TestMetadata("compiler/testData/loadJava8/compiledJava/typeUseAnnotations")
+        @TestDataPath("$PROJECT_ROOT")
+        @RunWith(JUnit3RunnerWithInners.class)
+        public static class TypeUseAnnotations extends AbstractLoadJava8Test {
+            private void runTest(String testDataFilePath) throws Exception {
+                KotlinTestUtils.runTest(this::doTestCompiledJava, this, testDataFilePath);
+            }
+
+            public void testAllFilesPresentInTypeUseAnnotations() throws Exception {
+                KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/loadJava8/compiledJava/typeUseAnnotations"), Pattern.compile("^(.+)\\.java$"), null, true);
+            }
+
+            @TestMetadata("Basic.java")
+            public void testBasic() throws Exception {
+                runTest("compiler/testData/loadJava8/compiledJava/typeUseAnnotations/Basic.java");
+            }
+
+            @TestMetadata("ClassTypeParameterUpperBounds.java")
+            public void testClassTypeParameterUpperBounds() throws Exception {
+                runTest("compiler/testData/loadJava8/compiledJava/typeUseAnnotations/ClassTypeParameterUpperBounds.java");
+            }
+
+            @TestMetadata("ReturnType.java")
+            public void testReturnType() throws Exception {
+                runTest("compiler/testData/loadJava8/compiledJava/typeUseAnnotations/ReturnType.java");
+            }
+
+            @TestMetadata("ValueArguments.java")
+            public void testValueArguments() throws Exception {
+                runTest("compiler/testData/loadJava8/compiledJava/typeUseAnnotations/ValueArguments.java");
+            }
         }
     }
 
@@ -73,14 +114,60 @@
             runTest("compiler/testData/loadJava8/sourceJava/MapRemove.java");
         }
 
-        @TestMetadata("TypeAnnotations.java")
-        public void testTypeAnnotations() throws Exception {
-            runTest("compiler/testData/loadJava8/sourceJava/TypeAnnotations.java");
-        }
-
         @TestMetadata("TypeParameterAnnotations.java")
         public void testTypeParameterAnnotations() throws Exception {
             runTest("compiler/testData/loadJava8/sourceJava/TypeParameterAnnotations.java");
         }
+
+        @TestMetadata("compiler/testData/loadJava8/sourceJava/typeParameterAnnotations")
+        @TestDataPath("$PROJECT_ROOT")
+        @RunWith(JUnit3RunnerWithInners.class)
+        public static class TypeParameterAnnotations extends AbstractLoadJava8Test {
+            private void runTest(String testDataFilePath) throws Exception {
+                KotlinTestUtils.runTest(this::doTestSourceJava, this, testDataFilePath);
+            }
+
+            public void testAllFilesPresentInTypeParameterAnnotations() throws Exception {
+                KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/loadJava8/sourceJava/typeParameterAnnotations"), Pattern.compile("^(.+)\\.java$"), null, true);
+            }
+
+            @TestMetadata("Basic.java")
+            public void testBasic() throws Exception {
+                runTest("compiler/testData/loadJava8/sourceJava/typeParameterAnnotations/Basic.java");
+            }
+        }
+
+        @TestMetadata("compiler/testData/loadJava8/sourceJava/typeUseAnnotations")
+        @TestDataPath("$PROJECT_ROOT")
+        @RunWith(JUnit3RunnerWithInners.class)
+        public static class TypeUseAnnotations extends AbstractLoadJava8Test {
+            private void runTest(String testDataFilePath) throws Exception {
+                KotlinTestUtils.runTest(this::doTestSourceJava, this, testDataFilePath);
+            }
+
+            public void testAllFilesPresentInTypeUseAnnotations() throws Exception {
+                KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/loadJava8/sourceJava/typeUseAnnotations"), Pattern.compile("^(.+)\\.java$"), null, true);
+            }
+
+            @TestMetadata("Basic.java")
+            public void testBasic() throws Exception {
+                runTest("compiler/testData/loadJava8/sourceJava/typeUseAnnotations/Basic.java");
+            }
+
+            @TestMetadata("ClassTypeParameterUpperBounds.java")
+            public void testClassTypeParameterUpperBounds() throws Exception {
+                runTest("compiler/testData/loadJava8/sourceJava/typeUseAnnotations/ClassTypeParameterUpperBounds.java");
+            }
+
+            @TestMetadata("ReturnType.java")
+            public void testReturnType() throws Exception {
+                runTest("compiler/testData/loadJava8/sourceJava/typeUseAnnotations/ReturnType.java");
+            }
+
+            @TestMetadata("ValueArguments.java")
+            public void testValueArguments() throws Exception {
+                runTest("compiler/testData/loadJava8/sourceJava/typeUseAnnotations/ValueArguments.java");
+            }
+        }
     }
 }
diff --git a/compiler/tests-java8/tests/org/jetbrains/kotlin/jvm/compiler/LoadJava8WithPsiClassReadingTestGenerated.java b/compiler/tests-java8/tests/org/jetbrains/kotlin/jvm/compiler/LoadJava8WithPsiClassReadingTestGenerated.java
index 7803a82..2cb29a0 100644
--- a/compiler/tests-java8/tests/org/jetbrains/kotlin/jvm/compiler/LoadJava8WithPsiClassReadingTestGenerated.java
+++ b/compiler/tests-java8/tests/org/jetbrains/kotlin/jvm/compiler/LoadJava8WithPsiClassReadingTestGenerated.java
@@ -43,13 +43,54 @@
         runTest("compiler/testData/loadJava8/compiledJava/ParameterNames.java");
     }
 
-    @TestMetadata("TypeAnnotations.java")
-    public void testTypeAnnotations() throws Exception {
-        runTest("compiler/testData/loadJava8/compiledJava/TypeAnnotations.java");
+    @TestMetadata("compiler/testData/loadJava8/compiledJava/typeParameterAnnotations")
+    @TestDataPath("$PROJECT_ROOT")
+    @RunWith(JUnit3RunnerWithInners.class)
+    public static class TypeParameterAnnotations extends AbstractLoadJava8WithPsiClassReadingTest {
+        private void runTest(String testDataFilePath) throws Exception {
+            KotlinTestUtils.runTest(this::doTestCompiledJava, this, testDataFilePath);
+        }
+
+        public void testAllFilesPresentInTypeParameterAnnotations() throws Exception {
+            KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/loadJava8/compiledJava/typeParameterAnnotations"), Pattern.compile("^(.+)\\.java$"), null, true);
+        }
+
+        @TestMetadata("Basic.java")
+        public void testBasic() throws Exception {
+            runTest("compiler/testData/loadJava8/compiledJava/typeParameterAnnotations/Basic.java");
+        }
     }
 
-    @TestMetadata("TypeParameterAnnotations.java")
-    public void testTypeParameterAnnotations() throws Exception {
-        runTest("compiler/testData/loadJava8/compiledJava/TypeParameterAnnotations.java");
+    @TestMetadata("compiler/testData/loadJava8/compiledJava/typeUseAnnotations")
+    @TestDataPath("$PROJECT_ROOT")
+    @RunWith(JUnit3RunnerWithInners.class)
+    public static class TypeUseAnnotations extends AbstractLoadJava8WithPsiClassReadingTest {
+        private void runTest(String testDataFilePath) throws Exception {
+            KotlinTestUtils.runTest(this::doTestCompiledJava, this, testDataFilePath);
+        }
+
+        public void testAllFilesPresentInTypeUseAnnotations() throws Exception {
+            KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/loadJava8/compiledJava/typeUseAnnotations"), Pattern.compile("^(.+)\\.java$"), null, true);
+        }
+
+        @TestMetadata("Basic.java")
+        public void testBasic() throws Exception {
+            runTest("compiler/testData/loadJava8/compiledJava/typeUseAnnotations/Basic.java");
+        }
+
+        @TestMetadata("ClassTypeParameterUpperBounds.java")
+        public void testClassTypeParameterUpperBounds() throws Exception {
+            runTest("compiler/testData/loadJava8/compiledJava/typeUseAnnotations/ClassTypeParameterUpperBounds.java");
+        }
+
+        @TestMetadata("ReturnType.java")
+        public void testReturnType() throws Exception {
+            runTest("compiler/testData/loadJava8/compiledJava/typeUseAnnotations/ReturnType.java");
+        }
+
+        @TestMetadata("ValueArguments.java")
+        public void testValueArguments() throws Exception {
+            runTest("compiler/testData/loadJava8/compiledJava/typeUseAnnotations/ValueArguments.java");
+        }
     }
 }
diff --git a/compiler/tests-java8/tests/org/jetbrains/kotlin/jvm/compiler/javac/LoadJava8UsingJavacTestGenerated.java b/compiler/tests-java8/tests/org/jetbrains/kotlin/jvm/compiler/javac/LoadJava8UsingJavacTestGenerated.java
index a7c2485..e7baf94 100644
--- a/compiler/tests-java8/tests/org/jetbrains/kotlin/jvm/compiler/javac/LoadJava8UsingJavacTestGenerated.java
+++ b/compiler/tests-java8/tests/org/jetbrains/kotlin/jvm/compiler/javac/LoadJava8UsingJavacTestGenerated.java
@@ -45,14 +45,55 @@
             runTest("compiler/testData/loadJava8/compiledJava/ParameterNames.java");
         }
 
-        @TestMetadata("TypeAnnotations.java")
-        public void testTypeAnnotations() throws Exception {
-            runTest("compiler/testData/loadJava8/compiledJava/TypeAnnotations.java");
+        @TestMetadata("compiler/testData/loadJava8/compiledJava/typeParameterAnnotations")
+        @TestDataPath("$PROJECT_ROOT")
+        @RunWith(JUnit3RunnerWithInners.class)
+        public static class TypeParameterAnnotations extends AbstractLoadJava8UsingJavacTest {
+            private void runTest(String testDataFilePath) throws Exception {
+                KotlinTestUtils.runTest(this::doTestCompiledJava, this, testDataFilePath);
+            }
+
+            public void testAllFilesPresentInTypeParameterAnnotations() throws Exception {
+                KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/loadJava8/compiledJava/typeParameterAnnotations"), Pattern.compile("^(.+)\\.java$"), null, true);
+            }
+
+            @TestMetadata("Basic.java")
+            public void testBasic() throws Exception {
+                runTest("compiler/testData/loadJava8/compiledJava/typeParameterAnnotations/Basic.java");
+            }
         }
 
-        @TestMetadata("TypeParameterAnnotations.java")
-        public void testTypeParameterAnnotations() throws Exception {
-            runTest("compiler/testData/loadJava8/compiledJava/TypeParameterAnnotations.java");
+        @TestMetadata("compiler/testData/loadJava8/compiledJava/typeUseAnnotations")
+        @TestDataPath("$PROJECT_ROOT")
+        @RunWith(JUnit3RunnerWithInners.class)
+        public static class TypeUseAnnotations extends AbstractLoadJava8UsingJavacTest {
+            private void runTest(String testDataFilePath) throws Exception {
+                KotlinTestUtils.runTest(this::doTestCompiledJava, this, testDataFilePath);
+            }
+
+            public void testAllFilesPresentInTypeUseAnnotations() throws Exception {
+                KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/loadJava8/compiledJava/typeUseAnnotations"), Pattern.compile("^(.+)\\.java$"), null, true);
+            }
+
+            @TestMetadata("Basic.java")
+            public void testBasic() throws Exception {
+                runTest("compiler/testData/loadJava8/compiledJava/typeUseAnnotations/Basic.java");
+            }
+
+            @TestMetadata("ClassTypeParameterUpperBounds.java")
+            public void testClassTypeParameterUpperBounds() throws Exception {
+                runTest("compiler/testData/loadJava8/compiledJava/typeUseAnnotations/ClassTypeParameterUpperBounds.java");
+            }
+
+            @TestMetadata("ReturnType.java")
+            public void testReturnType() throws Exception {
+                runTest("compiler/testData/loadJava8/compiledJava/typeUseAnnotations/ReturnType.java");
+            }
+
+            @TestMetadata("ValueArguments.java")
+            public void testValueArguments() throws Exception {
+                runTest("compiler/testData/loadJava8/compiledJava/typeUseAnnotations/ValueArguments.java");
+            }
         }
     }
 
@@ -73,14 +114,60 @@
             runTest("compiler/testData/loadJava8/sourceJava/MapRemove.java");
         }
 
-        @TestMetadata("TypeAnnotations.java")
-        public void testTypeAnnotations() throws Exception {
-            runTest("compiler/testData/loadJava8/sourceJava/TypeAnnotations.java");
-        }
-
         @TestMetadata("TypeParameterAnnotations.java")
         public void testTypeParameterAnnotations() throws Exception {
             runTest("compiler/testData/loadJava8/sourceJava/TypeParameterAnnotations.java");
         }
+
+        @TestMetadata("compiler/testData/loadJava8/sourceJava/typeParameterAnnotations")
+        @TestDataPath("$PROJECT_ROOT")
+        @RunWith(JUnit3RunnerWithInners.class)
+        public static class TypeParameterAnnotations extends AbstractLoadJava8UsingJavacTest {
+            private void runTest(String testDataFilePath) throws Exception {
+                KotlinTestUtils.runTest(this::doTestSourceJava, this, testDataFilePath);
+            }
+
+            public void testAllFilesPresentInTypeParameterAnnotations() throws Exception {
+                KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/loadJava8/sourceJava/typeParameterAnnotations"), Pattern.compile("^(.+)\\.java$"), null, true);
+            }
+
+            @TestMetadata("Basic.java")
+            public void testBasic() throws Exception {
+                runTest("compiler/testData/loadJava8/sourceJava/typeParameterAnnotations/Basic.java");
+            }
+        }
+
+        @TestMetadata("compiler/testData/loadJava8/sourceJava/typeUseAnnotations")
+        @TestDataPath("$PROJECT_ROOT")
+        @RunWith(JUnit3RunnerWithInners.class)
+        public static class TypeUseAnnotations extends AbstractLoadJava8UsingJavacTest {
+            private void runTest(String testDataFilePath) throws Exception {
+                KotlinTestUtils.runTest(this::doTestSourceJava, this, testDataFilePath);
+            }
+
+            public void testAllFilesPresentInTypeUseAnnotations() throws Exception {
+                KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/loadJava8/sourceJava/typeUseAnnotations"), Pattern.compile("^(.+)\\.java$"), null, true);
+            }
+
+            @TestMetadata("Basic.java")
+            public void testBasic() throws Exception {
+                runTest("compiler/testData/loadJava8/sourceJava/typeUseAnnotations/Basic.java");
+            }
+
+            @TestMetadata("ClassTypeParameterUpperBounds.java")
+            public void testClassTypeParameterUpperBounds() throws Exception {
+                runTest("compiler/testData/loadJava8/sourceJava/typeUseAnnotations/ClassTypeParameterUpperBounds.java");
+            }
+
+            @TestMetadata("ReturnType.java")
+            public void testReturnType() throws Exception {
+                runTest("compiler/testData/loadJava8/sourceJava/typeUseAnnotations/ReturnType.java");
+            }
+
+            @TestMetadata("ValueArguments.java")
+            public void testValueArguments() throws Exception {
+                runTest("compiler/testData/loadJava8/sourceJava/typeUseAnnotations/ValueArguments.java");
+            }
+        }
     }
 }
diff --git a/core/compiler.common.jvm/src/org/jetbrains/kotlin/load/java/structure/javaTypes.kt b/core/compiler.common.jvm/src/org/jetbrains/kotlin/load/java/structure/javaTypes.kt
index 1e87b4e..8896071 100644
--- a/core/compiler.common.jvm/src/org/jetbrains/kotlin/load/java/structure/javaTypes.kt
+++ b/core/compiler.common.jvm/src/org/jetbrains/kotlin/load/java/structure/javaTypes.kt
@@ -20,7 +20,7 @@
 
 interface JavaType
 
-interface JavaArrayType : JavaType {
+interface JavaArrayType : JavaType, JavaAnnotationOwner {
     val componentType: JavaType
 }
 
diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/types/JavaTypeResolver.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/types/JavaTypeResolver.kt
index 42a53d7..fdaa8ae 100644
--- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/types/JavaTypeResolver.kt
+++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/types/JavaTypeResolver.kt
@@ -19,6 +19,7 @@
 import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMapper
 import org.jetbrains.kotlin.descriptors.ClassDescriptor
 import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
+import org.jetbrains.kotlin.descriptors.annotations.Annotations
 import org.jetbrains.kotlin.load.java.components.TypeUsage
 import org.jetbrains.kotlin.load.java.components.TypeUsage.COMMON
 import org.jetbrains.kotlin.load.java.components.TypeUsage.SUPERTYPE
@@ -61,8 +62,13 @@
     fun transformArrayType(arrayType: JavaArrayType, attr: JavaTypeAttributes, isVararg: Boolean = false): KotlinType {
         val javaComponentType = arrayType.componentType
         val primitiveType = (javaComponentType as? JavaPrimitiveType)?.type
+        val annotations = LazyJavaAnnotations(c, arrayType)
+
         if (primitiveType != null) {
-            val jetType = c.module.builtIns.getPrimitiveArrayKotlinType(primitiveType)
+            val jetType = c.module.builtIns.getPrimitiveArrayKotlinType(primitiveType).let {
+                it.replaceAnnotations(Annotations.create(annotations + it.annotations))
+            }
+
             return if (attr.isForAnnotationParameter)
                 jetType
             else KotlinTypeFactory.flexibleType(jetType, jetType.makeNullableAsSpecified(true))
@@ -75,12 +81,12 @@
 
         if (attr.isForAnnotationParameter) {
             val projectionKind = if (isVararg) OUT_VARIANCE else INVARIANT
-            return c.module.builtIns.getArrayType(projectionKind, componentType)
+            return c.module.builtIns.getArrayType(projectionKind, componentType, annotations)
         }
 
         return KotlinTypeFactory.flexibleType(
-            c.module.builtIns.getArrayType(INVARIANT, componentType),
-            c.module.builtIns.getArrayType(OUT_VARIANCE, componentType).makeNullableAsSpecified(true)
+            c.module.builtIns.getArrayType(INVARIANT, componentType, annotations),
+            c.module.builtIns.getArrayType(OUT_VARIANCE, componentType, annotations).makeNullableAsSpecified(true)
         )
     }
 
diff --git a/core/descriptors.runtime/src/org/jetbrains/kotlin/descriptors/runtime/structure/ReflectJavaArrayType.kt b/core/descriptors.runtime/src/org/jetbrains/kotlin/descriptors/runtime/structure/ReflectJavaArrayType.kt
index e4c3463..73cd40e 100644
--- a/core/descriptors.runtime/src/org/jetbrains/kotlin/descriptors/runtime/structure/ReflectJavaArrayType.kt
+++ b/core/descriptors.runtime/src/org/jetbrains/kotlin/descriptors/runtime/structure/ReflectJavaArrayType.kt
@@ -16,7 +16,9 @@
 
 package org.jetbrains.kotlin.descriptors.runtime.structure
 
+import org.jetbrains.kotlin.load.java.structure.JavaAnnotation
 import org.jetbrains.kotlin.load.java.structure.JavaArrayType
+import org.jetbrains.kotlin.name.FqName
 import java.lang.reflect.GenericArrayType
 import java.lang.reflect.Type
 
@@ -28,4 +30,8 @@
             else -> throw IllegalArgumentException("Not an array type (${reflectType::class.java}): $reflectType")
         }
     }
+
+    override val annotations: Collection<JavaAnnotation> = emptyList()
+    override fun findAnnotation(fqName: FqName): JavaAnnotation? = null
+    override val isDeprecatedInJavaDoc = false
 }
diff --git a/core/descriptors.runtime/tests/org/jetbrains/kotlin/jvm/runtime/Jvm8RuntimeDescriptorLoaderTestGenerated.java b/core/descriptors.runtime/tests/org/jetbrains/kotlin/jvm/runtime/Jvm8RuntimeDescriptorLoaderTestGenerated.java
index 893482c..4d88091 100644
--- a/core/descriptors.runtime/tests/org/jetbrains/kotlin/jvm/runtime/Jvm8RuntimeDescriptorLoaderTestGenerated.java
+++ b/core/descriptors.runtime/tests/org/jetbrains/kotlin/jvm/runtime/Jvm8RuntimeDescriptorLoaderTestGenerated.java
@@ -43,13 +43,54 @@
         runTest("compiler/testData/loadJava8/compiledJava/ParameterNames.java");
     }
 
-    @TestMetadata("TypeAnnotations.java")
-    public void testTypeAnnotations() throws Exception {
-        runTest("compiler/testData/loadJava8/compiledJava/TypeAnnotations.java");
+    @TestMetadata("compiler/testData/loadJava8/compiledJava/typeParameterAnnotations")
+    @TestDataPath("$PROJECT_ROOT")
+    @RunWith(JUnit3RunnerWithInners.class)
+    public static class TypeParameterAnnotations extends AbstractJvm8RuntimeDescriptorLoaderTest {
+        private void runTest(String testDataFilePath) throws Exception {
+            KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
+        }
+
+        public void testAllFilesPresentInTypeParameterAnnotations() throws Exception {
+            KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/loadJava8/compiledJava/typeParameterAnnotations"), Pattern.compile("^(.+)\\.java$"), null, true);
+        }
+
+        @TestMetadata("Basic.java")
+        public void testBasic() throws Exception {
+            runTest("compiler/testData/loadJava8/compiledJava/typeParameterAnnotations/Basic.java");
+        }
     }
 
-    @TestMetadata("TypeParameterAnnotations.java")
-    public void testTypeParameterAnnotations() throws Exception {
-        runTest("compiler/testData/loadJava8/compiledJava/TypeParameterAnnotations.java");
+    @TestMetadata("compiler/testData/loadJava8/compiledJava/typeUseAnnotations")
+    @TestDataPath("$PROJECT_ROOT")
+    @RunWith(JUnit3RunnerWithInners.class)
+    public static class TypeUseAnnotations extends AbstractJvm8RuntimeDescriptorLoaderTest {
+        private void runTest(String testDataFilePath) throws Exception {
+            KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
+        }
+
+        public void testAllFilesPresentInTypeUseAnnotations() throws Exception {
+            KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/loadJava8/compiledJava/typeUseAnnotations"), Pattern.compile("^(.+)\\.java$"), null, true);
+        }
+
+        @TestMetadata("Basic.java")
+        public void testBasic() throws Exception {
+            runTest("compiler/testData/loadJava8/compiledJava/typeUseAnnotations/Basic.java");
+        }
+
+        @TestMetadata("ClassTypeParameterUpperBounds.java")
+        public void testClassTypeParameterUpperBounds() throws Exception {
+            runTest("compiler/testData/loadJava8/compiledJava/typeUseAnnotations/ClassTypeParameterUpperBounds.java");
+        }
+
+        @TestMetadata("ReturnType.java")
+        public void testReturnType() throws Exception {
+            runTest("compiler/testData/loadJava8/compiledJava/typeUseAnnotations/ReturnType.java");
+        }
+
+        @TestMetadata("ValueArguments.java")
+        public void testValueArguments() throws Exception {
+            runTest("compiler/testData/loadJava8/compiledJava/typeUseAnnotations/ValueArguments.java");
+        }
     }
 }
diff --git a/core/descriptors/src/org/jetbrains/kotlin/builtins/KotlinBuiltIns.java b/core/descriptors/src/org/jetbrains/kotlin/builtins/KotlinBuiltIns.java
index 415884e..e8ef967 100644
--- a/core/descriptors/src/org/jetbrains/kotlin/builtins/KotlinBuiltIns.java
+++ b/core/descriptors/src/org/jetbrains/kotlin/builtins/KotlinBuiltIns.java
@@ -653,9 +653,14 @@
     }
 
     @NotNull
-    public SimpleType getArrayType(@NotNull Variance projectionType, @NotNull KotlinType argument) {
+    public SimpleType getArrayType(@NotNull Variance projectionType, @NotNull KotlinType argument, @NotNull Annotations annotations) {
         List<TypeProjectionImpl> types = Collections.singletonList(new TypeProjectionImpl(projectionType, argument));
-        return KotlinTypeFactory.simpleNotNullType(Annotations.Companion.getEMPTY(), getArray(), types);
+        return KotlinTypeFactory.simpleNotNullType(annotations, getArray(), types);
+    }
+
+    @NotNull
+    public SimpleType getArrayType(@NotNull Variance projectionType, @NotNull KotlinType argument) {
+        return getArrayType(projectionType, argument, Annotations.Companion.getEMPTY());
     }
 
     @NotNull
diff --git a/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRendererImpl.kt b/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRendererImpl.kt
index 9c5e61f..7589d0c 100644
--- a/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRendererImpl.kt
+++ b/core/descriptors/src/org/jetbrains/kotlin/renderer/DescriptorRendererImpl.kt
@@ -405,6 +405,8 @@
     private fun StringBuilder.renderAnnotations(annotated: Annotated, target: AnnotationUseSiteTarget? = null) {
         if (DescriptorRendererModifier.ANNOTATIONS !in modifiers) return
 
+        // value-parameter vararg p0: (@test.A kotlin.String..@test.A kotlin.String?) defined in test.ReturnType.f20[ValueParameterDescriptorImpl@43186826]
+        // [@test.ReturnType.Anno] Array<(kotlin.String..kotlin.String?)>
         val excluded = if (annotated is KotlinType) excludedTypeAnnotationClasses else excludedAnnotationClasses
 
         val annotationFilter = annotationFilter