Report error on more than one class bound for type parameters
Such code may behave unexpectedly when compiled to JVM
This commit is contained in:
@@ -264,6 +264,7 @@ public interface Errors {
|
||||
DiagnosticFactory1<KtTypeReference, KotlinType> FINAL_UPPER_BOUND = DiagnosticFactory1.create(WARNING);
|
||||
DiagnosticFactory0<KtTypeReference> DYNAMIC_UPPER_BOUND = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtTypeReference> UPPER_BOUND_IS_EXTENSION_FUNCTION_TYPE = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtTypeReference> ONLY_ONE_CLASS_BOUND_ALLOWED = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
DiagnosticFactory1<KtNamedDeclaration, TypeParameterDescriptor> CONFLICTING_UPPER_BOUNDS =
|
||||
DiagnosticFactory1.create(ERROR, DECLARATION_NAME);
|
||||
|
||||
+1
@@ -394,6 +394,7 @@ public class DefaultErrorMessages {
|
||||
MAP.put(UPPER_BOUND_VIOLATED, "Type argument is not within its bounds: should be subtype of ''{0}''", RENDER_TYPE, RENDER_TYPE);
|
||||
MAP.put(FINAL_UPPER_BOUND, "''{0}'' is a final type, and thus a value of the type parameter is predetermined", RENDER_TYPE);
|
||||
MAP.put(UPPER_BOUND_IS_EXTENSION_FUNCTION_TYPE, "Extension function type can not be used as an upper bound");
|
||||
MAP.put(ONLY_ONE_CLASS_BOUND_ALLOWED, "Only one of the upper bounds can be a class");
|
||||
MAP.put(DYNAMIC_UPPER_BOUND, "Dynamic type can not be used as an upper bound");
|
||||
MAP.put(USELESS_ELVIS, "Elvis operator (?:) always returns the left operand of non-nullable type {0}", RENDER_TYPE);
|
||||
MAP.put(USELESS_ELVIS_ON_FUNCTION_LITERAL, "Left operand of elvis operator (?:) is function literal");
|
||||
|
||||
@@ -23,19 +23,19 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory0
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.diagnostics.Errors.*
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||
import org.jetbrains.kotlin.types.typeUtil.*
|
||||
|
||||
import java.util.*
|
||||
|
||||
import org.jetbrains.kotlin.diagnostics.Errors.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext.TYPE
|
||||
import org.jetbrains.kotlin.resolve.BindingContext.TYPE_PARAMETER
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils.classCanHaveAbstractMembers
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils.classCanHaveOpenMembers
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.SubstitutionUtils
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||
import org.jetbrains.kotlin.types.typeUtil.isNothing
|
||||
import java.util.*
|
||||
|
||||
fun KtDeclaration.checkTypeReferences(trace: BindingTrace) {
|
||||
if (this is KtCallableDeclaration) {
|
||||
@@ -147,38 +147,35 @@ class DeclarationsChecker(
|
||||
}
|
||||
|
||||
private fun checkTypesInClassHeader(classOrObject: KtClassOrObject) {
|
||||
fun KtTypeReference.type(): KotlinType? = trace.bindingContext.get(TYPE, this)
|
||||
|
||||
for (delegationSpecifier in classOrObject.getDelegationSpecifiers()) {
|
||||
delegationSpecifier.typeReference?.check(checkBoundsForTypeInClassHeader = true)
|
||||
val typeReference = delegationSpecifier.typeReference ?: continue
|
||||
typeReference.type()?.let { DescriptorResolver.checkBounds(typeReference, it, trace) }
|
||||
typeReference.checkNotEnumEntry(trace)
|
||||
}
|
||||
|
||||
if (classOrObject !is KtClass) return
|
||||
|
||||
for (jetTypeParameter in classOrObject.typeParameters) {
|
||||
jetTypeParameter.extendsBound?.check(checkBoundsForTypeInClassHeader = true, checkFinalUpperBounds = true)
|
||||
val tasks = ArrayList<DescriptorResolver.UpperBoundCheckerTask>()
|
||||
|
||||
for (typeParameter in classOrObject.typeParameters) {
|
||||
val typeReference = typeParameter.extendsBound ?: continue
|
||||
val type = typeReference.type() ?: continue
|
||||
tasks.add(DescriptorResolver.UpperBoundCheckerTask(typeParameter.nameAsName, typeReference, type))
|
||||
}
|
||||
|
||||
for (constraint in classOrObject.typeConstraints) {
|
||||
constraint.boundTypeReference?.check(checkBoundsForTypeInClassHeader = true, checkFinalUpperBounds = true)
|
||||
val typeReference = constraint.boundTypeReference ?: continue
|
||||
val type = typeReference.type() ?: continue
|
||||
val name = constraint.subjectTypeParameterName?.getReferencedNameAsName() ?: continue
|
||||
tasks.add(DescriptorResolver.UpperBoundCheckerTask(name, typeReference, type))
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtTypeReference.checkBoundsForTypeInClassHeader() {
|
||||
trace.bindingContext.get(TYPE, this)?.let { DescriptorResolver.checkBounds(this, it, trace) }
|
||||
}
|
||||
DescriptorResolver.checkUpperBoundTypes(trace, tasks)
|
||||
|
||||
private fun KtTypeReference.checkFinalUpperBounds() {
|
||||
trace.bindingContext.get(TYPE, this)?.let { DescriptorResolver.checkUpperBoundType(this, it, trace) }
|
||||
}
|
||||
|
||||
private fun KtTypeReference.check(checkBoundsForTypeInClassHeader: Boolean = false, checkFinalUpperBounds: Boolean = false) {
|
||||
if (checkFinalUpperBounds) {
|
||||
checkFinalUpperBounds()
|
||||
}
|
||||
else {
|
||||
checkNotEnumEntry(trace)
|
||||
}
|
||||
if (checkBoundsForTypeInClassHeader) {
|
||||
checkBoundsForTypeInClassHeader()
|
||||
for (task in tasks) {
|
||||
DescriptorResolver.checkBounds(task.upperBound, task.upperBoundType, trace)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -458,10 +458,12 @@ public class DescriptorResolver {
|
||||
}
|
||||
|
||||
static final class UpperBoundCheckerTask {
|
||||
KtTypeReference upperBound;
|
||||
KotlinType upperBoundType;
|
||||
public final Name typeParameterName;
|
||||
public final KtTypeReference upperBound;
|
||||
public final KotlinType upperBoundType;
|
||||
|
||||
private UpperBoundCheckerTask(KtTypeReference upperBound, KotlinType upperBoundType) {
|
||||
UpperBoundCheckerTask(Name typeParameterName, KtTypeReference upperBound, KotlinType upperBoundType) {
|
||||
this.typeParameterName = typeParameterName;
|
||||
this.upperBound = upperBound;
|
||||
this.upperBoundType = upperBoundType;
|
||||
}
|
||||
@@ -479,16 +481,16 @@ public class DescriptorResolver {
|
||||
List<KtTypeParameter> typeParameters = declaration.getTypeParameters();
|
||||
Map<Name, TypeParameterDescriptorImpl> parameterByName = Maps.newHashMap();
|
||||
for (int i = 0; i < typeParameters.size(); i++) {
|
||||
KtTypeParameter jetTypeParameter = typeParameters.get(i);
|
||||
KtTypeParameter ktTypeParameter = typeParameters.get(i);
|
||||
TypeParameterDescriptorImpl typeParameterDescriptor = parameters.get(i);
|
||||
|
||||
parameterByName.put(typeParameterDescriptor.getName(), typeParameterDescriptor);
|
||||
|
||||
KtTypeReference extendsBound = jetTypeParameter.getExtendsBound();
|
||||
KtTypeReference extendsBound = ktTypeParameter.getExtendsBound();
|
||||
if (extendsBound != null) {
|
||||
KotlinType type = typeResolver.resolveType(scope, extendsBound, trace, false);
|
||||
typeParameterDescriptor.addUpperBound(type);
|
||||
deferredUpperBoundCheckerTasks.add(new UpperBoundCheckerTask(extendsBound, type));
|
||||
deferredUpperBoundCheckerTasks.add(new UpperBoundCheckerTask(ktTypeParameter.getNameAsName(), extendsBound, type));
|
||||
}
|
||||
}
|
||||
for (KtTypeConstraint constraint : declaration.getTypeConstraints()) {
|
||||
@@ -502,7 +504,7 @@ public class DescriptorResolver {
|
||||
KotlinType bound = null;
|
||||
if (boundTypeReference != null) {
|
||||
bound = typeResolver.resolveType(scope, boundTypeReference, trace, false);
|
||||
deferredUpperBoundCheckerTasks.add(new UpperBoundCheckerTask(boundTypeReference, bound));
|
||||
deferredUpperBoundCheckerTasks.add(new UpperBoundCheckerTask(referencedName, boundTypeReference, bound));
|
||||
}
|
||||
|
||||
if (typeParameterDescriptor != null) {
|
||||
@@ -523,11 +525,33 @@ public class DescriptorResolver {
|
||||
}
|
||||
|
||||
if (!(declaration instanceof KtClass)) {
|
||||
for (UpperBoundCheckerTask checkerTask : deferredUpperBoundCheckerTasks) {
|
||||
checkUpperBoundType(checkerTask.upperBound, checkerTask.upperBoundType, trace);
|
||||
checkUpperBoundTypes(trace, deferredUpperBoundCheckerTasks);
|
||||
checkNamesInConstraints(declaration, descriptor, scope, trace);
|
||||
}
|
||||
}
|
||||
|
||||
public static void checkUpperBoundTypes(@NotNull BindingTrace trace, @NotNull List<UpperBoundCheckerTask> tasks) {
|
||||
if (tasks.isEmpty()) return;
|
||||
|
||||
Set<Name> classBoundEncountered = new HashSet<Name>();
|
||||
for (UpperBoundCheckerTask checkerTask : tasks) {
|
||||
Name typeParameterName = checkerTask.typeParameterName;
|
||||
KotlinType upperBound = checkerTask.upperBoundType;
|
||||
KtTypeReference upperBoundElement = checkerTask.upperBound;
|
||||
|
||||
if (!upperBound.isError()) {
|
||||
ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(upperBound);
|
||||
if (classDescriptor != null) {
|
||||
ClassKind kind = classDescriptor.getKind();
|
||||
if (kind == ClassKind.CLASS || kind == ClassKind.ENUM_CLASS || kind == ClassKind.OBJECT) {
|
||||
if (!classBoundEncountered.add(typeParameterName)) {
|
||||
trace.report(ONLY_ONE_CLASS_BOUND_ALLOWED.on(upperBoundElement));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
checkNamesInConstraints(declaration, descriptor, scope, trace);
|
||||
checkUpperBoundType(upperBoundElement, upperBound, trace);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-2
@@ -1,8 +1,10 @@
|
||||
val <T> T.valProp: T where T : Number, T : Int
|
||||
import java.io.Serializable
|
||||
|
||||
val <T> T.valProp: T where T : Number, T : Serializable
|
||||
get() = this
|
||||
|
||||
fun box(): String {
|
||||
0.valProp
|
||||
|
||||
return "OK"
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -48,7 +48,7 @@ class Bar<T : <!FINAL_UPPER_BOUND!>Foo<!>>
|
||||
class Buzz<T> where T : <!FINAL_UPPER_BOUND!>Bar<<!UPPER_BOUND_VIOLATED!>Int<!>><!>, T : <!UNRESOLVED_REFERENCE!>nioho<!>
|
||||
|
||||
class X<T : <!FINAL_UPPER_BOUND!>Foo<!>>
|
||||
class Y<<!CONFLICTING_UPPER_BOUNDS!>T<!>> where T : <!FINAL_UPPER_BOUND!>Foo<!>, T : <!FINAL_UPPER_BOUND!>Bar<Foo><!>
|
||||
class Y<<!CONFLICTING_UPPER_BOUNDS!>T<!>> where T : <!FINAL_UPPER_BOUND!>Foo<!>, T : <!ONLY_ONE_CLASS_BOUND_ALLOWED, FINAL_UPPER_BOUND!>Bar<Foo><!>
|
||||
|
||||
fun <T> test2(t : T)
|
||||
where
|
||||
|
||||
-6
@@ -15,10 +15,4 @@ fun <T, N: T, INDIRECT: N> misleadingNullableSimple(
|
||||
<!UNUSED_PARAMETER!>ind<!>: INDIRECT?
|
||||
) {}
|
||||
|
||||
fun <FIRST_BOUND, SECOND_BOUND> misleadingNullableMultiBound(
|
||||
<!UNUSED_PARAMETER!>fb<!>: FIRST_BOUND?,
|
||||
<!UNUSED_PARAMETER!>sb<!>: SECOND_BOUND?
|
||||
) where FIRST_BOUND: Any?, FIRST_BOUND: Any, SECOND_BOUND: Any, SECOND_BOUND: Any? {
|
||||
}
|
||||
|
||||
fun <T> interactionWithRedundant(<!UNUSED_PARAMETER!>t<!>: T?<!REDUNDANT_NULLABLE!>?<!>) {}
|
||||
-1
@@ -1,7 +1,6 @@
|
||||
package
|
||||
|
||||
public fun </*0*/ T> interactionWithRedundant(/*0*/ t: T?): kotlin.Unit
|
||||
public fun </*0*/ FIRST_BOUND, /*1*/ SECOND_BOUND : kotlin.Any> misleadingNullableMultiBound(/*0*/ fb: FIRST_BOUND?, /*1*/ sb: SECOND_BOUND?): kotlin.Unit where FIRST_BOUND : kotlin.Any, SECOND_BOUND : kotlin.Any?
|
||||
public fun </*0*/ T, /*1*/ N : T, /*2*/ INDIRECT : N> misleadingNullableSimple(/*0*/ t: T?, /*1*/ t2: T?, /*2*/ n: N?, /*3*/ ind: INDIRECT?): kotlin.Unit
|
||||
public fun </*0*/ NN : kotlin.Any, /*1*/ NNN : NN> nonMisleadingNullable(/*0*/ nn: NN?, /*1*/ nnn: NNN?): kotlin.Unit
|
||||
public fun </*0*/ NN : kotlin.Any, /*1*/ TWO_BOUNDS : kotlin.Any> twoBounds(/*0*/ tb: TWO_BOUNDS?): kotlin.Unit where TWO_BOUNDS : NN
|
||||
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
open class C1
|
||||
open class C2
|
||||
open class C3 : C2()
|
||||
|
||||
class A1<T> where T : C1, T : <!ONLY_ONE_CLASS_BOUND_ALLOWED!>C2<!>
|
||||
class A2<T> where T : C1, T : <!ONLY_ONE_CLASS_BOUND_ALLOWED!>C2<!>, T : <!ONLY_ONE_CLASS_BOUND_ALLOWED!>C3<!>
|
||||
class A3<T> where T : C2, T : <!ONLY_ONE_CLASS_BOUND_ALLOWED!>C3<!>
|
||||
class A4<T> where T : C3, T : <!ONLY_ONE_CLASS_BOUND_ALLOWED!>C2<!>
|
||||
|
||||
fun <T> f1() where T : C1, T : <!ONLY_ONE_CLASS_BOUND_ALLOWED!>C2<!>, T : <!ONLY_ONE_CLASS_BOUND_ALLOWED!>C3<!> {}
|
||||
fun <T> f2() where T : C2, T : <!ONLY_ONE_CLASS_BOUND_ALLOWED!>C3<!> {}
|
||||
fun <T> f3() where T : C3, T : <!ONLY_ONE_CLASS_BOUND_ALLOWED!>C2<!> {}
|
||||
|
||||
enum class E1
|
||||
class A5<<!CONFLICTING_UPPER_BOUNDS!>T<!>> where T : C1, T : <!ONLY_ONE_CLASS_BOUND_ALLOWED, FINAL_UPPER_BOUND!>E1<!>
|
||||
|
||||
object O1
|
||||
class A6<<!CONFLICTING_UPPER_BOUNDS!>T<!>> where T : <!FINAL_UPPER_BOUND!>O1<!>, T : <!ONLY_ONE_CLASS_BOUND_ALLOWED!>C2<!>
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
package
|
||||
|
||||
public fun </*0*/ T : C1> f1(): kotlin.Unit where T : C2, T : C3
|
||||
public fun </*0*/ T : C2> f2(): kotlin.Unit where T : C3
|
||||
public fun </*0*/ T : C3> f3(): kotlin.Unit where T : C2
|
||||
|
||||
public final class A1</*0*/ T : C1> where T : C2 {
|
||||
public constructor A1</*0*/ T : C1>() where T : C2
|
||||
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 A2</*0*/ T : C1> where T : C2, T : C3 {
|
||||
public constructor A2</*0*/ T : C1>() where T : C2, T : C3
|
||||
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 A3</*0*/ T : C2> where T : C3 {
|
||||
public constructor A3</*0*/ T : C2>() where T : C3
|
||||
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 A4</*0*/ T : C3> where T : C2 {
|
||||
public constructor A4</*0*/ T : C3>() where T : C2
|
||||
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 A5</*0*/ T : C1> where T : E1 {
|
||||
public constructor A5</*0*/ T : C1>() where T : E1
|
||||
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 A6</*0*/ T : O1> where T : C2 {
|
||||
public constructor A6</*0*/ T : O1>() where T : C2
|
||||
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 open class C1 {
|
||||
public constructor C1()
|
||||
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 open class C2 {
|
||||
public constructor C2()
|
||||
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 open class C3 : C2 {
|
||||
public constructor C3()
|
||||
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 enum class E1 : kotlin.Enum<E1> {
|
||||
private constructor E1()
|
||||
public final override /*1*/ /*fake_override*/ val name: kotlin.String
|
||||
public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int
|
||||
protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any
|
||||
public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: E1): kotlin.Int
|
||||
public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
// Static members
|
||||
@kotlin.Deprecated(message = "Use 'values()' function instead", replaceWith = kotlin.ReplaceWith(expression = "this.values()", imports = {})) public final /*synthesized*/ val values: kotlin.Array<E1>
|
||||
public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): E1
|
||||
public final /*synthesized*/ fun values(): kotlin.Array<E1>
|
||||
}
|
||||
|
||||
public object O1 {
|
||||
private constructor O1()
|
||||
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
|
||||
}
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
fun <<!UPPER_BOUND_CANNOT_BE_ARRAY!>A : Array<Any><!>> f1() {}
|
||||
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 : Array<out T> {}
|
||||
fun <S, T : S, <!INCONSISTENT_TYPE_PARAMETER_BOUNDS, UPPER_BOUND_CANNOT_BE_ARRAY!>A<!>> f3() where A : Array<out S>, A : <!ONLY_ONE_CLASS_BOUND_ALLOWED!>Array<out T><!> {}
|
||||
|
||||
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() = ""
|
||||
|
||||
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 : Array<out T>
|
||||
interface C3<S, T : S, <!INCONSISTENT_TYPE_PARAMETER_BOUNDS, UPPER_BOUND_CANNOT_BE_ARRAY!>A<!>> where A : Array<out S>, A : <!ONLY_ONE_CLASS_BOUND_ALLOWED!>Array<out T><!>
|
||||
|
||||
fun foo() {
|
||||
class C1<<!UPPER_BOUND_CANNOT_BE_ARRAY!>A : Array<Any><!>> {
|
||||
|
||||
@@ -16986,6 +16986,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/typeParameters"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("cannotHaveManyClassUpperBounds.kt")
|
||||
public void testCannotHaveManyClassUpperBounds() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/typeParameters/cannotHaveManyClassUpperBounds.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("deprecatedSyntax.kt")
|
||||
public void testDeprecatedSyntax() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/typeParameters/deprecatedSyntax.kt");
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ class Bar<T : <warning>Foo</warning>>
|
||||
class Buzz<T> where T : <warning>Bar<<error>Int</error>></warning>, T : <error>nioho</error>
|
||||
|
||||
class X<T : <warning>Foo</warning>>
|
||||
class Y<<error>T</error>> where T : <warning>Foo</warning>, T : <warning>Bar<Foo></warning>
|
||||
class Y<<error>T</error>> where T : <warning>Foo</warning>, T : <error>Bar<Foo></error>
|
||||
|
||||
fun <T> test2(t : T)
|
||||
where
|
||||
|
||||
Reference in New Issue
Block a user