Allow generic type parameter to have mixed constraints for @InlineOnly functions
#KT-19323 Fixed
This commit is contained in:
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.annotations.isInlineOnly
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory0
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.diagnostics.Errors.*
|
||||
@@ -45,6 +46,7 @@ import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||
import org.jetbrains.kotlin.types.typeUtil.*
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
import java.util.*
|
||||
|
||||
internal class DeclarationsCheckerBuilder(
|
||||
@@ -405,6 +407,8 @@ class DeclarationsChecker(
|
||||
declaration
|
||||
}
|
||||
|
||||
if (descriptor.containingDeclaration.safeAs<MemberDescriptor>()?.isInlineOnly() == true) return
|
||||
|
||||
trace.report(BOUNDS_NOT_ALLOWED_IF_BOUNDED_BY_TYPE_PARAMETER.on(reportOn))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,11 +90,22 @@ fun CallableDescriptor.hasInferredReturnType(constraintSystem: ConstraintSystem)
|
||||
return true
|
||||
}
|
||||
|
||||
private fun filterOutTypeParameters(upperBounds: List<KotlinType>, candidateDescriptor: CallableDescriptor): List<KotlinType> {
|
||||
if (upperBounds.size < 2) return upperBounds
|
||||
val result = upperBounds.filterNot {
|
||||
val declarationDescriptor = it.constructor.declarationDescriptor
|
||||
declarationDescriptor is TypeParameterDescriptor && declarationDescriptor.containingDeclaration == candidateDescriptor
|
||||
}
|
||||
if (result.isEmpty()) return upperBounds
|
||||
return result
|
||||
}
|
||||
|
||||
fun getErasedReceiverType(receiverParameterDescriptor: ReceiverParameterDescriptor, descriptor: CallableDescriptor): KotlinType {
|
||||
var receiverType = receiverParameterDescriptor.type
|
||||
for (typeParameter in descriptor.typeParameters) {
|
||||
if (typeParameter.typeConstructor == receiverType.constructor) {
|
||||
receiverType = TypeIntersector.getUpperBoundsAsType(typeParameter)
|
||||
val properUpperBounds = filterOutTypeParameters(typeParameter.upperBounds, descriptor)
|
||||
receiverType = TypeIntersector.intersectUpperBounds(typeParameter, properUpperBounds)
|
||||
}
|
||||
}
|
||||
val fakeTypeArguments = ContainerUtil.newSmartList<TypeProjection>()
|
||||
|
||||
@@ -150,7 +150,10 @@ public class TypeIntersector {
|
||||
*/
|
||||
@NotNull
|
||||
public static KotlinType getUpperBoundsAsType(@NotNull TypeParameterDescriptor descriptor) {
|
||||
List<KotlinType> upperBounds = descriptor.getUpperBounds();
|
||||
return intersectUpperBounds(descriptor, descriptor.getUpperBounds());
|
||||
}
|
||||
|
||||
public static KotlinType intersectUpperBounds(@NotNull TypeParameterDescriptor descriptor, @NotNull List<KotlinType> upperBounds) {
|
||||
assert !upperBounds.isEmpty() : "Upper bound list is empty: " + descriptor;
|
||||
KotlinType upperBoundsAsType = intersectTypes(upperBounds);
|
||||
return upperBoundsAsType != null ? upperBoundsAsType : getBuiltIns(descriptor).getNothingType();
|
||||
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// !CHECK_TYPE
|
||||
|
||||
|
||||
@<!INVISIBLE_MEMBER!>kotlin.internal.<!INVISIBLE_REFERENCE!>InlineOnly<!><!>
|
||||
public inline fun <C, R> C.ifEmpty(f: () -> R): R where C : Collection<*>, C : R = if (isEmpty()) f() else this
|
||||
|
||||
public fun <T> listOf(<!UNUSED_PARAMETER!>t<!>: T): List<T> = TODO()
|
||||
|
||||
|
||||
fun usage(c: List<String>) {
|
||||
val cn = c.ifEmpty { null }
|
||||
cn checkType { _<List<String>?>() }
|
||||
|
||||
val cs = c.ifEmpty { listOf("x") }
|
||||
cs checkType { _<List<String>>() }
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package
|
||||
|
||||
public fun </*0*/ T> listOf(/*0*/ t: T): kotlin.collections.List<T>
|
||||
public fun usage(/*0*/ c: kotlin.collections.List<kotlin.String>): kotlin.Unit
|
||||
@kotlin.internal.InlineOnly public inline fun </*0*/ C : kotlin.collections.Collection<*>, /*1*/ R> C.ifEmpty(/*0*/ f: () -> R): R where C : R
|
||||
@@ -10289,6 +10289,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/upperBounds/nonNullUpperBound.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("typeParameterAsUpperBound.kt")
|
||||
public void testTypeParameterAsUpperBound() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/upperBounds/typeParameterAsUpperBound.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("useBoundsIfUnknownParameters.kt")
|
||||
public void testUseBoundsIfUnknownParameters() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/upperBounds/useBoundsIfUnknownParameters.kt");
|
||||
|
||||
Generated
+5
@@ -10289,6 +10289,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
|
||||
runTest("compiler/testData/diagnostics/tests/inference/upperBounds/nonNullUpperBound.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("typeParameterAsUpperBound.kt")
|
||||
public void testTypeParameterAsUpperBound() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/upperBounds/typeParameterAsUpperBound.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("useBoundsIfUnknownParameters.kt")
|
||||
public void testUseBoundsIfUnknownParameters() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/upperBounds/useBoundsIfUnknownParameters.kt");
|
||||
|
||||
Reference in New Issue
Block a user