Add LanguageFeature prohibiting exposing function type parameter bound

 #KT-27112
diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt
index 46bfa4065..b6c8638 100644
--- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt
+++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt
@@ -77,7 +77,7 @@
 
     private val modifiersChecker = modifiersChecker.withTrace(trace)
 
-    private val exposedChecker = ExposedVisibilityChecker(trace)
+    private val exposedChecker = ExposedVisibilityChecker(trace, languageVersionSettings)
 
     private val shadowedExtensionChecker = ShadowedExtensionChecker(typeSpecificityComparator, trace)
 
diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/ExposedVisibilityChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/ExposedVisibilityChecker.kt
index 8f4dee2..4193e45 100644
--- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/ExposedVisibilityChecker.kt
+++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/ExposedVisibilityChecker.kt
@@ -16,6 +16,9 @@
 
 package org.jetbrains.kotlin.resolve
 
+import org.jetbrains.kotlin.config.LanguageFeature
+import org.jetbrains.kotlin.config.LanguageVersionSettings
+import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
 import org.jetbrains.kotlin.descriptors.*
 import org.jetbrains.kotlin.diagnostics.DiagnosticSink
 import org.jetbrains.kotlin.diagnostics.DiagnosticSink.DO_NOTHING
@@ -26,7 +29,10 @@
 
 // Checker for all seven EXPOSED_* errors
 // All functions return true if everything is OK, or false in case of any errors
-class ExposedVisibilityChecker(private val trace: DiagnosticSink = DO_NOTHING) {
+class ExposedVisibilityChecker(
+    private val trace: DiagnosticSink = DO_NOTHING,
+    private val languageVersionSettings: LanguageVersionSettings = LanguageVersionSettingsImpl.DEFAULT
+) {
 
     // NB: does not check any members
     fun checkClassHeader(klass: KtClassOrObject, classDescriptor: ClassDescriptor): Boolean {
@@ -89,6 +95,14 @@
                 )
                 result = false
             }
+
+            if (languageVersionSettings.supportsFeature(LanguageFeature.ProhibitExposingFunctionTypeParameterBound)) {
+                functionDescriptor.typeParameters.forEachIndexed { i, typeParameterDescriptor ->
+                    if (!checkParameterBounds(function.typeParameters[i], typeParameterDescriptor, functionVisibility)) {
+                        result = false
+                    }
+                }
+            }
         }
         functionDescriptor.valueParameters.forEachIndexed { i, parameterDescriptor ->
             val restricting = parameterDescriptor.type.leastPermissiveDescriptor(functionVisibility)
@@ -184,21 +198,30 @@
         var result = true
         classDescriptor.declaredTypeParameters.forEachIndexed { i, typeParameterDescriptor ->
             if (i >= typeParameterList.size) return result
-            for (upperBound in typeParameterDescriptor.upperBounds) {
-                val restricting = upperBound.leastPermissiveDescriptor(classVisibility)
-                if (restricting != null) {
-                    trace.report(
-                        Errors.EXPOSED_TYPE_PARAMETER_BOUND.on(
-                            typeParameterList[i], classVisibility,
-                            restricting, restricting.effectiveVisibility()
-                        )
-                    )
-                    result = false
-                    break
-                }
-            }
+            val ktTypeParameter = typeParameterList[i]
+            if (!checkParameterBounds(ktTypeParameter, typeParameterDescriptor, classVisibility)) result = false
         }
         return result
     }
+
+    private fun checkParameterBounds(
+        ktTypeParameter: KtTypeParameter,
+        typeParameterDescriptor: TypeParameterDescriptor,
+        ownerVisibility: EffectiveVisibility
+    ): Boolean {
+        for (upperBound in typeParameterDescriptor.upperBounds) {
+            val restricting = upperBound.leastPermissiveDescriptor(ownerVisibility)
+            if (restricting != null) {
+                trace.report(
+                    Errors.EXPOSED_TYPE_PARAMETER_BOUND.on(
+                        ktTypeParameter, ownerVisibility,
+                        restricting, restricting.effectiveVisibility()
+                    )
+                )
+                return false
+            }
+        }
+        return true
+    }
 }
 
diff --git a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt
index 69eae3b..a72da3f 100644
--- a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt
+++ b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt
@@ -115,6 +115,8 @@
 
     InlineClasses(sinceVersion = KOTLIN_1_3, defaultState = State.ENABLED_WITH_WARNING, kind = UNSTABLE_FEATURE),
 
+    ProhibitExposingFunctionTypeParameterBound(sinceVersion = null, defaultState = State.DISABLED, kind = BUG_FIX),
+
     ;
 
     val presentableName: String