Do not remove trivial substitutions

to avoid substituting a new type parameter by default instead of leaving the same
 #KT-4887 Fixed
This commit is contained in:
Svetlana Isakova
2014-04-28 10:03:53 +04:00
parent 808cf75060
commit 775606f80a
4 changed files with 15 additions and 28 deletions
@@ -0,0 +1,8 @@
package h
public class MyClass<S, T>(param: MyClass<S, T>) {
fun test() {
val result: MyClass<Any, Any>? = null
MyClass<S, Any>(result <!CAST_NEVER_SUCCEEDS!>as<!> MyClass<S, Any>)
}
}
@@ -6773,6 +6773,11 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
doTest("compiler/testData/diagnostics/tests/substitutions/kt1558-short.kt");
}
@TestMetadata("kt4887.kt")
public void testKt4887() throws Exception {
doTest("compiler/testData/diagnostics/tests/substitutions/kt4887.kt");
}
@TestMetadata("upperBoundsSubstitutionForOverloadResolutionWithAmbiguity.kt")
public void testUpperBoundsSubstitutionForOverloadResolutionWithAmbiguity() throws Exception {
doTest("compiler/testData/diagnostics/tests/substitutions/upperBoundsSubstitutionForOverloadResolutionWithAmbiguity.kt");
@@ -116,10 +116,7 @@ public abstract class AbstractClassDescriptor implements ClassDescriptor {
List<TypeParameterDescriptor> typeParameters = getTypeConstructor().getParameters();
Map<TypeConstructor, TypeProjection> substitutionContext = TypeSubstitutor.buildSubstitutionContext(typeParameters, typeArguments);
// Unsafe substitutor is OK, because no recursion can hurt us upon a trivial substitution:
// all the types are written explicitly in the code already, they can not get infinite.
// One exception is *-projections, but they need to be handled separately anyways.
TypeSubstitutor substitutor = TypeSubstitutor.createUnsafe(substitutionContext);
TypeSubstitutor substitutor = TypeSubstitutor.create(substitutionContext);
return new SubstitutingScope(getScopeForMemberLookup(), substitutor);
}
@@ -25,7 +25,6 @@ import org.jetbrains.jet.lang.resolve.scopes.SubstitutingScope;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -72,14 +71,8 @@ public class TypeSubstitutor {
return create(new CompositeTypeSubstitution(substitutions));
}
/** No assertion for immediate recursion */
public static TypeSubstitutor createUnsafe(@NotNull Map<TypeConstructor, TypeProjection> substitutionContext) {
Map<TypeConstructor, TypeProjection> cleanContext = removeTrivialSubstitutions(substitutionContext);
return create(new MapToTypeSubstitutionAdapter(cleanContext));
}
public static TypeSubstitutor create(@NotNull Map<TypeConstructor, TypeProjection> substitutionContext) {
return createUnsafe(removeTrivialSubstitutions(substitutionContext));
return create(new MapToTypeSubstitutionAdapter(substitutionContext));
}
public static TypeSubstitutor create(@NotNull JetType context) {
@@ -226,22 +219,6 @@ public class TypeSubstitutor {
return substitutedArguments;
}
@NotNull
private static Map<TypeConstructor, TypeProjection> removeTrivialSubstitutions(@NotNull Map<TypeConstructor, TypeProjection> context) {
Map<TypeConstructor, TypeProjection> clean = new HashMap<TypeConstructor, TypeProjection>(context);
boolean changed = false;
for (Iterator<Map.Entry<TypeConstructor, TypeProjection>> iterator = clean.entrySet().iterator(); iterator.hasNext(); ) {
Map.Entry<TypeConstructor, TypeProjection> entry = iterator.next();
TypeConstructor key = entry.getKey();
TypeProjection value = entry.getValue();
if (key == value.getType().getConstructor() && value.getProjectionKind() == Variance.INVARIANT) {
iterator.remove();
changed = true;
}
}
return changed ? clean : context;
}
private static Variance combine(Variance typeParameterVariance, Variance projectionKind) {
if (typeParameterVariance == Variance.INVARIANT) return projectionKind;
if (projectionKind == Variance.INVARIANT) return typeParameterVariance;