KT-11588 Type aliases

Create substituted constructor descriptors for generic type aliases.
This commit is contained in:
Dmitry Petrov
2016-05-24 18:29:34 +03:00
parent c63166047c
commit 62f8d00f89
8 changed files with 164 additions and 19 deletions
@@ -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<FunctionDescriptor> {
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<VariableDescriptor> {
@@ -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<ConstructorDescriptor> {
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
}
}
}
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))
}
@@ -0,0 +1,5 @@
class Pair<T1, T2>(val x1: T1, val x2: T2)
typealias P2<T> = Pair<T, T>
val test1 = P2<String>("", "")
@@ -0,0 +1,13 @@
package
public typealias P2</*0*/ T> = Pair<T, T>
public val test1: Pair<kotlin.String, kotlin.String>
public final class Pair</*0*/ T1, /*1*/ T2> {
public constructor Pair</*0*/ T1, /*1*/ T2>(/*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
}
@@ -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");
@@ -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
/**
@@ -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
@@ -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(),
@@ -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
}
}
}