diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolver.kt index 2487756f6f8..c0422096efc 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolver.kt @@ -99,9 +99,11 @@ class TypeResolver( if (!c.allowBareTypes && !c.forceResolveLazyTypes && lazinessToken.isLazy()) { // Bare types can be allowed only inside expressions; lazy type resolution is only relevant for declarations - class LazyKotlinType : DelegatingType(), LazyEntity { + class LazyKotlinType : WrappedType(), LazyEntity { private val _delegate = storageManager.createLazyValue { doResolvePossiblyBareType(c, typeReference).getActualType() } - override fun getDelegate() = _delegate() + + override fun unwrap() = _delegate() + override fun isComputed() = _delegate.isComputed() override fun forceResolveAllContents() { ForceResolveUtil.forceResolveAllContents(constructor) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/DeferredType.java b/compiler/frontend/src/org/jetbrains/kotlin/types/DeferredType.java index 79fe2166fd0..a4af4eefd57 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/DeferredType.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/DeferredType.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2015 JetBrains s.r.o. + * 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. @@ -27,7 +27,7 @@ import org.jetbrains.kotlin.util.ReenteringLazyValueComputationException; import static org.jetbrains.kotlin.resolve.BindingContext.DEFERRED_TYPE; -public class DeferredType extends DelegatingType implements LazyType { +public class DeferredType extends WrappedType implements LazyType { private static final Function1 EMPTY_CONSUMER = new Function1() { @Override @@ -81,15 +81,18 @@ public class DeferredType extends DelegatingType implements LazyType { return lazyValue.isComputing(); } + @Override public boolean isComputed() { return lazyValue.isComputed(); } + @NotNull @Override - public KotlinType getDelegate() { + public KotlinType unwrap() { return lazyValue.invoke(); } + @NotNull @Override public String toString() { try { diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/JvmBuiltInsSettings.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/JvmBuiltInsSettings.kt index ab3441c8ee2..b8274f19545 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/JvmBuiltInsSettings.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/JvmBuiltInsSettings.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2015 JetBrains s.r.o. + * 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. @@ -20,9 +20,7 @@ import org.jetbrains.kotlin.builtins.BuiltInsInitializer import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.AnnotationsImpl -import org.jetbrains.kotlin.descriptors.annotations.composeAnnotations import org.jetbrains.kotlin.descriptors.annotations.createDeprecatedAnnotation -import org.jetbrains.kotlin.descriptors.annotations.createUnsafeVarianceAnnotation import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.PackageFragmentDescriptorImpl import org.jetbrains.kotlin.incremental.components.NoLookupLocation @@ -45,8 +43,8 @@ import org.jetbrains.kotlin.serialization.deserialization.descriptors.Deserializ import org.jetbrains.kotlin.storage.LockBasedStorageManager import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.storage.getValue -import org.jetbrains.kotlin.types.* -import org.jetbrains.kotlin.types.typeUtil.replaceAnnotations +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.WrappedType import org.jetbrains.kotlin.utils.DFS import org.jetbrains.kotlin.utils.SmartSet import org.jetbrains.kotlin.utils.addToStdlib.check @@ -79,10 +77,8 @@ open class JvmBuiltInsSettings( } //NOTE: can't reference anyType right away, because this is sometimes called when JvmBuiltIns are initializing - val superTypes = listOf(object : DelegatingType() { - override fun getDelegate(): KotlinType { - return moduleDescriptor.builtIns.anyType - } + val superTypes = listOf(object : WrappedType() { + override fun unwrap() = moduleDescriptor.builtIns.anyType }) val mockSerializableClass = ClassDescriptorImpl( diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/calls/inference/CapturedTypeConstructor.kt b/core/descriptors/src/org/jetbrains/kotlin/resolve/calls/inference/CapturedTypeConstructor.kt index cdbdcdf7b1e..f4a1d00b1f0 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/calls/inference/CapturedTypeConstructor.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/calls/inference/CapturedTypeConstructor.kt @@ -119,8 +119,8 @@ private fun TypeProjection.createCapturedIfNeeded(typeParameterDescriptor: TypeP if (typeParameterDescriptor.variance == projectionKind) { // TODO: Make star projection type lazy return if (isStarProjection) - TypeProjectionImpl(object : DelegatingType() { - override fun getDelegate() = this@createCapturedIfNeeded.type + TypeProjectionImpl(object : WrappedType() { + override fun unwrap(): KotlinType = this@createCapturedIfNeeded.type }) else TypeProjectionImpl(this@createCapturedIfNeeded.type) diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/KotlinType.kt b/core/descriptors/src/org/jetbrains/kotlin/types/KotlinType.kt index d77ae2efa40..535eda1b3be 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/KotlinType.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/KotlinType.kt @@ -17,6 +17,8 @@ package org.jetbrains.kotlin.types import org.jetbrains.kotlin.descriptors.annotations.Annotated +import org.jetbrains.kotlin.descriptors.annotations.Annotations +import org.jetbrains.kotlin.renderer.DescriptorRenderer import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.types.checker.KotlinTypeChecker @@ -43,6 +45,93 @@ interface KotlinType : Annotated { } @Deprecated("Temporary marker method for refactoring") -fun KotlinType.asSimpleType(): SimpleType = this as SimpleType +fun KotlinType.asSimpleType(): SimpleType { + return unwrap() as SimpleType +} -interface SimpleType : KotlinType \ No newline at end of file +fun KotlinType.unwrap(): KotlinType { + if (this is WrappedType) return unwrap().unwrap() + return this +} + +interface SimpleType : KotlinType + +abstract class WrappedType() : KotlinType, LazyType { + override val annotations: Annotations get() = delegate.annotations + override val constructor: TypeConstructor get() = delegate.constructor + override val arguments: List get() = delegate.arguments + override val isMarkedNullable: Boolean get() = delegate.isMarkedNullable + override val memberScope: MemberScope get() = delegate.memberScope + + + open fun isComputed(): Boolean = true + open val delegate: KotlinType + get() = unwrap() + + abstract fun unwrap(): KotlinType + + override fun toString(): String { + if (isComputed()) { + return delegate.toString() + } + else { + return "" + } + } + + // todo: remove this later + override val isError: Boolean get() = delegate.isError + override val capabilities: TypeCapabilities get() = delegate.capabilities + override fun getCapability(capabilityClass: Class): T? = delegate.getCapability(capabilityClass) + override fun equals(other: Any?): Boolean = unwrap().equals(other) + override fun hashCode(): Int = unwrap().hashCode() +} + +fun SimpleType.lazyReplaceNullability(newNullable: Boolean): SimpleType { + if (this is WrappedSimpleType) { + return WrappedSimpleType(delegate, newAnnotations, newNullable) + } + else { + return WrappedSimpleType(this, newNullable = newNullable) + } +} + +fun SimpleType.lazyReplaceAnnotations(newAnnotations: Annotations): SimpleType { + if (this is WrappedSimpleType) { + return WrappedSimpleType(delegate, newAnnotations, newNullable) + } + else { + return WrappedSimpleType(this, newAnnotations) + } +} + +private class WrappedSimpleType( + override val delegate: SimpleType, + val newAnnotations: Annotations? = null, + val newNullable: Boolean? = null +): WrappedType(), SimpleType { + override val annotations: Annotations + get() = newAnnotations ?: delegate.annotations + + override val isMarkedNullable: Boolean + get() = newNullable ?: delegate.isMarkedNullable + + override fun unwrap(): KotlinType { + if (delegate.isError) return delegate // todo + return KotlinTypeImpl.create(annotations, constructor, isMarkedNullable, arguments, memberScope, capabilities) + } + + override fun toString(): String { + if (isError) return delegate.toString() + + return buildString { + for (annotation in annotations.getAllAnnotations()) { + append("[", DescriptorRenderer.DEBUG_TEXT.renderAnnotation(annotation.annotation, annotation.target), "] ") + } + + append(constructor) + if (!arguments.isEmpty()) arguments.joinTo(this, separator = ", ", prefix = "<", postfix = ">") + if (isMarkedNullable) append("?") + } + } +} \ No newline at end of file diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/TypeUtils.java b/core/descriptors/src/org/jetbrains/kotlin/types/TypeUtils.java index 94f4790488e..8b3ad5941d5 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/TypeUtils.java +++ b/core/descriptors/src/org/jetbrains/kotlin/types/TypeUtils.java @@ -139,22 +139,13 @@ public class TypeUtils { if (flexibility != null) { return flexibility.makeNullableAsSpecified(nullable); } + else { + SimpleType simpleType = KotlinTypeKt.asSimpleType(type); - // Wrapping serves two purposes here - // 1. It's requires less memory than copying with a changed nullability flag: a copy has many fields, while a wrapper has only one - // 2. It preserves laziness of types + if (!(simpleType instanceof LazyType) && simpleType.isMarkedNullable() == nullable) return simpleType; - // Unwrap to avoid long delegation call chains - if (type instanceof AbstractTypeWithKnownNullability) { - return makeNullableAsSpecified(((AbstractTypeWithKnownNullability) type).delegate, nullable); + return KotlinTypeKt.lazyReplaceNullability(simpleType, nullable); } - - // checking to preserve laziness - if (!(type instanceof LazyType) && type.isMarkedNullable() == nullable) { - return type; - } - - return nullable ? new NullableType(type) : new NotNullType(type); } @NotNull @@ -528,81 +519,4 @@ public class TypeUtils { } return null; } - - private static abstract class AbstractTypeWithKnownNullability extends AbstractKotlinType { - private final KotlinType delegate; - - private AbstractTypeWithKnownNullability(@NotNull KotlinType delegate) { - this.delegate = delegate; - } - - @Override - @NotNull - public TypeConstructor getConstructor() { - return delegate.getConstructor(); - } - - @Override - @NotNull - public List getArguments() { - return delegate.getArguments(); - } - - @Override - public abstract boolean isMarkedNullable(); - - @Override - @NotNull - public MemberScope getMemberScope() { - return delegate.getMemberScope(); - } - - @Override - public boolean isError() { - return delegate.isError(); - } - - @Override - @NotNull - public Annotations getAnnotations() { - return delegate.getAnnotations(); - } - - @Nullable - @Override - public T getCapability(@NotNull Class capabilityClass) { - return delegate.getCapability(capabilityClass); - } - - @NotNull - @Override - public TypeCapabilities getCapabilities() { - return delegate.getCapabilities(); - } - } - - private static class NullableType extends AbstractTypeWithKnownNullability { - - private NullableType(@NotNull KotlinType delegate) { - super(delegate); - } - - @Override - public boolean isMarkedNullable() { - return true; - } - } - - private static class NotNullType extends AbstractTypeWithKnownNullability { - - private NotNullType(@NotNull KotlinType delegate) { - super(delegate); - } - - @Override - public boolean isMarkedNullable() { - return false; - } - } - } diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/TypeUtils.kt b/core/descriptors/src/org/jetbrains/kotlin/types/TypeUtils.kt index 03957435099..a82d5217c6b 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/TypeUtils.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/TypeUtils.kt @@ -77,8 +77,6 @@ fun KotlinType.isSubtypeOf(superType: KotlinType): Boolean = KotlinTypeChecker.D fun KotlinType.cannotBeReified(): Boolean = KotlinBuiltIns.isNothingOrNullableNothing(this) || this.isDynamic() || this.isCaptured() -fun KotlinType.unsafeAsReifiedArgument(): Boolean = arguments.any { !it.isStarProjection } - fun TypeProjection.substitute(doSubstitute: (KotlinType) -> KotlinType): TypeProjection { return if (isStarProjection) this @@ -87,11 +85,9 @@ fun TypeProjection.substitute(doSubstitute: (KotlinType) -> KotlinType): TypePro fun KotlinType.replaceAnnotations(newAnnotations: Annotations): KotlinType { if (annotations.isEmpty() && newAnnotations.isEmpty()) return this - return object : DelegatingType() { - override fun getDelegate() = this@replaceAnnotations + if (isFlexible()) return flexibility().replaceAnnotations(newAnnotations) - override val annotations: Annotations get() = newAnnotations - } + return asSimpleType().lazyReplaceAnnotations(newAnnotations) } fun KotlinTypeChecker.equalTypesOrNulls(type1: KotlinType?, type2: KotlinType?): Boolean { diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/dynamicTypes.kt b/core/descriptors/src/org/jetbrains/kotlin/types/dynamicTypes.kt index c3c1c863a07..bce2f3c7cfc 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/dynamicTypes.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/dynamicTypes.kt @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.types import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.types.checker.KotlinTypeChecker import org.jetbrains.kotlin.types.typeUtil.builtIns @@ -32,9 +33,9 @@ class DynamicTypesAllowed: DynamicTypesSettings() { fun KotlinType.isDynamic(): Boolean = this.getCapability(Flexibility::class.java)?.factory == DynamicTypeFactory -fun createDynamicType(builtIns: KotlinBuiltIns) = DynamicType(builtIns) +fun createDynamicType(builtIns: KotlinBuiltIns) = DynamicType(builtIns, Annotations.EMPTY) -class DynamicType(builtIns: KotlinBuiltIns) : DelegatingFlexibleType(builtIns.nothingType, builtIns.nullableAnyType, DynamicTypeFactory) { +class DynamicType(builtIns: KotlinBuiltIns, override val annotations: Annotations) : DelegatingFlexibleType(builtIns.nothingType, builtIns.nullableAnyType, DynamicTypeFactory) { override val delegateType: KotlinType get() = upperBound override fun makeNullableAsSpecified(nullable: Boolean): KotlinType { @@ -43,6 +44,8 @@ class DynamicType(builtIns: KotlinBuiltIns) : DelegatingFlexibleType(builtIns.no } override val isMarkedNullable: Boolean get() = false + + override fun replaceAnnotations(newAnnotations: Annotations): KotlinType = DynamicType(delegateType.builtIns, annotations) } object DynamicTypeFactory : FlexibleTypeFactory { diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/flexibleTypes.kt b/core/descriptors/src/org/jetbrains/kotlin/types/flexibleTypes.kt index fb5e841ca27..9e63b491382 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/flexibleTypes.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/flexibleTypes.kt @@ -17,7 +17,9 @@ package org.jetbrains.kotlin.types import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor +import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.types.checker.KotlinTypeChecker +import org.jetbrains.kotlin.types.typeUtil.replaceAnnotations interface FlexibleTypeFactory { val id: String @@ -50,6 +52,7 @@ interface Flexibility : TypeCapability, SubtypingRepresentatives { fun makeNullableAsSpecified(nullable: Boolean): KotlinType + fun replaceAnnotations(newAnnotations: Annotations): KotlinType } fun KotlinType.isFlexible(): Boolean = this.getCapability(Flexibility::class.java) != null @@ -173,6 +176,9 @@ class FlexibleTypeImpl(lowerBound: SimpleType, upperBound: SimpleType) : return KotlinTypeFactory.flexibleType(simpleType, TypeUtils.makeNullable(simpleType)) } } + + override fun replaceAnnotations(newAnnotations: Annotations): KotlinType + = KotlinTypeFactory.flexibleType(lowerBound.replaceAnnotations(newAnnotations).asSimpleType(), upperBound) } // TODO: move Factory to descriptor.loader.java diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/SpecifyTypeExplicitlyIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/SpecifyTypeExplicitlyIntention.kt index ec3418bdde4..c0ace1c6a70 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/SpecifyTypeExplicitlyIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/SpecifyTypeExplicitlyIntention.kt @@ -104,10 +104,7 @@ class SpecifyTypeExplicitlyIntention : SelfTargetingIntention get() = newArguments - } + KotlinTypeFactory.simpleType(it.asSimpleType(), arguments = newArguments) } .ifEmpty { return null } return object : ChooseValueExpression(types, types.first()) { diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/callableBuilder/typeUtils.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/callableBuilder/typeUtils.kt index 6cc13ecb85d..8b6969264c4 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/callableBuilder/typeUtils.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/callableBuilder/typeUtils.kt @@ -54,9 +54,7 @@ private fun KotlinType.render(typeParameterNameMap: Map