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:
@@ -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");
|
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")
|
@TestMetadata("upperBoundsSubstitutionForOverloadResolutionWithAmbiguity.kt")
|
||||||
public void testUpperBoundsSubstitutionForOverloadResolutionWithAmbiguity() throws Exception {
|
public void testUpperBoundsSubstitutionForOverloadResolutionWithAmbiguity() throws Exception {
|
||||||
doTest("compiler/testData/diagnostics/tests/substitutions/upperBoundsSubstitutionForOverloadResolutionWithAmbiguity.kt");
|
doTest("compiler/testData/diagnostics/tests/substitutions/upperBoundsSubstitutionForOverloadResolutionWithAmbiguity.kt");
|
||||||
|
|||||||
+1
-4
@@ -116,10 +116,7 @@ public abstract class AbstractClassDescriptor implements ClassDescriptor {
|
|||||||
List<TypeParameterDescriptor> typeParameters = getTypeConstructor().getParameters();
|
List<TypeParameterDescriptor> typeParameters = getTypeConstructor().getParameters();
|
||||||
Map<TypeConstructor, TypeProjection> substitutionContext = TypeSubstitutor.buildSubstitutionContext(typeParameters, typeArguments);
|
Map<TypeConstructor, TypeProjection> substitutionContext = TypeSubstitutor.buildSubstitutionContext(typeParameters, typeArguments);
|
||||||
|
|
||||||
// Unsafe substitutor is OK, because no recursion can hurt us upon a trivial substitution:
|
TypeSubstitutor substitutor = TypeSubstitutor.create(substitutionContext);
|
||||||
// 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);
|
|
||||||
return new SubstitutingScope(getScopeForMemberLookup(), substitutor);
|
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 org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@@ -72,14 +71,8 @@ public class TypeSubstitutor {
|
|||||||
return create(new CompositeTypeSubstitution(substitutions));
|
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) {
|
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) {
|
public static TypeSubstitutor create(@NotNull JetType context) {
|
||||||
@@ -226,22 +219,6 @@ public class TypeSubstitutor {
|
|||||||
return substitutedArguments;
|
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) {
|
private static Variance combine(Variance typeParameterVariance, Variance projectionKind) {
|
||||||
if (typeParameterVariance == Variance.INVARIANT) return projectionKind;
|
if (typeParameterVariance == Variance.INVARIANT) return projectionKind;
|
||||||
if (projectionKind == Variance.INVARIANT) return typeParameterVariance;
|
if (projectionKind == Variance.INVARIANT) return typeParameterVariance;
|
||||||
|
|||||||
Reference in New Issue
Block a user