isFlexible() turned into a method in JetType
Otherwise delegated types were never recognized as flexible
This commit is contained in:
+2
-3
@@ -28,7 +28,6 @@ import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall
|
||||
import org.jetbrains.jet.lang.types.BoundsSubstitutor;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.TypeUtils;
|
||||
import org.jetbrains.jet.lang.types.TypesPackage;
|
||||
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
||||
|
||||
@@ -244,8 +243,8 @@ public class OverloadingConflictResolver {
|
||||
numericTypeMoreSpecific(specific, general);
|
||||
if (!isSubtype) return false;
|
||||
|
||||
boolean specificIsFlexible = TypesPackage.isFlexible(specific);
|
||||
boolean generalIsFlexible = TypesPackage.isFlexible(general);
|
||||
boolean specificIsFlexible = specific.isFlexible();
|
||||
boolean generalIsFlexible = general.isFlexible();
|
||||
|
||||
if (specificIsFlexible && !generalIsFlexible) {
|
||||
// Int! lessSpecific Int
|
||||
|
||||
@@ -24,7 +24,6 @@ import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.Annotations;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.types.FlexibleType;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.TypeConstructor;
|
||||
import org.jetbrains.jet.lang.types.TypeProjection;
|
||||
@@ -87,10 +86,9 @@ public class ForceResolveUtil {
|
||||
public static JetType forceResolveAllContents(@Nullable JetType type) {
|
||||
if (type == null) return null;
|
||||
|
||||
if (type instanceof FlexibleType) {
|
||||
FlexibleType flexibleType = (FlexibleType) type;
|
||||
forceResolveAllContents(flexibleType.getLowerBound());
|
||||
forceResolveAllContents(flexibleType.getUpperBound());
|
||||
if (type.isFlexible()) {
|
||||
forceResolveAllContents(type.getLowerBound());
|
||||
forceResolveAllContents(type.getUpperBound());
|
||||
}
|
||||
else {
|
||||
forceResolveAllContents(type.getConstructor());
|
||||
|
||||
+1
-1
@@ -421,7 +421,7 @@ public class ConstraintSystemImpl implements ConstraintSystem {
|
||||
// Foo? <: T!
|
||||
// Foo >: T!
|
||||
// both Foo and Foo? transform to Foo! here
|
||||
if (TypesPackage.isFlexible(parameterType)) {
|
||||
if (parameterType.isFlexible()) {
|
||||
if (parameterType instanceof CustomTypeVariable) {
|
||||
CustomTypeVariable typeVariable = (CustomTypeVariable) parameterType;
|
||||
if (typeVariable.getIsTypeVariable()) {
|
||||
|
||||
@@ -21,7 +21,7 @@ import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class AbstractJetType implements JetType {
|
||||
public abstract class AbstractJetType extends InflexibleType {
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
int result = getConstructor().hashCode();
|
||||
|
||||
@@ -81,11 +81,10 @@ public class CommonSupertypes {
|
||||
List<JetType> upper = new ArrayList<JetType>(types.size());
|
||||
List<JetType> lower = new ArrayList<JetType>(types.size());
|
||||
for (JetType type : types) {
|
||||
if (TypesPackage.isFlexible(type)) {
|
||||
if (type.isFlexible()) {
|
||||
hasFlexible = true;
|
||||
FlexibleType flexibleType = (FlexibleType) type;
|
||||
upper.add(flexibleType.getUpperBound());
|
||||
lower.add(flexibleType.getLowerBound());
|
||||
upper.add(type.getUpperBound());
|
||||
lower.add(type.getLowerBound());
|
||||
}
|
||||
else {
|
||||
upper.add(type);
|
||||
@@ -112,7 +111,7 @@ public class CommonSupertypes {
|
||||
for (Iterator<JetType> iterator = typeSet.iterator(); iterator.hasNext();) {
|
||||
JetType type = iterator.next();
|
||||
assert type != null;
|
||||
assert !TypesPackage.isFlexible(type) : "Flexible type " + type + " passed to commonSuperTypeForInflexible";
|
||||
assert !type.isFlexible() : "Flexible type " + type + " passed to commonSuperTypeForInflexible";
|
||||
if (KotlinBuiltIns.getInstance().isNothingOrNullableNothing(type)) {
|
||||
iterator.remove();
|
||||
}
|
||||
|
||||
@@ -31,6 +31,23 @@ public abstract class DelegatingType implements JetType {
|
||||
return getDelegate().getConstructor();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public JetType getUpperBound() {
|
||||
return getDelegate().getUpperBound();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public JetType getLowerBound() {
|
||||
return getDelegate().getLowerBound();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFlexible() {
|
||||
return getDelegate().isFlexible();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<TypeProjection> getArguments() {
|
||||
|
||||
@@ -378,7 +378,7 @@ public class ErrorUtils {
|
||||
);
|
||||
}
|
||||
|
||||
private static class ErrorTypeImpl implements JetType {
|
||||
private static class ErrorTypeImpl extends InflexibleType implements JetType {
|
||||
private final TypeConstructor constructor;
|
||||
private final JetScope memberScope;
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2010-2014 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.jet.lang.types;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public abstract class InflexibleType implements JetType {
|
||||
@NotNull
|
||||
@Override
|
||||
public JetType getUpperBound() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JetType getLowerBound() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFlexible() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -43,4 +43,14 @@ public interface JetType extends Annotated {
|
||||
|
||||
@Override
|
||||
boolean equals(Object other);
|
||||
|
||||
// lowerBound is a subtype of upperBound
|
||||
@NotNull
|
||||
JetType getUpperBound();
|
||||
|
||||
@NotNull
|
||||
JetType getLowerBound();
|
||||
|
||||
// isFlexible() == false <=> getLowerBound() == getUpperBound()
|
||||
boolean isFlexible();
|
||||
}
|
||||
|
||||
@@ -155,12 +155,11 @@ public class TypeSubstitutor {
|
||||
// The type is within the substitution range, i.e. T or T?
|
||||
JetType type = originalProjection.getType();
|
||||
Variance originalProjectionKind = originalProjection.getProjectionKind();
|
||||
if (type instanceof FlexibleType && !TypesPackage.isCustomTypeVariable(type)) {
|
||||
FlexibleType flexibleType = (FlexibleType) type;
|
||||
if (type.isFlexible() && !TypesPackage.isCustomTypeVariable(type)) {
|
||||
TypeProjection substitutedLower =
|
||||
unsafeSubstitute(new TypeProjectionImpl(originalProjectionKind, flexibleType.getLowerBound()), recursionDepth + 1);
|
||||
unsafeSubstitute(new TypeProjectionImpl(originalProjectionKind, type.getLowerBound()), recursionDepth + 1);
|
||||
TypeProjection substitutedUpper =
|
||||
unsafeSubstitute(new TypeProjectionImpl(originalProjectionKind, flexibleType.getUpperBound()), recursionDepth + 1);
|
||||
unsafeSubstitute(new TypeProjectionImpl(originalProjectionKind, type.getUpperBound()), recursionDepth + 1);
|
||||
// todo: projection kind is neglected
|
||||
return new TypeProjectionImpl(originalProjectionKind,
|
||||
DelegatingFlexibleType.OBJECT$.create(
|
||||
|
||||
@@ -44,7 +44,7 @@ public class TypeUtils {
|
||||
|
||||
public static final JetType CANT_INFER_LAMBDA_PARAM_TYPE = ErrorUtils.createErrorType("Cannot be inferred");
|
||||
|
||||
public static class SpecialType implements JetType {
|
||||
public static class SpecialType extends InflexibleType implements JetType {
|
||||
private final String name;
|
||||
|
||||
public SpecialType(String name) {
|
||||
@@ -424,7 +424,7 @@ public class TypeUtils {
|
||||
if (type.isNullable()) {
|
||||
return true;
|
||||
}
|
||||
if (TypesPackage.isFlexible(type) && isNullableType(((FlexibleType) type).getUpperBound())) {
|
||||
if (type.isFlexible() && isNullableType(type.getUpperBound())) {
|
||||
return true;
|
||||
}
|
||||
if (type.getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptor) {
|
||||
|
||||
+13
-16
@@ -69,18 +69,15 @@ public class TypeCheckingProcedure {
|
||||
}
|
||||
|
||||
public boolean equalTypes(@NotNull JetType type1, @NotNull JetType type2) {
|
||||
if (type1 instanceof FlexibleType) {
|
||||
FlexibleType flexibleType1 = (FlexibleType) type1;
|
||||
if (type2 instanceof FlexibleType) {
|
||||
FlexibleType flexibleType2 = (FlexibleType) type2;
|
||||
return equalTypes(flexibleType1.getLowerBound(), flexibleType2.getLowerBound())
|
||||
&& equalTypes(flexibleType1.getUpperBound(), flexibleType2.getUpperBound());
|
||||
if (type1.isFlexible()) {
|
||||
if (type2.isFlexible()) {
|
||||
return equalTypes(type1.getLowerBound(), type2.getLowerBound())
|
||||
&& equalTypes(type1.getUpperBound(), type2.getUpperBound());
|
||||
}
|
||||
return heterogeneousEquivalence(type2, flexibleType1);
|
||||
return heterogeneousEquivalence(type2, type1);
|
||||
}
|
||||
else if (type2 instanceof FlexibleType) {
|
||||
FlexibleType flexibleType2 = (FlexibleType) type2;
|
||||
return heterogeneousEquivalence(type1, flexibleType2);
|
||||
else if (type2.isFlexible()) {
|
||||
return heterogeneousEquivalence(type1, type2);
|
||||
}
|
||||
|
||||
if (type1.isNullable() != type2.isNullable()) {
|
||||
@@ -121,9 +118,9 @@ public class TypeCheckingProcedure {
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean heterogeneousEquivalence(JetType inflexibleType, FlexibleType flexibleType) {
|
||||
private boolean heterogeneousEquivalence(JetType inflexibleType, JetType flexibleType) {
|
||||
// This is to account for the case when we have Collection<X> vs (Mutable)Collection<X>! or K(java.util.Collection<? extends X>)
|
||||
assert !TypesPackage.isFlexible(inflexibleType) : "Only inflexible types are allowed here: " + inflexibleType;
|
||||
assert !inflexibleType.isFlexible() : "Only inflexible types are allowed here: " + inflexibleType;
|
||||
return isSubtypeOf(flexibleType.getLowerBound(), inflexibleType) && isSubtypeOf(inflexibleType, flexibleType.getUpperBound());
|
||||
}
|
||||
|
||||
@@ -183,11 +180,11 @@ public class TypeCheckingProcedure {
|
||||
}
|
||||
|
||||
public boolean isSubtypeOf(@NotNull JetType subtype, @NotNull JetType supertype) {
|
||||
if (subtype instanceof FlexibleType) {
|
||||
return isSubtypeOf(((FlexibleType) subtype).getLowerBound(), supertype);
|
||||
if (subtype.isFlexible()) {
|
||||
return isSubtypeOf(subtype.getLowerBound(), supertype);
|
||||
}
|
||||
if (supertype instanceof FlexibleType) {
|
||||
return isSubtypeOf(subtype, ((FlexibleType) supertype).getUpperBound());
|
||||
if (supertype.isFlexible()) {
|
||||
return isSubtypeOf(subtype, supertype.getUpperBound());
|
||||
}
|
||||
if (subtype.isError() || supertype.isError()) {
|
||||
return true;
|
||||
|
||||
@@ -22,19 +22,12 @@ public trait NullAwareType {
|
||||
public fun makeNullableAsSpecified(nullable: Boolean): JetType
|
||||
}
|
||||
|
||||
public trait FlexibleType : JetType {
|
||||
public val lowerBound: JetType
|
||||
public val upperBound: JetType
|
||||
}
|
||||
|
||||
public fun JetType.isFlexible(): Boolean = this is FlexibleType
|
||||
|
||||
public fun JetType.lowerIfFlexible(): JetType = if (this is FlexibleType) lowerBound else this
|
||||
public fun JetType.lowerIfFlexible(): JetType = if (this.isFlexible()) getLowerBound() else this
|
||||
|
||||
public open class DelegatingFlexibleType protected (
|
||||
override val lowerBound: JetType,
|
||||
override val upperBound: JetType
|
||||
) : DelegatingType(), FlexibleType, NullAwareType {
|
||||
private val _lowerBound: JetType,
|
||||
private val _upperBound: JetType
|
||||
) : DelegatingType(), NullAwareType {
|
||||
class object {
|
||||
public fun create(lowerBound: JetType, upperBound: JetType): JetType {
|
||||
if (lowerBound == upperBound) return lowerBound
|
||||
@@ -43,23 +36,27 @@ public open class DelegatingFlexibleType protected (
|
||||
}
|
||||
|
||||
{
|
||||
assert (!lowerBound.isFlexible()) { "Lower bound of a flexible type can not be flexible: $lowerBound" }
|
||||
assert (!upperBound.isFlexible()) { "Upper bound of a flexible type can not be flexible: $upperBound" }
|
||||
assert (lowerBound != upperBound) { "Lower and upper bounds are equal: $lowerBound == $upperBound" }
|
||||
assert (JetTypeChecker.DEFAULT.isSubtypeOf(lowerBound, upperBound)) {
|
||||
"Lower bound $lowerBound of a flexible type must be a subtype of the upper bound $upperBound"
|
||||
assert (!_lowerBound.isFlexible()) { "Lower bound of a flexible type can not be flexible: $_lowerBound" }
|
||||
assert (!_upperBound.isFlexible()) { "Upper bound of a flexible type can not be flexible: $_upperBound" }
|
||||
assert (_lowerBound != _upperBound) { "Lower and upper bounds are equal: $_lowerBound == $_upperBound" }
|
||||
assert (JetTypeChecker.DEFAULT.isSubtypeOf(_lowerBound, _upperBound)) {
|
||||
"Lower bound $_lowerBound of a flexible type must be a subtype of the upper bound $_upperBound"
|
||||
}
|
||||
}
|
||||
|
||||
override fun isFlexible(): Boolean = true
|
||||
override fun getUpperBound(): JetType = _upperBound
|
||||
override fun getLowerBound(): JetType = _lowerBound
|
||||
|
||||
protected open fun create(lowerBound: JetType, upperBound: JetType): JetType {
|
||||
return DelegatingFlexibleType.create(lowerBound, upperBound)
|
||||
}
|
||||
|
||||
override fun makeNullableAsSpecified(nullable: Boolean): JetType {
|
||||
return create(TypeUtils.makeNullableAsSpecified(lowerBound, nullable), TypeUtils.makeNullableAsSpecified(upperBound, nullable))
|
||||
return create(TypeUtils.makeNullableAsSpecified(_lowerBound, nullable), TypeUtils.makeNullableAsSpecified(_upperBound, nullable))
|
||||
}
|
||||
|
||||
override fun getDelegate() = lowerBound
|
||||
override fun getDelegate() = _lowerBound
|
||||
|
||||
override fun toString() = "('$lowerBound'..'$upperBound')"
|
||||
override fun toString() = "('$_lowerBound'..'$_upperBound')"
|
||||
}
|
||||
|
||||
@@ -293,20 +293,19 @@ public class DescriptorRendererImpl implements DescriptorRenderer {
|
||||
@NotNull
|
||||
@Override
|
||||
public String renderType(@NotNull JetType type) {
|
||||
if (type instanceof FlexibleType) {
|
||||
FlexibleType flexibleType = (FlexibleType) type;
|
||||
if (type.isFlexible()) {
|
||||
if (!debugMode) {
|
||||
return renderFlexibleType(flexibleType);
|
||||
return renderFlexibleType(type);
|
||||
}
|
||||
else {
|
||||
return "(" + renderType(flexibleType.getLowerBound()) + ".." + renderType(flexibleType.getUpperBound()) + ")";
|
||||
return "(" + renderType(type.getLowerBound()) + ".." + renderType(type.getUpperBound()) + ")";
|
||||
}
|
||||
}
|
||||
return renderInflexibleType(type);
|
||||
}
|
||||
|
||||
private String renderInflexibleType(@NotNull JetType type) {
|
||||
assert !TypesPackage.isFlexible(type) : "Flexible types not allowed here: " + renderType(type);
|
||||
assert !type.isFlexible() : "Flexible types not allowed here: " + renderType(type);
|
||||
|
||||
if (type == CANT_INFER_LAMBDA_PARAM_TYPE || type == DONT_CARE) {
|
||||
return "???";
|
||||
@@ -330,7 +329,7 @@ public class DescriptorRendererImpl implements DescriptorRenderer {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private String renderFlexibleType(@NotNull FlexibleType type) {
|
||||
private String renderFlexibleType(@NotNull JetType type) {
|
||||
JetType lower = type.getLowerBound();
|
||||
JetType upper = type.getUpperBound();
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@ import org.jetbrains.jet.lang.types.TypeProjectionImpl
|
||||
import org.jetbrains.jet.lang.types.ErrorUtils
|
||||
import org.jetbrains.jet.lang.resolve.java.kotlinSignature.CollectionClassMapping
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor
|
||||
import org.jetbrains.jet.lang.types.FlexibleType
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames
|
||||
|
||||
fun JetType.makeNullable() = TypeUtils.makeNullable(this)
|
||||
@@ -35,8 +34,8 @@ fun JetType.supertypes(): Set<JetType> = TypeUtils.getAllSupertypes(this)
|
||||
fun JetType.isUnit(): Boolean = KotlinBuiltIns.getInstance().isUnit(this)
|
||||
|
||||
public fun approximateFlexibleTypes(jetType: JetType, outermost: Boolean = true): JetType {
|
||||
if (jetType is FlexibleType) {
|
||||
val lowerClass = jetType.lowerBound.getConstructor().getDeclarationDescriptor() as? ClassDescriptor?
|
||||
if (jetType.isFlexible()) {
|
||||
val lowerClass = jetType.getLowerBound().getConstructor().getDeclarationDescriptor() as? ClassDescriptor?
|
||||
val isCollection = lowerClass != null && CollectionClassMapping.getInstance().isMutableCollection(lowerClass)
|
||||
// (Mutable)Collection<T>! -> MutableCollection<T>?
|
||||
// Foo<(Mutable)Collection<T>!>! -> Foo<Collection<T>>?
|
||||
@@ -44,9 +43,9 @@ public fun approximateFlexibleTypes(jetType: JetType, outermost: Boolean = true)
|
||||
// Foo<Bar!>! -> Foo<Bar>?
|
||||
val approximation =
|
||||
if (isCollection)
|
||||
TypeUtils.makeNullableAsSpecified(if (jetType.isMarkedReadOnly()) jetType.upperBound else jetType.lowerBound, outermost)
|
||||
TypeUtils.makeNullableAsSpecified(if (jetType.isMarkedReadOnly()) jetType.getUpperBound() else jetType.getLowerBound(), outermost)
|
||||
else
|
||||
if (outermost) jetType.upperBound else jetType.lowerBound
|
||||
if (outermost) jetType.getUpperBound() else jetType.getLowerBound()
|
||||
val approximated = approximateFlexibleTypes(approximation)
|
||||
return if (jetType.isMarkedNotNull()) approximated.makeNotNullable() else approximated
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user