check Nothing type for all expressions not only for calls and simple names

(but excluding statement expressions)
This commit is contained in:
svtk
2013-11-19 13:10:39 +04:00
parent 36ce8f24b3
commit c1ec8cbde9
7 changed files with 57 additions and 29 deletions
@@ -69,14 +69,14 @@ public class JetControlFlowProcessor {
JetDeclarationWithBody declarationWithBody = (JetDeclarationWithBody) subroutine;
List<JetParameter> valueParameters = declarationWithBody.getValueParameters();
for (JetParameter valueParameter : valueParameters) {
valueParameter.accept(cfpVisitor);
cfpVisitor.generateInstructions(valueParameter);
}
JetExpression bodyExpression = declarationWithBody.getBodyExpression();
if (bodyExpression != null) {
bodyExpression.accept(cfpVisitor);
cfpVisitor.generateInstructions(bodyExpression);
}
} else {
subroutine.accept(cfpVisitor);
cfpVisitor.generateInstructions(subroutine);
}
return builder.exitSubroutine(subroutine);
}
@@ -115,18 +115,15 @@ public class JetControlFlowProcessor {
throw new UnsupportedOperationException("[JetControlFlowProcessor] " + element.toString());
}
};
private final JetVisitorVoid patternVisitor = new JetVisitorVoid() {
@Override
public void visitJetElement(@NotNull JetElement element) {
throw new UnsupportedOperationException("[JetControlFlowProcessor] " + element.toString());
}
};
private CFPVisitor(boolean inCondition) {
this.inCondition = inCondition;
}
public void generateInstructions(@Nullable JetElement element) {
generateInstructions(element, inCondition);
}
private void generateInstructions(@Nullable JetElement element, boolean inCondition) {
if (element == null) return;
CFPVisitor visitor;
@@ -137,6 +134,22 @@ public class JetControlFlowProcessor {
visitor = new CFPVisitor(inCondition);
}
element.accept(visitor);
checkNothingType(element);
}
private void checkNothingType(JetElement element) {
if (!(element instanceof JetExpression)) return;
JetExpression expression = JetPsiUtil.deparenthesize((JetExpression) element);
if (expression instanceof JetStatementExpression || expression instanceof JetTryExpression
|| expression instanceof JetThrowExpression || expression instanceof JetFinallySection
|| expression instanceof JetIfExpression || expression instanceof JetWhenExpression) return;
//noinspection ConstantConditions
if (!trace.get(BindingContext.PROCESSED, expression)) return;
JetType type = trace.getBindingContext().get(BindingContext.EXPRESSION_TYPE, expression);
if (type != null && KotlinBuiltIns.getInstance().isNothing(type)) {
builder.jumpToError();
}
}
@Override
@@ -172,12 +185,6 @@ public class JetControlFlowProcessor {
@Override
public void visitSimpleNameExpression(@NotNull JetSimpleNameExpression expression) {
builder.read(expression);
if (trace.get(BindingContext.PROCESSED, expression)) {
JetType type = trace.getBindingContext().get(BindingContext.EXPRESSION_TYPE, expression);
if (type != null && KotlinBuiltIns.getInstance().isNothing(type)) {
builder.jumpToError();
}
}
}
@Override
@@ -662,12 +669,6 @@ public class JetControlFlowProcessor {
generateInstructions(selectorExpression, false);
}
builder.read(expression);
if (trace.get(BindingContext.PROCESSED, expression)) {
JetType type = trace.getBindingContext().get(BindingContext.EXPRESSION_TYPE, expression);
if (type != null && KotlinBuiltIns.getInstance().isNothing(type)) {
builder.jumpToError();
}
}
}
private void visitCall(JetCallElement call) {
@@ -693,12 +694,6 @@ public class JetControlFlowProcessor {
generateInstructions(expression.getCalleeExpression(), false);
builder.read(expression);
if (trace.get(BindingContext.PROCESSED, expression)) {
JetType type = trace.getBindingContext().get(BindingContext.EXPRESSION_TYPE, expression);
if (type != null && KotlinBuiltIns.getInstance().isNothing(type)) {
builder.jumpToError();
}
}
}
@Override
@@ -0,0 +1,23 @@
package c
fun test1() {
<!UNREACHABLE_CODE!>val <!UNUSED_VARIABLE!>r<!>: Nothing = null!!<!>
}
fun test2(a: A) {
a + a
<!UNREACHABLE_CODE!>bar()<!>
}
fun test3() {
null!!
<!UNREACHABLE_CODE!>bar()<!>
}
fun throwNPE() = null!!
class A {
fun plus(<!UNUSED_PARAMETER!>a<!>: A): Nothing = throw Exception()
}
fun bar() {}
@@ -1,3 +1,5 @@
// !DIAGNOSTICS: -UNREACHABLE_CODE -UNUSED_PARAMETER
// t is unused due to KT-4233
trait Tr<T> {
var v: T
}
@@ -1,3 +1,4 @@
// !DIAGNOSTICS: -UNREACHABLE_CODE
trait Tr<T> {
var v: T
}
@@ -1,3 +1,4 @@
// !DIAGNOSTICS: -UNREACHABLE_CODE
trait Tr<T> {
var v: T
}
@@ -7,4 +7,5 @@ fun main(args: Array<String>) {
}
}
fun test<R>(callback: (R) -> Unit):Unit = callback(null!!)
// callback is unused due to KT-4233
fun test<R>(<!UNUSED_PARAMETER!>callback<!>: (R) -> Unit):Unit = <!UNREACHABLE_CODE!>callback(null!!)<!>
@@ -1402,6 +1402,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/checkInnerLocalDeclarations.kt");
}
@TestMetadata("DeadCode.kt")
public void testDeadCode() throws Exception {
doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/DeadCode.kt");
}
@TestMetadata("kt1001.kt")
public void testKt1001() throws Exception {
doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/kt1001.kt");