KT-11588 Type aliases
- Nested type aliases - UNSUPPORTED_TYPEALIAS error (language level < 1.1) - tests for is/as/as? with type alias
This commit is contained in:
@@ -115,6 +115,7 @@ public interface Errors {
|
||||
DiagnosticFactory0<KtParameter> REIFIED_TYPE_IN_CATCH_CLAUSE = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtTypeParameterList> GENERIC_THROWABLE_SUBCLASS = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
DiagnosticFactory0<PsiElement> UNSUPPORTED_TYPEALIAS = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory1<KtUserType, ClassifierDescriptor> RECURSIVE_TYPEALIAS_EXPANSION = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory3<KtElement, KotlinType, KotlinType, ClassifierDescriptor> UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION =
|
||||
DiagnosticFactory3.create(ERROR);
|
||||
|
||||
+1
@@ -417,6 +417,7 @@ public class DefaultErrorMessages {
|
||||
MAP.put(USELESS_ELVIS_ON_LAMBDA_EXPRESSION, "Left operand of elvis operator (?:) is a lambda expression");
|
||||
MAP.put(CONFLICTING_UPPER_BOUNDS, "Upper bounds of {0} have empty intersection", NAME);
|
||||
|
||||
MAP.put(UNSUPPORTED_TYPEALIAS, "Type aliases are unsupported (min Kotlin language level: 1.1)");
|
||||
MAP.put(RECURSIVE_TYPEALIAS_EXPANSION, "Recursive type alias in expansion: {0}", NAME);
|
||||
MAP.put(UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION,
|
||||
"Type argument resulting from type alias expansion is not within required bounds for ''{2}'': " +
|
||||
|
||||
@@ -17,7 +17,9 @@
|
||||
package org.jetbrains.kotlin.psi
|
||||
|
||||
import com.intellij.lang.ASTNode
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.KtNodeTypes
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.stubs.KotlinTypeAliasStub
|
||||
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes
|
||||
|
||||
@@ -31,6 +33,10 @@ class KtTypeAlias : KtTypeParameterListOwnerStub<KotlinTypeAliasStub>, KtNamedDe
|
||||
fun isTopLevel(): Boolean =
|
||||
stub?.isTopLevel() ?: parent is KtFile
|
||||
|
||||
@IfNotParsed
|
||||
fun getTypeAliasKeyword(): PsiElement? =
|
||||
findChildByType(KtTokens.TYPE_ALIAS_KEYWORD)
|
||||
|
||||
@IfNotParsed
|
||||
fun getTypeReference(): KtTypeReference? =
|
||||
findChildByType(KtNodeTypes.TYPE_REFERENCE)
|
||||
|
||||
@@ -29,6 +29,8 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.builtins.FunctionTypesKt;
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.config.LanguageFeature;
|
||||
import org.jetbrains.kotlin.config.LanguageFeatureSettings;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationSplitter;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget;
|
||||
@@ -61,9 +63,7 @@ import java.util.*;
|
||||
import static org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget.*;
|
||||
import static org.jetbrains.kotlin.diagnostics.Errors.*;
|
||||
import static org.jetbrains.kotlin.lexer.KtTokens.*;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContext.CONSTRUCTOR;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContext.PACKAGE_TO_FILES;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContext.TYPE_ALIAS;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContext.*;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
|
||||
import static org.jetbrains.kotlin.resolve.ModifiersChecker.resolveModalityFromModifiers;
|
||||
import static org.jetbrains.kotlin.resolve.ModifiersChecker.resolveVisibilityFromModifiers;
|
||||
@@ -79,6 +79,7 @@ public class DescriptorResolver {
|
||||
@NotNull private final VariableTypeResolver variableTypeResolver;
|
||||
@NotNull private final ExpressionTypingServices expressionTypingServices;
|
||||
@NotNull private final OverloadChecker overloadChecker;
|
||||
@NotNull private final LanguageFeatureSettings languageFeatureSettings;
|
||||
|
||||
public DescriptorResolver(
|
||||
@NotNull AnnotationResolver annotationResolver,
|
||||
@@ -88,7 +89,8 @@ public class DescriptorResolver {
|
||||
@NotNull SupertypeLoopChecker supertypeLoopsResolver,
|
||||
@NotNull VariableTypeResolver variableTypeResolver,
|
||||
@NotNull ExpressionTypingServices expressionTypingServices,
|
||||
@NotNull OverloadChecker overloadChecker
|
||||
@NotNull OverloadChecker overloadChecker,
|
||||
@NotNull LanguageFeatureSettings languageFeatureSettings
|
||||
) {
|
||||
this.annotationResolver = annotationResolver;
|
||||
this.builtIns = builtIns;
|
||||
@@ -98,6 +100,7 @@ public class DescriptorResolver {
|
||||
this.variableTypeResolver = variableTypeResolver;
|
||||
this.expressionTypingServices = expressionTypingServices;
|
||||
this.overloadChecker = overloadChecker;
|
||||
this.languageFeatureSettings = languageFeatureSettings;
|
||||
}
|
||||
|
||||
public List<KotlinType> resolveSupertypes(
|
||||
@@ -675,21 +678,24 @@ public class DescriptorResolver {
|
||||
return variableDescriptor;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Nullable
|
||||
public TypeAliasDescriptor resolveTypeAliasDescriptor(
|
||||
@NotNull DeclarationDescriptor containingDeclaration,
|
||||
@NotNull LexicalScope scope,
|
||||
@NotNull KtTypeAlias typeAlias,
|
||||
@NotNull final BindingTrace trace
|
||||
) {
|
||||
final KtTypeReference typeReference = typeAlias.getTypeReference();
|
||||
if (typeReference == null) return null;
|
||||
|
||||
KtModifierList modifierList = typeAlias.getModifierList();
|
||||
Visibility visibility = resolveVisibilityFromModifiers(typeAlias, getDefaultVisibility(typeAlias, containingDeclaration));
|
||||
|
||||
Annotations allAnnotations = annotationResolver.resolveAnnotationsWithArguments(scope, modifierList, trace);
|
||||
Name name = KtPsiUtil.safeName(typeAlias.getName());
|
||||
SourceElement sourceElement = KotlinSourceElementKt.toSourceElement(typeAlias);
|
||||
LazyTypeAliasDescriptor typeAliasDescriptor = LazyTypeAliasDescriptor.create(
|
||||
containingDeclaration, allAnnotations, name, sourceElement, visibility);
|
||||
final LazyTypeAliasDescriptor typeAliasDescriptor = LazyTypeAliasDescriptor.create(
|
||||
storageManager, trace, containingDeclaration, allAnnotations, name, sourceElement, visibility);
|
||||
|
||||
List<TypeParameterDescriptorImpl> typeParameterDescriptors;
|
||||
final LexicalScope scopeWithTypeParameters;
|
||||
@@ -712,20 +718,25 @@ public class DescriptorResolver {
|
||||
}
|
||||
}
|
||||
|
||||
final KtTypeReference typeReference = typeAlias.getTypeReference();
|
||||
if (!languageFeatureSettings.supportsFeature(LanguageFeature.TypeAliases)) {
|
||||
typeResolver.resolveType(scopeWithTypeParameters, typeReference, trace, true);
|
||||
trace.report(UNSUPPORTED_TYPEALIAS.on(typeAlias.getTypeAliasKeyword()));
|
||||
return null;
|
||||
}
|
||||
|
||||
typeAliasDescriptor.initialize(
|
||||
typeParameterDescriptors,
|
||||
storageManager.createLazyValue(new Function0<KotlinType>() {
|
||||
DeferredType.create(storageManager, trace, new Function0<KotlinType>() {
|
||||
@Override
|
||||
public KotlinType invoke() {
|
||||
return typeResolver.resolveAbbreviatedType(scopeWithTypeParameters, typeReference, trace, true);
|
||||
}
|
||||
}),
|
||||
storageManager.createLazyValue(new Function0<KotlinType>() {
|
||||
DeferredType.create(storageManager, trace, new Function0<KotlinType>() {
|
||||
@Override
|
||||
public KotlinType invoke() {
|
||||
// TODO do not reparse
|
||||
// TODO do not reparse type alias RHS, just expand it instead
|
||||
// NB this messes up with diagnostics
|
||||
return typeResolver.resolveType(scopeWithTypeParameters, typeReference, trace, true);
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -19,6 +19,8 @@ package org.jetbrains.kotlin.resolve
|
||||
import com.google.common.collect.HashMultimap
|
||||
import com.google.common.collect.Multimap
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageFeatureSettings
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.diagnostics.Errors.*
|
||||
import org.jetbrains.kotlin.incremental.KotlinLookupLocation
|
||||
@@ -44,7 +46,8 @@ class LazyTopDownAnalyzer(
|
||||
private val fileScopeProvider: FileScopeProvider,
|
||||
private val declarationScopeProvider: DeclarationScopeProvider,
|
||||
private val qualifiedExpressionResolver: QualifiedExpressionResolver,
|
||||
private val identifierChecker: IdentifierChecker
|
||||
private val identifierChecker: IdentifierChecker,
|
||||
private val languageFeatureSettings: LanguageFeatureSettings
|
||||
) {
|
||||
fun analyzeDeclarations(topDownAnalysisMode: TopDownAnalysisMode, declarations: Collection<PsiElement>, outerDataFlowInfo: DataFlowInfo): TopDownAnalysisContext {
|
||||
|
||||
@@ -207,6 +210,8 @@ class LazyTopDownAnalyzer(
|
||||
}
|
||||
|
||||
private fun createTypeAliasDescriptors(c: TopDownAnalysisContext, topLevelFqNames: Multimap<FqName, KtElement>, typeAliases: List<KtTypeAlias>) {
|
||||
if (!languageFeatureSettings.supportsFeature(LanguageFeature.TypeAliases)) return
|
||||
|
||||
for (typeAlias in typeAliases) {
|
||||
val descriptor = lazyDeclarationResolver.resolveToDescriptor(typeAlias) as TypeAliasDescriptor
|
||||
|
||||
|
||||
@@ -369,8 +369,8 @@ class TypeResolver(
|
||||
}
|
||||
|
||||
val collectedArgumentAsTypeProjections =
|
||||
collectArgumentsForClassTypeConstructor(c, classDescriptor, qualifierResolutionResult.qualifierParts)
|
||||
?: return createErrorTypeAndResolveArguments(c, projectionFromAllQualifierParts, typeConstructor.toString())
|
||||
collectArgumentsForClassifierTypeConstructor(c, classDescriptor, qualifierResolutionResult.qualifierParts)
|
||||
?: return createErrorTypeForTypeConstructor(c, projectionFromAllQualifierParts, typeConstructor)
|
||||
|
||||
assert(collectedArgumentAsTypeProjections.size <= parameters.size) {
|
||||
"Collected arguments count should be not greater then parameters count," +
|
||||
@@ -423,63 +423,70 @@ class TypeResolver(
|
||||
private fun resolveTypeForTypeAlias(
|
||||
c: TypeResolutionContext,
|
||||
annotations: Annotations,
|
||||
typeAliasDescriptor: TypeAliasDescriptor,
|
||||
descriptor: TypeAliasDescriptor,
|
||||
type: KtUserType,
|
||||
qualifierResolutionResult: QualifiedExpressionResolver.TypeQualifierResolutionResult
|
||||
): PossiblyBareType {
|
||||
val typeAliasConstructor = typeAliasDescriptor.typeConstructor
|
||||
val typeConstructor = descriptor.typeConstructor
|
||||
val projectionFromAllQualifierParts = qualifierResolutionResult.allProjections
|
||||
|
||||
if (ErrorUtils.isError(typeAliasDescriptor)) {
|
||||
return createErrorTypeForTypeConstructor(c, projectionFromAllQualifierParts, typeAliasConstructor)
|
||||
if (ErrorUtils.isError(descriptor)) {
|
||||
return createErrorTypeForTypeConstructor(c, projectionFromAllQualifierParts, typeConstructor)
|
||||
}
|
||||
|
||||
// TODO type arguments substitution for type parameters of outer classes
|
||||
// TODO should we support type aliases as qualifiers? what about generics?
|
||||
val parameters = typeConstructor.parameters
|
||||
|
||||
val typeAliasParameters = typeAliasDescriptor.declaredTypeParameters
|
||||
val typeAliasQualifierPart =
|
||||
qualifierResolutionResult.qualifierParts.lastOrNull()
|
||||
?: return createErrorTypeForTypeConstructor(c, projectionFromAllQualifierParts, typeConstructor)
|
||||
|
||||
val typeAliasQualifierPart = qualifierResolutionResult.qualifierParts.lastOrNull()
|
||||
?: return createErrorTypeForTypeConstructor(c, projectionFromAllQualifierParts, typeAliasConstructor)
|
||||
val argumentElementsFromUserType =
|
||||
collectArgumentsForClassifierTypeConstructor(c, descriptor, qualifierResolutionResult.qualifierParts)
|
||||
?: return createErrorTypeForTypeConstructor(c, projectionFromAllQualifierParts, typeConstructor)
|
||||
|
||||
// TODO appendDefaultArgumentsForInnerScope
|
||||
val typeAliasArguments = typeAliasQualifierPart.typeArguments?.arguments.orEmpty()
|
||||
val argumentsFromUserType = resolveTypeProjections(c, typeConstructor, argumentElementsFromUserType)
|
||||
|
||||
val arguments = argumentsFromUserType + appendDefaultArgumentsForInnerScope(argumentsFromUserType.size, parameters)
|
||||
|
||||
val reportStrategy = TracingTypeAliasExpansionReportStrategy(
|
||||
c.trace,
|
||||
type, typeAliasQualifierPart.typeArguments ?: typeAliasQualifierPart.expression,
|
||||
typeAliasDescriptor, typeAliasDescriptor.declaredTypeParameters, typeAliasArguments)
|
||||
descriptor, descriptor.declaredTypeParameters,
|
||||
argumentElementsFromUserType // TODO arguments from inner scope
|
||||
)
|
||||
|
||||
if (typeAliasParameters.size != typeAliasArguments.size) {
|
||||
reportStrategy.wrongNumberOfTypeArguments(typeAliasDescriptor, typeAliasParameters.size)
|
||||
return createErrorTypeForTypeConstructor(c, projectionFromAllQualifierParts, typeAliasConstructor)
|
||||
if (parameters.size != arguments.size) {
|
||||
reportStrategy.wrongNumberOfTypeArguments(descriptor, parameters.size)
|
||||
return createErrorTypeForTypeConstructor(c, projectionFromAllQualifierParts, typeConstructor)
|
||||
}
|
||||
|
||||
return if (c.abbreviated) {
|
||||
val arguments = resolveTypeProjections(c, typeAliasDescriptor.typeConstructor, typeAliasArguments)
|
||||
val abbreviatedType = KotlinTypeImpl.create(annotations, typeAliasDescriptor.typeConstructor, false, arguments, MemberScope.Empty)
|
||||
val abbreviatedType = KotlinTypeImpl.create(annotations, descriptor.typeConstructor, false, arguments, MemberScope.Empty)
|
||||
type(abbreviatedType)
|
||||
}
|
||||
else {
|
||||
val arguments = resolveTypeProjections(c, typeAliasDescriptor.typeConstructor, typeAliasArguments)
|
||||
val typeAliasExpansion = createTypeAliasExpansion(null, typeAliasDescriptor, arguments)
|
||||
val expandedType = expandTypeAlias(c, typeAliasExpansion, reportStrategy, annotations, 0)
|
||||
val typeAliasExpansion = createTypeAliasExpansion(null, descriptor, arguments)
|
||||
val expandedType = expandTypeAlias(typeAliasExpansion, reportStrategy, annotations, 0)
|
||||
type(expandedType)
|
||||
}
|
||||
}
|
||||
|
||||
private class TracingTypeAliasExpansionReportStrategy(
|
||||
val trace: BindingTrace,
|
||||
val type: KtUserType,
|
||||
val typeArgumentsOrTypeName: KtElement,
|
||||
val type: KtUserType?,
|
||||
val typeArgumentsOrTypeName: KtElement?,
|
||||
val typeAliasDescriptor: TypeAliasDescriptor,
|
||||
val typeParameters: List<TypeParameterDescriptor>,
|
||||
val typeArguments: List<KtTypeProjection>
|
||||
typeParameters: List<TypeParameterDescriptor>,
|
||||
typeArguments: List<KtTypeProjection>
|
||||
) : TypeAliasExpansionReportStrategy {
|
||||
constructor (trace: BindingTrace, typeAliasDescriptor: TypeAliasDescriptor) : this(trace, null, null, typeAliasDescriptor, emptyList(), emptyList())
|
||||
|
||||
private val mappedArguments = typeParameters.zip(typeArguments).toMap()
|
||||
|
||||
override fun wrongNumberOfTypeArguments(typeAlias: TypeAliasDescriptor, numberOfParameters: Int) {
|
||||
trace.report(WRONG_NUMBER_OF_TYPE_ARGUMENTS.on(typeArgumentsOrTypeName, numberOfParameters, typeAliasDescriptor))
|
||||
if (typeArgumentsOrTypeName != null) {
|
||||
trace.report(WRONG_NUMBER_OF_TYPE_ARGUMENTS.on(typeArgumentsOrTypeName, numberOfParameters, typeAliasDescriptor))
|
||||
}
|
||||
}
|
||||
|
||||
override fun conflictingProjection(typeAlias: TypeAliasDescriptor, typeParameter: TypeParameterDescriptor?, expandingType: KotlinType) {
|
||||
@@ -487,13 +494,15 @@ class TypeResolver(
|
||||
if (argumentElement != null && typeParameter != null) {
|
||||
trace.report(CONFLICTING_PROJECTION.on(argumentElement, typeParameter))
|
||||
}
|
||||
else {
|
||||
else if (type != null) {
|
||||
trace.report(CONFLICTING_PROJECTION_IN_TYPEALIAS_EXPANSION.on(type, typeAliasDescriptor.underlyingType))
|
||||
}
|
||||
}
|
||||
|
||||
override fun recursiveTypeAlias(typeAlias: TypeAliasDescriptor) {
|
||||
trace.report(RECURSIVE_TYPEALIAS_EXPANSION.on(type, typeAlias))
|
||||
if (type != null) {
|
||||
trace.report(RECURSIVE_TYPEALIAS_EXPANSION.on(type, typeAlias))
|
||||
}
|
||||
}
|
||||
|
||||
override fun boundsViolationInSubstitution(bound: KotlinType, unsubstitutedArgument: KotlinType, argument: KotlinType, typeParameter: TypeParameterDescriptor) {
|
||||
@@ -503,7 +512,7 @@ class TypeResolver(
|
||||
if (argumentTypeReferenceElement != null) {
|
||||
trace.report(UPPER_BOUND_VIOLATED.on(argumentTypeReferenceElement, bound, argument))
|
||||
}
|
||||
else {
|
||||
else if (type != null) {
|
||||
trace.report(UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION.on(type, bound, argument, typeParameter))
|
||||
}
|
||||
}
|
||||
@@ -532,20 +541,19 @@ class TypeResolver(
|
||||
typeAliasDescriptor: TypeAliasDescriptor,
|
||||
arguments: List<TypeProjection>
|
||||
): TypeAliasExpansion {
|
||||
val typeParameters = typeAliasDescriptor.declaredTypeParameters // TODO inner type aliases
|
||||
val typeParameters = typeAliasDescriptor.typeConstructor.parameters.map { it.original as TypeParameterDescriptor }
|
||||
val mappedArguments = typeParameters.zip(arguments).toMap()
|
||||
return TypeAliasExpansion(parent, typeAliasDescriptor, arguments, mappedArguments)
|
||||
}
|
||||
|
||||
private fun expandTypeAlias(
|
||||
c: TypeResolutionContext,
|
||||
typeAliasExpansion: TypeAliasExpansion,
|
||||
reportStrategy: TypeAliasExpansionReportStrategy,
|
||||
annotations: Annotations,
|
||||
recursionDepth: Int
|
||||
): KotlinType {
|
||||
val originalProjection = TypeProjectionImpl(Variance.INVARIANT, typeAliasExpansion.descriptor.underlyingType)
|
||||
val expandedProjection = expandTypeProjectionForTypeAlias(c, originalProjection, typeAliasExpansion, null, reportStrategy, recursionDepth)
|
||||
val expandedProjection = expandTypeProjectionForTypeAlias(originalProjection, typeAliasExpansion, null, reportStrategy, recursionDepth)
|
||||
val expandedType = expandedProjection.type
|
||||
|
||||
if (expandedType.isError) return expandedType
|
||||
@@ -564,7 +572,6 @@ class TypeResolver(
|
||||
}
|
||||
|
||||
private fun expandTypeProjectionForTypeAlias(
|
||||
c: TypeResolutionContext,
|
||||
originalProjection: TypeProjection,
|
||||
typeAliasExpansion: TypeAliasExpansion,
|
||||
typeParameterDescriptor: TypeParameterDescriptor?,
|
||||
@@ -580,7 +587,7 @@ class TypeResolver(
|
||||
val typeAliasArgument = typeAliasExpansion.getReplacement(originalType.constructor)
|
||||
|
||||
if (typeAliasArgument == null) {
|
||||
return substituteNonArgumentTypeForTypeAlias(c, originalProjection, typeAliasExpansion, reportStrategy, recursionDepth)
|
||||
return substituteNonArgumentTypeForTypeAlias(originalProjection, typeAliasExpansion, reportStrategy, recursionDepth)
|
||||
}
|
||||
|
||||
val originalVariance =
|
||||
@@ -613,7 +620,6 @@ class TypeResolver(
|
||||
}
|
||||
|
||||
private fun substituteNonArgumentTypeForTypeAlias(
|
||||
c: TypeResolutionContext,
|
||||
originalProjection: TypeProjection,
|
||||
typeAliasExpansion: TypeAliasExpansion,
|
||||
reportStrategy: TypeAliasExpansionReportStrategy,
|
||||
@@ -634,18 +640,18 @@ class TypeResolver(
|
||||
}
|
||||
|
||||
val expandedArguments = type.arguments.mapIndexed { i, typeAliasArgument ->
|
||||
expandTypeProjectionForTypeAlias(c, typeAliasArgument, typeAliasExpansion, typeConstructor.parameters[i], reportStrategy, recursionDepth + 1)
|
||||
expandTypeProjectionForTypeAlias(typeAliasArgument, typeAliasExpansion, typeConstructor.parameters[i], reportStrategy, recursionDepth + 1)
|
||||
}
|
||||
|
||||
val nestedExpansion = createTypeAliasExpansion(typeAliasExpansion, typeDescriptor, expandedArguments)
|
||||
|
||||
val expandedType = expandTypeAlias(c, nestedExpansion, reportStrategy, type.annotations, recursionDepth + 1)
|
||||
val expandedType = expandTypeAlias(nestedExpansion, reportStrategy, type.annotations, recursionDepth + 1)
|
||||
|
||||
return TypeProjectionImpl(originalProjection.projectionKind, expandedType.withAbbreviatedType(type))
|
||||
}
|
||||
else -> {
|
||||
val substitutedArguments = type.arguments.mapIndexed { i, originalArgument ->
|
||||
expandTypeProjectionForTypeAlias(c, originalArgument, typeAliasExpansion, typeConstructor.parameters[i], reportStrategy, recursionDepth + 1)
|
||||
expandTypeProjectionForTypeAlias(originalArgument, typeAliasExpansion, typeConstructor.parameters[i], reportStrategy, recursionDepth + 1)
|
||||
}
|
||||
|
||||
val substitutedType = type.replace(newArguments = substitutedArguments)
|
||||
@@ -677,8 +683,11 @@ class TypeResolver(
|
||||
c: TypeResolutionContext,
|
||||
arguments: List<KtTypeProjection>,
|
||||
typeConstructor: TypeConstructor
|
||||
) =
|
||||
createErrorTypeAndResolveArguments(c, arguments, "[Error type: $typeConstructor]")
|
||||
): PossiblyBareType =
|
||||
type(ErrorUtils.createErrorTypeWithArguments(
|
||||
"$typeConstructor",
|
||||
resolveTypeProjectionsWithErrorConstructor(c, arguments)
|
||||
))
|
||||
|
||||
// Returns true in case when at least one argument for this class could be specified
|
||||
// It could be always equal to 'typeConstructor.parameters.isNotEmpty()' unless local classes could captured type parameters
|
||||
@@ -691,30 +700,30 @@ class TypeResolver(
|
||||
// }
|
||||
//
|
||||
// It's needed to determine whether this particular type could be bare
|
||||
private fun isPossibleToSpecifyTypeArgumentsFor(classDescriptor: ClassDescriptor): Boolean {
|
||||
private fun isPossibleToSpecifyTypeArgumentsFor(classifierDescriptor: ClassifierDescriptorWithTypeParameters): Boolean {
|
||||
// First parameter relates to the innermost declaration
|
||||
// If it's declared in function there
|
||||
val firstTypeParameter = classDescriptor.typeConstructor.parameters.firstOrNull() ?: return false
|
||||
val firstTypeParameter = classifierDescriptor.typeConstructor.parameters.firstOrNull() ?: return false
|
||||
return firstTypeParameter.original.containingDeclaration is ClassDescriptor
|
||||
}
|
||||
|
||||
private fun collectArgumentsForClassTypeConstructor(
|
||||
private fun collectArgumentsForClassifierTypeConstructor(
|
||||
c: TypeResolutionContext,
|
||||
classDescriptor: ClassDescriptor,
|
||||
classifierDescriptor: ClassifierDescriptorWithTypeParameters,
|
||||
qualifierParts: List<QualifiedExpressionResolver.QualifierPart>
|
||||
): List<KtTypeProjection>? {
|
||||
val classDescriptorChain = classDescriptor.classDescriptorChain()
|
||||
val classifierDescriptorChain = classifierDescriptor.classifierDescriptorsFromInnerToOuter()
|
||||
val reversedQualifierParts = qualifierParts.asReversed()
|
||||
|
||||
var wasStatic = false
|
||||
var result = SmartList<KtTypeProjection>()
|
||||
val result = SmartList<KtTypeProjection>()
|
||||
|
||||
val classChainLastIndex = Math.min(classDescriptorChain.size, reversedQualifierParts.size) - 1
|
||||
val classifierChainLastIndex = Math.min(classifierDescriptorChain.size, reversedQualifierParts.size) - 1
|
||||
|
||||
for (index in 0..classChainLastIndex) {
|
||||
for (index in 0..classifierChainLastIndex) {
|
||||
val qualifierPart = reversedQualifierParts[index]
|
||||
val currentArguments = qualifierPart.typeArguments?.arguments.orEmpty()
|
||||
val declaredTypeParameters = classDescriptorChain[index].declaredTypeParameters
|
||||
val declaredTypeParameters = classifierDescriptorChain[index].declaredTypeParameters
|
||||
val currentParameters = if (wasStatic) emptyList() else declaredTypeParameters
|
||||
|
||||
if (wasStatic && currentArguments.isNotEmpty() && declaredTypeParameters.isNotEmpty()) {
|
||||
@@ -725,7 +734,8 @@ class TypeResolver(
|
||||
if (currentArguments.size != currentParameters.size) {
|
||||
c.trace.report(
|
||||
WRONG_NUMBER_OF_TYPE_ARGUMENTS.on(
|
||||
qualifierPart.typeArguments ?: qualifierPart.expression, currentParameters.size, classDescriptorChain[index]
|
||||
qualifierPart.typeArguments ?: qualifierPart.expression,
|
||||
currentParameters.size, classifierDescriptorChain[index]
|
||||
)
|
||||
)
|
||||
return null
|
||||
@@ -733,12 +743,12 @@ class TypeResolver(
|
||||
|
||||
result.addAll(currentArguments)
|
||||
|
||||
wasStatic = wasStatic || !classDescriptorChain[index].isInner
|
||||
wasStatic = wasStatic || !classifierDescriptorChain[index].isInner
|
||||
}
|
||||
|
||||
val nonClassQualifierParts =
|
||||
reversedQualifierParts.subList(
|
||||
Math.min(classChainLastIndex + 1, reversedQualifierParts.size),
|
||||
Math.min(classifierChainLastIndex + 1, reversedQualifierParts.size),
|
||||
reversedQualifierParts.size)
|
||||
|
||||
for (qualifierPart in nonClassQualifierParts) {
|
||||
@@ -748,12 +758,12 @@ class TypeResolver(
|
||||
}
|
||||
}
|
||||
|
||||
val parameters = classDescriptor.typeConstructor.parameters
|
||||
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, classDescriptor))
|
||||
c.trace.report(WRONG_NUMBER_OF_TYPE_ARGUMENTS.on(qualifierParts.last().expression, parameters.size, classifierDescriptor))
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -761,11 +771,16 @@ class TypeResolver(
|
||||
return result
|
||||
}
|
||||
|
||||
private fun ClassifierDescriptor?.classDescriptorChain(): List<ClassDescriptor>
|
||||
= generateSequence({ this as? ClassDescriptor }, { it.containingDeclaration as? ClassDescriptor }).toList()
|
||||
private fun ClassifierDescriptor?.classifierDescriptorsFromInnerToOuter(): List<ClassifierDescriptorWithTypeParameters> =
|
||||
generateSequence(
|
||||
{ this as? ClassifierDescriptorWithTypeParameters },
|
||||
{ it.containingDeclaration as? ClassifierDescriptorWithTypeParameters }
|
||||
).toList()
|
||||
|
||||
private fun TypeParameterDescriptor.isDeclaredInScope(c: TypeResolutionContext): Boolean {
|
||||
assert(containingDeclaration is ClassDescriptor) { "This function is implemented for classes only, but $containingDeclaration was given" }
|
||||
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
|
||||
@@ -776,11 +791,11 @@ class TypeResolver(
|
||||
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 ClassDescriptor)
|
||||
return c.scope.ownerDescriptor.isInsideOfClass(original.containingDeclaration as ClassifierDescriptorWithTypeParameters)
|
||||
}
|
||||
|
||||
private fun DeclarationDescriptor.isInsideOfClass(classDescriptor: ClassDescriptor)
|
||||
= generateSequence(this, { it.containingDeclaration }).any { it.original == classDescriptor }
|
||||
private fun DeclarationDescriptor.isInsideOfClass(classifierDescriptor: ClassifierDescriptorWithTypeParameters)
|
||||
= generateSequence(this, { it.containingDeclaration }).any { it.original == classifierDescriptor }
|
||||
|
||||
|
||||
private fun resolveTypeProjectionsWithErrorConstructor(
|
||||
@@ -789,13 +804,6 @@ class TypeResolver(
|
||||
message: String = "Error type for resolving type projections"
|
||||
) = resolveTypeProjections(c, ErrorUtils.createErrorTypeConstructor(message), argumentElements)
|
||||
|
||||
private fun createErrorTypeAndResolveArguments(
|
||||
c: TypeResolutionContext,
|
||||
argumentElements: List<KtTypeProjection>,
|
||||
message: String = ""
|
||||
): PossiblyBareType
|
||||
= type(ErrorUtils.createErrorTypeWithArguments(message, resolveTypeProjectionsWithErrorConstructor(c, argumentElements)))
|
||||
|
||||
// In cases like
|
||||
// class Outer<F> {
|
||||
// inner class Inner<E>
|
||||
|
||||
+1
-1
@@ -124,7 +124,7 @@ protected constructor(
|
||||
}
|
||||
|
||||
private fun doGetTypeAliases(name: Name): Collection<TypeAliasDescriptor> =
|
||||
declarationProvider.getTypeAliasDeclarations(name).map { ktTypeAlias ->
|
||||
declarationProvider.getTypeAliasDeclarations(name).mapNotNull { ktTypeAlias ->
|
||||
c.descriptorResolver.resolveTypeAliasDescriptor(
|
||||
thisDescriptor,
|
||||
getScopeForMemberDeclarationResolution(ktTypeAlias),
|
||||
|
||||
+36
-10
@@ -20,10 +20,16 @@ import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.AbstractTypeAliasDescriptor
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.storage.NotNullLazyValue
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
import org.jetbrains.kotlin.types.DeferredType
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
|
||||
class LazyTypeAliasDescriptor(
|
||||
private val storageManager: StorageManager,
|
||||
private val trace: BindingTrace,
|
||||
containingDeclaration: DeclarationDescriptor,
|
||||
annotations: Annotations,
|
||||
name: Name,
|
||||
@@ -32,30 +38,50 @@ class LazyTypeAliasDescriptor(
|
||||
) : AbstractTypeAliasDescriptor(containingDeclaration, annotations, name, sourceElement, visibility),
|
||||
TypeAliasDescriptor {
|
||||
|
||||
private lateinit var underlyingTypeImpl: NotNullLazyValue<KotlinType>
|
||||
private lateinit var expandedTypeImpl: NotNullLazyValue<KotlinType>
|
||||
override lateinit var underlyingType: KotlinType private set
|
||||
override lateinit var expandedType: KotlinType private set
|
||||
|
||||
override val underlyingType: KotlinType get() = underlyingTypeImpl()
|
||||
override val expandedType: KotlinType get() = expandedTypeImpl()
|
||||
private val lazyTypeConstructorParameters =
|
||||
storageManager.createLazyValue { this.computeConstructorTypeParameters() }
|
||||
|
||||
fun initialize(
|
||||
declaredTypeParameters: List<TypeParameterDescriptor>,
|
||||
lazyUnderlyingType: NotNullLazyValue<KotlinType>,
|
||||
lazyExpandedType: NotNullLazyValue<KotlinType>
|
||||
underlyingType: KotlinType,
|
||||
expandedType: KotlinType
|
||||
) {
|
||||
super.initialize(declaredTypeParameters)
|
||||
this.underlyingTypeImpl = lazyUnderlyingType
|
||||
this.expandedTypeImpl = lazyExpandedType
|
||||
this.underlyingType = underlyingType
|
||||
this.expandedType = expandedType
|
||||
}
|
||||
|
||||
override fun substitute(substitutor: TypeSubstitutor): TypeAliasDescriptor {
|
||||
if (substitutor.isEmpty) return this
|
||||
val substituted = LazyTypeAliasDescriptor(storageManager, trace,
|
||||
containingDeclaration, annotations, name, source, visibility)
|
||||
substituted.initialize(declaredTypeParameters,
|
||||
DeferredType.create(storageManager, trace) {
|
||||
substitutor.substitute(underlyingType, Variance.INVARIANT)
|
||||
},
|
||||
DeferredType.create(storageManager, trace) {
|
||||
substitutor.substitute(expandedType, Variance.INVARIANT)
|
||||
})
|
||||
return substituted
|
||||
}
|
||||
|
||||
override fun getTypeConstructorTypeParameters(): List<TypeParameterDescriptor> =
|
||||
lazyTypeConstructorParameters()
|
||||
|
||||
companion object {
|
||||
@JvmStatic fun create(
|
||||
storageManager: StorageManager,
|
||||
trace: BindingTrace,
|
||||
containingDeclaration: DeclarationDescriptor,
|
||||
annotations: Annotations,
|
||||
name: Name,
|
||||
sourceElement: SourceElement,
|
||||
visibility: Visibility
|
||||
): LazyTypeAliasDescriptor =
|
||||
LazyTypeAliasDescriptor(containingDeclaration, annotations, name, sourceElement, visibility)
|
||||
LazyTypeAliasDescriptor(storageManager, trace,
|
||||
containingDeclaration, annotations, name, sourceElement, visibility)
|
||||
}
|
||||
}
|
||||
|
||||
+11
-7
@@ -172,12 +172,17 @@ public class DescriptorSerializer {
|
||||
}
|
||||
|
||||
for (DeclarationDescriptor descriptor : sort(DescriptorUtils.getAllDescriptors(classDescriptor.getUnsubstitutedInnerClassesScope()))) {
|
||||
int name = getSimpleNameIndex(descriptor.getName());
|
||||
if (isEnumEntry(descriptor)) {
|
||||
builder.addEnumEntry(enumEntryProto((ClassDescriptor) descriptor));
|
||||
if (descriptor instanceof TypeAliasDescriptor) {
|
||||
builder.addTypeAlias(typeAliasProto((TypeAliasDescriptor) descriptor));
|
||||
}
|
||||
else {
|
||||
builder.addNestedClassName(name);
|
||||
int name = getSimpleNameIndex(descriptor.getName());
|
||||
if (isEnumEntry(descriptor)) {
|
||||
builder.addEnumEntry(enumEntryProto((ClassDescriptor) descriptor));
|
||||
}
|
||||
else {
|
||||
builder.addNestedClassName(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -520,9 +525,8 @@ public class DescriptorSerializer {
|
||||
assert possiblyInnerType != null : "possiblyInnerType should not be null in case of class";
|
||||
|
||||
fillFromPossiblyInnerType(builder, possiblyInnerType);
|
||||
|
||||
}
|
||||
if (descriptor instanceof TypeParameterDescriptor) {
|
||||
else if (descriptor instanceof TypeParameterDescriptor) {
|
||||
TypeParameterDescriptor typeParameter = (TypeParameterDescriptor) descriptor;
|
||||
if (typeParameter.getContainingDeclaration() == containingDeclaration) {
|
||||
builder.setTypeParameterName(getSimpleNameIndex(typeParameter.getName()));
|
||||
@@ -533,7 +537,7 @@ public class DescriptorSerializer {
|
||||
|
||||
assert type.getArguments().isEmpty() : "Found arguments for type constructor build on type parameter: " + descriptor;
|
||||
}
|
||||
if (descriptor instanceof TypeAliasDescriptor) {
|
||||
else if (descriptor instanceof TypeAliasDescriptor) {
|
||||
PossiblyInnerType possiblyInnerType = TypeParameterUtilsKt.buildPossiblyInnerType(type);
|
||||
assert possiblyInnerType != null : "possiblyInnerType should not be null in case of type alias";
|
||||
fillFromPossiblyInnerType(builder, possiblyInnerType);
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
typealias S = String
|
||||
|
||||
fun test1(x: Any) = x is S
|
||||
fun test2(x: Any) = x as S
|
||||
fun test3(x: Any) = x as? S
|
||||
@@ -0,0 +1,6 @@
|
||||
package
|
||||
|
||||
public typealias S = kotlin.String
|
||||
public fun test1(/*0*/ x: kotlin.Any): kotlin.Boolean
|
||||
public fun test2(/*0*/ x: kotlin.Any): S [= kotlin.String]
|
||||
public fun test3(/*0*/ x: kotlin.Any): S [= kotlin.String?]
|
||||
@@ -0,0 +1,24 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
|
||||
|
||||
class Pair<T1, T2>(val x1: T1, val x2: T2)
|
||||
|
||||
class C {
|
||||
typealias P2 = Pair<Int, Int>
|
||||
|
||||
fun p() = P2(1, 1)
|
||||
fun first(p: P2) = p.x1
|
||||
fun second(p: P2) = p.x2
|
||||
}
|
||||
|
||||
val p1 = Pair(1, 1)
|
||||
|
||||
val test1: Int = C().first(p1)
|
||||
val test2: Int = C().second(p1)
|
||||
|
||||
fun C.testExtFun1(x: C.P2) = x
|
||||
|
||||
fun C.testExtFun2(): C.P2 {
|
||||
val x: C.P2 = p()
|
||||
val y = C.P2(1, 1)
|
||||
return x
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package
|
||||
|
||||
public val p1: Pair<kotlin.Int, kotlin.Int>
|
||||
public val test1: kotlin.Int
|
||||
public val test2: kotlin.Int
|
||||
public fun C.testExtFun1(/*0*/ x: C.P2 [= Pair<kotlin.Int, kotlin.Int>]): C.P2 [= Pair<kotlin.Int, kotlin.Int>]
|
||||
public fun C.testExtFun2(): C.P2 [= Pair<kotlin.Int, kotlin.Int>]
|
||||
|
||||
public final class C {
|
||||
public typealias P2 = Pair<kotlin.Int, kotlin.Int>
|
||||
public constructor C()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public final fun first(/*0*/ p: C.P2 [= Pair<kotlin.Int, kotlin.Int>]): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public final fun p(): Pair<kotlin.Int, kotlin.Int>
|
||||
public final fun second(/*0*/ p: C.P2 [= Pair<kotlin.Int, kotlin.Int>]): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): 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
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
class Pair<T1, T2>(val x1: T1, val x2: T2)
|
||||
|
||||
class C<T> {
|
||||
typealias P2 = Pair<T, T>
|
||||
typealias PT2<T2> = Pair<T, T2>
|
||||
|
||||
fun first(p: P2) = p.x1
|
||||
fun second(p: P2) = p.x2
|
||||
|
||||
fun <T2> first2(p: PT2<T2>) = p.x1
|
||||
fun <T2> second2(p: PT2<T2>) = p.x2
|
||||
}
|
||||
|
||||
val p1 = Pair(1, 1)
|
||||
val p2 = Pair(1, "")
|
||||
|
||||
val test1: Int = C<Int>().first(p1)
|
||||
val test2: Int = C<Int>().second(p1)
|
||||
|
||||
val test3: Int = C<Int>().first2(p2)
|
||||
val test4: String = C<Int>().second2(p2)
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package
|
||||
|
||||
public val p1: Pair<kotlin.Int, kotlin.Int>
|
||||
public val p2: Pair<kotlin.Int, kotlin.String>
|
||||
public val test1: kotlin.Int
|
||||
public val test2: kotlin.Int
|
||||
public val test3: kotlin.Int
|
||||
public val test4: kotlin.String
|
||||
|
||||
public final class C</*0*/ T> {
|
||||
public typealias P2 /*captured type parameters: /*0*/ T*/ = Pair<T, T>
|
||||
public typealias PT2</*0*/ T2> /*captured type parameters: /*1*/ T*/ = Pair<T, T2>
|
||||
public constructor C</*0*/ T>()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public final fun first(/*0*/ p: C<T>.P2 [= Pair<T, T>]): T
|
||||
public final fun </*0*/ T2> first2(/*0*/ p: C<T>.PT2<T2> [= Pair<T, T2>]): T
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public final fun second(/*0*/ p: C<T>.P2 [= Pair<T, T>]): T
|
||||
public final fun </*0*/ T2> second2(/*0*/ p: C<T>.PT2<T2> [= Pair<T, T2>]): T2
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): 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
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
|
||||
|
||||
class Pair<T1, T2>(val x1: T1, val x2: T2)
|
||||
|
||||
class C<T> {
|
||||
typealias P2 = Pair<T, Int>
|
||||
}
|
||||
|
||||
val p1: C<String>.P2 = Pair("", 1)
|
||||
@@ -0,0 +1,20 @@
|
||||
package
|
||||
|
||||
public val p1: C<kotlin.String>.P2 [= Pair<kotlin.String, kotlin.Int>]
|
||||
|
||||
public final class C</*0*/ T> {
|
||||
public typealias P2 /*captured type parameters: /*0*/ T*/ = Pair<T, kotlin.Int>
|
||||
public constructor C</*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 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
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
typealias A = B
|
||||
typealias B = A
|
||||
typealias A = <!RECURSIVE_TYPEALIAS_EXPANSION!>B<!>
|
||||
typealias B = <!RECURSIVE_TYPEALIAS_EXPANSION!>A<!>
|
||||
|
||||
val x: <!RECURSIVE_TYPEALIAS_EXPANSION!>A<!> = TODO()
|
||||
@@ -3,13 +3,13 @@ class Out<out T>
|
||||
class Inv<T>
|
||||
|
||||
typealias In1<T> = In<T>
|
||||
typealias In2<T> = In<<!REDUNDANT_PROJECTION!>in<!> T>
|
||||
typealias In3<T> = In<<!CONFLICTING_PROJECTION!>out<!> T>
|
||||
typealias In2<T> = In<<!REDUNDANT_PROJECTION, REDUNDANT_PROJECTION!>in<!> T>
|
||||
typealias In3<T> = In<<!CONFLICTING_PROJECTION, CONFLICTING_PROJECTION!>out<!> T>
|
||||
typealias In4<T> = In<*>
|
||||
|
||||
typealias Out1<T> = Out<T>
|
||||
typealias Out2<T> = Out<<!CONFLICTING_PROJECTION!>in<!> T>
|
||||
typealias Out3<T> = Out<<!REDUNDANT_PROJECTION!>out<!> T>
|
||||
typealias Out2<T> = Out<<!CONFLICTING_PROJECTION, CONFLICTING_PROJECTION!>in<!> T>
|
||||
typealias Out3<T> = Out<<!REDUNDANT_PROJECTION, REDUNDANT_PROJECTION!>out<!> T>
|
||||
typealias Out4<T> = Out<*>
|
||||
|
||||
typealias Inv1<T> = Inv<T>
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
// !LANGUAGE: -TypeAliases
|
||||
|
||||
class C
|
||||
|
||||
<!UNSUPPORTED_TYPEALIAS!>typealias<!> S = String
|
||||
<!UNSUPPORTED_TYPEALIAS!>typealias<!> L<T> = List<T>
|
||||
<!UNSUPPORTED_TYPEALIAS!>typealias<!> CA = C
|
||||
|
||||
val test1: <!UNRESOLVED_REFERENCE!>S<!> = ""
|
||||
|
||||
fun test2(x: <!UNRESOLVED_REFERENCE!>L<!><<!UNRESOLVED_REFERENCE!>S<!>>) = <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>x<!>
|
||||
|
||||
class Test3 : <!UNRESOLVED_REFERENCE!>CA<!>()
|
||||
@@ -0,0 +1,18 @@
|
||||
package
|
||||
|
||||
public val test1: [ERROR : S]
|
||||
public fun test2(/*0*/ x: [ERROR : L<S>]<[ERROR : S]>): [ERROR : L<S>]<[ERROR : S]>
|
||||
|
||||
public final class C {
|
||||
public constructor C()
|
||||
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 Test3 {
|
||||
public constructor Test3()
|
||||
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
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
//ALLOW_AST_ACCESS
|
||||
package test
|
||||
|
||||
open class Pair<T1, T2>
|
||||
open class Triple<T1, T2, T3>
|
||||
|
||||
class Outer<X> {
|
||||
inner class InnerTest1<A>: Pair<X, A>()
|
||||
typealias Test1<A> = Pair<X, A>
|
||||
|
||||
class Nested<Y> {
|
||||
typealias Test2<B> = Pair<Y, B>
|
||||
}
|
||||
|
||||
inner class Inner<Z> {
|
||||
typealias Test3<C> = Triple<X, Z, C>
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package test
|
||||
|
||||
public final class Outer</*0*/ X> {
|
||||
public typealias Test1</*0*/ A> /*captured type parameters: /*1*/ X*/ = test.Pair<X, A>
|
||||
/*primary*/ public constructor Outer</*0*/ X>()
|
||||
|
||||
public final inner class Inner</*0*/ Z> /*captured type parameters: /*1*/ X*/ {
|
||||
public typealias Test3</*0*/ C> /*captured type parameters: /*1*/ Z, /*2*/ X*/ = test.Triple<X, Z, C>
|
||||
/*primary*/ public constructor Inner</*0*/ Z>()
|
||||
}
|
||||
|
||||
public final inner class InnerTest1</*0*/ A> /*captured type parameters: /*1*/ X*/ : test.Pair<X, A> {
|
||||
/*primary*/ public constructor InnerTest1</*0*/ A>()
|
||||
}
|
||||
|
||||
public final class Nested</*0*/ Y> {
|
||||
public typealias Test2</*0*/ B> /*captured type parameters: /*1*/ Y*/ = test.Pair<Y, B>
|
||||
/*primary*/ public constructor Nested</*0*/ Y>()
|
||||
}
|
||||
}
|
||||
|
||||
public open class Pair</*0*/ T1, /*1*/ T2> {
|
||||
/*primary*/ public constructor Pair</*0*/ T1, /*1*/ T2>()
|
||||
}
|
||||
|
||||
public open class Triple</*0*/ T1, /*1*/ T2, /*2*/ T3> {
|
||||
/*primary*/ public constructor Triple</*0*/ T1, /*1*/ T2, /*2*/ T3>()
|
||||
}
|
||||
@@ -19167,6 +19167,30 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("isAsWithTypeAlias.kt")
|
||||
public void testIsAsWithTypeAlias() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/typealias/isAsWithTypeAlias.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("nested.kt")
|
||||
public void testNested() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/typealias/nested.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("nestedCapturingTypeParameters.kt")
|
||||
public void testNestedCapturingTypeParameters() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/typealias/nestedCapturingTypeParameters.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("nestedSubstituted.kt")
|
||||
public void testNestedSubstituted() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/typealias/nestedSubstituted.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("parameterRestrictions.kt")
|
||||
public void testParameterRestrictions() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/typealias/parameterRestrictions.kt");
|
||||
@@ -19226,6 +19250,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/typealias/typeAliasObjectWithInvoke.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("unsupportedTypeAlias.kt")
|
||||
public void testUnsupportedTypeAlias() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/typealias/unsupportedTypeAlias.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/unit")
|
||||
|
||||
@@ -4815,6 +4815,12 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/typealias/Generic.kt");
|
||||
doTestCompiledKotlin(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("Nested.kt")
|
||||
public void testNested() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/typealias/Nested.kt");
|
||||
doTestCompiledKotlin(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/loadJava/compiledKotlin/visibility")
|
||||
|
||||
+6
@@ -3048,6 +3048,12 @@ public class LoadKotlinWithTypeTableTestGenerated extends AbstractLoadKotlinWith
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/typealias/Generic.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("Nested.kt")
|
||||
public void testNested() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/typealias/Nested.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/loadJava/compiledKotlin/visibility")
|
||||
|
||||
+6
@@ -3050,6 +3050,12 @@ public class JvmRuntimeDescriptorLoaderTestGenerated extends AbstractJvmRuntimeD
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/typealias/Generic.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("Nested.kt")
|
||||
public void testNested() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/typealias/Nested.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/loadJava/compiledKotlin/visibility")
|
||||
|
||||
+6
-9
@@ -44,24 +44,19 @@ abstract class AbstractTypeAliasDescriptor(
|
||||
override fun <R, D> accept(visitor: DeclarationDescriptorVisitor<R, D>, data: D): R =
|
||||
visitor.visitTypeAliasDescriptor(this, data)
|
||||
|
||||
override fun isInner(): Boolean = false // TODO treat all nested type aliases as inner?
|
||||
override fun isInner(): Boolean =
|
||||
containingDeclaration !is PackageFragmentDescriptor
|
||||
|
||||
override fun getDeclaredTypeParameters(): List<TypeParameterDescriptor> =
|
||||
declaredTypeParametersImpl
|
||||
|
||||
override val classDescriptor: ClassDescriptor?
|
||||
get() = expandedType.let { expandedType ->
|
||||
if (expandedType.isError) null else expandedType.constructor.declarationDescriptor as? ClassDescriptor
|
||||
}
|
||||
get() = if (expandedType.isError) null else expandedType.constructor.declarationDescriptor as? ClassDescriptor
|
||||
|
||||
override fun getModality() = Modality.FINAL
|
||||
|
||||
override fun getVisibility() = visibilityImpl
|
||||
|
||||
override fun substitute(substitutor: TypeSubstitutor): TypeAliasDescriptor =
|
||||
if (substitutor.isEmpty) this
|
||||
else TODO("typealias doSubstitute")
|
||||
|
||||
override fun getDefaultType(): KotlinType =
|
||||
TODO("typealias getDefaultType")
|
||||
|
||||
@@ -70,12 +65,14 @@ abstract class AbstractTypeAliasDescriptor(
|
||||
|
||||
override fun toString(): String = "typealias ${name.asString()}"
|
||||
|
||||
protected abstract fun getTypeConstructorTypeParameters(): List<TypeParameterDescriptor>
|
||||
|
||||
private val typeConstructor = object : TypeConstructor {
|
||||
override fun getDeclarationDescriptor(): TypeAliasDescriptor =
|
||||
this@AbstractTypeAliasDescriptor
|
||||
|
||||
override fun getParameters(): List<TypeParameterDescriptor> =
|
||||
declarationDescriptor.declaredTypeParameters // TODO type parameters of outer class
|
||||
getTypeConstructorTypeParameters()
|
||||
|
||||
override fun getSupertypes(): Collection<KotlinType> =
|
||||
declarationDescriptor.underlyingType.constructor.supertypes
|
||||
|
||||
@@ -23,7 +23,7 @@ import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeProjection
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||
|
||||
fun ClassDescriptor.computeConstructorTypeParameters(): List<TypeParameterDescriptor> {
|
||||
fun ClassifierDescriptorWithTypeParameters.computeConstructorTypeParameters(): List<TypeParameterDescriptor> {
|
||||
val declaredParameters = declaredTypeParameters
|
||||
|
||||
if (!isInner && containingDeclaration !is CallableDescriptor) return declaredParameters
|
||||
|
||||
@@ -810,10 +810,24 @@ internal class DescriptorRendererImpl(
|
||||
renderVisibility(typeAlias.visibility, builder)
|
||||
builder.append(renderKeyword("typealias")).append(" ")
|
||||
renderName(typeAlias, builder)
|
||||
|
||||
renderTypeParameters(typeAlias.declaredTypeParameters, builder, true)
|
||||
renderCapturedTypeParametersIfRequired(typeAlias, builder)
|
||||
|
||||
builder.append(" = ").append(renderType(typeAlias.underlyingType))
|
||||
}
|
||||
|
||||
private fun renderCapturedTypeParametersIfRequired(classifier: ClassifierDescriptorWithTypeParameters, builder: StringBuilder) {
|
||||
val typeParameters = classifier.declaredTypeParameters
|
||||
val typeConstructorParameters = classifier.typeConstructor.parameters
|
||||
|
||||
if (verbose && classifier.isInner && typeConstructorParameters.size > typeParameters.size) {
|
||||
builder.append(" /*captured type parameters: ")
|
||||
renderTypeParameterList(builder, typeConstructorParameters.subList(typeParameters.size, typeConstructorParameters.size))
|
||||
builder.append("*/")
|
||||
}
|
||||
}
|
||||
|
||||
/* CLASSES */
|
||||
private fun renderClass(klass: ClassDescriptor, builder: StringBuilder) {
|
||||
val isEnumEntry = klass.kind == ClassKind.ENUM_ENTRY
|
||||
@@ -844,14 +858,7 @@ internal class DescriptorRendererImpl(
|
||||
|
||||
val typeParameters = klass.declaredTypeParameters
|
||||
renderTypeParameters(typeParameters, builder, false)
|
||||
|
||||
if (verbose && klass.isInner && klass.typeConstructor.parameters.size > typeParameters.size) {
|
||||
builder.append(" /*captured type parameters: ")
|
||||
val constructorTypeParameters = klass.typeConstructor.parameters
|
||||
renderTypeParameterList(
|
||||
builder, constructorTypeParameters.subList(typeParameters.size, constructorTypeParameters.size))
|
||||
builder.append("*/")
|
||||
}
|
||||
renderCapturedTypeParametersIfRequired(klass, builder)
|
||||
|
||||
if (!klass.kind.isSingleton && classWithPrimaryConstructor) {
|
||||
val primaryConstructor = klass.unsubstitutedPrimaryConstructor
|
||||
|
||||
+9
-3
@@ -17,16 +17,22 @@
|
||||
package org.jetbrains.kotlin.resolve.scopes
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters
|
||||
import org.jetbrains.kotlin.descriptors.TypeAliasDescriptor
|
||||
import org.jetbrains.kotlin.incremental.components.LookupLocation
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.utils.Printer
|
||||
|
||||
class InnerClassesScopeWrapper(val workerScope: MemberScope) : MemberScopeImpl() {
|
||||
override fun getContributedClassifier(name: Name, location: LookupLocation) = workerScope.getContributedClassifier(name, location) as? ClassDescriptor
|
||||
override fun getContributedClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? =
|
||||
workerScope.getContributedClassifier(name, location)?.let {
|
||||
it as? ClassDescriptor ?: it as? TypeAliasDescriptor
|
||||
}
|
||||
|
||||
override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean): List<ClassDescriptor> {
|
||||
override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean): List<ClassifierDescriptor> {
|
||||
val restrictedFilter = kindFilter.restrictedToKindsOrNull(DescriptorKindFilter.CLASSIFIERS_MASK) ?: return listOf()
|
||||
return workerScope.getContributedDescriptors(restrictedFilter, nameFilter).filterIsInstance<ClassDescriptor>()
|
||||
return workerScope.getContributedDescriptors(restrictedFilter, nameFilter).filterIsInstance<ClassifierDescriptorWithTypeParameters>()
|
||||
}
|
||||
|
||||
override fun printScopeStructure(p: Printer) {
|
||||
|
||||
+1
-1
@@ -82,7 +82,7 @@ class TypeDeserializer(
|
||||
proto.hasTypeParameterName() -> {
|
||||
val container = c.containingDeclaration
|
||||
val typeParameters = when (container) {
|
||||
is ClassDescriptor -> container.typeConstructor.parameters
|
||||
is ClassifierDescriptorWithTypeParameters -> container.typeConstructor.parameters
|
||||
is CallableDescriptor -> container.typeParameters
|
||||
else -> emptyList<TypeParameterDescriptor>()
|
||||
}
|
||||
|
||||
+22
-7
@@ -25,6 +25,8 @@ import org.jetbrains.kotlin.serialization.ProtoBuf
|
||||
import org.jetbrains.kotlin.serialization.deserialization.NameResolver
|
||||
import org.jetbrains.kotlin.serialization.deserialization.TypeTable
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
|
||||
interface DeserializedMemberDescriptor : MemberDescriptor {
|
||||
val proto: MessageLite
|
||||
@@ -146,11 +148,9 @@ class DeserializedTypeAliasDescriptor(
|
||||
) : AbstractTypeAliasDescriptor(containingDeclaration, annotations, name, SourceElement.NO_SOURCE, visibility),
|
||||
DeserializedMemberDescriptor {
|
||||
|
||||
private lateinit var underlyingTypeImpl: KotlinType
|
||||
private lateinit var expandedTypeImpl: KotlinType
|
||||
|
||||
override val underlyingType: KotlinType get() = underlyingTypeImpl
|
||||
override val expandedType: KotlinType get() = expandedTypeImpl
|
||||
override lateinit var underlyingType: KotlinType private set
|
||||
override lateinit var expandedType: KotlinType private set
|
||||
private lateinit var typeConstructorParameters: List<TypeParameterDescriptor>
|
||||
|
||||
fun initialize(
|
||||
declaredTypeParameters: List<TypeParameterDescriptor>,
|
||||
@@ -158,7 +158,22 @@ class DeserializedTypeAliasDescriptor(
|
||||
expandedType: KotlinType
|
||||
) {
|
||||
initialize(declaredTypeParameters)
|
||||
underlyingTypeImpl = underlyingType
|
||||
expandedTypeImpl = expandedType
|
||||
this.underlyingType = underlyingType
|
||||
this.expandedType = expandedType
|
||||
typeConstructorParameters = computeConstructorTypeParameters()
|
||||
}
|
||||
|
||||
override fun substitute(substitutor: TypeSubstitutor): TypeAliasDescriptor {
|
||||
if (substitutor.isEmpty) return this
|
||||
val substituted = DeserializedTypeAliasDescriptor(containingDeclaration, annotations, name, visibility, proto, nameResolver, typeTable, containerSource)
|
||||
substituted.initialize(declaredTypeParameters,
|
||||
substitutor.safeSubstitute(underlyingType, Variance.INVARIANT),
|
||||
substitutor.safeSubstitute(expandedType, Variance.INVARIANT))
|
||||
|
||||
return substituted
|
||||
}
|
||||
|
||||
override fun getTypeConstructorTypeParameters(): List<TypeParameterDescriptor> =
|
||||
typeConstructorParameters
|
||||
|
||||
}
|
||||
|
||||
@@ -3048,6 +3048,12 @@ public class ResolveByStubTestGenerated extends AbstractResolveByStubTest {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/typealias/Generic.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("Nested.kt")
|
||||
public void testNested() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/typealias/Nested.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/loadJava/compiledKotlin/visibility")
|
||||
|
||||
Reference in New Issue
Block a user