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.*
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
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.DiagnosticFactory0
|
||||||
import org.jetbrains.kotlin.diagnostics.Errors
|
import org.jetbrains.kotlin.diagnostics.Errors
|
||||||
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.*
|
||||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||||
import org.jetbrains.kotlin.types.typeUtil.*
|
import org.jetbrains.kotlin.types.typeUtil.*
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
internal class DeclarationsCheckerBuilder(
|
internal class DeclarationsCheckerBuilder(
|
||||||
@@ -405,6 +407,8 @@ class DeclarationsChecker(
|
|||||||
declaration
|
declaration
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (descriptor.containingDeclaration.safeAs<MemberDescriptor>()?.isInlineOnly() == true) return
|
||||||
|
|
||||||
trace.report(BOUNDS_NOT_ALLOWED_IF_BOUNDED_BY_TYPE_PARAMETER.on(reportOn))
|
trace.report(BOUNDS_NOT_ALLOWED_IF_BOUNDED_BY_TYPE_PARAMETER.on(reportOn))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,11 +90,22 @@ fun CallableDescriptor.hasInferredReturnType(constraintSystem: ConstraintSystem)
|
|||||||
return true
|
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 {
|
fun getErasedReceiverType(receiverParameterDescriptor: ReceiverParameterDescriptor, descriptor: CallableDescriptor): KotlinType {
|
||||||
var receiverType = receiverParameterDescriptor.type
|
var receiverType = receiverParameterDescriptor.type
|
||||||
for (typeParameter in descriptor.typeParameters) {
|
for (typeParameter in descriptor.typeParameters) {
|
||||||
if (typeParameter.typeConstructor == receiverType.constructor) {
|
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>()
|
val fakeTypeArguments = ContainerUtil.newSmartList<TypeProjection>()
|
||||||
|
|||||||
@@ -150,7 +150,10 @@ public class TypeIntersector {
|
|||||||
*/
|
*/
|
||||||
@NotNull
|
@NotNull
|
||||||
public static KotlinType getUpperBoundsAsType(@NotNull TypeParameterDescriptor descriptor) {
|
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;
|
assert !upperBounds.isEmpty() : "Upper bound list is empty: " + descriptor;
|
||||||
KotlinType upperBoundsAsType = intersectTypes(upperBounds);
|
KotlinType upperBoundsAsType = intersectTypes(upperBounds);
|
||||||
return upperBoundsAsType != null ? upperBoundsAsType : getBuiltIns(descriptor).getNothingType();
|
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");
|
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")
|
@TestMetadata("useBoundsIfUnknownParameters.kt")
|
||||||
public void testUseBoundsIfUnknownParameters() throws Exception {
|
public void testUseBoundsIfUnknownParameters() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/inference/upperBounds/useBoundsIfUnknownParameters.kt");
|
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");
|
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")
|
@TestMetadata("useBoundsIfUnknownParameters.kt")
|
||||||
public void testUseBoundsIfUnknownParameters() throws Exception {
|
public void testUseBoundsIfUnknownParameters() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/inference/upperBounds/useBoundsIfUnknownParameters.kt");
|
runTest("compiler/testData/diagnostics/tests/inference/upperBounds/useBoundsIfUnknownParameters.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user