check for violation of Finite Bound Restriction and Non-Expansive Inheritance Restriction
This commit is contained in:
@@ -99,6 +99,8 @@ public interface Errors {
|
||||
DiagnosticFactory1<KtTypeProjection, ClassifierDescriptor> REDUNDANT_PROJECTION = DiagnosticFactory1.create(WARNING, VARIANCE_IN_PROJECTION);
|
||||
DiagnosticFactory1<PsiElement, VarianceConflictDiagnosticData> TYPE_VARIANCE_CONFLICT =
|
||||
DiagnosticFactory1.create(ERROR, DECLARATION_SIGNATURE_OR_DEFAULT);
|
||||
DiagnosticFactory1<PsiElement, String> FINITE_BOUNDS_VIOLATION = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory1<PsiElement, String> EXPANSIVE_INHERITANCE = DiagnosticFactory1.create(ERROR);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
+2
@@ -510,6 +510,8 @@ public class DefaultErrorMessages {
|
||||
}
|
||||
});
|
||||
|
||||
MAP.put(FINITE_BOUNDS_VIOLATION, "{0}", STRING);
|
||||
MAP.put(EXPANSIVE_INHERITANCE, "{0}", STRING);
|
||||
MAP.put(REDUNDANT_PROJECTION, "Projection is redundant: the corresponding type parameter of {0} has the same variance", NAME);
|
||||
MAP.put(CONFLICTING_PROJECTION, "Projection is conflicting with variance of the corresponding type parameter of {0}. Remove the projection or replace it with ''*''", NAME);
|
||||
|
||||
|
||||
@@ -317,6 +317,8 @@ public class DeclarationsChecker {
|
||||
checkOpenMembers(classDescriptor);
|
||||
checkTypeParameters(aClass);
|
||||
checkTypeParameterConstraints(aClass);
|
||||
FiniteBoundRestrictionChecker.check(aClass, classDescriptor, trace);
|
||||
NonExpansiveInheritanceRestrictionChecker.check(aClass, classDescriptor, trace);
|
||||
|
||||
if (aClass.isInterface()) {
|
||||
checkConstructorInInterface(aClass);
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.SourceElement
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.psi.KtClass
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
||||
import org.jetbrains.kotlin.types.TypeConstructor
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.types.typeUtil.boundClosure
|
||||
import org.jetbrains.kotlin.types.typeUtil.constituentTypes
|
||||
import org.jetbrains.kotlin.utils.DFS
|
||||
|
||||
public object FiniteBoundRestrictionChecker {
|
||||
@JvmStatic
|
||||
fun check(
|
||||
declaration: KtClass,
|
||||
classDescriptor: ClassDescriptor,
|
||||
diagnosticHolder: DiagnosticSink
|
||||
) {
|
||||
val typeConstructor = classDescriptor.typeConstructor
|
||||
if (typeConstructor.parameters.isEmpty()) return
|
||||
|
||||
// For every projection type argument A in every generic type B<…> in the set of constituent types
|
||||
// of every type in the B-closure the set of declared upper bounds of every type parameter T add an
|
||||
// edge from T to U, where U is the type parameter of the declaration of B<…> corresponding to the type argument A.
|
||||
// It is a compile-time error if the graph G has a cycle.
|
||||
val graph = GraphBuilder(typeConstructor).build()
|
||||
|
||||
val problemNodes = graph.nodes.filter { graph.isInCycle(it) }
|
||||
if (problemNodes.isEmpty()) return
|
||||
|
||||
for (typeParameter in typeConstructor.parameters) {
|
||||
if (typeParameter in problemNodes) {
|
||||
val element = DescriptorToSourceUtils.descriptorToDeclaration(typeParameter) ?: declaration
|
||||
diagnosticHolder.report(Errors.FINITE_BOUNDS_VIOLATION.on(element, "Type argument is not within its bounds (violation of Finite Bound Restriction)"))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if (problemNodes.any { it.source != SourceElement.NO_SOURCE }) return
|
||||
|
||||
val superTypeFqNames = problemNodes.map { it.containingDeclaration }.map { it.fqNameUnsafe.asString() }.toSortedSet()
|
||||
diagnosticHolder.report(Errors.FINITE_BOUNDS_VIOLATION.on(declaration, "Violation of Finite Bound Restriction for supertypes: " + superTypeFqNames.joinToString(", ")))
|
||||
}
|
||||
|
||||
private class GraphBuilder(val typeConstructor: TypeConstructor) {
|
||||
private val nodes: MutableSet<TypeParameterDescriptor> = hashSetOf()
|
||||
private val edgeLists = hashMapOf<TypeParameterDescriptor, MutableList<TypeParameterDescriptor>>()
|
||||
private val processedTypeConstructors = hashSetOf<TypeConstructor>()
|
||||
|
||||
fun build(): Graph<TypeParameterDescriptor> {
|
||||
buildGraph(typeConstructor)
|
||||
|
||||
return object : Graph<TypeParameterDescriptor> {
|
||||
override val nodes = this@GraphBuilder.nodes
|
||||
override fun getNeighbors(node: TypeParameterDescriptor) = edgeLists[node] ?: emptyList<TypeParameterDescriptor>()
|
||||
}
|
||||
}
|
||||
|
||||
private fun addEdge(from: TypeParameterDescriptor, to: TypeParameterDescriptor) = edgeLists.getOrPut(from) { arrayListOf() }.add(to)
|
||||
|
||||
private fun buildGraph(typeConstructor: TypeConstructor) {
|
||||
typeConstructor.parameters.forEach { typeParameter ->
|
||||
val boundClosure = boundClosure(typeParameter.upperBounds)
|
||||
val constituentTypes = constituentTypes(boundClosure)
|
||||
for (constituentType in constituentTypes) {
|
||||
val constituentTypeConstructor = constituentType.constructor
|
||||
if (constituentTypeConstructor !in processedTypeConstructors) {
|
||||
processedTypeConstructors.add(constituentTypeConstructor)
|
||||
buildGraph(constituentTypeConstructor)
|
||||
}
|
||||
if (constituentTypeConstructor.parameters.size != constituentType.arguments.size) continue
|
||||
|
||||
constituentType.arguments.forEachIndexed { i, typeProjection ->
|
||||
if (typeProjection.projectionKind != Variance.INVARIANT) {
|
||||
nodes.add(typeParameter)
|
||||
nodes.add(constituentTypeConstructor.parameters[i])
|
||||
addEdge(typeParameter, constituentTypeConstructor.parameters[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private interface Graph<T> {
|
||||
val nodes: Set<T>
|
||||
fun getNeighbors(node: T): List<T>
|
||||
}
|
||||
|
||||
private fun <T> Graph<T>.isInCycle(from: T): Boolean {
|
||||
var result = false
|
||||
|
||||
val visited = object : DFS.VisitedWithSet<T>() {
|
||||
override fun checkAndMarkVisited(current: T): Boolean {
|
||||
val added = super.checkAndMarkVisited(current)
|
||||
if (!added && current == from) {
|
||||
result = true
|
||||
}
|
||||
return added
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
val handler = object : DFS.AbstractNodeHandler<T, Unit>() {
|
||||
override fun result() {}
|
||||
}
|
||||
|
||||
val neighbors = object : DFS.Neighbors<T> {
|
||||
override fun getNeighbors(current: T) = this@isInCycle.getNeighbors(current)
|
||||
}
|
||||
|
||||
DFS.dfs(listOf(from), neighbors, visited, handler)
|
||||
|
||||
return result
|
||||
}
|
||||
}
|
||||
+166
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.SourceElement
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.psi.KtClass
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
||||
import org.jetbrains.kotlin.types.KtType
|
||||
import org.jetbrains.kotlin.types.TypeConstructor
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.types.typeUtil.boundClosure
|
||||
import org.jetbrains.kotlin.types.typeUtil.constituentTypes
|
||||
import org.jetbrains.kotlin.utils.DFS
|
||||
|
||||
public object NonExpansiveInheritanceRestrictionChecker {
|
||||
@JvmStatic
|
||||
fun check(
|
||||
declaration: KtClass,
|
||||
classDescriptor: ClassDescriptor,
|
||||
diagnosticHolder: DiagnosticSink
|
||||
) {
|
||||
val typeConstructor = classDescriptor.typeConstructor
|
||||
if (typeConstructor.parameters.isEmpty()) return
|
||||
|
||||
val builder = GraphBuilder(typeConstructor)
|
||||
val graph = builder.build()
|
||||
|
||||
val edgesInCycles = graph.expansiveEdges.filter { graph.isEdgeInCycle(it) }
|
||||
if (edgesInCycles.isEmpty()) return
|
||||
|
||||
val problemNodes = edgesInCycles.flatMap { setOf(it.from, it.to) }
|
||||
|
||||
for (typeParameter in typeConstructor.parameters) {
|
||||
if (typeParameter in problemNodes) {
|
||||
val element = DescriptorToSourceUtils.descriptorToDeclaration(typeParameter) ?: declaration
|
||||
diagnosticHolder.report(Errors.EXPANSIVE_INHERITANCE.on(element, "Type argument is not within its bounds (violation of Non-Expansive Inheritance Restriction"))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if (problemNodes.any { it.source != SourceElement.NO_SOURCE }) return
|
||||
|
||||
val superTypeFqNames = problemNodes.map { it.containingDeclaration }.map { it.fqNameUnsafe.asString() }.toSortedSet()
|
||||
diagnosticHolder.report(Errors.EXPANSIVE_INHERITANCE.on(declaration, "Violation of Non-Expansive Inheritance Restriction for supertypes: " + superTypeFqNames.joinToString(", ")))
|
||||
}
|
||||
|
||||
private class GraphBuilder(val typeConstructor: TypeConstructor) {
|
||||
private val processedTypeConstructors = hashSetOf<TypeConstructor>()
|
||||
private val expansiveEdges = hashSetOf<ExpansiveEdge<TypeParameterDescriptor>>()
|
||||
private val edgeLists = hashMapOf<TypeParameterDescriptor, MutableSet<TypeParameterDescriptor>>()
|
||||
|
||||
fun build(): Graph<TypeParameterDescriptor> {
|
||||
doBuildGraph(typeConstructor)
|
||||
|
||||
return object : Graph<TypeParameterDescriptor> {
|
||||
override fun getNeighbors(node: TypeParameterDescriptor) = edgeLists[node] ?: emptyList<TypeParameterDescriptor>()
|
||||
override val expansiveEdges = this@GraphBuilder.expansiveEdges
|
||||
}
|
||||
}
|
||||
|
||||
private fun addEdge(from: TypeParameterDescriptor, to: TypeParameterDescriptor, expansive: Boolean = false) {
|
||||
edgeLists.getOrPut(from) { linkedSetOf() }.add(to)
|
||||
if (expansive) {
|
||||
expansiveEdges.add(ExpansiveEdge(from, to))
|
||||
}
|
||||
}
|
||||
|
||||
private fun doBuildGraph(typeConstructor: TypeConstructor) {
|
||||
if (typeConstructor.parameters.isEmpty()) return
|
||||
|
||||
val typeParameters = typeConstructor.parameters
|
||||
|
||||
// For each type parameter T, let ST be the set of all constituent types of all immediate supertypes of the owner of T.
|
||||
// If T appears as a constituent type of a simple type argument A in a generic type in ST, add an edge from T
|
||||
// to U, where U is the type parameter corresponding to A, and where the edge is non-expansive if A has the form T or T?,
|
||||
// the edge is expansive otherwise.
|
||||
for (constituentType in constituentTypes(typeConstructor.supertypes)) {
|
||||
val constituentTypeConstructor = constituentType.constructor
|
||||
if (constituentTypeConstructor !in processedTypeConstructors) {
|
||||
processedTypeConstructors.add(constituentTypeConstructor)
|
||||
doBuildGraph(constituentTypeConstructor)
|
||||
}
|
||||
if (constituentTypeConstructor.parameters.size != constituentType.arguments.size) continue
|
||||
|
||||
constituentType.arguments.forEachIndexed { i, typeProjection ->
|
||||
if (typeProjection.projectionKind == Variance.INVARIANT) {
|
||||
val constituents = constituentTypes(setOf(typeProjection.type))
|
||||
|
||||
for (typeParameter in typeParameters) {
|
||||
if (typeParameter.defaultType in constituents || TypeUtils.makeNullable(typeParameter.defaultType) in constituents) {
|
||||
addEdge(typeParameter, constituentTypeConstructor.parameters[i], !TypeUtils.isTypeParameter(typeProjection.type))
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Furthermore, if T appears as a constituent type of an element of the B-closure of the set of lower and
|
||||
// upper bounds of a skolem type variable Q in a skolemization of a projected generic type in ST, add an
|
||||
// expanding edge from T to V, where V is the type parameter corresponding to Q.
|
||||
val originalTypeParameter = constituentTypeConstructor.parameters[i]
|
||||
val bounds = hashSetOf<KtType>()
|
||||
|
||||
val substitutor = constituentType.substitution.buildSubstitutor()
|
||||
val adaptedUpperBounds = originalTypeParameter.upperBounds.map { substitutor.substitute(it, Variance.INVARIANT) }.filterNotNull()
|
||||
bounds.addAll(adaptedUpperBounds)
|
||||
|
||||
if (!typeProjection.isStarProjection) {
|
||||
bounds.add(typeProjection.type)
|
||||
}
|
||||
|
||||
val boundClosure = boundClosure(bounds)
|
||||
val constituentTypes = constituentTypes(boundClosure)
|
||||
for (typeParameter in typeParameters) {
|
||||
if (typeParameter.defaultType in constituentTypes || TypeUtils.makeNullable(typeParameter.defaultType) in constituentTypes) {
|
||||
addEdge(typeParameter, originalTypeParameter, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private data class ExpansiveEdge<T>(val from: T, val to: T)
|
||||
|
||||
private interface Graph<T> {
|
||||
fun getNeighbors(node: T): Collection<T>
|
||||
val expansiveEdges: Set<ExpansiveEdge<T>>
|
||||
}
|
||||
|
||||
private fun <T> Graph<T>.isEdgeInCycle(edge: ExpansiveEdge<T>) = edge.from in collectReachable(edge.to)
|
||||
|
||||
private fun <T> Graph<T>.collectReachable(from: T): List<T> {
|
||||
val handler = object : DFS.NodeHandlerWithListResult<T, T>() {
|
||||
override fun afterChildren(current: T?) {
|
||||
result.add(current)
|
||||
}
|
||||
}
|
||||
|
||||
val neighbors = object : DFS.Neighbors<T> {
|
||||
override fun getNeighbors(current: T): Iterable<T> = this@collectReachable.getNeighbors(current)
|
||||
}
|
||||
|
||||
DFS.dfs(listOf(from), neighbors, handler)
|
||||
|
||||
return handler.result()
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
interface A0<T : A0<T>>
|
||||
interface A1<<!FINITE_BOUNDS_VIOLATION!>T : A1<*><!>>
|
||||
interface A2<<!FINITE_BOUNDS_VIOLATION!>T : A2<out T><!>>
|
||||
// StackOverflowError
|
||||
//interface A3<T : A3<in T>>
|
||||
interface A4<<!FINITE_BOUNDS_VIOLATION!>T : A4<*>?<!>>
|
||||
|
||||
interface B0<<!FINITE_BOUNDS_VIOLATION!>T : B1<*><!>>
|
||||
interface B1<<!FINITE_BOUNDS_VIOLATION!>T : B0<*><!>>
|
||||
|
||||
interface AA<<!FINITE_BOUNDS_VIOLATION!>T: AA<*><!>>
|
||||
interface BB<S : List<AA<*>>>
|
||||
|
||||
interface A<T: List<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!><T, T, T><!>>
|
||||
|
||||
class X<Y>
|
||||
class D<T : X<in X<out X<T>>>>
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
package
|
||||
|
||||
public interface A</*0*/ T : [ERROR : List]<T, T, T>> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface A0</*0*/ T : A0<T>> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface A1</*0*/ T : A1<*>> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface A2</*0*/ T : A2<out T>> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface A4</*0*/ T : A4<*>?> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface AA</*0*/ T : AA<*>> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface B0</*0*/ T : B1<*>> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface B1</*0*/ T : B0<*>> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface BB</*0*/ S : kotlin.List<AA<*>>> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final class D</*0*/ T : X<in X<out X<T>>>> {
|
||||
public constructor D</*0*/ T : X<in X<out X<T>>>>()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final class X</*0*/ Y> {
|
||||
public constructor X</*0*/ Y>()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
// !DIAGNOSTICS: -UPPER_BOUND_VIOLATED
|
||||
|
||||
interface C0<T, S : C0<*, S>>
|
||||
|
||||
interface C1<T : C1<T, *>, <!FINITE_BOUNDS_VIOLATION!>S : C1<S, *><!>> // T -> S, S -> S
|
||||
interface C2<<!FINITE_BOUNDS_VIOLATION!>T : C2<T, *><!>, S : C2<*, S>> // T -> S, S -> T
|
||||
|
||||
interface D1<<!FINITE_BOUNDS_VIOLATION!>T<!>, U> where T : U, U: D1<*, U>
|
||||
interface D2<<!FINITE_BOUNDS_VIOLATION!>T<!>, U> where T : U?, U: D2<*, *>
|
||||
interface D3<<!FINITE_BOUNDS_VIOLATION!>T<!>, U, V> where T : U, U : V, V: D3<*, *, V>
|
||||
|
||||
interface A<T, U> where T : A<U, T>, U: A<T, A<in U, T>>
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
package
|
||||
|
||||
public interface A</*0*/ T : A<U, T>, /*1*/ U : A<T, A<in U, T>>> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface C0</*0*/ T, /*1*/ S : C0<*, S>> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface C1</*0*/ T : C1<T, *>, /*1*/ S : C1<S, *>> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface C2</*0*/ T : C2<T, *>, /*1*/ S : C2<*, S>> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface D1</*0*/ T : U, /*1*/ U : D1<*, U>> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface D2</*0*/ T : U?, /*1*/ U : D2<*, *>> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface D3</*0*/ T : U, /*1*/ U : V, /*2*/ V : D3<*, *, V>> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
// FILE: A.java
|
||||
public class A<T extends A> {}
|
||||
|
||||
// FILE: 1.kt
|
||||
<!FINITE_BOUNDS_VIOLATION!>class B<S: A<*>><!>
|
||||
Vendored
+15
@@ -0,0 +1,15 @@
|
||||
package
|
||||
|
||||
public open class A</*0*/ T : A<(raw) A<*>>!> {
|
||||
public constructor A</*0*/ T : A<(raw) A<*>>!>()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final class B</*0*/ S : A<*>> {
|
||||
public constructor B</*0*/ S : A<*>>()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
// !DIAGNOSTICS: -UPPER_BOUND_VIOLATED
|
||||
|
||||
//// FILE: D.java
|
||||
public interface D<W> {}
|
||||
|
||||
// FILE: Q.java
|
||||
public interface Q<Z1, Z2> {}
|
||||
|
||||
// FILE: C.java
|
||||
public interface C<X> extends D<P<X,X>> {}
|
||||
|
||||
// FILE: 1.kt
|
||||
interface P<Y1, <!EXPANSIVE_INHERITANCE!>Y2<!>> : Q<C<Y1>, C<D<Y2>>>
|
||||
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
package
|
||||
|
||||
public interface C</*0*/ X : kotlin.Any!> : D<P<X!, X!>!> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface D</*0*/ W : kotlin.Any!> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface P</*0*/ Y1, /*1*/ Y2> : Q<C<Y1>, C<D<Y2>>> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface Q</*0*/ Z1 : kotlin.Any!, /*1*/ Z2 : kotlin.Any!> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// !DIAGNOSTICS: -UPPER_BOUND_VIOLATED
|
||||
|
||||
//// FILE: D.java
|
||||
public interface D<W> {}
|
||||
|
||||
// FILE: Q.java
|
||||
public interface Q<Z1, Z2> {}
|
||||
|
||||
// FILE: C.java
|
||||
public interface C<X> extends D<P<X,X>> {}
|
||||
|
||||
// FILE: P.java
|
||||
public interface P<Y1, Y2> extends Q<C<Y1>, C<D<Y2>>> {}
|
||||
|
||||
// FILE: 1.kt
|
||||
<!EXPANSIVE_INHERITANCE!>interface P1<YY1, YY2> : P<YY1, YY2><!>
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package
|
||||
|
||||
public interface C</*0*/ X : kotlin.Any!> : D<P<X!, X!>!> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface D</*0*/ W : kotlin.Any!> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface P</*0*/ Y1 : kotlin.Any!, /*1*/ Y2 : kotlin.Any!> : Q<C<Y1!>!, C<D<Y2!>!>!> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface P1</*0*/ YY1, /*1*/ YY2> : P<YY1, YY2> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface Q</*0*/ Z1 : kotlin.Any!, /*1*/ Z2 : kotlin.Any!> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
// !DIAGNOSTICS: -UPPER_BOUND_VIOLATED
|
||||
|
||||
interface A<T>
|
||||
interface B<T> : A<A<*>>
|
||||
|
||||
interface N0<in T>
|
||||
interface C0<<!EXPANSIVE_INHERITANCE!>X<!>> : N0<N0<C0<C0<X>>>>
|
||||
|
||||
interface N1<in T>
|
||||
interface C1<<!EXPANSIVE_INHERITANCE!>X<!>> : N1<N1<C1<C1<X?>>>>
|
||||
interface C2<T> : C1<C1<T>>
|
||||
|
||||
interface C<<!EXPANSIVE_INHERITANCE!>X<!>> : D<P<X, X>>
|
||||
interface P<Y1, <!EXPANSIVE_INHERITANCE!>Y2<!>> : Q<C<Y1>, C<D<Y2>>>
|
||||
interface Q<Z1, Z2>
|
||||
interface D<W>
|
||||
|
||||
interface E0<T>
|
||||
interface E1<T : E2>
|
||||
interface E2 : E0<E1<out E2>>
|
||||
|
||||
interface F0<T>
|
||||
interface F1<T : F2<*>, U : F2<*>>
|
||||
interface F2<T> : F0<F1<out F2<*>, T>>
|
||||
|
||||
interface G0<T>
|
||||
interface G1<T : U, U : G2<*>>
|
||||
interface G2<T> : G0<G1<out G2<*>, T>>
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
package
|
||||
|
||||
public interface A</*0*/ T> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface B</*0*/ T> : A<A<*>> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface C</*0*/ X> : D<P<X, X>> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface C0</*0*/ X> : N0<N0<C0<C0<X>>>> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface C1</*0*/ X> : N1<N1<C1<C1<X?>>>> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface C2</*0*/ T> : C1<C1<T>> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface D</*0*/ W> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface E0</*0*/ T> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface E1</*0*/ T : E2> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface E2 : E0<E1<out E2>> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface F0</*0*/ T> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface F1</*0*/ T : F2<*>, /*1*/ U : F2<*>> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface F2</*0*/ T> : F0<F1<out F2<*>, T>> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface G0</*0*/ T> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface G1</*0*/ T : U, /*1*/ U : G2<*>> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface G2</*0*/ T> : G0<G1<out G2<*>, T>> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface N0</*0*/ in T> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface N1</*0*/ in T> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface P</*0*/ Y1, /*1*/ Y2> : Q<C<Y1>, C<D<Y2>>> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface Q</*0*/ Z1, /*1*/ Z2> {
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
@@ -4206,6 +4206,33 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/declarationChecks/finiteBoundRestriction")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class FiniteBoundRestriction extends AbstractJetDiagnosticsTest {
|
||||
public void testAllFilesPresentInFiniteBoundRestriction() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/declarationChecks/finiteBoundRestriction"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("CasesWithOneTypeParameter.kt")
|
||||
public void testCasesWithOneTypeParameter() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/declarationChecks/finiteBoundRestriction/CasesWithOneTypeParameter.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("CasesWithTwoTypeParameters.kt")
|
||||
public void testCasesWithTwoTypeParameters() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/declarationChecks/finiteBoundRestriction/CasesWithTwoTypeParameters.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("JavaSuperType.kt")
|
||||
public void testJavaSuperType() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/declarationChecks/finiteBoundRestriction/JavaSuperType.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/declarationChecks/multiDeclarations")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
@@ -4268,6 +4295,33 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/declarationChecks/nonExpansiveInheritanceRestriction")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class NonExpansiveInheritanceRestriction extends AbstractJetDiagnosticsTest {
|
||||
public void testAllFilesPresentInNonExpansiveInheritanceRestriction() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/declarationChecks/nonExpansiveInheritanceRestriction"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("JavaWithKotlin.kt")
|
||||
public void testJavaWithKotlin() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/declarationChecks/nonExpansiveInheritanceRestriction/JavaWithKotlin.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("JavaWithKotlin2.kt")
|
||||
public void testJavaWithKotlin2() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/declarationChecks/nonExpansiveInheritanceRestriction/JavaWithKotlin2.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("PureKotlin.kt")
|
||||
public void testPureKotlin() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/declarationChecks/nonExpansiveInheritanceRestriction/PureKotlin.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/defaultArguments")
|
||||
|
||||
@@ -25,9 +25,7 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||
import org.jetbrains.kotlin.utils.toReadOnlyList
|
||||
import java.util.ArrayDeque
|
||||
import java.util.ArrayList
|
||||
import java.util.LinkedHashSet
|
||||
import java.util.*
|
||||
|
||||
public enum class TypeNullability {
|
||||
NOT_NULL,
|
||||
@@ -142,3 +140,41 @@ public fun KotlinType.isDefaultBound(): Boolean = KotlinBuiltIns.isDefaultBound(
|
||||
|
||||
public fun createProjection(type: KotlinType, projectionKind: Variance, typeParameterDescriptor: TypeParameterDescriptor?): TypeProjection =
|
||||
TypeProjectionImpl(if (typeParameterDescriptor?.variance == projectionKind) Variance.INVARIANT else projectionKind, type)
|
||||
|
||||
fun Collection<KtType>.closure(f: (KtType) -> Collection<KtType>): Collection<KtType> {
|
||||
if (size == 0) return this
|
||||
|
||||
val result = HashSet(this)
|
||||
var elementsToCheck = result
|
||||
var oldSize = 0
|
||||
while (result.size > oldSize) {
|
||||
oldSize = result.size
|
||||
val toAdd = hashSetOf<KtType>()
|
||||
elementsToCheck.forEach { toAdd.addAll(f(it)) }
|
||||
result.addAll(toAdd)
|
||||
elementsToCheck = toAdd
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
fun boundClosure(types: Collection<KtType>): Collection<KtType> =
|
||||
types.closure { type -> TypeUtils.getTypeParameterDescriptorOrNull(type)?.upperBounds ?: emptySet() }
|
||||
|
||||
fun constituentTypes(types: Collection<KtType>): Collection<KtType> {
|
||||
val result = hashSetOf<KtType>()
|
||||
constituentTypes(result, types)
|
||||
return result
|
||||
}
|
||||
|
||||
private fun constituentTypes(result: MutableSet<KtType>, types: Collection<KtType>) {
|
||||
result.addAll(types)
|
||||
for (type in types) {
|
||||
if (type.isFlexible()) {
|
||||
with (type.flexibility()) { constituentTypes(result, setOf(lowerBound, upperBound)) }
|
||||
}
|
||||
else {
|
||||
constituentTypes(result, type.arguments.filterNot { it.isStarProjection }.map { it.type })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user