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; JetDeclarationWithBody declarationWithBody = (JetDeclarationWithBody) subroutine;
List<JetParameter> valueParameters = declarationWithBody.getValueParameters(); List<JetParameter> valueParameters = declarationWithBody.getValueParameters();
for (JetParameter valueParameter : valueParameters) { for (JetParameter valueParameter : valueParameters) {
valueParameter.accept(cfpVisitor); cfpVisitor.generateInstructions(valueParameter);
} }
JetExpression bodyExpression = declarationWithBody.getBodyExpression(); JetExpression bodyExpression = declarationWithBody.getBodyExpression();
if (bodyExpression != null) { if (bodyExpression != null) {
bodyExpression.accept(cfpVisitor); cfpVisitor.generateInstructions(bodyExpression);
} }
} else { } else {
subroutine.accept(cfpVisitor); cfpVisitor.generateInstructions(subroutine);
} }
return builder.exitSubroutine(subroutine); return builder.exitSubroutine(subroutine);
} }
@@ -115,18 +115,15 @@ public class JetControlFlowProcessor {
throw new UnsupportedOperationException("[JetControlFlowProcessor] " + element.toString()); 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) { private CFPVisitor(boolean inCondition) {
this.inCondition = inCondition; this.inCondition = inCondition;
} }
public void generateInstructions(@Nullable JetElement element) {
generateInstructions(element, inCondition);
}
private void generateInstructions(@Nullable JetElement element, boolean inCondition) { private void generateInstructions(@Nullable JetElement element, boolean inCondition) {
if (element == null) return; if (element == null) return;
CFPVisitor visitor; CFPVisitor visitor;
@@ -137,6 +134,22 @@ public class JetControlFlowProcessor {
visitor = new CFPVisitor(inCondition); visitor = new CFPVisitor(inCondition);
} }
element.accept(visitor); 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 @Override
@@ -172,12 +185,6 @@ public class JetControlFlowProcessor {
@Override @Override
public void visitSimpleNameExpression(@NotNull JetSimpleNameExpression expression) { public void visitSimpleNameExpression(@NotNull JetSimpleNameExpression expression) {
builder.read(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 @Override
@@ -662,12 +669,6 @@ public class JetControlFlowProcessor {
generateInstructions(selectorExpression, false); generateInstructions(selectorExpression, false);
} }
builder.read(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();
}
}
} }
private void visitCall(JetCallElement call) { private void visitCall(JetCallElement call) {
@@ -693,12 +694,6 @@ public class JetControlFlowProcessor {
generateInstructions(expression.getCalleeExpression(), false); generateInstructions(expression.getCalleeExpression(), false);
builder.read(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 @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> { trait Tr<T> {
var v: T var v: T
} }
@@ -1,3 +1,4 @@
// !DIAGNOSTICS: -UNREACHABLE_CODE
trait Tr<T> { trait Tr<T> {
var v: T var v: T
} }
@@ -1,3 +1,4 @@
// !DIAGNOSTICS: -UNREACHABLE_CODE
trait Tr<T> { trait Tr<T> {
var v: 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"); 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") @TestMetadata("kt1001.kt")
public void testKt1001() throws Exception { public void testKt1001() throws Exception {
doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/kt1001.kt"); doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/kt1001.kt");