From 578f6d48119bfeff868fb78b50b3f857670290cf Mon Sep 17 00:00:00 2001 From: Svetlana Isakova Date: Mon, 21 Jul 2014 13:16:53 +0400 Subject: [PATCH] Converted ConstraintSystem to Kotlin --- .../lang/diagnostics/rendering/Renderers.java | 4 +- .../jet/lang/resolve/calls/CallCompleter.kt | 2 +- .../calls/inference/ConstraintPosition.kt | 3 + .../calls/inference/ConstraintSystem.kt | 45 +- .../calls/inference/ConstraintSystemImpl.kt | 622 +++++++----------- .../calls/inference/ConstraintSystemStatus.kt | 32 +- .../resolve/calls/inference/TypeBounds.kt | 53 +- .../resolve/calls/inference/TypeBoundsImpl.kt | 269 +++----- .../jetbrains/jet/lang/types/TypeUtils.java | 1 + 9 files changed, 390 insertions(+), 641 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/Renderers.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/Renderers.java index 2a59a1083dd..4a2ebf3464c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/Renderers.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/Renderers.java @@ -428,8 +428,8 @@ public class Renderers { Function renderBound = new Function() { @Override public String fun(TypeBoundsImpl.Bound bound) { - String arrow = bound.kind == LOWER_BOUND ? ">: " : bound.kind == UPPER_BOUND ? "<: " : ":= "; - return arrow + RENDER_TYPE.render(bound.type) + '(' + bound.position + ')'; + String arrow = bound.getKind() == LOWER_BOUND ? ">: " : bound.getKind() == UPPER_BOUND ? "<: " : ":= "; + return arrow + RENDER_TYPE.render(bound.getConstrainingType()) + '(' + bound.getPosition() + ')'; } }; Name typeVariableName = typeBounds.getTypeVariable().getName(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallCompleter.kt b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallCompleter.kt index 198a32d484e..8276625297c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallCompleter.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallCompleter.kt @@ -134,7 +134,7 @@ public class CallCompleter( trace: BindingTrace ) { fun updateSystemIfSuccessful(update: (ConstraintSystem) -> Boolean) { - val copy = getConstraintSystem()!!.copy() + val copy = (getConstraintSystem() as ConstraintSystemImpl).copy() if (update(copy)) { setConstraintSystem(copy) } diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintPosition.kt b/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintPosition.kt index ab84613f92f..42f24567ae3 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintPosition.kt +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintPosition.kt @@ -34,6 +34,7 @@ public class ConstraintPosition { private static final Map valueParameterPositions = new HashMap(); private static final Map typeBoundPositions = new HashMap(); + @NotNull public static ConstraintPosition getValueParameterPosition(int index) { ConstraintPosition position = valueParameterPositions.get(index); if (position == null) { @@ -43,6 +44,7 @@ public class ConstraintPosition { return position; } + @NotNull public static ConstraintPosition getTypeBoundPosition(int index) { ConstraintPosition position = typeBoundPositions.get(index); if (position == null) { @@ -74,6 +76,7 @@ public class ConstraintPosition { } } + @NotNull public static ConstraintPosition getCompoundConstraintPosition(ConstraintPosition... positions) { return new CompoundConstraintPosition(Arrays.asList(positions)); } diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystem.kt b/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystem.kt index 610718c8be5..17e5dd19e1d 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystem.kt +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystem.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2013 JetBrains s.r.o. + * 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. @@ -14,30 +14,24 @@ * limitations under the License. */ -package org.jetbrains.jet.lang.resolve.calls.inference; +package org.jetbrains.jet.lang.resolve.calls.inference -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; -import org.jetbrains.jet.lang.types.JetType; -import org.jetbrains.jet.lang.types.TypeSubstitutor; -import org.jetbrains.jet.lang.types.Variance; +import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor +import org.jetbrains.jet.lang.types.Variance +import org.jetbrains.jet.lang.types.JetType +import org.jetbrains.jet.lang.types.TypeSubstitutor -import java.util.Map; -import java.util.Set; - -public interface ConstraintSystem { +public trait ConstraintSystem { /** * Registers variables in a constraint system. */ - void registerTypeVariables(@NotNull Map typeVariables); + public fun registerTypeVariables(typeVariables: Map) /** * Returns a set of all registered type variables. */ - @NotNull - Set getTypeVariables(); + public fun getTypeVariables(): Set /** * Adds a constraint that the constraining type is a subtype of the subject type.

@@ -46,7 +40,7 @@ public interface ConstraintSystem { * For example, for {@code "fun id(t: T) {}"} to infer T in invocation "id(1)" * should be generated a constraint "Int is a subtype of T" where T is a subject type, and Int is a constraining type. */ - void addSubtypeConstraint(@Nullable JetType constrainingType, @NotNull JetType subjectType, @NotNull ConstraintPosition constraintPosition); + public fun addSubtypeConstraint(constrainingType: JetType?, subjectType: JetType, constraintPosition: ConstraintPosition) /** * Adds a constraint that the constraining type is a supertype of the subject type.

@@ -55,17 +49,15 @@ public interface ConstraintSystem { * For example, for {@code "fun create() : T"} to infer T in invocation "val i: Int = create()" * should be generated a constraint "Int is a supertype of T" where T is a subject type, and Int is a constraining type. */ - void addSupertypeConstraint(@Nullable JetType constrainingType, @NotNull JetType subjectType, @NotNull ConstraintPosition constraintPosition); + public fun addSupertypeConstraint(constrainingType: JetType?, subjectType: JetType, constraintPosition: ConstraintPosition) - @NotNull - ConstraintSystemStatus getStatus(); + public fun getStatus(): ConstraintSystemStatus /** * Returns the resulting type constraints of solving the constraint system for specific type variable.

* Returns null if the type variable was not registered. */ - @NotNull - TypeBounds getTypeBounds(@NotNull TypeParameterDescriptor typeVariable); + public fun getTypeBounds(typeVariable: TypeParameterDescriptor): TypeBounds /** * Returns a result of solving the constraint system (mapping from the type variable to the resulting type projection).

@@ -76,16 +68,11 @@ public interface ConstraintSystem { * If the addition of the 'expected type' constraint made the system fail, * this constraint is not included in the resulting substitution. */ - @NotNull - TypeSubstitutor getResultingSubstitutor(); + public fun getResultingSubstitutor(): TypeSubstitutor /** * Returns a current result of solving the constraint system (mapping from the type variable to the resulting type projection). * If there is no information for type parameter, returns type projection for DONT_CARE type. */ - @NotNull - TypeSubstitutor getCurrentSubstitutor(); - - @NotNull - ConstraintSystem copy(); -} + public fun getCurrentSubstitutor(): TypeSubstitutor +} \ No newline at end of file diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemImpl.kt b/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemImpl.kt index c456f6115b0..5ff1da7cc4e 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemImpl.kt +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemImpl.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2013 JetBrains s.r.o. + * 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. @@ -14,464 +14,337 @@ * limitations under the License. */ -package org.jetbrains.jet.lang.resolve.calls.inference; +package org.jetbrains.jet.lang.resolve.calls.inference -import kotlin.Function1; -import kotlin.KotlinPackage; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor; -import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; -import org.jetbrains.jet.lang.types.*; -import org.jetbrains.jet.lang.types.checker.JetTypeChecker; -import org.jetbrains.jet.lang.types.checker.TypeCheckingProcedure; -import org.jetbrains.jet.lang.types.checker.TypingConstraints; -import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; -import org.jetbrains.jet.utils.UtilsPackage; +import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor +import org.jetbrains.jet.lang.types.TypeProjection +import org.jetbrains.jet.lang.types.JetType +import org.jetbrains.jet.lang.types.TypeUtils +import org.jetbrains.jet.lang.types.TypeUtils.DONT_CARE +import org.jetbrains.jet.lang.types.TypeProjectionImpl +import org.jetbrains.jet.lang.types.TypeSubstitutor +import org.jetbrains.jet.lang.types.ErrorUtils +import org.jetbrains.jet.lang.types.Variance +import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns +import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemImpl.ConstraintKind +import org.jetbrains.jet.lang.types.checker.TypeCheckingProcedure +import org.jetbrains.jet.lang.types.checker.TypingConstraints +import org.jetbrains.jet.lang.types.TypeConstructor +import java.util.LinkedHashMap +import java.util.HashSet +import org.jetbrains.jet.lang.resolve.calls.inference.TypeBounds.BoundKind.* +import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemImpl.ConstraintKind.* +import java.util.HashMap +import java.util.ArrayList +import org.jetbrains.kotlin.util.sure -import java.util.*; +public class ConstraintSystemImpl : ConstraintSystem { -import static org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemImpl.ConstraintKind.EQUAL; -import static org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemImpl.ConstraintKind.SUB_TYPE; -import static org.jetbrains.jet.lang.resolve.calls.inference.TypeBounds.Bound; -import static org.jetbrains.jet.lang.resolve.calls.inference.TypeBounds.BoundKind.*; -import static org.jetbrains.jet.lang.types.TypeUtils.DONT_CARE; - -public class ConstraintSystemImpl implements ConstraintSystem { - - public enum ConstraintKind { - SUB_TYPE, EQUAL + public enum class ConstraintKind { + SUB_TYPE + EQUAL } - private final Map typeParameterBounds = - new LinkedHashMap(); - private final Set errorConstraintPositions = new HashSet(); - private boolean hasErrorInConstrainingTypes; + private val typeParameterBounds = LinkedHashMap() + private val errorConstraintPositions = HashSet() + private var hasErrorInConstrainingTypes: Boolean = false - private final ConstraintSystemStatus constraintSystemStatus = new ConstraintSystemStatus() { + private val constraintSystemStatus = object : ConstraintSystemStatus { // for debug ConstraintsUtil.getDebugMessageForStatus might be used - @Override - public boolean isSuccessful() { - return !hasContradiction() && !hasUnknownParameters(); + override fun isSuccessful() = !hasContradiction() && !hasUnknownParameters() + + override fun hasContradiction() = hasTypeConstructorMismatch() || hasConflictingConstraints() + + override fun hasViolatedUpperBound(): Boolean { + if (isSuccessful()) return false + return getSystemWithoutWeakConstraints().getStatus().isSuccessful() } - @Override - public boolean hasContradiction() { - return hasTypeConstructorMismatch() || hasConflictingConstraints(); - } - - @Override - public boolean hasViolatedUpperBound() { - if (isSuccessful()) return false; - return getSystemWithoutWeakConstraints().getStatus().isSuccessful(); - } - - @Override - public boolean hasConflictingConstraints() { - for (TypeBoundsImpl typeBounds : typeParameterBounds.values()) { - if (typeBounds.getValues().size() > 1) return true; + override fun hasConflictingConstraints(): Boolean { + for (typeBounds in typeParameterBounds.values()) { + if (typeBounds.getValues().size() > 1) return true } - return false; + return false } - @Override - public boolean hasUnknownParameters() { - for (TypeBoundsImpl typeBounds : typeParameterBounds.values()) { + override fun hasUnknownParameters(): Boolean { + for (typeBounds in typeParameterBounds.values()) { if (typeBounds.isEmpty()) { - return true; + return true } } - return false; + return false } - @Override - public boolean hasTypeConstructorMismatch() { - return !errorConstraintPositions.isEmpty(); - } + override fun hasTypeConstructorMismatch() = !errorConstraintPositions.isEmpty() - @Override - public boolean hasTypeConstructorMismatchAt(@NotNull ConstraintPosition constraintPosition) { - return errorConstraintPositions.contains(constraintPosition); - } + override fun hasTypeConstructorMismatchAt(constraintPosition: ConstraintPosition) = + errorConstraintPositions.contains(constraintPosition) - @Override - public boolean hasOnlyErrorsFromPosition(ConstraintPosition constraintPosition) { - if (isSuccessful()) return false; - ConstraintSystem systemWithoutConstraintsFromPosition = filterConstraintsOut(constraintPosition); + override fun hasOnlyErrorsFromPosition(constraintPosition: ConstraintPosition): Boolean { + if (isSuccessful()) return false + val systemWithoutConstraintsFromPosition = filterConstraintsOut(constraintPosition) if (systemWithoutConstraintsFromPosition.getStatus().isSuccessful()) { - return true; + return true } if (errorConstraintPositions.size() == 1 && errorConstraintPositions.contains(constraintPosition)) { // e.g. if systemWithoutConstraintsFromPosition has unknown type parameters, it's not successful - return true; + return true } - return false; + return false } - @Override - public boolean hasErrorInConstrainingTypes() { - return hasErrorInConstrainingTypes; - } - }; + override fun hasErrorInConstrainingTypes() = hasErrorInConstrainingTypes + } - @NotNull - private static Map getParameterToInferredValueMap( - @NotNull Map typeParameterBounds, - @NotNull Function1 getDefaultTypeProjection - ) { - Map substitutionContext = - UtilsPackage.newHashMapWithExpectedSize(typeParameterBounds.size()); - for (Map.Entry entry : typeParameterBounds.entrySet()) { - TypeParameterDescriptor typeParameter = entry.getKey(); - TypeBounds typeBounds = entry.getValue(); - - TypeProjection typeProjection; - JetType value = typeBounds.getValue(); - if (value != null && !TypeUtils.containsSpecialType(value, TypeUtils.DONT_CARE)) { - typeProjection = new TypeProjectionImpl(value); + private fun getParameterToInferredValueMap(typeParameterBounds: Map, getDefaultTypeProjection: Function1): Map { + val substitutionContext = HashMap() + for ((typeParameter, typeBounds) in typeParameterBounds) { + val typeProjection: TypeProjection + val value = typeBounds.getValue() + if (value != null && !TypeUtils.containsSpecialType(value, DONT_CARE)) { + typeProjection = TypeProjectionImpl(value) } else { - typeProjection = getDefaultTypeProjection.invoke(typeParameter); + typeProjection = getDefaultTypeProjection.invoke(typeParameter) } - substitutionContext.put(typeParameter, typeProjection); + substitutionContext.put(typeParameter, typeProjection) } - return substitutionContext; + return substitutionContext } - private TypeSubstitutor replaceUninferredBy(@NotNull Function1 getDefaultValue) { - return TypeUtils.makeSubstitutorForTypeParametersMap(getParameterToInferredValueMap(typeParameterBounds, getDefaultValue)); + private fun replaceUninferredBy(getDefaultValue: (TypeParameterDescriptor) -> TypeProjection): TypeSubstitutor { + return TypeUtils.makeSubstitutorForTypeParametersMap(getParameterToInferredValueMap(typeParameterBounds, getDefaultValue)) } - private TypeSubstitutor replaceUninferredBy(@NotNull final JetType defaultValue) { - return replaceUninferredBy( - new Function1() { - @Override - public TypeProjection invoke(TypeParameterDescriptor descriptor) { - return new TypeProjectionImpl(defaultValue); - } - } - ); + private fun replaceUninferredBy(defaultValue: JetType): TypeSubstitutor { + return replaceUninferredBy { TypeProjectionImpl(defaultValue) } } - private TypeSubstitutor replaceUninferredBySpecialErrorType() { - return replaceUninferredBy( - new Function1() { - @Override - public TypeProjection invoke(TypeParameterDescriptor descriptor) { - return new TypeProjectionImpl(ErrorUtils.createUninferredParameterType(descriptor)); - } - } - ); + private fun replaceUninferredBySpecialErrorType(): TypeSubstitutor { + return replaceUninferredBy { TypeProjectionImpl(ErrorUtils.createUninferredParameterType(it)) } } - @NotNull - @Override - public ConstraintSystemStatus getStatus() { - return constraintSystemStatus; - } + override fun getStatus(): ConstraintSystemStatus = constraintSystemStatus - @Override - public void registerTypeVariables(@NotNull Map typeVariables) { - for (Map.Entry entry : typeVariables.entrySet()) { - TypeParameterDescriptor typeVariable = entry.getKey(); - Variance positionVariance = entry.getValue(); - typeParameterBounds.put(typeVariable, new TypeBoundsImpl(typeVariable, positionVariance)); + override fun registerTypeVariables(typeVariables: Map) { + for ((typeVariable, positionVariance) in typeVariables) { + typeParameterBounds.put(typeVariable, TypeBoundsImpl(typeVariable, positionVariance)) } - TypeSubstitutor constantSubstitutor = TypeUtils.makeConstantSubstitutor(typeParameterBounds.keySet(), DONT_CARE); - for (Map.Entry entry : typeParameterBounds.entrySet()) { - TypeParameterDescriptor typeVariable = entry.getKey(); - TypeBoundsImpl typeBounds = entry.getValue(); - - for (JetType declaredUpperBound : typeVariable.getUpperBounds()) { - if (KotlinBuiltIns.getInstance().getNullableAnyType().equals(declaredUpperBound)) continue; //todo remove this line (?) - JetType substitutedBound = constantSubstitutor.substitute(declaredUpperBound, Variance.INVARIANT); + val constantSubstitutor = TypeUtils.makeConstantSubstitutor(typeParameterBounds.keySet(), DONT_CARE) + for ((typeVariable, typeBounds) in typeParameterBounds) { + for (declaredUpperBound in typeVariable.getUpperBounds()) { + if (KotlinBuiltIns.getInstance().getNullableAnyType() == declaredUpperBound) continue //todo remove this line (?) + val substitutedBound = constantSubstitutor?.substitute(declaredUpperBound, Variance.INVARIANT) if (substitutedBound != null) { - typeBounds.addBound(UPPER_BOUND, substitutedBound, ConstraintPosition.getTypeBoundPosition(typeVariable.getIndex())); + typeBounds.addBound(UPPER_BOUND, substitutedBound, ConstraintPosition.getTypeBoundPosition(typeVariable.getIndex())) } } } } - @Override - @NotNull - public ConstraintSystem copy() { - return createNewConstraintSystemFromThis( - UtilsPackage.identity(), - new Function1() { - @Override - public TypeBoundsImpl invoke(TypeBoundsImpl typeBounds) { - return typeBounds.copy(); - } - }, - UtilsPackage.alwaysTrue() - ); + public fun copy(): ConstraintSystem = createNewConstraintSystemFromThis({ it }, { it.copy() }, { true }) + + public fun substituteTypeVariables(typeVariablesMap: (TypeParameterDescriptor) -> TypeParameterDescriptor?): ConstraintSystem { + // type bounds are proper types and don't contain other variables + return createNewConstraintSystemFromThis(typeVariablesMap, { it }, { true }) } - @NotNull - public ConstraintSystem substituteTypeVariables(@NotNull Function1 typeVariablesMap) { - return createNewConstraintSystemFromThis( - typeVariablesMap, - // type bounds are proper types and don't contain other variables - UtilsPackage.identity(), - UtilsPackage.alwaysTrue() - ); + public fun filterConstraintsOut(vararg excludePositions: ConstraintPosition): ConstraintSystem { + val positions = excludePositions.toSet() + return filterConstraints { !positions.contains(it) } } - @NotNull - public ConstraintSystem filterConstraintsOut(@NotNull final ConstraintPosition excludePosition) { - return filterConstraints(new Function1() { - @Override - public Boolean invoke(ConstraintPosition constraintPosition) { - return !excludePosition.equals(constraintPosition); + public fun filterConstraints(condition: (ConstraintPosition) -> Boolean): ConstraintSystem { + return createNewConstraintSystemFromThis({ it }, { it.filter(condition) }, condition) + } + + public fun getSystemWithoutWeakConstraints(): ConstraintSystem { + return filterConstraints { + constraintPosition -> + // 'isStrong' for compound means 'has some strong constraints' + // but for testing absence of weak constraints we need 'has only strong constraints' here + if (constraintPosition is ConstraintPosition.CompoundConstraintPosition) { + val position = constraintPosition as ConstraintPosition.CompoundConstraintPosition + position.consistsOfOnlyStrongConstraints() } - }); - } - - @NotNull - private ConstraintSystem filterConstraints(@NotNull final Function1 condition) { - return createNewConstraintSystemFromThis( - UtilsPackage.identity(), - new Function1() { - @Override - public TypeBoundsImpl invoke(TypeBoundsImpl typeBounds) { - return typeBounds.filter(condition); - } - }, - condition - ); - } - - @NotNull - public ConstraintSystem getSystemWithoutWeakConstraints() { - return filterConstraints(new Function1() { - @Override - public Boolean invoke(ConstraintPosition constraintPosition) { - // 'isStrong' for compound means 'has some strong constraints' - // but for testing absence of weak constraints we need 'has only strong constraints' here - if (constraintPosition instanceof ConstraintPosition.CompoundConstraintPosition) { - ConstraintPosition.CompoundConstraintPosition position = - (ConstraintPosition.CompoundConstraintPosition) constraintPosition; - return position.consistsOfOnlyStrongConstraints(); - } - return constraintPosition.isStrong(); + else { + constraintPosition.isStrong() } - }); - } - - @NotNull - private ConstraintSystem createNewConstraintSystemFromThis( - @NotNull Function1 substituteTypeVariable, - @NotNull Function1 replaceTypeBounds, - @NotNull Function1 filterConstraintPosition - ) { - ConstraintSystemImpl newSystem = new ConstraintSystemImpl(); - for (Map.Entry entry : typeParameterBounds.entrySet()) { - TypeParameterDescriptor typeParameter = entry.getKey(); - TypeBoundsImpl typeBounds = entry.getValue(); - - TypeParameterDescriptor newTypeParameter = substituteTypeVariable.invoke(typeParameter); - assert newTypeParameter != null; - newSystem.typeParameterBounds.put(newTypeParameter, replaceTypeBounds.invoke(typeBounds)); } - newSystem.errorConstraintPositions.addAll(KotlinPackage.filter(errorConstraintPositions, filterConstraintPosition)); + } + + private fun createNewConstraintSystemFromThis( + substituteTypeVariable: (TypeParameterDescriptor) -> TypeParameterDescriptor?, + replaceTypeBounds: (TypeBoundsImpl) -> TypeBoundsImpl, + filterConstraintPosition: (ConstraintPosition) -> Boolean + ): ConstraintSystem { + val newSystem = ConstraintSystemImpl() + for ((typeParameter, typeBounds) in typeParameterBounds) { + val newTypeParameter = substituteTypeVariable(typeParameter) + newSystem.typeParameterBounds.put(newTypeParameter!!, replaceTypeBounds(typeBounds)) + } + newSystem.errorConstraintPositions.addAll(errorConstraintPositions.filter(filterConstraintPosition)) //todo if 'filterConstraintPosition' is not trivial, it's incorrect to just copy 'hasErrorInConstrainingTypes' - newSystem.hasErrorInConstrainingTypes = hasErrorInConstrainingTypes; - return newSystem; + newSystem.hasErrorInConstrainingTypes = hasErrorInConstrainingTypes + return newSystem } - @Override - public void addSupertypeConstraint( - @Nullable JetType constrainingType, - @NotNull JetType subjectType, - @NotNull ConstraintPosition constraintPosition - ) { - if (constrainingType != null && TypeUtils.noExpectedType(constrainingType)) return; + override fun addSupertypeConstraint(constrainingType: JetType?, subjectType: JetType, constraintPosition: ConstraintPosition) { + if (constrainingType != null && TypeUtils.noExpectedType(constrainingType)) return - addConstraint(SUB_TYPE, subjectType, constrainingType, constraintPosition); + addConstraint(SUB_TYPE, subjectType, constrainingType, constraintPosition) } - @Override - public void addSubtypeConstraint( - @Nullable JetType constrainingType, - @NotNull JetType subjectType, - @NotNull ConstraintPosition constraintPosition - ) { - addConstraint(SUB_TYPE, constrainingType, subjectType, constraintPosition); + override fun addSubtypeConstraint(constrainingType: JetType?, subjectType: JetType, constraintPosition: ConstraintPosition) { + addConstraint(SUB_TYPE, constrainingType, subjectType, constraintPosition) } - private void addConstraint( - @NotNull ConstraintKind constraintKind, - @Nullable JetType subType, - @Nullable JetType superType, - @NotNull final ConstraintPosition constraintPosition - ) { - TypeCheckingProcedure typeCheckingProcedure = new TypeCheckingProcedure(new TypingConstraints() { - @Override - public boolean assertEqualTypes( - @NotNull JetType a, @NotNull JetType b, @NotNull TypeCheckingProcedure typeCheckingProcedure - ) { - doAddConstraint(EQUAL, a, b, constraintPosition, typeCheckingProcedure); - return true; + private fun addConstraint(constraintKind: ConstraintKind, subType: JetType?, superType: JetType?, constraintPosition: ConstraintPosition) { + val typeCheckingProcedure = TypeCheckingProcedure(object : TypingConstraints { + override fun assertEqualTypes(a: JetType, b: JetType, typeCheckingProcedure: TypeCheckingProcedure): Boolean { + doAddConstraint(EQUAL, a, b, constraintPosition, typeCheckingProcedure) + return true } - @Override - public boolean assertEqualTypeConstructors( - @NotNull TypeConstructor a, @NotNull TypeConstructor b - ) { - return a.equals(b); + override fun assertEqualTypeConstructors(a: TypeConstructor, b: TypeConstructor): Boolean { + return a == b } - @Override - public boolean assertSubtype( - @NotNull JetType subtype, @NotNull JetType supertype, @NotNull TypeCheckingProcedure typeCheckingProcedure - ) { - doAddConstraint(SUB_TYPE, subtype, supertype, constraintPosition, typeCheckingProcedure); - return true; + override fun assertSubtype(subtype: JetType, supertype: JetType, typeCheckingProcedure: TypeCheckingProcedure): Boolean { + doAddConstraint(SUB_TYPE, subtype, supertype, constraintPosition, typeCheckingProcedure) + return true } - @Override - public boolean noCorrespondingSupertype( - @NotNull JetType subtype, @NotNull JetType supertype - ) { - errorConstraintPositions.add(constraintPosition); - return true; + override fun noCorrespondingSupertype(subtype: JetType, supertype: JetType): Boolean { + errorConstraintPositions.add(constraintPosition) + return true } - }); - doAddConstraint(constraintKind, subType, superType, constraintPosition, typeCheckingProcedure); + }) + doAddConstraint(constraintKind, subType, superType, constraintPosition, typeCheckingProcedure) } - private boolean isErrorOrSpecialType(@Nullable JetType type) { + private fun isErrorOrSpecialType(type: JetType?): Boolean { if (TypeUtils.isDontCarePlaceholder(type) || ErrorUtils.isUninferredParameter(type)) { - return true; + return true } if (type == null || (type.isError() && type != TypeUtils.PLACEHOLDER_FUNCTION_TYPE)) { - hasErrorInConstrainingTypes = true; - return true; + hasErrorInConstrainingTypes = true + return true } - return false; + return false } - private void doAddConstraint( - @NotNull ConstraintKind constraintKind, - @Nullable JetType subType, - @Nullable JetType superType, - @NotNull ConstraintPosition constraintPosition, - @NotNull TypeCheckingProcedure typeCheckingProcedure + private fun doAddConstraint( + constraintKind: ConstraintKind, + subType: JetType?, + superType: JetType?, + constraintPosition: ConstraintPosition, + typeCheckingProcedure: TypeCheckingProcedure ) { + if (isErrorOrSpecialType(subType) || isErrorOrSpecialType(superType)) return + if (subType == null || superType == null) return - if (isErrorOrSpecialType(subType) || isErrorOrSpecialType(superType)) return; - assert subType != null && superType != null; - - assert superType != TypeUtils.PLACEHOLDER_FUNCTION_TYPE : "The type for " + constraintPosition + " shouldn't be a placeholder for function type"; + assert(superType != TypeUtils.PLACEHOLDER_FUNCTION_TYPE) { + "The type for " + constraintPosition + " shouldn't be a placeholder for function type" + } if (subType == TypeUtils.PLACEHOLDER_FUNCTION_TYPE) { if (!KotlinBuiltIns.isFunctionOrExtensionFunctionType(superType)) { if (isMyTypeVariable(superType)) { // a constraint binds type parameter and any function type, so there is no new info and no error - return; + return } - errorConstraintPositions.add(constraintPosition); + errorConstraintPositions.add(constraintPosition) } - return; + return } // todo temporary hack // function literal without declaring receiver type { x -> ... } // can be considered as extension function if one is expected // (special type constructor for function/ extension function should be introduced like PLACEHOLDER_FUNCTION_TYPE) - if (constraintKind == SUB_TYPE && KotlinBuiltIns.isFunctionType(subType) && KotlinBuiltIns.isExtensionFunctionType(superType)) { - subType = createCorrespondingExtensionFunctionType(subType, DONT_CARE); + val newSubType = if (constraintKind == SUB_TYPE + && KotlinBuiltIns.isFunctionType(subType) + && KotlinBuiltIns.isExtensionFunctionType(superType)) { + createCorrespondingExtensionFunctionType(subType, DONT_CARE) + } + else { + subType : JetType } - // can be equal for the recursive invocations: - // fun foo(i: Int) : T { ... return foo(i); } => T <: T - if (isMyTypeVariable(subType) && isMyTypeVariable(superType) && JetTypeChecker.DEFAULT.equalTypes(subType, superType)) return; + fun simplifyConstraint(subType: JetType, superType: JetType) { + // can be equal for the recursive invocations: + // fun foo(i: Int) : T { ... return foo(i); } => T <: T + if (subType == superType) return - //todo temporary hack KT-6320 - if (isMyTypeVariable(subType) && isMyTypeVariable(superType)) return; - assert !isMyTypeVariable(subType) || !isMyTypeVariable(superType) : - "The constraint shouldn't contain different type variables on both sides: " + subType + " <: " + superType; + assert(!isMyTypeVariable(subType) || !isMyTypeVariable(superType)) { + "The constraint shouldn't contain different type variables on both sides: " + subType + " <: " + superType + } - - if (isMyTypeVariable(subType)) { - generateTypeParameterConstraint(subType, superType, constraintKind == SUB_TYPE ? UPPER_BOUND : EXACT_BOUND, constraintPosition); - return; + if (isMyTypeVariable(subType)) { + val boundKind = if (constraintKind == SUB_TYPE) UPPER_BOUND else EXACT_BOUND + generateTypeParameterConstraint(subType, superType, boundKind, constraintPosition) + return + } + if (isMyTypeVariable(superType)) { + val boundKind = if (constraintKind == SUB_TYPE) LOWER_BOUND else EXACT_BOUND + generateTypeParameterConstraint(superType, subType, boundKind, constraintPosition) + return + } + // if superType is nullable and subType is not nullable, unsafe call error will be generated later, + // but constraint system should be solved anyway + typeCheckingProcedure.isSubtypeOf(TypeUtils.makeNotNullable(subType), TypeUtils.makeNotNullable(superType)) } - if (isMyTypeVariable(superType)) { - generateTypeParameterConstraint(superType, subType, constraintKind == SUB_TYPE ? LOWER_BOUND : EXACT_BOUND, constraintPosition); - return; - } - // if superType is nullable and subType is not nullable, unsafe call error will be generated later, - // but constraint system should be solved anyway - typeCheckingProcedure.isSubtypeOf(TypeUtils.makeNotNullable(subType), TypeUtils.makeNotNullable(superType)); + simplifyConstraint(newSubType, superType) } - private void generateTypeParameterConstraint( - @NotNull JetType parameterType, - @NotNull JetType constrainingType, - @NotNull TypeBoundsImpl.BoundKind boundKind, - @NotNull ConstraintPosition constraintPosition + private fun generateTypeParameterConstraint( + parameterType: JetType, + constrainingType: JetType, + boundKind: TypeBounds.BoundKind, + constraintPosition: ConstraintPosition ) { - // Here we are handling the case when T! gets a bound Foo (or Foo?) - // In this case, type parameter T is supposed to get the bound Foo! - // Example: - // val c: Collection = Collections.singleton(null : Foo?) - // Constraints for T are: - // Foo? <: T! - // Foo >: T! - // both Foo and Foo? transform to Foo! here - if (TypesPackage.isFlexible(parameterType)) { - CustomTypeVariable typeVariable = TypesPackage.getCustomTypeVariable(parameterType); - if (typeVariable != null) { - constrainingType = typeVariable.substitutionResult(constrainingType); - } - } - - TypeBoundsImpl typeBounds = getTypeBounds(parameterType); - assert typeBounds != null : "constraint should be generated only for type variables"; + val typeBounds = getTypeBounds(parameterType).sure("constraint should be generated only for type variables") if (!parameterType.isMarkedNullable() || !constrainingType.isMarkedNullable()) { - typeBounds.addBound(boundKind, constrainingType, constraintPosition); - return; + typeBounds.addBound(boundKind, constrainingType, constraintPosition) + return } // For parameter type T: // constraint T? = Int? should transform to T >: Int and T <: Int? // constraint T? >: Int? should transform to T >: Int - JetType notNullConstrainingType = TypeUtils.makeNotNullable(constrainingType); + val notNullConstrainingType = TypeUtils.makeNotNullable(constrainingType) if (boundKind == EXACT_BOUND || boundKind == LOWER_BOUND) { - typeBounds.addBound(LOWER_BOUND, notNullConstrainingType, constraintPosition); + typeBounds.addBound(LOWER_BOUND, notNullConstrainingType, constraintPosition) } // constraint T? <: Int? should transform to T <: Int? if (boundKind == EXACT_BOUND || boundKind == UPPER_BOUND) { - typeBounds.addBound(UPPER_BOUND, constrainingType, constraintPosition); + typeBounds.addBound(UPPER_BOUND, constrainingType, constraintPosition) } } - public void processDeclaredBoundConstraints() { - for (Map.Entry entry : typeParameterBounds.entrySet()) { - TypeParameterDescriptor typeParameterDescriptor = entry.getKey(); - TypeBoundsImpl typeBounds = entry.getValue(); - for (JetType declaredUpperBound : typeParameterDescriptor.getUpperBounds()) { + public fun processDeclaredBoundConstraints() { + for ((typeParameterDescriptor, typeBounds) in typeParameterBounds) { + for (declaredUpperBound in typeParameterDescriptor.getUpperBounds()) { //todo order matters here - Collection bounds = new ArrayList(typeBounds.getBounds()); - for (Bound bound : bounds) { + val bounds = ArrayList(typeBounds.bounds) + for (bound in bounds) { if (bound.kind == LOWER_BOUND || bound.kind == EXACT_BOUND) { - ConstraintPosition position = ConstraintPosition.getCompoundConstraintPosition( - ConstraintPosition.getTypeBoundPosition(typeParameterDescriptor.getIndex()), bound.position); - addSubtypeConstraint(bound.type, declaredUpperBound, position); + val position = ConstraintPosition.getCompoundConstraintPosition(ConstraintPosition.getTypeBoundPosition(typeParameterDescriptor.getIndex()), bound.position) + addSubtypeConstraint(bound.constrainingType, declaredUpperBound, position) } } - ClassifierDescriptor declarationDescriptor = declaredUpperBound.getConstructor().getDeclarationDescriptor(); - if (declarationDescriptor instanceof TypeParameterDescriptor && typeParameterBounds.containsKey(declarationDescriptor)) { - TypeBoundsImpl typeBoundsForUpperBound = typeParameterBounds.get(declarationDescriptor); - for (Bound bound : typeBoundsForUpperBound.getBounds()) { + val declarationDescriptor = declaredUpperBound.getConstructor().getDeclarationDescriptor() + if (declarationDescriptor is TypeParameterDescriptor && typeParameterBounds.containsKey(declarationDescriptor)) { + val typeBoundsForUpperBound = typeParameterBounds.get(declarationDescriptor) + for (bound in typeBoundsForUpperBound!!.bounds) { if (bound.kind == UPPER_BOUND || bound.kind == EXACT_BOUND) { - ConstraintPosition position = ConstraintPosition.getCompoundConstraintPosition( - ConstraintPosition.getTypeBoundPosition(typeParameterDescriptor.getIndex()), bound.position); - typeBounds.addBound(UPPER_BOUND, bound.type, position); + val position = ConstraintPosition.getCompoundConstraintPosition(ConstraintPosition.getTypeBoundPosition(typeParameterDescriptor.getIndex()), bound.position) + typeBounds.addBound(UPPER_BOUND, bound.constrainingType, position) } } } @@ -479,64 +352,47 @@ public class ConstraintSystemImpl implements ConstraintSystem { } } - @NotNull - @Override - public Set getTypeVariables() { - return typeParameterBounds.keySet(); + override fun getTypeVariables() = typeParameterBounds.keySet() + + override fun getTypeBounds(typeVariable: TypeParameterDescriptor): TypeBounds { + return typeParameterBounds.get(typeVariable).sure( + "TypeParameterDescriptor is not a type variable for constraint system: $typeVariable") } - @Override - @NotNull - public TypeBounds getTypeBounds(@NotNull TypeParameterDescriptor typeVariable) { - TypeBoundsImpl typeBounds = typeParameterBounds.get(typeVariable); - assert typeBounds != null : "TypeParameterDescriptor is not a type variable for constraint system: " + typeVariable; - return typeBounds; - } - - @Nullable - private TypeBoundsImpl getTypeBounds(@NotNull JetType type) { - ClassifierDescriptor parameterDescriptor = type.getConstructor().getDeclarationDescriptor(); - if (parameterDescriptor instanceof TypeParameterDescriptor) { - return typeParameterBounds.get(parameterDescriptor); + private fun getTypeBounds(type: JetType): TypeBoundsImpl? { + val parameterDescriptor = type.getConstructor().getDeclarationDescriptor() + if (parameterDescriptor is TypeParameterDescriptor) { + return typeParameterBounds.get(parameterDescriptor) } - return null; + return null } - private boolean isMyTypeVariable(@NotNull JetType type) { - ClassifierDescriptor descriptor = type.getConstructor().getDeclarationDescriptor(); - return descriptor instanceof TypeParameterDescriptor && typeParameterBounds.get(descriptor) != null; + private fun isMyTypeVariable(type: JetType): Boolean { + val descriptor = type.getConstructor().getDeclarationDescriptor() + return descriptor is TypeParameterDescriptor && typeParameterBounds.get(descriptor) != null } - @NotNull - @Override - public TypeSubstitutor getResultingSubstitutor() { - return replaceUninferredBySpecialErrorType(); - } + override fun getResultingSubstitutor() = replaceUninferredBySpecialErrorType() - @NotNull - @Override - public TypeSubstitutor getCurrentSubstitutor() { - return replaceUninferredBy(TypeUtils.DONT_CARE); - } + override fun getCurrentSubstitutor() = replaceUninferredBy(TypeUtils.DONT_CARE) - @NotNull - public static JetType createCorrespondingExtensionFunctionType(@NotNull JetType functionType, @NotNull JetType receiverType) { - assert KotlinBuiltIns.isFunctionType(functionType); + private fun createCorrespondingExtensionFunctionType(functionType: JetType, receiverType: JetType): JetType { + assert(KotlinBuiltIns.isFunctionType(functionType)) - List typeArguments = functionType.getArguments(); - assert !typeArguments.isEmpty(); + val typeArguments = functionType.getArguments() + assert(!typeArguments.isEmpty()) + val arguments = ArrayList() // excluding the last type argument of the function type, which is the return type - int index = 0; - int lastIndex = typeArguments.size() - 1; - List arguments = new ArrayList(lastIndex); - for (TypeProjection typeArgument : typeArguments) { + var index = 0 + val lastIndex = typeArguments.size() - 1 + for (typeArgument in typeArguments) { if (index < lastIndex) { - arguments.add(typeArgument.getType()); + arguments.add(typeArgument.getType()) } - index++; + index++ } - JetType returnType = typeArguments.get(lastIndex).getType(); - return KotlinBuiltIns.getInstance().getFunctionType(functionType.getAnnotations(), receiverType, arguments, returnType); + val returnType = typeArguments.get(lastIndex).getType() + return KotlinBuiltIns.getInstance().getFunctionType(functionType.getAnnotations(), receiverType, arguments, returnType) } -} +} \ No newline at end of file diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemStatus.kt b/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemStatus.kt index ae7877eaf02..9d8aa6ecdf0 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemStatus.kt +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintSystemStatus.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2013 JetBrains s.r.o. + * 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. @@ -14,24 +14,18 @@ * limitations under the License. */ -package org.jetbrains.jet.lang.resolve.calls.inference; +package org.jetbrains.jet.lang.resolve.calls.inference -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; -import org.jetbrains.jet.lang.types.JetType; -import org.jetbrains.jet.lang.types.TypeSubstitutor; - -public interface ConstraintSystemStatus { +public trait ConstraintSystemStatus { /** * Returns true if constraint system has a solution (has no contradiction and has enough information to infer each registered type variable). */ - boolean isSuccessful(); + public fun isSuccessful(): Boolean /** * Return true if constraint system has no contradiction (it can be not successful because of the lack of information for a type variable). */ - boolean hasContradiction(); + public fun hasContradiction(): Boolean /** * Returns true if type constraints for some type variable are contradicting.

@@ -41,7 +35,7 @@ public interface ConstraintSystemStatus { * - "R is a supertype of Int"

* - "List<R> is a supertype of List<String>" which leads to "R is equal to String" */ - boolean hasConflictingConstraints(); + public fun hasConflictingConstraints(): Boolean /** * Returns true if contradiction of type constraints comes from declared bounds for type parameters. @@ -51,7 +45,7 @@ public interface ConstraintSystemStatus { * * It's the special case of 'hasConflictingConstraints' case. */ - boolean hasViolatedUpperBound(); + public fun hasViolatedUpperBound(): Boolean /** * Returns true if there is no information for some registered type variable. @@ -59,7 +53,7 @@ public interface ConstraintSystemStatus { * For example, for

fun <E> newList()
in invocation "val nl = newList()" * there is no information to infer type variable E. */ - boolean hasUnknownParameters(); + public fun hasUnknownParameters(): Boolean /** * Returns true if some constraint cannot be processed because of type constructor mismatch. @@ -67,7 +61,7 @@ public interface ConstraintSystemStatus { * For example, for
fun <R> foo(t: List<R>) {}
in invocation foo(hashSet("s")) * there is type constructor mismatch: "HashSet<String> cannot be a subtype of List<R>". */ - boolean hasTypeConstructorMismatch(); + public fun hasTypeConstructorMismatch(): Boolean /** * Returns true if there is type constructor mismatch error at a specific {@code constraintPosition}. @@ -76,17 +70,17 @@ public interface ConstraintSystemStatus { * there is type constructor mismatch: "HashSet<String> cannot be a subtype of List<R>" * at a constraint position {@code ConstraintPosition.getValueParameterPosition(0)}. */ - boolean hasTypeConstructorMismatchAt(@NotNull ConstraintPosition constraintPosition); + public fun hasTypeConstructorMismatchAt(constraintPosition: ConstraintPosition): Boolean /** * Returns true if there is type constructor mismatch only in constraintPosition or * constraint system is successful without constraints from this position. */ - boolean hasOnlyErrorsFromPosition(ConstraintPosition constraintPosition); + public fun hasOnlyErrorsFromPosition(constraintPosition: ConstraintPosition): Boolean /** * Returns true if there is an error in constraining types.

* Is used not to generate type inference error if there was one in argument types. */ - boolean hasErrorInConstrainingTypes(); -} + public fun hasErrorInConstrainingTypes(): Boolean +} \ No newline at end of file diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/TypeBounds.kt b/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/TypeBounds.kt index e9b67f24a87..79bb7ed6f87 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/TypeBounds.kt +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/TypeBounds.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2013 JetBrains s.r.o. + * 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. @@ -14,47 +14,30 @@ * limitations under the License. */ -package org.jetbrains.jet.lang.resolve.calls.inference; +package org.jetbrains.jet.lang.resolve.calls.inference -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; -import org.jetbrains.jet.lang.types.JetType; -import org.jetbrains.jet.lang.types.Variance; +import org.jetbrains.jet.lang.types.Variance +import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor +import org.jetbrains.jet.lang.types.JetType -import java.util.Collection; +public trait TypeBounds { + public val varianceOfPosition: Variance -public interface TypeBounds { - @NotNull - Variance getVarianceOfPosition(); + public val typeVariable: TypeParameterDescriptor - @NotNull - TypeParameterDescriptor getTypeVariable(); + public val bounds: Collection - @NotNull - Collection getBounds(); + public fun isEmpty(): Boolean - boolean isEmpty(); + public fun getValue(): JetType? - @Nullable - JetType getValue(); + public fun getValues(): Collection - @NotNull - Collection getValues(); - - enum BoundKind { - LOWER_BOUND, UPPER_BOUND, EXACT_BOUND + public enum class BoundKind { + LOWER_BOUND + UPPER_BOUND + EXACT_BOUND } - class Bound { - public final JetType type; - public final BoundKind kind; - public final ConstraintPosition position; - - public Bound(@NotNull JetType type, @NotNull BoundKind kind, @NotNull ConstraintPosition position) { - this.type = type; - this.kind = kind; - this.position = position; - } - } -} + public class Bound(public val constrainingType: JetType, public val kind: BoundKind, public val position: ConstraintPosition) +} \ No newline at end of file diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/TypeBoundsImpl.kt b/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/TypeBoundsImpl.kt index 57a3580048a..7c171b5e4fc 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/TypeBoundsImpl.kt +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/calls/inference/TypeBoundsImpl.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2013 JetBrains s.r.o. + * 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. @@ -14,238 +14,163 @@ * limitations under the License. */ -package org.jetbrains.jet.lang.resolve.calls.inference; +package org.jetbrains.jet.lang.resolve.calls.inference -import kotlin.Function1; -import kotlin.KotlinPackage; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; -import org.jetbrains.jet.lang.resolve.constants.IntegerValueTypeConstructor; -import org.jetbrains.jet.lang.types.*; -import org.jetbrains.jet.lang.types.checker.JetTypeChecker; -import org.jetbrains.jet.utils.UtilsPackage; +import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor +import org.jetbrains.jet.lang.types.Variance +import org.jetbrains.jet.lang.resolve.calls.inference.TypeBounds.Bound +import org.jetbrains.jet.lang.types.JetType +import org.jetbrains.jet.lang.resolve.calls.inference.TypeBounds.BoundKind +import org.jetbrains.jet.lang.types.ErrorUtils +import org.jetbrains.jet.lang.types.CommonSupertypes +import org.jetbrains.jet.lang.types.TypeUtils +import org.jetbrains.jet.lang.types.checker.JetTypeChecker +import org.jetbrains.jet.lang.resolve.constants.IntegerValueTypeConstructor +import java.util.LinkedHashSet +import org.jetbrains.jet.lang.resolve.calls.inference.TypeBounds.BoundKind.* +import org.jetbrains.jet.utils.addIfNotNull -import java.util.*; +public class TypeBoundsImpl( + override val typeVariable: TypeParameterDescriptor, + override val varianceOfPosition: Variance +) : TypeBounds { + override val bounds = LinkedHashSet() -import static org.jetbrains.jet.lang.resolve.calls.inference.TypeBounds.BoundKind.LOWER_BOUND; + private var resultValues: Collection? = null -public class TypeBoundsImpl implements TypeBounds { - private final TypeParameterDescriptor typeVariable; - private final Variance varianceOfPosition; - private final Set bounds = new LinkedHashSet(); - - private Collection resultValues; - - public TypeBoundsImpl( - @NotNull TypeParameterDescriptor typeVariable, - @NotNull Variance varianceOfPosition - ) { - this.typeVariable = typeVariable; - this.varianceOfPosition = varianceOfPosition; + public fun addBound(kind: BoundKind, constrainingType: JetType, position: ConstraintPosition) { + resultValues = null + bounds.add(Bound(constrainingType, kind, position)) } - @NotNull - @Override - public Variance getVarianceOfPosition() { - return varianceOfPosition; + override fun isEmpty(): Boolean { + return getValues().isEmpty() } - public void addBound(@NotNull BoundKind kind, @NotNull JetType type, @NotNull ConstraintPosition position) { - resultValues = null; - bounds.add(new Bound(type, kind, position)); + private fun filterBounds(bounds: Collection, kind: BoundKind): Set { + return filterBounds(bounds, kind, null) } - @Override - public boolean isEmpty() { - return getValues().isEmpty(); - } - - @NotNull - @Override - public TypeParameterDescriptor getTypeVariable() { - return typeVariable; - } - - @Override - @NotNull - public Collection getBounds() { - return bounds; - } - - @NotNull - private static Set filterBounds( - @NotNull Collection bounds, - @NotNull BoundKind kind - ) { - return filterBounds(bounds, kind, null); - } - - @NotNull - private static Set filterBounds( - @NotNull Collection bounds, - @NotNull BoundKind kind, - @Nullable Collection errorValues - ) { - Set result = new LinkedHashSet(); - for (Bound bound : bounds) { + private fun filterBounds(bounds: Collection, kind: BoundKind, errorValues: MutableCollection?): Set { + val result = LinkedHashSet() + for (bound in bounds) { if (bound.kind == kind) { - if (!ErrorUtils.containsErrorType(bound.type)) { - result.add(bound.type); + if (!ErrorUtils.containsErrorType(bound.constrainingType)) { + result.add(bound.constrainingType) } - else if (errorValues != null) { - errorValues.add(bound.type); + else { + errorValues?.add(bound.constrainingType) } } } - return result; + return result } - /*package*/ TypeBoundsImpl copy() { - TypeBoundsImpl typeBounds = new TypeBoundsImpl(typeVariable, varianceOfPosition); - typeBounds.bounds.addAll(bounds); - typeBounds.resultValues = resultValues; - return typeBounds; + fun copy(): TypeBoundsImpl { + val typeBounds = TypeBoundsImpl(typeVariable, varianceOfPosition) + typeBounds.bounds.addAll(bounds) + typeBounds.resultValues = resultValues + return typeBounds } - @NotNull - public TypeBoundsImpl filter(@NotNull final Function1 condition) { - TypeBoundsImpl result = new TypeBoundsImpl(typeVariable, varianceOfPosition); - result.bounds.addAll(KotlinPackage.filter(bounds, new Function1() { - @Override - public Boolean invoke(Bound bound) { - return condition.invoke(bound.position); - } - })); - return result; + public fun filter(condition: (ConstraintPosition) -> Boolean): TypeBoundsImpl { + val result = TypeBoundsImpl(typeVariable, varianceOfPosition) + result.bounds.addAll(bounds.filter { condition(it.position) }) + return result } - @Nullable - @Override - public JetType getValue() { - Collection values = getValues(); + override fun getValue(): JetType? { + val values = getValues() if (values.size() == 1) { - return values.iterator().next(); + return values.iterator().next() } - return null; + return null } - @NotNull - @Override - public Collection getValues() { + override fun getValues(): Collection { if (resultValues == null) { - resultValues = computeValues(); + resultValues = computeValues() } - return resultValues; + return resultValues!! } - @NotNull - private Collection computeValues() { - Set values = new LinkedHashSet(); + private fun computeValues(): Collection { + val values = LinkedHashSet() if (bounds.isEmpty()) { - return Collections.emptyList(); + return listOf() } - boolean hasStrongBound = KotlinPackage.any(bounds, new Function1() { - @Override - public Boolean invoke(Bound bound) { - return bound.position.isStrong(); - } - }); + val hasStrongBound = bounds.any { it.position.isStrong() } if (!hasStrongBound) { - return Collections.emptyList(); + return listOf() } - Set exactBounds = filterBounds(bounds, BoundKind.EXACT_BOUND, values); - JetType bestFit = TypesPackage.singleBestRepresentative(exactBounds); - if (bestFit != null) { - if (tryPossibleAnswer(bestFit)) { - return Collections.singleton(bestFit); + val exactBounds = filterBounds(bounds, EXACT_BOUND, values) + if (exactBounds.size() == 1) { + val exactBound = exactBounds.iterator().next() + if (tryPossibleAnswer(exactBound)) { + return setOf(exactBound) } } - values.addAll(exactBounds); + values.addAll(exactBounds) - Collection numberLowerBounds = new LinkedHashSet(); - Collection generalLowerBounds = new LinkedHashSet(); - filterNumberTypes(filterBounds(bounds, LOWER_BOUND, values), numberLowerBounds, generalLowerBounds); + val (numberLowerBounds, generalLowerBounds) = + filterBounds(bounds, LOWER_BOUND, values).partition { it.getConstructor() is IntegerValueTypeConstructor } - JetType superTypeOfLowerBounds = CommonSupertypes.commonSupertypeForNonDenotableTypes(generalLowerBounds); + val superTypeOfLowerBounds = CommonSupertypes.commonSupertypeForNonDenotableTypes(generalLowerBounds) if (tryPossibleAnswer(superTypeOfLowerBounds)) { - return Collections.singleton(superTypeOfLowerBounds); + return setOf(superTypeOfLowerBounds!!) } - UtilsPackage.addIfNotNull(values, superTypeOfLowerBounds); + values.addIfNotNull(superTypeOfLowerBounds) //todo //fun foo(t: T, consumer: Consumer): T //foo(1, c: Consumer) - infer Int, not Any here - JetType superTypeOfNumberLowerBounds = TypeUtils.commonSupertypeForNumberTypes(numberLowerBounds); + val superTypeOfNumberLowerBounds = TypeUtils.commonSupertypeForNumberTypes(numberLowerBounds) if (tryPossibleAnswer(superTypeOfNumberLowerBounds)) { - return Collections.singleton(superTypeOfNumberLowerBounds); + return setOf(superTypeOfNumberLowerBounds!!) } - UtilsPackage.addIfNotNull(values, superTypeOfNumberLowerBounds); + values.addIfNotNull(superTypeOfNumberLowerBounds) if (superTypeOfLowerBounds != null && superTypeOfNumberLowerBounds != null) { - JetType superTypeOfAllLowerBounds = CommonSupertypes.commonSupertypeForNonDenotableTypes( - Arrays.asList(superTypeOfLowerBounds, superTypeOfNumberLowerBounds) - ); + val superTypeOfAllLowerBounds = CommonSupertypes.commonSupertypeForNonDenotableTypes(listOf(superTypeOfLowerBounds, superTypeOfNumberLowerBounds)) if (tryPossibleAnswer(superTypeOfAllLowerBounds)) { - return Collections.singleton(superTypeOfAllLowerBounds); + return setOf(superTypeOfAllLowerBounds!!) } } - Set upperBounds = filterBounds(bounds, BoundKind.UPPER_BOUND, values); - JetType intersectionOfUpperBounds = TypeUtils.intersect(JetTypeChecker.DEFAULT, upperBounds); + val upperBounds = filterBounds(bounds, TypeBounds.BoundKind.UPPER_BOUND, values) + val intersectionOfUpperBounds = TypeUtils.intersect(JetTypeChecker.DEFAULT, upperBounds) if (!upperBounds.isEmpty() && intersectionOfUpperBounds != null) { if (tryPossibleAnswer(intersectionOfUpperBounds)) { - return Collections.singleton(intersectionOfUpperBounds); + return setOf(intersectionOfUpperBounds) } } - values.addAll(filterBounds(bounds, BoundKind.UPPER_BOUND)); + values.addAll(filterBounds(bounds, TypeBounds.BoundKind.UPPER_BOUND)) - return values; + return values } - private static void filterNumberTypes( - @NotNull Collection types, - @NotNull Collection numberTypes, - @NotNull Collection otherTypes - ) { - for (JetType type : types) { - if (type.getConstructor() instanceof IntegerValueTypeConstructor) { - numberTypes.add(type); - } - else { - otherTypes.add(type); + private fun tryPossibleAnswer(possibleAnswer: JetType?): Boolean { + if (possibleAnswer == null) return false + if (!possibleAnswer.getConstructor().isDenotable()) return false + + for (bound in bounds) { + when (bound.kind) { + LOWER_BOUND -> if (!JetTypeChecker.DEFAULT.isSubtypeOf(bound.constrainingType, possibleAnswer)) { + return false + } + + UPPER_BOUND -> if (!JetTypeChecker.DEFAULT.isSubtypeOf(possibleAnswer, bound.constrainingType)) { + return false + } + + EXACT_BOUND -> if (!JetTypeChecker.DEFAULT.equalTypes(bound.constrainingType, possibleAnswer)) { + return false + } } } + return true } - - private boolean tryPossibleAnswer(@Nullable JetType possibleAnswer) { - if (possibleAnswer == null) return false; - if (!possibleAnswer.getConstructor().isDenotable()) return false; - - for (Bound bound : bounds) { - switch (bound.kind) { - case LOWER_BOUND: - if (!JetTypeChecker.DEFAULT.isSubtypeOf(bound.type, possibleAnswer)) { - return false; - } - break; - - case UPPER_BOUND: - if (!JetTypeChecker.DEFAULT.isSubtypeOf(possibleAnswer, bound.type)) { - return false; - } - break; - - case EXACT_BOUND: - if (!JetTypeChecker.DEFAULT.equalTypes(bound.type, possibleAnswer)) { - return false; - } - break; - } - } - return true; - } -} +} \ No newline at end of file diff --git a/core/descriptors/src/org/jetbrains/jet/lang/types/TypeUtils.java b/core/descriptors/src/org/jetbrains/jet/lang/types/TypeUtils.java index eb13dfca91a..cfd2c3389fb 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/types/TypeUtils.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/types/TypeUtils.java @@ -711,6 +711,7 @@ public class TypeUtils { }); } + @NotNull public static TypeSubstitutor makeSubstitutorForTypeParametersMap( @NotNull final Map substitutionContext ) {