Support only simple declarations for 'impl' type aliases

E.g. 'impl typealias Foo<A, B> = Bar<A, B>' is allowed; everything else
(variance, changing order of parameters, etc.) is pretty much disallowed.

This is done for simplicity: otherwise matching the platform/impl class scopes
would be not so straightforward
This commit is contained in:
Alexander Udalov
2016-11-22 15:03:36 +03:00
parent 751949db69
commit a8bd82e863
6 changed files with 163 additions and 0 deletions
@@ -497,6 +497,11 @@ public interface Errors {
DiagnosticFactory0<KtParameter> PLATFORM_CLASS_CONSTRUCTOR_PROPERTY_PARAMETER = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtExpression> PLATFORM_PROPERTY_INITIALIZER = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtTypeAlias> IMPL_TYPE_ALIAS_NOT_TO_CLASS = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
DiagnosticFactory0<KtTypeAlias> IMPL_TYPE_ALIAS_TO_CLASS_WITH_DECLARATION_SITE_VARIANCE = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
DiagnosticFactory0<KtTypeAlias> IMPL_TYPE_ALIAS_WITH_USE_SITE_VARIANCE = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
DiagnosticFactory0<KtTypeAlias> IMPL_TYPE_ALIAS_WITH_COMPLEX_SUBSTITUTION = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Errors/warnings inside code blocks
@@ -263,6 +263,11 @@ public class DefaultErrorMessages {
MAP.put(PLATFORM_CLASS_CONSTRUCTOR_PROPERTY_PARAMETER, "Platform class constructor cannot have a property parameter");
MAP.put(PLATFORM_PROPERTY_INITIALIZER, "Platform property cannot have an initializer");
MAP.put(IMPL_TYPE_ALIAS_NOT_TO_CLASS, "Right-hand side of 'impl' type alias should be a class, not another type alias");
MAP.put(IMPL_TYPE_ALIAS_TO_CLASS_WITH_DECLARATION_SITE_VARIANCE, "Aliased class should not have type parameters with declaration-site variance");
MAP.put(IMPL_TYPE_ALIAS_WITH_USE_SITE_VARIANCE, "Right-hand side of 'impl' type alias cannot contain use-site variance or star projections");
MAP.put(IMPL_TYPE_ALIAS_WITH_COMPLEX_SUBSTITUTION, "Type arguments in the right-hand side of 'impl' type alias should be its type parameters in the same order, e.g. 'impl typealias Foo<A, B> = Bar<A, B>'");
MAP.put(PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT, "Projections are not allowed on type arguments of functions and properties");
MAP.put(SUPERTYPE_NOT_INITIALIZED, "This type has a constructor, and thus must be initialized here");
MAP.put(NOTHING_TO_OVERRIDE, "''{0}'' overrides nothing", NAME);
@@ -181,6 +181,35 @@ class DeclarationsChecker(
trace.report(UNUSED_TYPEALIAS_PARAMETER.on(source, typeParameter, expandedType))
}
}
if (declaration.hasModifier(KtTokens.IMPL_KEYWORD)) {
checkImplTypeAlias(declaration, typeAliasDescriptor)
}
}
private fun checkImplTypeAlias(declaration: KtTypeAlias, typeAliasDescriptor: TypeAliasDescriptor) {
val rhs = typeAliasDescriptor.underlyingType
val classDescriptor = rhs.constructor.declarationDescriptor
if (classDescriptor !is ClassDescriptor) {
trace.report(IMPL_TYPE_ALIAS_NOT_TO_CLASS.on(declaration))
return
}
if (classDescriptor.declaredTypeParameters.any { it.variance != Variance.INVARIANT }) {
trace.report(IMPL_TYPE_ALIAS_TO_CLASS_WITH_DECLARATION_SITE_VARIANCE.on(declaration))
return
}
if (rhs.arguments.any { it.projectionKind != Variance.INVARIANT || it.isStarProjection }) {
trace.report(IMPL_TYPE_ALIAS_WITH_USE_SITE_VARIANCE.on(declaration))
return
}
if (rhs.arguments.map { it.type.constructor.declarationDescriptor as? TypeParameterDescriptor } !=
typeAliasDescriptor.declaredTypeParameters) {
trace.report(IMPL_TYPE_ALIAS_WITH_COMPLEX_SUBSTITUTION.on(declaration))
return
}
}
private fun getUsedTypeAliasParameters(type: KotlinType, typeAlias: TypeAliasDescriptor): Set<TypeParameterDescriptor> =