check Nothing type for all expressions not only for calls and simple names
(but excluding statement expressions)
This commit is contained in:
@@ -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
@@ -1,3 +1,4 @@
|
|||||||
|
// !DIAGNOSTICS: -UNREACHABLE_CODE
|
||||||
trait Tr<T> {
|
trait Tr<T> {
|
||||||
var v: T
|
var v: T
|
||||||
}
|
}
|
||||||
|
|||||||
+1
@@ -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");
|
||||||
|
|||||||
Reference in New Issue
Block a user