KT-4198 On covariant projection, do not throw whole var's away

#KT-4198 Fixed
This commit is contained in:
Andrey Breslav
2013-11-16 19:38:45 +04:00
parent 3fe55c997f
commit 38b38e7b6d
11 changed files with 123 additions and 4 deletions
@@ -443,6 +443,7 @@ public interface Errors {
DiagnosticFactory0<JetFunctionLiteralExpression> UNUSED_FUNCTION_LITERAL = DiagnosticFactory0.create(WARNING);
DiagnosticFactory1<JetExpression, DeclarationDescriptor> VAL_REASSIGNMENT = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<JetExpression, DeclarationDescriptor> SETTER_PROJECTED_OUT = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<JetExpression, DeclarationDescriptor> INITIALIZATION_BEFORE_DECLARATION = DiagnosticFactory1.create(ERROR);
@@ -175,6 +175,7 @@ public class DefaultErrorMessages {
MAP.put(UNUSED_FUNCTION_LITERAL, "The function literal is unused. If you mean block, you can use 'run { ... }'");
MAP.put(VAL_REASSIGNMENT, "Val cannot be reassigned", NAME);
MAP.put(SETTER_PROJECTED_OUT, "Setter for ''{0}'' is removed by type projection", NAME);
MAP.put(INVISIBLE_SETTER, "Cannot assign to ''{0}'': the setter is ''{1}'' in ''{2}''", NAME, TO_STRING, NAME);
MAP.put(INITIALIZATION_BEFORE_DECLARATION, "Variable cannot be initialized before declaration", NAME);
MAP.put(VARIABLE_EXPECTED, "Variable expected");
@@ -758,8 +758,17 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
}
if (canBeThis && expression instanceof JetThisExpression) return;
VariableDescriptor variable = BindingContextUtils.extractVariableDescriptorIfAny(trace.getBindingContext(), expression, true);
JetExpression reportOn = expression != null ? expression : expressionWithParenthesis;
if (variable instanceof PropertyDescriptor) {
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) variable;
if (propertyDescriptor.isSetterProjectedOut()) {
trace.report(SETTER_PROJECTED_OUT.on(reportOn, propertyDescriptor));
}
}
if (variable == null) {
trace.report(VARIABLE_EXPECTED.on(expression != null ? expression : expressionWithParenthesis));
trace.report(VARIABLE_EXPECTED.on(reportOn));
}
}
@@ -0,0 +1,11 @@
trait Tr<T> {
var v: Tr<T>
}
fun test(t: Tr<*>) {
t.v = t
val v = TypeOf(t.v)
v: TypeOf<Tr<*>>
}
class TypeOf<T>(t: T)
@@ -0,0 +1,11 @@
trait Tr<T> {
var v: T
}
fun test(t: Tr<*>) {
<!SETTER_PROJECTED_OUT!>t.v<!> = null!!
val v = TypeOf(t.v)
v: TypeOf<Any?>
}
class TypeOf<T>(t: T)
@@ -0,0 +1,7 @@
trait Tr<T> {
var v: T
}
fun test(t: Tr<out String>) {
<!SETTER_PROJECTED_OUT!>t.v<!> += null!!
}
@@ -0,0 +1,12 @@
trait Tr<T> {
var v: T
}
class C {
fun plusAssign(<!UNUSED_PARAMETER!>c<!>: C) {}
}
fun test(t: Tr<out C>) {
// No error because no real assignment happens
t.v += null!!
}
@@ -2860,7 +2860,7 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
}
@TestMetadata("compiler/testData/diagnostics/tests/generics")
@InnerTestClasses({Generics.TpAsReified.class})
@InnerTestClasses({Generics.TpAsReified.class, Generics.VarProjection.class})
public static class Generics extends AbstractDiagnosticsTestWithEagerResolve {
public void testAllFilesPresentInGenerics() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/diagnostics/tests/generics"), Pattern.compile("^(.+)\\.kt$"), true);
@@ -2949,10 +2949,39 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
}
@TestMetadata("compiler/testData/diagnostics/tests/generics/varProjection")
public static class VarProjection extends AbstractDiagnosticsTestWithEagerResolve {
public void testAllFilesPresentInVarProjection() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/diagnostics/tests/generics/varProjection"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("setterNotProjectedOutAssign.kt")
public void testSetterNotProjectedOutAssign() throws Exception {
doTest("compiler/testData/diagnostics/tests/generics/varProjection/setterNotProjectedOutAssign.kt");
}
@TestMetadata("setterProjectedOutAssign.kt")
public void testSetterProjectedOutAssign() throws Exception {
doTest("compiler/testData/diagnostics/tests/generics/varProjection/setterProjectedOutAssign.kt");
}
@TestMetadata("setterProjectedOutNoPlusAssign.kt")
public void testSetterProjectedOutNoPlusAssign() throws Exception {
doTest("compiler/testData/diagnostics/tests/generics/varProjection/setterProjectedOutNoPlusAssign.kt");
}
@TestMetadata("setterProjectedOutPlusAssignDefined.kt")
public void testSetterProjectedOutPlusAssignDefined() throws Exception {
doTest("compiler/testData/diagnostics/tests/generics/varProjection/setterProjectedOutPlusAssignDefined.kt");
}
}
public static Test innerSuite() {
TestSuite suite = new TestSuite("Generics");
suite.addTestSuite(Generics.class);
suite.addTestSuite(TpAsReified.class);
suite.addTestSuite(VarProjection.class);
return suite;
}
}