001/*
002 * Copyright 2010-2013 JetBrains s.r.o.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.jetbrains.jet.lang.resolve.calls.inference;
018
019import org.jetbrains.annotations.NotNull;
020import org.jetbrains.annotations.Nullable;
021import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
022import org.jetbrains.jet.lang.types.JetType;
023import org.jetbrains.jet.lang.types.TypeSubstitutor;
024import org.jetbrains.jet.lang.types.Variance;
025
026import java.util.Set;
027
028public interface ConstraintSystem {
029
030    /**
031     * Registers a variable in a constraint system.
032     */
033    void registerTypeVariable(@NotNull TypeParameterDescriptor typeVariable, @NotNull Variance positionVariance);
034
035    /**
036     * Returns a set of all registered type variables.
037     */
038    @NotNull
039    Set<TypeParameterDescriptor> getTypeVariables();
040
041    /**
042     * Adds a constraint that the constraining type is a subtype of the subject type.<p/>
043     * Asserts that only subject type may contain registered type variables. <p/>
044     *
045     * For example, for {@code "fun <T> id(t: T) {}"} to infer <tt>T</tt> in invocation <tt>"id(1)"</tt>
046     * should be generated a constraint <tt>"Int is a subtype of T"</tt> where T is a subject type, and Int is a constraining type.
047     */
048    void addSubtypeConstraint(@Nullable JetType constrainingType, @NotNull JetType subjectType, @NotNull ConstraintPosition constraintPosition);
049
050    /**
051     * Adds a constraint that the constraining type is a supertype of the subject type. <p/>
052     * Asserts that only subject type may contain registered type variables. <p/>
053     *
054     * For example, for {@code "fun <T> create() : T"} to infer <tt>T</tt> in invocation <tt>"val i: Int = create()"</tt>
055     * should be generated a constraint <tt>"Int is a supertype of T"</tt> where T is a subject type, and Int is a constraining type.
056     */
057    void addSupertypeConstraint(@Nullable JetType constrainingType, @NotNull JetType subjectType, @NotNull ConstraintPosition constraintPosition);
058
059    /**
060     * Returns <tt>true</tt> if constraint system has a solution (has no contradiction and has enough information to infer each registered type variable).
061     */
062    boolean isSuccessful();
063
064    /**
065     * Return <tt>true</tt> if constraint system has no contradiction (it can be not successful because of the lack of information for a type variable).
066     */
067    boolean hasContradiction();
068
069    /**
070     * Returns <tt>true</tt> if type constraints for some type variable are contradicting. <p/>
071     *
072     * For example, for <pre>fun &lt;R&gt; foo(r: R, t: java.util.List&lt;R&gt;) {}</pre> in invocation <tt>foo(1, arrayList("s"))</tt>
073     * type variable <tt>R</tt> has two conflicting constraints: <p/>
074     * - <tt>"R is a supertype of Int"</tt> <p/>
075     * - <tt>"List&lt;R&gt; is a supertype of List&lt;String&gt;"</tt> which leads to <tt>"R is equal to String"</tt>
076     */
077    boolean hasConflictingConstraints();
078
079    /**
080     * Returns <tt>true</tt> if there is no information for some registered type variable.
081     *
082     * For example, for <pre>fun &lt;E&gt; newList()</pre> in invocation <tt>"val nl = newList()"</tt>
083     * there is no information to infer type variable <tt>E</tt>.
084     */
085    boolean hasUnknownParameters();
086
087    /**
088     * Returns <tt>true</tt> if some constraint cannot be processed because of type constructor mismatch.
089     *
090     * For example, for <pre>fun &lt;R&gt; foo(t: List&lt;R&gt;) {}</pre> in invocation <tt>foo(hashSet("s"))</tt>
091     * there is type constructor mismatch: <tt>"HashSet&lt;String&gt; cannot be a subtype of List&lt;R&gt;"</tt>.
092     */
093    boolean hasTypeConstructorMismatch();
094
095    /**
096     * Returns <tt>true</tt> if there is type constructor mismatch error at a specific {@code constraintPosition}.
097     *
098     * For example, for <pre>fun &lt;R&gt; foo(t: List&lt;R&gt;) {}</pre> in invocation <tt>foo(hashSet("s"))</tt>
099     * there is type constructor mismatch: <tt>"HashSet&lt;String&gt; cannot be a subtype of List&lt;R&gt;"</tt>
100     * at a constraint position {@code ConstraintPosition.getValueParameterPosition(0)}.
101     */
102    boolean hasTypeConstructorMismatchAt(@NotNull ConstraintPosition constraintPosition);
103
104    /**
105     * Returns <tt>true</tt> if there is type constructor mismatch only in {@link ConstraintPosition.EXPECTED_TYPE_POSITION}.
106     */
107    boolean hasOnlyExpectedTypeMismatch();
108
109    /**
110     * Returns <tt>true</tt> if there is an error in constraining types. <p/>
111     * Is used not to generate type inference error if there was one in argument types.
112     */
113    boolean hasErrorInConstrainingTypes();
114
115    /**
116     * Returns the resulting type constraints of solving the constraint system for specific type variable. <p/>
117     * Returns null if the type variable was not registered.
118     */
119    @Nullable
120    TypeConstraints getTypeConstraints(@NotNull TypeParameterDescriptor typeVariable);
121
122    /**
123     * Returns a result of solving the constraint system (mapping from the type variable to the resulting type projection). <p/>
124     * In the resulting substitution should be concerned: <p/>
125     * - type constraints <p/>
126     * - variance of the type variable  // not implemented yet <p/>
127     * - type parameter bounds (that can bind type variables with each other). // not implemented yet
128     * If the addition of the 'expected type' constraint made the system fail,
129     * this constraint is not included in the resulting substitution.
130     */
131    @NotNull
132    TypeSubstitutor getResultingSubstitutor();
133
134    /**
135     * Returns a current result of solving the constraint system (mapping from the type variable to the resulting type projection).
136     * If there is no information for type parameter, returns type projection for DONT_CARE type.
137     */
138    @NotNull
139    TypeSubstitutor getCurrentSubstitutor();
140
141    ConstraintSystem copy();
142}