Do not report "inconsistent bounds" when there are repeated bounds
Also slightly refactor DeclarationsChecker#checkSupertypesForConsistency
This commit is contained in:
@@ -179,35 +179,37 @@ class DeclarationsChecker(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkSupertypesForConsistency(
|
private fun checkSupertypesForConsistency(classifier: ClassifierDescriptor, sourceElement: PsiElement) {
|
||||||
classifierDescriptor: ClassifierDescriptor,
|
if (classifier is TypeParameterDescriptor) {
|
||||||
sourceElement: PsiElement) {
|
val immediateUpperBounds = classifier.upperBounds.map { it.constructor }
|
||||||
val multimap = SubstitutionUtils.buildDeepSubstitutionMultimap(classifierDescriptor.defaultType)
|
if (immediateUpperBounds.size != immediateUpperBounds.toSet().size) {
|
||||||
for ((typeParameterDescriptor, projections) in multimap.asMap().entries) {
|
// If there are duplicate type constructors among the _immediate_ upper bounds,
|
||||||
if (projections.size > 1) {
|
// then the REPEATED_BOUNDS diagnostic would be already reported for those bounds of this type parameter
|
||||||
// Immediate arguments of supertypes cannot be projected
|
return
|
||||||
val conflictingTypes = Sets.newLinkedHashSet<KotlinType>()
|
}
|
||||||
for (projection in projections) {
|
}
|
||||||
conflictingTypes.add(projection.type)
|
|
||||||
}
|
val multiMap = SubstitutionUtils.buildDeepSubstitutionMultimap(classifier.defaultType)
|
||||||
removeDuplicateTypes(conflictingTypes)
|
for ((typeParameterDescriptor, projections) in multiMap.asMap()) {
|
||||||
if (conflictingTypes.size > 1) {
|
if (projections.size <= 1) continue
|
||||||
val containingDeclaration = typeParameterDescriptor.containingDeclaration as? ClassDescriptor
|
|
||||||
?: throw AssertionError("Not a class descriptor : " + typeParameterDescriptor.containingDeclaration)
|
// Immediate arguments of supertypes cannot be projected
|
||||||
if (sourceElement is KtClassOrObject) {
|
val conflictingTypes = projections.map { it.type }.toMutableSet()
|
||||||
val delegationSpecifierList = sourceElement.getDelegationSpecifierList() ?: continue
|
removeDuplicateTypes(conflictingTypes)
|
||||||
trace.report(INCONSISTENT_TYPE_PARAMETER_VALUES.on(delegationSpecifierList,
|
if (conflictingTypes.size <= 1) continue
|
||||||
typeParameterDescriptor,
|
|
||||||
containingDeclaration,
|
val containingDeclaration = typeParameterDescriptor.containingDeclaration as? ClassDescriptor
|
||||||
conflictingTypes))
|
?: throw AssertionError("Not a class descriptor: " + typeParameterDescriptor.containingDeclaration)
|
||||||
}
|
if (sourceElement is KtClassOrObject) {
|
||||||
else if (sourceElement is KtTypeParameter) {
|
val delegationSpecifierList = sourceElement.getDelegationSpecifierList() ?: continue
|
||||||
trace.report(INCONSISTENT_TYPE_PARAMETER_BOUNDS.on(sourceElement,
|
trace.report(INCONSISTENT_TYPE_PARAMETER_VALUES.on(
|
||||||
typeParameterDescriptor,
|
delegationSpecifierList, typeParameterDescriptor, containingDeclaration, conflictingTypes
|
||||||
containingDeclaration,
|
))
|
||||||
conflictingTypes))
|
}
|
||||||
}
|
else if (sourceElement is KtTypeParameter) {
|
||||||
}
|
trace.report(INCONSISTENT_TYPE_PARAMETER_BOUNDS.on(
|
||||||
|
sourceElement, typeParameterDescriptor, containingDeclaration, conflictingTypes
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,15 +6,15 @@ interface B
|
|||||||
|
|
||||||
interface D<T>
|
interface D<T>
|
||||||
|
|
||||||
interface IncorrectF<<!MISPLACED_TYPE_PARAMETER_CONSTRAINTS, INCONSISTENT_TYPE_PARAMETER_BOUNDS!>T : D<A><!>> where T : <!REPEATED_BOUND!>D<B><!>
|
interface IncorrectF<<!MISPLACED_TYPE_PARAMETER_CONSTRAINTS!>T : D<A><!>> where T : <!REPEATED_BOUND!>D<B><!>
|
||||||
|
|
||||||
interface CorrectF<<!INCONSISTENT_TYPE_PARAMETER_BOUNDS!>T<!>> where T : D<A>, T : <!REPEATED_BOUND!>D<B><!>
|
interface CorrectF<T> where T : D<A>, T : <!REPEATED_BOUND!>D<B><!>
|
||||||
|
|
||||||
interface G<T>
|
interface G<T>
|
||||||
|
|
||||||
interface IncorrectH<<!MISPLACED_TYPE_PARAMETER_CONSTRAINTS, INCONSISTENT_TYPE_PARAMETER_BOUNDS!>T : G<D<A>><!>> where T : <!REPEATED_BOUND!>G<D<T>><!>
|
interface IncorrectH<<!MISPLACED_TYPE_PARAMETER_CONSTRAINTS!>T : G<D<A>><!>> where T : <!REPEATED_BOUND!>G<D<T>><!>
|
||||||
|
|
||||||
interface CorrectH<<!INCONSISTENT_TYPE_PARAMETER_BOUNDS!>T<!>> where T : G<D<A>>, T : <!REPEATED_BOUND!>G<D<B>><!>
|
interface CorrectH<T> where T : G<D<A>>, T : <!REPEATED_BOUND!>G<D<B>><!>
|
||||||
|
|
||||||
interface I<T : G<D<T>>> {
|
interface I<T : G<D<T>>> {
|
||||||
fun <<!MISPLACED_TYPE_PARAMETER_CONSTRAINTS, INCONSISTENT_TYPE_PARAMETER_BOUNDS!>S : T?<!>> incorrectFoo() where S : G<D<S>>
|
fun <<!MISPLACED_TYPE_PARAMETER_CONSTRAINTS, INCONSISTENT_TYPE_PARAMETER_BOUNDS!>S : T?<!>> incorrectFoo() where S : G<D<S>>
|
||||||
@@ -22,8 +22,8 @@ interface I<T : G<D<T>>> {
|
|||||||
fun <<!INCONSISTENT_TYPE_PARAMETER_BOUNDS!>S<!>> correctFoo() where S : T?, S : G<D<S>>
|
fun <<!INCONSISTENT_TYPE_PARAMETER_BOUNDS!>S<!>> correctFoo() where S : T?, S : G<D<S>>
|
||||||
}
|
}
|
||||||
|
|
||||||
interface incorrectJ<<!MISPLACED_TYPE_PARAMETER_CONSTRAINTS, INCONSISTENT_TYPE_PARAMETER_BOUNDS!>T: G<D<T>><!>> where T : <!REPEATED_BOUND!>G<D<T?>><!>
|
interface incorrectJ<<!MISPLACED_TYPE_PARAMETER_CONSTRAINTS!>T: G<D<T>><!>> where T : <!REPEATED_BOUND!>G<D<T?>><!>
|
||||||
|
|
||||||
interface correctJ<<!INCONSISTENT_TYPE_PARAMETER_BOUNDS!>T<!>> where T : G<D<T>>, T : <!REPEATED_BOUND!>G<D<T?>><!>
|
interface correctJ<T> where T : G<D<T>>, T : <!REPEATED_BOUND!>G<D<T?>><!>
|
||||||
|
|
||||||
fun <<!INCONSISTENT_TYPE_PARAMETER_BOUNDS!>T<!>> bar() where T : D<A>, T : <!REPEATED_BOUND!>D<B><!> {}
|
fun <T> bar() where T : D<A>, T : <!REPEATED_BOUND!>D<B><!> {}
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
fun <<!UPPER_BOUND_CANNOT_BE_ARRAY!>A : Array<Any><!>> f1() {}
|
fun <<!UPPER_BOUND_CANNOT_BE_ARRAY!>A : Array<Any><!>> f1() {}
|
||||||
fun <T, <!UPPER_BOUND_CANNOT_BE_ARRAY!>A : Array<out T><!>> f2() {}
|
fun <T, <!UPPER_BOUND_CANNOT_BE_ARRAY!>A : Array<out T><!>> f2() {}
|
||||||
fun <S, T : S, <!INCONSISTENT_TYPE_PARAMETER_BOUNDS, UPPER_BOUND_CANNOT_BE_ARRAY!>A<!>> f3() where A : Array<out S>, A : <!REPEATED_BOUND!>Array<out T><!> {}
|
fun <S, T : S, <!UPPER_BOUND_CANNOT_BE_ARRAY!>A<!>> f3() where A : Array<out S>, A : <!REPEATED_BOUND!>Array<out T><!> {}
|
||||||
|
|
||||||
fun <<!UPPER_BOUND_CANNOT_BE_ARRAY!>T : <!FINAL_UPPER_BOUND!>IntArray<!><!>> f4() {}
|
fun <<!UPPER_BOUND_CANNOT_BE_ARRAY!>T : <!FINAL_UPPER_BOUND!>IntArray<!><!>> f4() {}
|
||||||
|
|
||||||
@@ -9,7 +9,7 @@ fun <<!UPPER_BOUND_CANNOT_BE_ARRAY!>T<!>> f5() where T : Array<Any> {}
|
|||||||
val <<!UPPER_BOUND_CANNOT_BE_ARRAY!>T : Array<Any?><!>> T.v: String get() = ""
|
val <<!UPPER_BOUND_CANNOT_BE_ARRAY!>T : Array<Any?><!>> T.v: String get() = ""
|
||||||
|
|
||||||
class C2<T, <!UPPER_BOUND_CANNOT_BE_ARRAY!>A : Array<out T><!>>
|
class C2<T, <!UPPER_BOUND_CANNOT_BE_ARRAY!>A : Array<out T><!>>
|
||||||
interface C3<S, T : S, <!INCONSISTENT_TYPE_PARAMETER_BOUNDS, UPPER_BOUND_CANNOT_BE_ARRAY!>A<!>> where A : Array<out S>, A : <!REPEATED_BOUND!>Array<out T><!>
|
interface C3<S, T : S, <!UPPER_BOUND_CANNOT_BE_ARRAY!>A<!>> where A : Array<out S>, A : <!REPEATED_BOUND!>Array<out T><!>
|
||||||
|
|
||||||
fun foo() {
|
fun foo() {
|
||||||
class C1<<!UPPER_BOUND_CANNOT_BE_ARRAY!>A : Array<Any><!>> {
|
class C1<<!UPPER_BOUND_CANNOT_BE_ARRAY!>A : Array<Any><!>> {
|
||||||
|
|||||||
+2
-2
@@ -6,6 +6,6 @@ interface B
|
|||||||
|
|
||||||
interface D<T>
|
interface D<T>
|
||||||
|
|
||||||
interface CorrectF<<error descr="[INCONSISTENT_TYPE_PARAMETER_BOUNDS] Type parameter T of 'D' has inconsistent bounds: A, B">T</error>> where T : D<A>, T : <error descr="[REPEATED_BOUND] Type parameter already has this bound">D<B></error>
|
interface CorrectF<T> where T : D<A>, T : <error descr="[REPEATED_BOUND] Type parameter already has this bound">D<B></error>
|
||||||
|
|
||||||
fun <<error descr="[INCONSISTENT_TYPE_PARAMETER_BOUNDS] Type parameter T of 'D' has inconsistent bounds: A, B">T</error>> bar() where T : D<A>, T : <error descr="[REPEATED_BOUND] Type parameter already has this bound">D<B></error> {}
|
fun <T> bar() where T : D<A>, T : <error descr="[REPEATED_BOUND] Type parameter already has this bound">D<B></error> {}
|
||||||
|
|||||||
Reference in New Issue
Block a user