Fix implicit type arguments resolution for inner classes
When resolving arguments on inner classifier, one can omit the arguments for outer class 'Outer' if they are present implicitly in the scope: - One of the supertypes of current class is Outer - One of the outer classes or one of their supertypes is Outer Relevant arguments are obtained from the first type found by the algorithm above Note that before this commit implicit arguments were only been searched in containing classes #KT-11123 Fixed
This commit is contained in:
@@ -25,7 +25,6 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.VariableDescriptorImpl
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.diagnostics.Errors.*
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
@@ -36,10 +35,12 @@ import org.jetbrains.kotlin.resolve.PossiblyBareType.type
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.recordScope
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.DynamicCallableDescriptors
|
||||
import org.jetbrains.kotlin.resolve.calls.util.createFunctionType
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.findImplicitOuterClassArguments
|
||||
import org.jetbrains.kotlin.resolve.scopes.LazyScopeAdapter
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScopeKind
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.utils.findClassifier
|
||||
import org.jetbrains.kotlin.resolve.scopes.utils.findFirstFromMeAndParent
|
||||
import org.jetbrains.kotlin.resolve.source.toSourceElement
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
@@ -379,7 +380,7 @@ class TypeResolver(
|
||||
return createErrorTypeForTypeConstructor(c, projectionFromAllQualifierParts, typeConstructor)
|
||||
}
|
||||
|
||||
val collectedArgumentAsTypeProjections =
|
||||
val (collectedArgumentAsTypeProjections, argumentsForOuterClass) =
|
||||
collectArgumentsForClassifierTypeConstructor(c, classDescriptor, qualifierResolutionResult.qualifierParts)
|
||||
?: return createErrorTypeForTypeConstructor(c, projectionFromAllQualifierParts, typeConstructor)
|
||||
|
||||
@@ -389,7 +390,7 @@ class TypeResolver(
|
||||
}
|
||||
|
||||
val argumentsFromUserType = resolveTypeProjections(c, typeConstructor, collectedArgumentAsTypeProjections)
|
||||
val arguments = argumentsFromUserType + appendDefaultArgumentsForInnerScope(argumentsFromUserType.size, parameters)
|
||||
val arguments = buildFinalArgumentList(argumentsFromUserType, argumentsForOuterClass, parameters)
|
||||
|
||||
assert(arguments.size == parameters.size) {
|
||||
"Collected arguments count should be equal to parameters count," +
|
||||
@@ -423,6 +424,15 @@ class TypeResolver(
|
||||
return type(resultingType)
|
||||
}
|
||||
|
||||
private fun buildFinalArgumentList(
|
||||
argumentsFromUserType: List<TypeProjection>,
|
||||
argumentsForOuterClass: List<TypeProjection>?,
|
||||
parameters: List<TypeParameterDescriptor>
|
||||
): List<TypeProjection> {
|
||||
return argumentsFromUserType +
|
||||
(argumentsForOuterClass ?: appendDefaultArgumentsForLocalClassifier(argumentsFromUserType.size, parameters))
|
||||
}
|
||||
|
||||
private fun shouldCheckBounds(c: TypeResolutionContext, inType: KotlinType): Boolean {
|
||||
if (!c.checkBounds) return false
|
||||
if (inType.containsTypeAliasParameters()) return false
|
||||
@@ -455,13 +465,13 @@ class TypeResolver(
|
||||
qualifierResolutionResult.qualifierParts.lastOrNull()
|
||||
?: return createErrorTypeForTypeConstructor(c, projectionFromAllQualifierParts, typeConstructor)
|
||||
|
||||
val argumentElementsFromUserType =
|
||||
val (argumentElementsFromUserType, argumentsForOuterClass) =
|
||||
collectArgumentsForClassifierTypeConstructor(c, descriptor, qualifierResolutionResult.qualifierParts)
|
||||
?: return createErrorTypeForTypeConstructor(c, projectionFromAllQualifierParts, typeConstructor)
|
||||
|
||||
val argumentsFromUserType = resolveTypeProjections(c, typeConstructor, argumentElementsFromUserType)
|
||||
|
||||
val arguments = argumentsFromUserType + appendDefaultArgumentsForInnerScope(argumentsFromUserType.size, parameters)
|
||||
val arguments = buildFinalArgumentList(argumentsFromUserType, argumentsForOuterClass, parameters)
|
||||
|
||||
val reportStrategy = TracingTypeAliasExpansionReportStrategy(
|
||||
c.trace,
|
||||
@@ -562,11 +572,17 @@ class TypeResolver(
|
||||
return firstTypeParameter.original.containingDeclaration is ClassDescriptor
|
||||
}
|
||||
|
||||
/**
|
||||
* @return yet unresolved KtTypeProjection arguments and already resolved ones relevant to an outer class
|
||||
* @return null if error was reported
|
||||
*
|
||||
* If second component is null then rest of the arguments should be appended using default types of relevant parameters
|
||||
*/
|
||||
private fun collectArgumentsForClassifierTypeConstructor(
|
||||
c: TypeResolutionContext,
|
||||
classifierDescriptor: ClassifierDescriptorWithTypeParameters,
|
||||
qualifierParts: List<QualifiedExpressionResolver.QualifierPart>
|
||||
): List<KtTypeProjection>? {
|
||||
): Pair<List<KtTypeProjection>, List<TypeProjection>?>? {
|
||||
val classifierDescriptorChain = classifierDescriptor.classifierDescriptorsFromInnerToOuter()
|
||||
val reversedQualifierParts = qualifierParts.asReversed()
|
||||
|
||||
@@ -615,15 +631,42 @@ class TypeResolver(
|
||||
|
||||
val parameters = classifierDescriptor.typeConstructor.parameters
|
||||
if (result.size < parameters.size) {
|
||||
val typeParametersToSpecify =
|
||||
parameters.subList(result.size, parameters.size).takeWhile { it.original.containingDeclaration is ClassDescriptor }
|
||||
if (typeParametersToSpecify.any { parameter -> !parameter.isDeclaredInScope(c) }) {
|
||||
c.trace.report(WRONG_NUMBER_OF_TYPE_ARGUMENTS.on(qualifierParts.last().expression, parameters.size, classifierDescriptor))
|
||||
val nextParameterOwner =
|
||||
parameters[result.size].original.containingDeclaration as? ClassDescriptor
|
||||
// If next parameter is captured from the enclosing function, default arguments must be used
|
||||
// (see appendDefaultArgumentsForLocalClassifier)
|
||||
?: return Pair(result, null)
|
||||
|
||||
val restArguments = c.scope.findImplicitOuterClassArguments(nextParameterOwner)
|
||||
val restParameters = parameters.subList(result.size, parameters.size)
|
||||
|
||||
val typeArgumentsCanBeSpecifiedCount =
|
||||
classifierDescriptor.classifierDescriptorsFromInnerToOuter().sumBy { it.declaredTypeParameters.size }
|
||||
|
||||
if (restArguments == null && typeArgumentsCanBeSpecifiedCount > result.size) {
|
||||
c.trace.report(
|
||||
WRONG_NUMBER_OF_TYPE_ARGUMENTS.on(
|
||||
qualifierParts.last().expression, typeArgumentsCanBeSpecifiedCount, classifierDescriptor))
|
||||
return null
|
||||
}
|
||||
else if (restArguments == null) {
|
||||
assert(typeArgumentsCanBeSpecifiedCount == result.size) {
|
||||
"Number of type arguments that can be specified ($typeArgumentsCanBeSpecifiedCount) " +
|
||||
"should be equal to actual arguments number ${result.size}, (classifier: $classifierDescriptor)"
|
||||
}
|
||||
return Pair(result, null)
|
||||
}
|
||||
else {
|
||||
assert(restParameters.size == restArguments.size) {
|
||||
"Number of type of restParameters should be equal to ${restArguments.size}, " +
|
||||
"but ${restArguments.size} were found for $classifierDescriptor/$nextParameterOwner"
|
||||
}
|
||||
|
||||
return Pair(result, restArguments)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
return Pair(result, null)
|
||||
}
|
||||
|
||||
private fun ClassifierDescriptor?.classifierDescriptorsFromInnerToOuter(): List<ClassifierDescriptorWithTypeParameters> =
|
||||
@@ -632,42 +675,22 @@ class TypeResolver(
|
||||
{ it.containingDeclaration as? ClassifierDescriptorWithTypeParameters }
|
||||
).toList()
|
||||
|
||||
private fun TypeParameterDescriptor.isDeclaredInScope(c: TypeResolutionContext): Boolean {
|
||||
assert(containingDeclaration is ClassifierDescriptorWithTypeParameters) {
|
||||
"This function is implemented for ClassifierDescriptorWithTypeParameters only, but $containingDeclaration was given"
|
||||
}
|
||||
|
||||
// This function checks whether this@TypeParameterDescriptor ()is reachable from current scope by it's name
|
||||
// The only way it can be is that we are within class that contains it
|
||||
// We could just walk through containing declarations as it's done on last return, but it can be rather slow, so we at first look into scope.
|
||||
// Latter can fail if we found some other classifier with same name, but parameter can still be reachable, so
|
||||
// in case of fail we fall back into slow but exact computation.
|
||||
|
||||
val contributedClassifier = c.scope.findClassifier(name, NoLookupLocation.WHEN_RESOLVING_DEFAULT_TYPE_ARGUMENTS) ?: return false
|
||||
if (contributedClassifier.typeConstructor == typeConstructor) return true
|
||||
|
||||
return c.scope.ownerDescriptor.isInsideOfClass(original.containingDeclaration as ClassifierDescriptorWithTypeParameters)
|
||||
}
|
||||
|
||||
private fun DeclarationDescriptor.isInsideOfClass(classifierDescriptor: ClassifierDescriptorWithTypeParameters)
|
||||
= generateSequence(this, { it.containingDeclaration }).any { it.original == classifierDescriptor }
|
||||
|
||||
|
||||
private fun resolveTypeProjectionsWithErrorConstructor(
|
||||
c: TypeResolutionContext,
|
||||
argumentElements: List<KtTypeProjection>,
|
||||
message: String = "Error type for resolving type projections"
|
||||
) = resolveTypeProjections(c, ErrorUtils.createErrorTypeConstructor(message), argumentElements)
|
||||
|
||||
// In cases like
|
||||
// class Outer<F> {
|
||||
// inner class Inner<E>
|
||||
// val inner: Inner<String>
|
||||
// }
|
||||
//
|
||||
// FQ type of 'inner' val is Outer<F>.Inner<String> (saying strictly it's Outer.Inner<String, F>), but 'F' is implicitly came from scope
|
||||
// So we just add it explicitly to make type complete, in a sense of having arguments count equal to parameters one.
|
||||
private fun appendDefaultArgumentsForInnerScope(
|
||||
/**
|
||||
* For cases like:
|
||||
* fun <E> foo() {
|
||||
* class Local<F>
|
||||
* val x: Local<Int> <-- resolve this type
|
||||
* }
|
||||
*
|
||||
* type constructor for `Local` captures type parameter E from containing outer function
|
||||
*/
|
||||
private fun appendDefaultArgumentsForLocalClassifier(
|
||||
fromIndex: Int,
|
||||
constructorParameters: List<TypeParameterDescriptor>
|
||||
) = constructorParameters.subList(fromIndex, constructorParameters.size).map {
|
||||
@@ -712,6 +735,19 @@ class TypeResolver(
|
||||
}
|
||||
}
|
||||
|
||||
private fun LexicalScope.findImplicitOuterClassArguments(
|
||||
outerClass: ClassDescriptor
|
||||
): List<TypeProjection>? {
|
||||
val enclosingClass = findFirstFromMeAndParent { scope ->
|
||||
if (scope is LexicalScope && scope.kind == LexicalScopeKind.CLASS_MEMBER_SCOPE)
|
||||
scope.ownerDescriptor as ClassDescriptor
|
||||
else
|
||||
null
|
||||
} ?: return null
|
||||
|
||||
return findImplicitOuterClassArguments(enclosingClass, outerClass)
|
||||
}
|
||||
|
||||
fun resolveClass(
|
||||
scope: LexicalScope, userType: KtUserType, trace: BindingTrace, isDebuggerContext: Boolean
|
||||
): ClassifierDescriptor? = resolveDescriptorForType(scope, userType, trace, isDebuggerContext).classifierDescriptor
|
||||
|
||||
Vendored
+21
@@ -0,0 +1,21 @@
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE
|
||||
open class Outer<E> {
|
||||
inner class Inner<F>
|
||||
|
||||
}
|
||||
|
||||
class Derived : Outer<String>() {
|
||||
// Inner<Int> here means Outer<String>.Inner<Int>
|
||||
fun foo(x: Inner<Int>) {}
|
||||
}
|
||||
|
||||
class A {
|
||||
companion object : Outer<String>()
|
||||
|
||||
// Does not work, could be Outer<String>.Inner<Int>
|
||||
// TODO: Should work?
|
||||
fun foo(x: <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>Inner<!><Int>) {
|
||||
// Inner<Char>() call use companion as implicit receiver
|
||||
val y: Outer<String>.Inner<Char> = Inner<Char>()
|
||||
}
|
||||
}
|
||||
Vendored
+38
@@ -0,0 +1,38 @@
|
||||
package
|
||||
|
||||
public final class A {
|
||||
public constructor A()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public final fun foo(/*0*/ x: [ERROR : Inner]<kotlin.Int>): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
public companion object Companion : Outer<kotlin.String> {
|
||||
private constructor Companion()
|
||||
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 Derived : Outer<kotlin.String> {
|
||||
public constructor Derived()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public final fun foo(/*0*/ x: Outer<kotlin.String>.Inner<kotlin.Int>): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public open class Outer</*0*/ E> {
|
||||
public constructor Outer</*0*/ E>()
|
||||
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 inner class Inner</*0*/ F> /*captured type parameters: /*1*/ E*/ {
|
||||
public constructor Inner</*0*/ F>()
|
||||
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
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
class A<T> {
|
||||
fun foo() {
|
||||
val q = object {
|
||||
open inner class B
|
||||
inner class C : B()
|
||||
|
||||
// No WRONG_NUMBER_OF_TYPE_ARGUMENTS should be reported on these types
|
||||
val x: B = B()
|
||||
val y: C = C()
|
||||
}
|
||||
|
||||
q.x
|
||||
q.y
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package
|
||||
|
||||
public final class A</*0*/ T> {
|
||||
public constructor A</*0*/ T>()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public final fun foo(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
Vendored
+25
@@ -0,0 +1,25 @@
|
||||
// !CHECK_TYPE
|
||||
open class Outer<X, Y> {
|
||||
inner class Inner<Z>
|
||||
typealias Alias<W> = Map<W, X>
|
||||
}
|
||||
|
||||
class Derived : Outer<String, Int>() {
|
||||
fun foo(): Inner<Char> = null!!
|
||||
fun baz(): Alias<Char> = null!!
|
||||
}
|
||||
|
||||
|
||||
class A : Outer<Double, Short>() {
|
||||
class B : Outer<Float, Long>() {
|
||||
fun bar(): Inner<String> = null!!
|
||||
fun x(): Alias<String> = null!!
|
||||
}
|
||||
}
|
||||
|
||||
fun foo() {
|
||||
Derived().foo() checkType { _<Outer<String, Int>.Inner<Char>>() }
|
||||
Derived().baz() checkType { _<Map<Char, String>>() }
|
||||
A.B().bar() checkType { _<Outer<Float, Long>.Inner<String>>() }
|
||||
A.B().x() checkType { _<Map<String, Float>>() }
|
||||
}
|
||||
Vendored
+43
@@ -0,0 +1,43 @@
|
||||
package
|
||||
|
||||
public fun foo(): kotlin.Unit
|
||||
|
||||
public final class A : Outer<kotlin.Double, kotlin.Short> {
|
||||
public constructor 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 : Outer<kotlin.Float, kotlin.Long> {
|
||||
public constructor B()
|
||||
public final fun bar(): Outer<kotlin.Float, kotlin.Long>.Inner<kotlin.String>
|
||||
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 fun x(): Outer<kotlin.Float, kotlin.Long>.Alias<kotlin.String> /* = kotlin.collections.Map<kotlin.String, out kotlin.Float> */
|
||||
}
|
||||
}
|
||||
|
||||
public final class Derived : Outer<kotlin.String, kotlin.Int> {
|
||||
public constructor Derived()
|
||||
public final fun baz(): Outer<kotlin.String, kotlin.Int>.Alias<kotlin.Char> /* = kotlin.collections.Map<kotlin.Char, out kotlin.String> */
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public final fun foo(): Outer<kotlin.String, kotlin.Int>.Inner<kotlin.Char>
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public open class Outer</*0*/ X, /*1*/ Y> {
|
||||
public constructor Outer</*0*/ X, /*1*/ 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
|
||||
|
||||
public final inner class Inner</*0*/ Z> /*captured type parameters: /*1*/ X, /*2*/ Y*/ {
|
||||
public constructor Inner</*0*/ Z>()
|
||||
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 typealias Alias</*0*/ W> /*captured type parameters: /*1*/ X, /*2*/ Y*/ = kotlin.collections.Map<W, X>
|
||||
}
|
||||
compiler/testData/diagnostics/tests/generics/innerClasses/implicitArguments/fromSuperClassesLocal.kt
Vendored
+54
@@ -0,0 +1,54 @@
|
||||
// !CHECK_TYPE
|
||||
// !DIAGNOSTICS: -UNUSED_VALUE -VARIABLE_WITH_REDUNDANT_INITIALIZER
|
||||
|
||||
class A<R1, R2, R3, R4>
|
||||
|
||||
private fun <E> foobar() = {
|
||||
open class LocalOuter<X, Y> {
|
||||
inner class LocalInner<Z> {
|
||||
fun a() = A<E, X, Y, Z>()
|
||||
}
|
||||
|
||||
typealias LocalAlias<W> = A<E, X, Y, W>
|
||||
}
|
||||
|
||||
class Derived : LocalOuter<Double, Short>() {
|
||||
fun foo(): LocalInner<Long> = null!!
|
||||
fun bar(): LocalAlias<Char> = null!!
|
||||
}
|
||||
|
||||
Derived()
|
||||
}
|
||||
|
||||
private fun noParameters() = {
|
||||
open class LocalOuter2<X, Y> {
|
||||
inner class LocalInner2<Z> {
|
||||
fun a() = A<Any, X, Y, Z>()
|
||||
}
|
||||
|
||||
typealias LocalAlias2<W> = A<Any, X, Y, W>
|
||||
}
|
||||
|
||||
class Derived2 : LocalOuter2<Double, Short>() {
|
||||
fun foo(): LocalInner2<Long> = null!!
|
||||
fun bar(): LocalAlias2<Char> = null!!
|
||||
}
|
||||
|
||||
Derived2()
|
||||
}
|
||||
|
||||
fun test() {
|
||||
var x = foobar<String>()
|
||||
x = foobar<String>()
|
||||
|
||||
x().foo().a() checkType { _<A<String, Double, Short, Long>>() }
|
||||
x().bar() checkType { _<A<String, Double, Short, Char>>() }
|
||||
|
||||
x = <!TYPE_MISMATCH!>foobar<Int>()<!>
|
||||
|
||||
var y = noParameters()
|
||||
y = noParameters()
|
||||
|
||||
y().foo().a() checkType { _<A<Any, Double, Short, Long>>() }
|
||||
y().bar() checkType { _<A<Any, Double, Short, Char>>() }
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package
|
||||
|
||||
private fun </*0*/ E> foobar(): () -> foobar.<anonymous>.Derived<E>
|
||||
private fun noParameters(): () -> noParameters.<anonymous>.Derived2
|
||||
public fun test(): kotlin.Unit
|
||||
|
||||
public final class A</*0*/ R1, /*1*/ R2, /*2*/ R3, /*3*/ R4> {
|
||||
public constructor A</*0*/ R1, /*1*/ R2, /*2*/ R3, /*3*/ R4>()
|
||||
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
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
// !CHECK_TYPE
|
||||
// !DIAGNOSTICS: -UNUSED_VALUE -VARIABLE_WITH_REDUNDANT_INITIALIZER
|
||||
|
||||
class A<R1, R2, R3, R4, R5, R6>
|
||||
|
||||
class Outer<T> {
|
||||
inner class Inner<F> {
|
||||
private fun <E> foobar() = {
|
||||
open class LocalOuter<X, Y> {
|
||||
inner class LocalInner<Z> {
|
||||
fun a() = A<T, F, E, X, Y, Z>()
|
||||
}
|
||||
|
||||
typealias LocalAlias<W> = A<T, F, E, X, Y, W>
|
||||
}
|
||||
|
||||
class Derived : LocalOuter<Double, Short>() {
|
||||
fun foo(): LocalInner<Long> = null!!
|
||||
fun bar(): LocalAlias<Char> = null!!
|
||||
}
|
||||
|
||||
Derived()
|
||||
}
|
||||
|
||||
private fun noParameters() = {
|
||||
open class LocalOuter2<X, Y> {
|
||||
inner class LocalInner2<Z> {
|
||||
fun a() = A<T, F, Any, X, Y, Z>()
|
||||
}
|
||||
|
||||
typealias LocalAlias2<W> = A<T, F, Any, X, Y, W>
|
||||
}
|
||||
|
||||
class Derived2 : LocalOuter2<Double, Short>() {
|
||||
fun foo(): LocalInner2<Long> = null!!
|
||||
fun bar(): LocalAlias2<Char> = null!!
|
||||
}
|
||||
Derived2()
|
||||
}
|
||||
|
||||
fun test(z: Outer<String>.Inner<F>) {
|
||||
var x = foobar<String>()
|
||||
x = foobar<String>()
|
||||
|
||||
x().foo().a() checkType { _<A<T, F, String, Double, Short, Long>>() }
|
||||
x().bar() checkType { _<A<T, F, String, Double, Short, Char>>() }
|
||||
|
||||
x = <!TYPE_MISMATCH!>foobar<Int>()<!>
|
||||
x = <!TYPE_MISMATCH!>z.foobar<String>()<!>
|
||||
|
||||
var y = noParameters()
|
||||
y = noParameters()
|
||||
|
||||
y().foo().a() checkType { _<A<T, F, Any, Double, Short, Long>>() }
|
||||
y().bar() checkType { _<A<T, F, Any, Double, Short, Char>>() }
|
||||
}
|
||||
}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
package
|
||||
|
||||
public final class A</*0*/ R1, /*1*/ R2, /*2*/ R3, /*3*/ R4, /*4*/ R5, /*5*/ R6> {
|
||||
public constructor A</*0*/ R1, /*1*/ R2, /*2*/ R3, /*3*/ R4, /*4*/ R5, /*5*/ R6>()
|
||||
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 Outer</*0*/ T> {
|
||||
public constructor Outer</*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 final inner class Inner</*0*/ F> /*captured type parameters: /*1*/ T*/ {
|
||||
public constructor Inner</*0*/ F>()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
private final fun </*0*/ E> foobar(): () -> Outer.Inner.foobar.<anonymous>.Derived<E, F, T>
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
private final fun noParameters(): () -> Outer.Inner.noParameters.<anonymous>.Derived2<F, T>
|
||||
public final fun test(/*0*/ z: Outer<kotlin.String>.Inner<F>): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
// !CHECK_TYPE
|
||||
open class Outer<X, Y> {
|
||||
inner class Inner<Z>
|
||||
typealias Alias<W> = Map<W, X>
|
||||
}
|
||||
|
||||
open class BaseDerived1<E, F> : Outer<F, E>()
|
||||
open class BaseDerived2<X> : BaseDerived1<String, X>()
|
||||
|
||||
class Derived : BaseDerived2<Int>() {
|
||||
fun foo(): Inner<Char> = null!!
|
||||
fun baz(): Alias<Char> = null!!
|
||||
}
|
||||
|
||||
fun foo() {
|
||||
Derived().foo() checkType { _<Outer<Int, String>.Inner<Char>>() }
|
||||
Derived().baz() checkType { _<Map<Char, Int>>() }
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package
|
||||
|
||||
public fun foo(): kotlin.Unit
|
||||
|
||||
public open class BaseDerived1</*0*/ E, /*1*/ F> : Outer<F, E> {
|
||||
public constructor BaseDerived1</*0*/ E, /*1*/ F>()
|
||||
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 BaseDerived2</*0*/ X> : BaseDerived1<kotlin.String, X> {
|
||||
public constructor BaseDerived2</*0*/ 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 final class Derived : BaseDerived2<kotlin.Int> {
|
||||
public constructor Derived()
|
||||
public final fun baz(): Outer<kotlin.Int, kotlin.String>.Alias<kotlin.Char> /* = kotlin.collections.Map<kotlin.Char, out kotlin.Int> */
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public final fun foo(): Outer<kotlin.Int, kotlin.String>.Inner<kotlin.Char>
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public open class Outer</*0*/ X, /*1*/ Y> {
|
||||
public constructor Outer</*0*/ X, /*1*/ 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
|
||||
|
||||
public final inner class Inner</*0*/ Z> /*captured type parameters: /*1*/ X, /*2*/ Y*/ {
|
||||
public constructor Inner</*0*/ Z>()
|
||||
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 typealias Alias</*0*/ W> /*captured type parameters: /*1*/ X, /*2*/ Y*/ = kotlin.collections.Map<W, X>
|
||||
}
|
||||
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
interface Inv<X>
|
||||
class Outer<E> {
|
||||
inner class Inner
|
||||
|
||||
class Nested : Inv<<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>Inner<!>>
|
||||
object Obj : Inv<<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>Inner<!>>
|
||||
}
|
||||
Vendored
+35
@@ -0,0 +1,35 @@
|
||||
package
|
||||
|
||||
public interface Inv</*0*/ 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 final class Outer</*0*/ E> {
|
||||
public constructor Outer</*0*/ E>()
|
||||
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 inner class Inner /*captured type parameters: /*0*/ E*/ {
|
||||
public constructor Inner()
|
||||
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 Nested : Inv<[ERROR : Inner]> {
|
||||
public constructor Nested()
|
||||
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 object Obj : Inv<[ERROR : Inner]> {
|
||||
private constructor Obj()
|
||||
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
+18
@@ -0,0 +1,18 @@
|
||||
// !CHECK_TYPE
|
||||
open class Outer<E> {
|
||||
inner open class Inner<F> {
|
||||
inner class Inner2<D> {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DerivedOuter : Outer<String>() {
|
||||
inner class DerivedInner : Inner<Int>() {
|
||||
fun foo(): Inner2<Char> = null!!
|
||||
}
|
||||
}
|
||||
|
||||
fun foo() {
|
||||
DerivedOuter().DerivedInner().foo() checkType { _<Outer<String>.Inner<Int>.Inner2<Char>>() }
|
||||
}
|
||||
Vendored
+39
@@ -0,0 +1,39 @@
|
||||
package
|
||||
|
||||
public fun foo(): kotlin.Unit
|
||||
|
||||
public final class DerivedOuter : Outer<kotlin.String> {
|
||||
public constructor DerivedOuter()
|
||||
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 inner class DerivedInner : Outer<kotlin.String>.Inner<kotlin.Int> {
|
||||
public constructor DerivedInner()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public final fun foo(): Outer<kotlin.String>.Inner<kotlin.Int>.Inner2<kotlin.Char>
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
}
|
||||
|
||||
public open class Outer</*0*/ E> {
|
||||
public constructor Outer</*0*/ E>()
|
||||
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 inner class Inner</*0*/ F> /*captured type parameters: /*1*/ E*/ {
|
||||
public constructor Inner</*0*/ F>()
|
||||
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 inner class Inner2</*0*/ D> /*captured type parameters: /*1*/ F, /*2*/ E*/ {
|
||||
public constructor Inner2</*0*/ D>()
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,8 +9,12 @@ class Outer<E> {
|
||||
class E
|
||||
val x: Inner = Inner()
|
||||
}
|
||||
|
||||
class Nested {
|
||||
fun bar(x: <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>Inner<!>) {}
|
||||
}
|
||||
}
|
||||
|
||||
class E
|
||||
|
||||
fun bar(x: <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>Inner<!>) {}
|
||||
fun bar(x: <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>Inner<!>) {}
|
||||
|
||||
@@ -22,4 +22,12 @@ public final class Outer</*0*/ E> {
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final class Nested {
|
||||
public constructor Nested()
|
||||
public final fun bar(/*0*/ x: [ERROR : Inner]): kotlin.Unit
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
+13
-4
@@ -1,14 +1,23 @@
|
||||
// KT-5508 Stackoverflow in type substitution
|
||||
|
||||
abstract class A<T> {
|
||||
public abstract fun Foo(x: T)
|
||||
public abstract fun foo(x: T)
|
||||
public abstract fun bar(x: T)
|
||||
|
||||
public inner abstract class B<S> : A<B<S>>() {
|
||||
public inner class C<U> : B<C<U>>()
|
||||
public inner <!ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED!>class C<!><U> : B<C<U>>()
|
||||
{
|
||||
override fun Foo(x: B<C<U>>) {
|
||||
// Here B<C<U>> means A<A<A<T>.B<S>>.B<A<T>.B<S>.C<U>>>.B<A<A<T>.B<S>>.B<A<T>.B<S>.C<U>>.C<U>>
|
||||
// while for being a correct override it should be A<A<T>.B<S>>.B<A<T>.B<S>.C<U>>
|
||||
// It happens because at the beginning we search implicit arguments for an outer classes through supertypes
|
||||
// See TypeResolver.computeImplicitOuterClassArguments for clarifications
|
||||
<!NOTHING_TO_OVERRIDE!>override<!> fun foo(x: B<C<U>>) {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
override fun bar(x: A<A<T>.B<S>>.B<A<T>.B<S>.C<U>>) {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+8
-4
@@ -2,22 +2,26 @@ package
|
||||
|
||||
public abstract class A</*0*/ T> {
|
||||
public constructor A</*0*/ T>()
|
||||
public abstract fun Foo(/*0*/ x: T): kotlin.Unit
|
||||
public abstract fun bar(/*0*/ x: T): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public abstract fun foo(/*0*/ x: T): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
public abstract inner class B</*0*/ S> /*captured type parameters: /*1*/ T*/ : A<A<T>.B<S>> {
|
||||
public constructor B</*0*/ S>()
|
||||
public abstract override /*1*/ /*fake_override*/ fun Foo(/*0*/ x: A<T>.B<S>): kotlin.Unit
|
||||
public abstract override /*1*/ /*fake_override*/ fun bar(/*0*/ x: A<T>.B<S>): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public abstract override /*1*/ /*fake_override*/ fun foo(/*0*/ x: A<T>.B<S>): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
public final inner class C</*0*/ U> /*captured type parameters: /*1*/ S, /*2*/ T*/ : A<T>.B<A<T>.B<S>.C<U>> {
|
||||
public final inner class C</*0*/ U> /*captured type parameters: /*1*/ S, /*2*/ T*/ : A<A<T>.B<S>>.B<A<T>.B<S>.C<U>> {
|
||||
public constructor C</*0*/ U>()
|
||||
public open override /*1*/ fun Foo(/*0*/ x: A<T>.B<A<T>.B<S>.C<U>>): kotlin.Unit
|
||||
public open override /*1*/ fun bar(/*0*/ x: A<A<T>.B<S>>.B<A<T>.B<S>.C<U>>): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open fun foo(/*0*/ x: A<A<A<T>.B<S>>.B<A<T>.B<S>.C<U>>>.B<A<A<T>.B<S>>.B<A<T>.B<S>.C<U>>.C<U>>): kotlin.Unit
|
||||
public abstract override /*1*/ /*fake_override*/ fun foo(/*0*/ x: A<A<T>.B<S>>.B<A<T>.B<S>.C<U>>): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
@@ -10,11 +10,9 @@ open class Base<T> {
|
||||
}
|
||||
|
||||
class Derived : Base<Int>() {
|
||||
// TODO KT-11123
|
||||
|
||||
val x1: <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>InnerCell<!> = InnerCell(42)
|
||||
val x1: InnerCell = InnerCell(42)
|
||||
val x2: Base<Int>.InnerCell = InnerCell(42)
|
||||
|
||||
val test1: <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>CT<!> = Cell(42)
|
||||
val test1: CT = Cell(42)
|
||||
val test2: Base<Int>.CT = Cell(42)
|
||||
}
|
||||
|
||||
@@ -26,9 +26,9 @@ public final class Cell</*0*/ T> : ICell<T> {
|
||||
|
||||
public final class Derived : Base<kotlin.Int> {
|
||||
public constructor Derived()
|
||||
public final val test1: [ERROR : CT]
|
||||
public final val test1: Base<kotlin.Int>.CT /* = Cell<kotlin.Int> */
|
||||
public final val test2: Base<kotlin.Int>.CT /* = Cell<kotlin.Int> */
|
||||
public final val x1: [ERROR : InnerCell]
|
||||
public final val x1: Base<kotlin.Int>.InnerCell
|
||||
public final val x2: Base<kotlin.Int>.InnerCell
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
|
||||
@@ -7981,6 +7981,63 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/innerClasses/substitutedMemberScope.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/generics/innerClasses/implicitArguments")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class ImplicitArguments extends AbstractDiagnosticsTest {
|
||||
public void testAllFilesPresentInImplicitArguments() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/generics/innerClasses/implicitArguments"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("fromCompanionObject.kt")
|
||||
public void testFromCompanionObject() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/innerClasses/implicitArguments/fromCompanionObject.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("fromOuterClassInObjectLiteral.kt")
|
||||
public void testFromOuterClassInObjectLiteral() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/innerClasses/implicitArguments/fromOuterClassInObjectLiteral.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("fromSuperClasses.kt")
|
||||
public void testFromSuperClasses() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/innerClasses/implicitArguments/fromSuperClasses.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("fromSuperClassesLocal.kt")
|
||||
public void testFromSuperClassesLocal() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/innerClasses/implicitArguments/fromSuperClassesLocal.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("fromSuperClassesLocalInsideInner.kt")
|
||||
public void testFromSuperClassesLocalInsideInner() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/innerClasses/implicitArguments/fromSuperClassesLocalInsideInner.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("fromSuperClassesTransitive.kt")
|
||||
public void testFromSuperClassesTransitive() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/innerClasses/implicitArguments/fromSuperClassesTransitive.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inStaticScope.kt")
|
||||
public void testInStaticScope() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/innerClasses/implicitArguments/inStaticScope.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("secondLevelDepth.kt")
|
||||
public void testSecondLevelDepth() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/generics/innerClasses/implicitArguments/secondLevelDepth.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/generics/multipleBoundsMemberScope")
|
||||
|
||||
@@ -29,6 +29,10 @@ import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.constants.EnumValue
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeProjection
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.types.typeUtil.isAnyOrNullableAny
|
||||
import org.jetbrains.kotlin.utils.DFS
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.check
|
||||
|
||||
@@ -264,3 +268,54 @@ fun getConstructorByParamsMap(classDescriptor: ClassDescriptor, params: List<Pai
|
||||
|
||||
fun CallableDescriptor.varargParameterPosition() =
|
||||
valueParameters.indexOfFirst { it.varargElementType != null }
|
||||
|
||||
/**
|
||||
* When `Inner` is used as type outside of `Outer` class all type arguments should be specified, e.g. `Outer<String, Int>.Inner<Double>`
|
||||
* However, it's not necessary inside Outer's members, only the last one should be specified there.
|
||||
* So this function return a list of arguments that should be used if relevant arguments weren't specified explicitly inside the [scopeOwner].
|
||||
*
|
||||
* Examples:
|
||||
* for `Outer` class the map will contain: Outer -> (X, Y) (i.e. defaultType mapping)
|
||||
* for `Derived` class the map will contain: Derived -> (E), Outer -> (E, String)
|
||||
* for `A.B` class the map will contain: B -> (), Outer -> (Int, CharSequence), A -> ()
|
||||
*
|
||||
* open class Outer<X, Y> {
|
||||
* inner class Inner<Z>
|
||||
* }
|
||||
*
|
||||
* class Derived<E> : Outer<E, String>()
|
||||
*
|
||||
* class A : Outer<String, Double>() {
|
||||
* inner class B : Outer<Int, CharSequence>()
|
||||
* }
|
||||
*/
|
||||
fun findImplicitOuterClassArguments(scopeOwner: ClassDescriptor, outerClass: ClassDescriptor): List<TypeProjection>? {
|
||||
for (current in scopeOwner.classesFromInnerToOuter()) {
|
||||
for (supertype in current.getAllSuperClassesTypesIncludeItself()) {
|
||||
val classDescriptor = supertype.constructor.declarationDescriptor as ClassDescriptor
|
||||
if (classDescriptor == outerClass) return supertype.arguments
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
private fun ClassDescriptor.classesFromInnerToOuter() = generateSequence(this) {
|
||||
if (it.isInner)
|
||||
it.containingDeclaration.original as? ClassDescriptor
|
||||
else
|
||||
null
|
||||
}
|
||||
|
||||
private fun ClassDescriptor.getAllSuperClassesTypesIncludeItself(): List<KotlinType> {
|
||||
val result = arrayListOf<KotlinType>()
|
||||
var current: KotlinType = defaultType
|
||||
|
||||
while (!current.isAnyOrNullableAny()) {
|
||||
result.add(current)
|
||||
val next = DescriptorUtils.getSuperClassType(current.constructor.declarationDescriptor as ClassDescriptor)
|
||||
current = TypeSubstitutor.create(current).substitute(next, Variance.INVARIANT) ?: break
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user