From 8d634f600363b8fd01763e2800a83cd929e45d94 Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Mon, 10 Oct 2016 18:21:19 +0300 Subject: [PATCH] KT-14274: resolve type alias constructors calls in supertypes list as type alias constructors. Support @Deprecated for type aliases, including type alias constructors. --- .../kotlin/codegen/ExpressionCodegen.java | 2 +- .../codegen/ImplementationBodyCodegen.java | 6 +- .../codegen/state/KotlinTypeMapper.java | 16 +++-- .../kotlin/resolve/BindingContext.java | 2 +- .../kotlin/resolve/BindingContextUtils.java | 2 +- .../kotlin/resolve/BodyResolver.java | 4 +- .../kotlin/resolve/calls/CallResolver.java | 28 ++++---- .../kotlin/resolve/calls/CallResolverUtil.kt | 32 +++++++-- .../ProtectedConstructorCallChecker.kt | 11 ++- .../kotlin/resolve/deprecationUtil.kt | 6 ++ .../typeAliasConstructorInSuperCall.kt | 10 +++ .../tests/deprecated/typealiasConstructor.kt | 14 ++++ .../tests/deprecated/typealiasConstructor.txt | 34 +++++++++ .../tests/deprecated/typealiasUsage.kt | 24 +++++++ .../tests/deprecated/typealiasUsage.txt | 69 +++++++++++++++++++ .../typeAliasConstructorWrongVisibility.kt | 2 +- .../typeAliasConstructorWrongVisibility.txt | 2 +- .../checkers/DiagnosticsTestGenerated.java | 12 ++++ .../codegen/BlackBoxCodegenTestGenerated.java | 6 ++ .../impl/TypeAliasConstructorDescriptor.kt | 15 ++-- .../TypeAliasAsSupertypeConstructor.kt | 9 +++ .../ReferenceResolveTestGenerated.java | 6 ++ .../kotlin/js/naming/NameSuggestion.kt | 4 ++ .../semantics/TypeAliasesTestsGenerated.java | 6 ++ .../translate/context/TranslationContext.java | 6 ++ 25 files changed, 285 insertions(+), 43 deletions(-) create mode 100644 compiler/testData/codegen/box/typealias/typeAliasConstructorInSuperCall.kt create mode 100644 compiler/testData/diagnostics/tests/deprecated/typealiasConstructor.kt create mode 100644 compiler/testData/diagnostics/tests/deprecated/typealiasConstructor.txt create mode 100644 compiler/testData/diagnostics/tests/deprecated/typealiasUsage.kt create mode 100644 compiler/testData/diagnostics/tests/deprecated/typealiasUsage.txt create mode 100644 idea/testData/resolve/references/TypeAliasAsSupertypeConstructor.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index 2d0f5a5997f..d788ee86b38 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -1639,7 +1639,7 @@ public class ExpressionCodegen extends KtVisitor impleme ConstructorDescriptor primaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor(); assert primaryConstructor != null : "There should be primary constructor for object literal"; - ResolvedCall superCall = getDelegationConstructorCall(bindingContext, primaryConstructor); + ResolvedCall superCall = getDelegationConstructorCall(bindingContext, primaryConstructor); if (superCall != null) { // For an anonymous object, we should also generate all non-default arguments that it captures for its super call ConstructorDescriptor superConstructor = superCall.getResultingDescriptor(); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java index 2be22f52a21..4949197f9e4 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java @@ -1049,10 +1049,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { markLineNumberForConstructor(constructorDescriptor, constructor, codegen); - ResolvedCall constructorDelegationCall = + ResolvedCall constructorDelegationCall = getDelegationConstructorCall(bindingContext, constructorDescriptor); ConstructorDescriptor delegateConstructor = constructorDelegationCall == null ? null : - constructorDelegationCall.getResultingDescriptor(); + constructorDelegationCall.getResultingDescriptor(); generateDelegatorToConstructorCall(iv, codegen, constructorDescriptor, constructorDelegationCall); if (!isSameClassConstructor(delegateConstructor)) { @@ -1383,7 +1383,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { @NotNull InstructionAdapter iv, @NotNull ExpressionCodegen codegen, @NotNull ClassConstructorDescriptor constructorDescriptor, - @Nullable ResolvedCall delegationConstructorCall + @Nullable ResolvedCall delegationConstructorCall ) { if (delegationConstructorCall == null) { genSimpleSuperCall(iv); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java index 4d6d6029a8a..a78cab0413e 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java @@ -36,6 +36,7 @@ import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.impl.LocalVariableAccessorDescriptor; import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor; +import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor; import org.jetbrains.kotlin.fileClasses.FileClasses; import org.jetbrains.kotlin.fileClasses.JvmFileClassInfo; import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil; @@ -934,6 +935,9 @@ public class KotlinTypeMapper { if (f instanceof FunctionImportedFromObject) { return mapSignature(((FunctionImportedFromObject) f).getCallableFromObject(), kind, skipGenericSignature); } + else if (f instanceof TypeAliasConstructorDescriptor) { + return mapSignature(((TypeAliasConstructorDescriptor) f).getUnderlyingConstructorDescriptor(), kind, valueParameters, skipGenericSignature); + } checkOwnerCompatibility(f); @@ -1272,7 +1276,7 @@ public class KotlinTypeMapper { // We may generate a slightly wrong signature for a local class / anonymous object in light classes mode but we don't care, // because such classes are not accessible from the outside world if (classBuilderMode.generateBodies) { - ResolvedCall superCall = findFirstDelegatingSuperCall(descriptor); + ResolvedCall superCall = findFirstDelegatingSuperCall(descriptor); if (superCall == null) return; writeSuperConstructorCallParameters(sw, descriptor, superCall, captureThis != null); } @@ -1281,7 +1285,7 @@ public class KotlinTypeMapper { private void writeSuperConstructorCallParameters( @NotNull JvmSignatureWriter sw, @NotNull ClassConstructorDescriptor descriptor, - @NotNull ResolvedCall superCall, + @NotNull ResolvedCall superCall, boolean hasOuter ) { ConstructorDescriptor superDescriptor = SamCodegenUtil.resolveSamAdapter(superCall.getResultingDescriptor()); @@ -1320,13 +1324,13 @@ public class KotlinTypeMapper { } @Nullable - private ResolvedCall findFirstDelegatingSuperCall(@NotNull ClassConstructorDescriptor descriptor) { - ClassDescriptor classDescriptor = descriptor.getContainingDeclaration(); + private ResolvedCall findFirstDelegatingSuperCall(@NotNull ConstructorDescriptor descriptor) { + ClassifierDescriptorWithTypeParameters constructorOwner = descriptor.getContainingDeclaration(); while (true) { - ResolvedCall next = getDelegationConstructorCall(bindingContext, descriptor); + ResolvedCall next = getDelegationConstructorCall(bindingContext, descriptor); if (next == null) return null; descriptor = next.getResultingDescriptor(); - if (descriptor.getContainingDeclaration() != classDescriptor) return next; + if (descriptor.getContainingDeclaration() != constructorOwner) return next; } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java index 2d95d8a4a58..6d0d9cf3497 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java @@ -222,7 +222,7 @@ public interface BindingContext { */ WritableSlice FUNCTION = Slices.createSimpleSlice(); WritableSlice CONSTRUCTOR = Slices.createSimpleSlice(); - WritableSlice> CONSTRUCTOR_RESOLVED_DELEGATION_CALL = + WritableSlice> CONSTRUCTOR_RESOLVED_DELEGATION_CALL = Slices.createSimpleSlice(); WritableSlice VARIABLE = Slices.createSimpleSlice(); WritableSlice VALUE_PARAMETER = Slices.createSimpleSlice(); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContextUtils.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContextUtils.java index f9f977bdba0..60ee2626c83 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContextUtils.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContextUtils.java @@ -222,7 +222,7 @@ public class BindingContextUtils { } @Nullable - public static ResolvedCall getDelegationConstructorCall( + public static ResolvedCall getDelegationConstructorCall( @NotNull BindingContext bindingContext, @NotNull ConstructorDescriptor constructorDescriptor ) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodyResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodyResolver.java index ca209572c82..93e54e49c86 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodyResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BodyResolver.java @@ -231,7 +231,7 @@ public class BodyResolver { @Nullable private ConstructorDescriptor getDelegatedConstructor(@NotNull ConstructorDescriptor constructor) { - ResolvedCall call = trace.get(CONSTRUCTOR_RESOLVED_DELEGATION_CALL, constructor); + ResolvedCall call = trace.get(CONSTRUCTOR_RESOLVED_DELEGATION_CALL, constructor); return call == null || !call.getStatus().isSuccess() ? null : call.getResultingDescriptor().getOriginal(); } @@ -430,7 +430,7 @@ public class BodyResolver { @NotNull ResolvedCall call ) { //noinspection unchecked - trace.record(CONSTRUCTOR_RESOLVED_DELEGATION_CALL, constructor, (ResolvedCall) call); + trace.record(CONSTRUCTOR_RESOLVED_DELEGATION_CALL, constructor, (ResolvedCall) call); } private void checkSupertypeList( diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolver.java index b23586de025..bab6fffad62 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolver.java @@ -307,7 +307,7 @@ public class CallResolver { return resolveCallForInvoke(context.replaceCall(call), tracingForInvoke); } - private OverloadResolutionResults resolveCallForConstructor( + private OverloadResolutionResults resolveCallForConstructor( @NotNull BasicCallResolutionContext context, @NotNull KtConstructorCalleeExpression expression ) { @@ -340,17 +340,17 @@ public class CallResolver { return checkArgumentTypesAndFail(context); } - Pair>, BasicCallResolutionContext> candidatesAndContext = + Pair>, BasicCallResolutionContext> candidatesAndContext = prepareCandidatesAndContextForConstructorCall(constructedType, context); - Collection> candidates = candidatesAndContext.getFirst(); + Collection> candidates = candidatesAndContext.getFirst(); context = candidatesAndContext.getSecond(); return computeTasksFromCandidatesAndResolvedCall(context, functionReference, candidates); } @Nullable - public OverloadResolutionResults resolveConstructorDelegationCall( + public OverloadResolutionResults resolveConstructorDelegationCall( @NotNull BindingTrace trace, @NotNull LexicalScope scope, @NotNull DataFlowInfo dataFlowInfo, @NotNull ClassConstructorDescriptor constructorDescriptor, @NotNull KtConstructorDelegationCall call @@ -380,7 +380,7 @@ public class CallResolver { } @NotNull - private OverloadResolutionResults resolveConstructorDelegationCall( + private OverloadResolutionResults resolveConstructorDelegationCall( @NotNull BasicCallResolutionContext context, @NotNull KtConstructorDelegationCall call, @NotNull KtConstructorDelegationReferenceExpression calleeExpression, @@ -420,9 +420,9 @@ public class CallResolver { calleeConstructor.getContainingDeclaration().getDefaultType() : DescriptorUtils.getSuperClassType(currentClassDescriptor); - Pair>, BasicCallResolutionContext> candidatesAndContext = + Pair>, BasicCallResolutionContext> candidatesAndContext = prepareCandidatesAndContextForConstructorCall(superType, context); - Collection> candidates = candidatesAndContext.getFirst(); + Collection> candidates = candidatesAndContext.getFirst(); context = candidatesAndContext.getSecond(); TracingStrategy tracing = call.isImplicit() ? @@ -441,17 +441,15 @@ public class CallResolver { } @NotNull - private static Pair>, BasicCallResolutionContext> prepareCandidatesAndContextForConstructorCall( + private static Pair>, BasicCallResolutionContext> prepareCandidatesAndContextForConstructorCall( @NotNull KotlinType superType, @NotNull BasicCallResolutionContext context ) { if (!(superType.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor)) { - return new Pair>, BasicCallResolutionContext>( - Collections.>emptyList(), context); + return new Pair>, BasicCallResolutionContext>( + Collections.>emptyList(), context); } - ClassDescriptor superClass = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor(); - // If any constructor has type parameter (currently it only can be true for ones from Java), try to infer arguments for them // Otherwise use NO_EXPECTED_TYPE and knownTypeParametersSubstitutor boolean anyConstructorHasDeclaredTypeParameters = @@ -462,10 +460,10 @@ public class CallResolver { context = context.replaceExpectedType(superType); } - Collection> candidates = - CallResolverUtilKt.createResolutionCandidatesForConstructors(context.scope, context.call, superClass, knownTypeParametersSubstitutor); + Collection> candidates = + CallResolverUtilKt.createResolutionCandidatesForConstructors(context.scope, context.call, superType, knownTypeParametersSubstitutor); - return new Pair>, BasicCallResolutionContext>(candidates, context); + return new Pair>, BasicCallResolutionContext>(candidates, context); } private static boolean anyConstructorHasDeclaredTypeParameters(@Nullable ClassifierDescriptor classDescriptor) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolverUtil.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolverUtil.kt index 9d1e59e3d03..c9876bf2f19 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolverUtil.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/CallResolverUtil.kt @@ -23,6 +23,8 @@ import org.jetbrains.kotlin.builtins.getReceiverTypeFromFunctionType import org.jetbrains.kotlin.builtins.isExtensionFunctionType import org.jetbrains.kotlin.coroutines.getExpectedTypeForCoroutineControllerHandleResult import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor +import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptorImpl import org.jetbrains.kotlin.incremental.KotlinLookupLocation import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.BindingContext @@ -200,9 +202,18 @@ fun getEffectiveExpectedType(parameterDescriptor: ValueParameterDescriptor, argu fun createResolutionCandidatesForConstructors( lexicalScope: LexicalScope, call: Call, - classWithConstructors: ClassDescriptor, + typeWithConstructors: KotlinType, knownSubstitutor: TypeSubstitutor? = null -): Collection> { +): Collection> { + val classWithConstructors = typeWithConstructors.constructor.declarationDescriptor as ClassDescriptor + + val unwrappedType = typeWithConstructors.unwrap() + val typeAliasDescriptor = + if (unwrappedType is AbbreviatedType) + unwrappedType.abbreviation.constructor.declarationDescriptor as? TypeAliasDescriptor + else + null + val constructors = classWithConstructors.constructors if (constructors.isEmpty()) return emptyList() @@ -212,7 +223,7 @@ fun createResolutionCandidatesForConstructors( if (classWithConstructors.isInner) { val outerClassType = (classWithConstructors.containingDeclaration as? ClassDescriptor)?.defaultType ?: return emptyList() - val substitutedOuterClassType = knownSubstitutor?.let { it.substitute(outerClassType, Variance.INVARIANT) } ?: outerClassType + val substitutedOuterClassType = knownSubstitutor?.substitute(outerClassType, Variance.INVARIANT) ?: outerClassType val receiver = lexicalScope.getImplicitReceiversHierarchy().firstOrNull { KotlinTypeChecker.DEFAULT.isSubtypeOf(it.type, substitutedOuterClassType) @@ -226,9 +237,22 @@ fun createResolutionCandidatesForConstructors( dispatchReceiver = null } - return constructors.map { ResolutionCandidate.create(call, it, dispatchReceiver, receiverKind, knownSubstitutor) } + return constructors.map { + val constructorDescriptor = it.getConstructorDescriptorForResolution(knownSubstitutor, typeAliasDescriptor) + ResolutionCandidate.create(call, constructorDescriptor, dispatchReceiver, receiverKind, knownSubstitutor) + } } +private fun ClassConstructorDescriptor.getConstructorDescriptorForResolution( + knownSubstitutor: TypeSubstitutor?, + typeAliasDescriptor: TypeAliasDescriptor? +): ConstructorDescriptor = + if (typeAliasDescriptor != null) + TypeAliasConstructorDescriptorImpl.create(typeAliasDescriptor, this, knownSubstitutor ?: TypeSubstitutor.EMPTY) + ?: throw AssertionError("Failed to create type alias constructor with substitutor: $knownSubstitutor") + else + this + fun KtLambdaExpression.getCorrespondingParameterForFunctionArgument( bindingContext: BindingContext ): ValueParameterDescriptor? { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/ProtectedConstructorCallChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/ProtectedConstructorCallChecker.kt index f11edff30bd..e1a667daf24 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/ProtectedConstructorCallChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/ProtectedConstructorCallChecker.kt @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.resolve.calls.checkers import com.intellij.psi.PsiElement import org.jetbrains.kotlin.descriptors.ConstructorDescriptor import org.jetbrains.kotlin.descriptors.Visibilities +import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.psi.KtConstructorCalleeExpression import org.jetbrains.kotlin.psi.KtConstructorDelegationReferenceExpression @@ -32,7 +33,13 @@ object ProtectedConstructorCallChecker : CallChecker { val constructorOwner = descriptor.containingDeclaration.original val scopeOwner = context.scope.ownerDescriptor - if (descriptor.visibility.normalize() != Visibilities.PROTECTED) return + val actualConstructor = + if (descriptor is TypeAliasConstructorDescriptor) + descriptor.underlyingConstructorDescriptor + else + descriptor + + if (actualConstructor.visibility.normalize() != Visibilities.PROTECTED) return // Error already reported if (!Visibilities.isVisibleWithAnyReceiver(descriptor, scopeOwner)) return @@ -52,7 +59,7 @@ object ProtectedConstructorCallChecker : CallChecker { // And without ProtectedConstructorCallChecker such calls would be allowed only because they are performed within subclass // of constructor owner @Suppress("DEPRECATION") - if (Visibilities.findInvisibleMember(Visibilities.FALSE_IF_PROTECTED, descriptor, scopeOwner) == descriptor) { + if (Visibilities.findInvisibleMember(Visibilities.FALSE_IF_PROTECTED, descriptor, scopeOwner) == actualConstructor) { context.trace.report(Errors.PROTECTED_CONSTRUCTOR_NOT_IN_SUPER_CALL.on(reportOn, descriptor)) } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/deprecationUtil.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/deprecationUtil.kt index 352aac4fe52..3104f7a0b0a 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/deprecationUtil.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/deprecationUtil.kt @@ -23,6 +23,7 @@ import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget import org.jetbrains.kotlin.descriptors.annotations.Annotations +import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.name.FqName @@ -137,6 +138,11 @@ private fun DeclarationDescriptor.getDeprecationByAnnotation(): DeprecatedByAnno val classAnnotation = classDescriptor.getDeclaredDeprecatedAnnotation() if (classAnnotation != null) return DeprecatedByAnnotation(classAnnotation, classDescriptor) + if (this is TypeAliasConstructorDescriptor) { + val underlyingConstructorDeprecation = underlyingConstructorDescriptor.getDeprecationByAnnotation() + if (underlyingConstructorDeprecation != null) + return underlyingConstructorDeprecation + } } is PropertyAccessorDescriptor -> { val propertyDescriptor = correspondingProperty diff --git a/compiler/testData/codegen/box/typealias/typeAliasConstructorInSuperCall.kt b/compiler/testData/codegen/box/typealias/typeAliasConstructorInSuperCall.kt new file mode 100644 index 00000000000..95cee2f88ef --- /dev/null +++ b/compiler/testData/codegen/box/typealias/typeAliasConstructorInSuperCall.kt @@ -0,0 +1,10 @@ +open class Cell(val value: T) + +typealias CT = Cell +typealias CStr = Cell + +class C1 : CT("O") +class C2 : CStr("K") + +fun box(): String = + C1().value + C2().value \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/deprecated/typealiasConstructor.kt b/compiler/testData/diagnostics/tests/deprecated/typealiasConstructor.kt new file mode 100644 index 00000000000..a3735aa78c3 --- /dev/null +++ b/compiler/testData/diagnostics/tests/deprecated/typealiasConstructor.kt @@ -0,0 +1,14 @@ +@Deprecated("Deprecated class") +open class DeprecatedClass + +open class WithDeprecatedCtor(val x: Int) { + @Deprecated("Deprecated constructor") + constructor() : this(0) +} + +typealias DeprecatedClassAlias = DeprecatedClass +typealias WithDeprecatedCtorAlias = WithDeprecatedCtor + +class Test1 : DeprecatedClassAlias() + +class Test2 : WithDeprecatedCtorAlias() \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/deprecated/typealiasConstructor.txt b/compiler/testData/diagnostics/tests/deprecated/typealiasConstructor.txt new file mode 100644 index 00000000000..f48baacaea2 --- /dev/null +++ b/compiler/testData/diagnostics/tests/deprecated/typealiasConstructor.txt @@ -0,0 +1,34 @@ +package + +@kotlin.Deprecated(message = "Deprecated class") public open class DeprecatedClass { + public constructor DeprecatedClass() + 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 Test1 : DeprecatedClassAlias /* = DeprecatedClass */ { + public constructor Test1() + 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 Test2 : WithDeprecatedCtorAlias /* = WithDeprecatedCtor */ { + public constructor Test2() + public final override /*1*/ /*fake_override*/ val x: kotlin.Int + 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 WithDeprecatedCtor { + @kotlin.Deprecated(message = "Deprecated constructor") public constructor WithDeprecatedCtor() + public constructor WithDeprecatedCtor(/*0*/ x: kotlin.Int) + public final val x: kotlin.Int + 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 DeprecatedClassAlias = DeprecatedClass +public typealias WithDeprecatedCtorAlias = WithDeprecatedCtor diff --git a/compiler/testData/diagnostics/tests/deprecated/typealiasUsage.kt b/compiler/testData/diagnostics/tests/deprecated/typealiasUsage.kt new file mode 100644 index 00000000000..a679866e2c6 --- /dev/null +++ b/compiler/testData/diagnostics/tests/deprecated/typealiasUsage.kt @@ -0,0 +1,24 @@ +open class Base { + companion object +} +interface IFoo +open class CG +interface IG + +@Deprecated("Obsolete") +typealias Obsolete = Base + +@Deprecated("Obsolete") +typealias IObsolete = IFoo + +fun test1(x: Obsolete) = x +fun test1a(x: List<Obsolete>) = x + +val test2 = Obsolete() + +val test3 = Obsolete + +class Test4: Obsolete() +class Test4a: IObsolete +class Test4b: IG<Obsolete> +class Test4c: CG<Obsolete>() \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/deprecated/typealiasUsage.txt b/compiler/testData/diagnostics/tests/deprecated/typealiasUsage.txt new file mode 100644 index 00000000000..2002a92aa79 --- /dev/null +++ b/compiler/testData/diagnostics/tests/deprecated/typealiasUsage.txt @@ -0,0 +1,69 @@ +package + +public val test2: Base +public val test3: Base.Companion +public fun test1(/*0*/ x: Obsolete /* = Base */): Obsolete /* = Base */ +public fun test1a(/*0*/ x: kotlin.collections.List): kotlin.collections.List + +public open class Base { + public constructor Base() + 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 companion object Companion { + 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 open class CG { + public constructor CG() + 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 IFoo { + 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 IG { + 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 Test4 : Obsolete /* = Base */ { + public constructor Test4() + 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 Test4a : IObsolete /* = IFoo */ { + public constructor Test4a() + 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 Test4b : IG { + public constructor Test4b() + 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 Test4c : CG { + public constructor Test4c() + 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 +} +@kotlin.Deprecated(message = "Obsolete") public typealias IObsolete = IFoo +@kotlin.Deprecated(message = "Obsolete") public typealias Obsolete = Base diff --git a/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorWrongVisibility.kt b/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorWrongVisibility.kt index 69aaa4e1793..7a927e6ac66 100644 --- a/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorWrongVisibility.kt +++ b/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorWrongVisibility.kt @@ -19,7 +19,7 @@ val test3a = MyClass(1.0) class MyDerived : MyClass(1.0) { val test4 = MyAlias(1) val test4a = MyClass(1) - val test5 = MyAlias("") + val test5 = MyAlias("") val test5a = MyClass("") val test6 = MyAlias(1.0) val test6a = MyClass(1.0) diff --git a/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorWrongVisibility.txt b/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorWrongVisibility.txt index 5228945270b..674c26e5999 100644 --- a/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorWrongVisibility.txt +++ b/compiler/testData/diagnostics/tests/typealias/typeAliasConstructorWrongVisibility.txt @@ -21,7 +21,7 @@ public final class MyDerived : MyClass { public constructor MyDerived() public final val test4: [ERROR : Type for MyAlias(1)] public final val test4a: [ERROR : Type for MyClass(1)] - public final val test5: [ERROR : Type for MyAlias("")] + public final val test5: MyClass public final val test5a: MyClass public final val test6: MyClass public final val test6a: MyClass diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index f3639cad18e..9415e593b84 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -6048,6 +6048,18 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("typealiasConstructor.kt") + public void testTypealiasConstructor() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/deprecated/typealiasConstructor.kt"); + doTest(fileName); + } + + @TestMetadata("typealiasUsage.kt") + public void testTypealiasUsage() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/deprecated/typealiasUsage.kt"); + doTest(fileName); + } + @TestMetadata("unusedImport.kt") public void testUnusedImport() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/deprecated/unusedImport.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 1bed76f3870..17183e34061 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -15952,6 +15952,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } + @TestMetadata("typeAliasConstructorInSuperCall.kt") + public void testTypeAliasConstructorInSuperCall() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/typealias/typeAliasConstructorInSuperCall.kt"); + doTest(fileName); + } + @TestMetadata("typeAliasObject.kt") public void testTypeAliasObject() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/typealias/typeAliasObject.kt"); diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/TypeAliasConstructorDescriptor.kt b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/TypeAliasConstructorDescriptor.kt index 4b738f30e0b..274e4333883 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/TypeAliasConstructorDescriptor.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/TypeAliasConstructorDescriptor.kt @@ -111,17 +111,18 @@ class TypeAliasConstructorDescriptorImpl private constructor( fun create( typeAliasDescriptor: TypeAliasDescriptor, constructor: ClassConstructorDescriptor, - substitutor: TypeSubstitutor + substitutor: TypeSubstitutor? ): TypeAliasConstructorDescriptor? { + val actualSubstitutor = substitutor ?: TypeSubstitutor.EMPTY + val typeAliasConstructor = TypeAliasConstructorDescriptorImpl(typeAliasDescriptor, constructor, null, constructor.annotations, constructor.kind, typeAliasDescriptor.source) - val valueParameters = - FunctionDescriptorImpl.getSubstitutedValueParameters(typeAliasConstructor, constructor.valueParameters, substitutor, false) - ?: return null + val valueParameters = FunctionDescriptorImpl.getSubstitutedValueParameters(typeAliasConstructor, constructor.valueParameters, actualSubstitutor, false) + ?: return null - val returnType = substitutor.substitute(constructor.returnType, Variance.INVARIANT) + val returnType = actualSubstitutor.substitute(constructor.returnType, Variance.INVARIANT) ?: return null val containingDeclaration = constructor.containingDeclaration @@ -137,10 +138,12 @@ class TypeAliasConstructorDescriptorImpl private constructor( valueParameters, returnType, Modality.FINAL, - constructor.visibility) + typeAliasDescriptor.visibility) return typeAliasConstructor } + + } } diff --git a/idea/testData/resolve/references/TypeAliasAsSupertypeConstructor.kt b/idea/testData/resolve/references/TypeAliasAsSupertypeConstructor.kt new file mode 100644 index 00000000000..e9a5a677543 --- /dev/null +++ b/idea/testData/resolve/references/TypeAliasAsSupertypeConstructor.kt @@ -0,0 +1,9 @@ +package test + +open class C + +typealias CA = C + +class D : CA() + +// REF: (test).CA diff --git a/idea/tests/org/jetbrains/kotlin/idea/resolve/ReferenceResolveTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/resolve/ReferenceResolveTestGenerated.java index 8908744bd69..19f2476df8b 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/resolve/ReferenceResolveTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/resolve/ReferenceResolveTestGenerated.java @@ -395,6 +395,12 @@ public class ReferenceResolveTestGenerated extends AbstractReferenceResolveTest doTest(fileName); } + @TestMetadata("TypeAliasAsSupertypeConstructor.kt") + public void testTypeAliasAsSupertypeConstructor() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/resolve/references/TypeAliasAsSupertypeConstructor.kt"); + doTest(fileName); + } + @TestMetadata("TypeAliasRHS.kt") public void testTypeAliasRHS() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/resolve/references/TypeAliasRHS.kt"); diff --git a/js/js.frontend/src/org/jetbrains/kotlin/js/naming/NameSuggestion.kt b/js/js.frontend/src/org/jetbrains/kotlin/js/naming/NameSuggestion.kt index 72c666a02da..dcbc259f565 100644 --- a/js/js.frontend/src/org/jetbrains/kotlin/js/naming/NameSuggestion.kt +++ b/js/js.frontend/src/org/jetbrains/kotlin/js/naming/NameSuggestion.kt @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.js.naming import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor import org.jetbrains.kotlin.js.descriptorUtils.getJetTypeFqName import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils.* import org.jetbrains.kotlin.resolve.DescriptorUtils @@ -89,6 +90,9 @@ class NameSuggestion { // It's a special case when an object has `invoke` operator defined, in this case we simply generate object itself is FakeCallableDescriptorForObject -> return suggest(descriptor.getReferencedObject()) + // For type alias constructor descriptors we generate references to underlying constructors + is TypeAliasConstructorDescriptor -> return suggest(descriptor.underlyingConstructorDescriptor) + // For primary constructors and constructors of native classes we generate references to containing classes is ConstructorDescriptor -> { if (descriptor.isPrimary || isNativeObject(descriptor)) { diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/TypeAliasesTestsGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/TypeAliasesTestsGenerated.java index 6242d7cd0db..629635e7ccc 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/TypeAliasesTestsGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/TypeAliasesTestsGenerated.java @@ -71,6 +71,12 @@ public class TypeAliasesTestsGenerated extends AbstractTypeAliasesTests { doTest(fileName); } + @TestMetadata("typeAliasConstructorInSuperCall.kt") + public void testTypeAliasConstructorInSuperCall() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/typealias/typeAliasConstructorInSuperCall.kt"); + doTest(fileName); + } + @TestMetadata("typeAliasObject.kt") public void testTypeAliasObject() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/typealias/typeAliasObject.kt"); diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/TranslationContext.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/TranslationContext.java index 044ebfd42aa..b69839d7473 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/TranslationContext.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/TranslationContext.java @@ -21,6 +21,7 @@ import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.descriptors.*; +import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor; import org.jetbrains.kotlin.js.config.JsConfig; import org.jetbrains.kotlin.js.translate.intrinsic.Intrinsics; import org.jetbrains.kotlin.js.translate.utils.TranslationUtils; @@ -463,6 +464,11 @@ public class TranslationContext { @Nullable public List getClassOrConstructorClosure(@NotNull MemberDescriptor classOrConstructor) { + if (classOrConstructor instanceof TypeAliasConstructorDescriptor) { + ClassConstructorDescriptor constructorDescriptor = ((TypeAliasConstructorDescriptor) classOrConstructor).getUnderlyingConstructorDescriptor(); + return getClassOrConstructorClosure(constructorDescriptor); + } + List result = staticContext.getClassOrConstructorClosure(classOrConstructor); if (result == null && classOrConstructor instanceof ConstructorDescriptor &&