diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerLevels.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerLevels.kt index 9687fe48c49..6f68820ae5b 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerLevels.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/tower/TowerLevels.kt @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.resolve.calls.tower import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptorImpl import org.jetbrains.kotlin.incremental.components.LookupLocation import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.calls.smartcasts.getReceiverValueWithSmartCast @@ -33,9 +34,7 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue import org.jetbrains.kotlin.resolve.scopes.utils.collectFunctions import org.jetbrains.kotlin.resolve.scopes.utils.collectVariables import org.jetbrains.kotlin.resolve.selectMostSpecificInEachOverridableGroup -import org.jetbrains.kotlin.types.ErrorUtils -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.isDynamic +import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.typeUtil.getImmediateSuperclassNotAny import org.jetbrains.kotlin.utils.SmartList import org.jetbrains.kotlin.utils.addIfNotNull @@ -230,9 +229,10 @@ private fun KotlinType?.getInnerConstructors(name: Name, location: LookupLocatio } private fun ResolutionScope.getContributedFunctionsAndConstructors(name: Name, location: LookupLocation): Collection { - val classWithConstructors = getClassWithConstructors(getContributedClassifier(name, location)) + val classifier = getContributedClassifier(name, location) return getContributedFunctions(name, location) + - (classWithConstructors?.constructors?.filter { it.dispatchReceiverParameter == null } ?: emptyList()) + (getClassWithConstructors(classifier)?.constructors?.filter { it.dispatchReceiverParameter == null } ?: emptyList()) + + (classifier?.getTypeAliasConstructors(false) ?: emptyList()) } private fun ResolutionScope.getContributedVariablesAndObjects(name: Name, location: LookupLocation): Collection { @@ -255,16 +255,34 @@ private fun getFakeDescriptorForObject(classifier: ClassifierDescriptor?): FakeC } } -private fun getClassWithConstructors(classifier: ClassifierDescriptor?): ClassDescriptor? { - if (classifier is TypeAliasDescriptor) { - return getClassWithConstructors(classifier.classDescriptor) +private fun getClassWithConstructors(classifier: ClassifierDescriptor?): ClassDescriptor? = + if (classifier !is ClassDescriptor || !classifier.canHaveCallableConstructors()) + null + else + classifier + +private fun ClassDescriptor.canHaveCallableConstructors() = + !ErrorUtils.isError(this) && !kind.isSingleton + +private fun ClassifierDescriptor.getTypeAliasConstructors(inner: Boolean): Collection { + if (this !is TypeAliasDescriptor) return emptyList() + + val classDescriptor = this.classDescriptor ?: return emptyList() + if (!classDescriptor.canHaveCallableConstructors()) return emptyList() + + val substitutor = this.getTypeSubstitutorForUnderlyingClass() ?: throw AssertionError("classDescriptor should be non-null for $this") + + return classDescriptor.constructors.filter { + if (inner) it.dispatchReceiverParameter != null else it.dispatchReceiverParameter == null + }.mapNotNull { + TypeAliasConstructorDescriptorImpl.create(this, it, substitutor) } - else if (classifier !is ClassDescriptor || ErrorUtils.isError(classifier) - // Constructors of singletons shouldn't be callable from the code - || classifier.kind.isSingleton) { - return null - } - else { - return classifier - } -} \ No newline at end of file +} + +private fun TypeAliasDescriptor.getTypeSubstitutorForUnderlyingClass(): TypeSubstitutor? { + if (classDescriptor == null) return null + + val expandedTypeParameters = expandedType.constructor.parameters + val expandedTypeArguments = expandedType.arguments + return TypeSubstitutor.create(IndexedParametersSubstitution(expandedTypeParameters, expandedTypeArguments)) +} diff --git a/compiler/testData/diagnostics/tests/typealias/typeAliasArgumentsInConstructor.kt b/compiler/testData/diagnostics/tests/typealias/typeAliasArgumentsInConstructor.kt new file mode 100644 index 00000000000..7f32a3cbe36 --- /dev/null +++ b/compiler/testData/diagnostics/tests/typealias/typeAliasArgumentsInConstructor.kt @@ -0,0 +1,5 @@ +class Pair(val x1: T1, val x2: T2) + +typealias P2 = Pair + +val test1 = P2("", "") \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/typealias/typeAliasArgumentsInConstructor.txt b/compiler/testData/diagnostics/tests/typealias/typeAliasArgumentsInConstructor.txt new file mode 100644 index 00000000000..78be3c1e82d --- /dev/null +++ b/compiler/testData/diagnostics/tests/typealias/typeAliasArgumentsInConstructor.txt @@ -0,0 +1,13 @@ +package + +public typealias P2 = Pair +public val test1: Pair + +public final class Pair { + public constructor Pair(/*0*/ x1: T1, /*1*/ x2: T2) + public final val x1: T1 + public final val x2: T2 + 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 +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 86b2e26d694..f4b166aaafb 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -19179,6 +19179,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("typeAliasArgumentsInConstructor.kt") + public void testTypeAliasArgumentsInConstructor() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/typealias/typeAliasArgumentsInConstructor.kt"); + doTest(fileName); + } + @TestMetadata("typeAliasConstructor.kt") public void testTypeAliasConstructor() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/typealias/typeAliasConstructor.kt"); diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/ValueParameterDescriptor.kt b/core/descriptors/src/org/jetbrains/kotlin/descriptors/ValueParameterDescriptor.kt index ebf71b312c6..55d6c3b0a91 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/ValueParameterDescriptor.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/ValueParameterDescriptor.kt @@ -18,6 +18,7 @@ package org.jetbrains.kotlin.descriptors import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.TypeSubstitutor interface ValueParameterDescriptor : VariableDescriptor, ParameterDescriptor { override fun getContainingDeclaration(): CallableDescriptor @@ -39,6 +40,8 @@ interface ValueParameterDescriptor : VariableDescriptor, ParameterDescriptor { override fun getOriginal(): ValueParameterDescriptor + override fun substitute(substitutor: TypeSubstitutor): ValueParameterDescriptor + fun copy(newOwner: CallableDescriptor, newName: Name): ValueParameterDescriptor /** diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractTypeAliasDescriptor.kt b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractTypeAliasDescriptor.kt index 92cd83039c4..3d450b96da4 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractTypeAliasDescriptor.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/AbstractTypeAliasDescriptor.kt @@ -51,7 +51,7 @@ abstract class AbstractTypeAliasDescriptor( override val classDescriptor: ClassDescriptor? get() = expandedType.let { expandedType -> - if (expandedType.isError) null else expandedType.constructor.declarationDescriptor as ClassDescriptor + if (expandedType.isError) null else expandedType.constructor.declarationDescriptor as? ClassDescriptor } override fun getModality() = Modality.FINAL diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/FunctionDescriptorImpl.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/FunctionDescriptorImpl.java index 48982552544..f1d291be6fd 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/FunctionDescriptorImpl.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/FunctionDescriptorImpl.java @@ -513,7 +513,7 @@ public abstract class FunctionDescriptorImpl extends DeclarationDescriptorNonRoo } @NotNull - private CopyConfiguration newCopyBuilder(@NotNull TypeSubstitutor substitutor) { + protected CopyConfiguration newCopyBuilder(@NotNull TypeSubstitutor substitutor) { return new CopyConfiguration( substitutor.getSubstitution(), getContainingDeclaration(), getModality(), getVisibility(), getKind(), getValueParameters(), diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/TypeAliasConstructorDescriptor.kt b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/TypeAliasConstructorDescriptor.kt new file mode 100644 index 00000000000..595df285988 --- /dev/null +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/TypeAliasConstructorDescriptor.kt @@ -0,0 +1,100 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.descriptors.impl + +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind +import org.jetbrains.kotlin.descriptors.annotations.Annotations +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.TypeSubstitutor +import org.jetbrains.kotlin.types.Variance + +interface TypeAliasConstructorDescriptor : ConstructorDescriptor { + val typeAliasDescriptor: TypeAliasDescriptor +} + +class TypeAliasConstructorDescriptorImpl private constructor( + override val typeAliasDescriptor: TypeAliasDescriptor, + containingDeclaration: ClassDescriptor, + original: ConstructorDescriptor, + annotations: Annotations, + primary: Boolean, + kind: Kind, + source: SourceElement +) : TypeAliasConstructorDescriptor, + ConstructorDescriptorImpl(containingDeclaration, original, annotations, primary, kind, source) +{ + override fun substitute(substitutor: TypeSubstitutor): TypeAliasConstructorDescriptor = + super.substitute(substitutor) as TypeAliasConstructorDescriptor + + override fun copy( + newOwner: DeclarationDescriptor, + modality: Modality, + visibility: Visibility, + kind: Kind, + copyOverrides: Boolean + ): TypeAliasConstructorDescriptor = + newCopyBuilder() + .setOwner(newOwner) + .setModality(modality) + .setVisibility(visibility) + .setKind(kind) + .setCopyOverrides(copyOverrides) + .build() as TypeAliasConstructorDescriptor + + override fun createSubstitutedCopy( + newOwner: DeclarationDescriptor, + original: FunctionDescriptor?, + kind: Kind, + newName: Name?, + annotations: Annotations, + preserveSource: Boolean + ): TypeAliasConstructorDescriptorImpl { + assert(kind == Kind.DECLARATION || kind == Kind.SYNTHESIZED) { + "Creating a type alias constructor that is not a declaration: \ncopy from: ${this}\nnewOwner: $newOwner\nkind: $kind" + } + assert(newName == null) { "Renaming type alias constructor: $this" } + return TypeAliasConstructorDescriptorImpl( + typeAliasDescriptor, + newOwner as ClassDescriptor, + this, annotations, isPrimary, Kind.DECLARATION, + getSourceToUseForCopy(preserveSource, original)) + } + + companion object { + fun create( + typeAliasDescriptor: TypeAliasDescriptor, + original: ConstructorDescriptor, + substitutor: TypeSubstitutor + ): TypeAliasConstructorDescriptor? { + val descriptor = TypeAliasConstructorDescriptorImpl(typeAliasDescriptor, original.containingDeclaration, original, + original.annotations, original.isPrimary, original.kind, original.source) + val valueParameters = FunctionDescriptorImpl.getSubstitutedValueParameters(descriptor, original.valueParameters, substitutor, false) + ?: return null + + descriptor.initialize(valueParameters, original.visibility, typeAliasDescriptor.typeConstructor.parameters) + + descriptor.returnType = substitutor.substitute(original.returnType, Variance.OUT_VARIANCE) ?: return null + + return descriptor + } + } +} + + +