Do not report IMPLICIT_CAST_TO_ANY on last statement of lambda with Unit(?) in at least one branch.
This commit is contained in:
+60
-17
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.cfg;
|
package org.jetbrains.kotlin.cfg;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
@@ -53,7 +52,6 @@ import org.jetbrains.kotlin.diagnostics.Errors;
|
|||||||
import org.jetbrains.kotlin.idea.MainFunctionDetector;
|
import org.jetbrains.kotlin.idea.MainFunctionDetector;
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||||
import org.jetbrains.kotlin.psi.*;
|
import org.jetbrains.kotlin.psi.*;
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
|
|
||||||
import org.jetbrains.kotlin.resolve.*;
|
import org.jetbrains.kotlin.resolve.*;
|
||||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.BindingContextUtilsKt;
|
import org.jetbrains.kotlin.resolve.bindingContextUtil.BindingContextUtilsKt;
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
|
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
|
||||||
@@ -65,14 +63,12 @@ import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils;
|
|||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static org.jetbrains.kotlin.cfg.VariableUseState.*;
|
|
||||||
import static org.jetbrains.kotlin.cfg.TailRecursionKind.*;
|
import static org.jetbrains.kotlin.cfg.TailRecursionKind.*;
|
||||||
|
import static org.jetbrains.kotlin.cfg.VariableUseState.*;
|
||||||
import static org.jetbrains.kotlin.diagnostics.Errors.*;
|
import static org.jetbrains.kotlin.diagnostics.Errors.*;
|
||||||
import static org.jetbrains.kotlin.diagnostics.Errors.UNREACHABLE_CODE;
|
import static org.jetbrains.kotlin.diagnostics.Errors.UNREACHABLE_CODE;
|
||||||
import static org.jetbrains.kotlin.resolve.BindingContext.*;
|
import static org.jetbrains.kotlin.resolve.BindingContext.*;
|
||||||
import static org.jetbrains.kotlin.types.TypeUtils.DONT_CARE;
|
import static org.jetbrains.kotlin.types.TypeUtils.*;
|
||||||
import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE;
|
|
||||||
import static org.jetbrains.kotlin.types.TypeUtils.noExpectedType;
|
|
||||||
|
|
||||||
public class ControlFlowInformationProvider {
|
public class ControlFlowInformationProvider {
|
||||||
|
|
||||||
@@ -689,15 +685,32 @@ public class ControlFlowInformationProvider {
|
|||||||
? ((InstructionWithValue) instruction).getOutputValue()
|
? ((InstructionWithValue) instruction).getOutputValue()
|
||||||
: null;
|
: null;
|
||||||
Pseudocode pseudocode = instruction.getOwner();
|
Pseudocode pseudocode = instruction.getOwner();
|
||||||
boolean isUsedAsExpression = !pseudocode.getUsages(value).isEmpty();
|
List<Instruction> usages = pseudocode.getUsages(value);
|
||||||
|
boolean isUsedAsExpression = !usages.isEmpty();
|
||||||
|
boolean isUsedAsResultOfLambda = isUsedAsResultOfLambda(usages);
|
||||||
for (KtElement element : pseudocode.getValueElements(value)) {
|
for (KtElement element : pseudocode.getValueElements(value)) {
|
||||||
trace.record(BindingContext.USED_AS_EXPRESSION, element, isUsedAsExpression);
|
trace.record(BindingContext.USED_AS_EXPRESSION, element, isUsedAsExpression);
|
||||||
|
trace.record(BindingContext.USED_AS_RESULT_OF_LAMBDA, element, isUsedAsResultOfLambda);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean isUsedAsResultOfLambda(List<Instruction> usages) {
|
||||||
|
for (Instruction usage : usages) {
|
||||||
|
if (usage instanceof ReturnValueInstruction) {
|
||||||
|
KtElement returnElement = ((ReturnValueInstruction) usage).getElement();
|
||||||
|
PsiElement parentElement = returnElement.getParent();
|
||||||
|
if (!(returnElement instanceof KtReturnExpression ||
|
||||||
|
parentElement instanceof KtDeclaration && !(parentElement instanceof KtFunctionLiteral))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public void checkIfExpressions() {
|
public void checkIfExpressions() {
|
||||||
PseudocodeTraverserKt.traverse(
|
PseudocodeTraverserKt.traverse(
|
||||||
pseudocode, TraversalOrder.FORWARD, new ControlFlowInformationProvider.FunctionVoid1<Instruction>() {
|
pseudocode, TraversalOrder.FORWARD, new ControlFlowInformationProvider.FunctionVoid1<Instruction>() {
|
||||||
@@ -718,7 +731,7 @@ public class ControlFlowInformationProvider {
|
|||||||
trace.report(INVALID_IF_AS_EXPRESSION.on(ifExpression));
|
trace.report(INVALID_IF_AS_EXPRESSION.on(ifExpression));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
checkImplicitCastOnConditionalExpression(ifExpression, ImmutableList.of(thenExpression, elseExpression));
|
checkImplicitCastOnConditionalExpression(ifExpression);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -727,10 +740,41 @@ public class ControlFlowInformationProvider {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkImplicitCastOnConditionalExpression(
|
private static List<KtExpression> collectResultingExpressionsOfConditionalExpression(KtExpression expression) {
|
||||||
@NotNull KtExpression expression,
|
List<KtExpression> leafBranches = new ArrayList<KtExpression>();
|
||||||
@NotNull Collection<KtExpression> branchExpressions
|
collectResultingExpressionsOfConditionalExpressionRec(expression, leafBranches);
|
||||||
|
return leafBranches;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void collectResultingExpressionsOfConditionalExpressionRec(
|
||||||
|
@Nullable KtExpression expression,
|
||||||
|
@NotNull List<KtExpression> resultingExpressions
|
||||||
) {
|
) {
|
||||||
|
if (expression instanceof KtIfExpression) {
|
||||||
|
KtIfExpression ifExpression = (KtIfExpression) expression;
|
||||||
|
collectResultingExpressionsOfConditionalExpressionRec(ifExpression.getThen(), resultingExpressions);
|
||||||
|
collectResultingExpressionsOfConditionalExpressionRec(ifExpression.getElse(), resultingExpressions);
|
||||||
|
}
|
||||||
|
else if (expression instanceof KtWhenExpression) {
|
||||||
|
KtWhenExpression whenExpression = (KtWhenExpression) expression;
|
||||||
|
for (KtWhenEntry whenEntry : whenExpression.getEntries()) {
|
||||||
|
collectResultingExpressionsOfConditionalExpressionRec(whenEntry.getExpression(), resultingExpressions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (expression != null){
|
||||||
|
KtExpression resultingExpression = getResultingExpression(expression);
|
||||||
|
if (resultingExpression instanceof KtIfExpression || resultingExpression instanceof KtWhenExpression) {
|
||||||
|
collectResultingExpressionsOfConditionalExpressionRec(resultingExpression, resultingExpressions);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
resultingExpressions.add(resultingExpression);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkImplicitCastOnConditionalExpression(@NotNull KtExpression expression) {
|
||||||
|
Collection<KtExpression> branchExpressions = collectResultingExpressionsOfConditionalExpression(expression);
|
||||||
|
|
||||||
KotlinType expectedExpressionType = trace.get(EXPECTED_EXPRESSION_TYPE, expression);
|
KotlinType expectedExpressionType = trace.get(EXPECTED_EXPRESSION_TYPE, expression);
|
||||||
if (expectedExpressionType != null && expectedExpressionType != DONT_CARE) return;
|
if (expectedExpressionType != null && expectedExpressionType != DONT_CARE) return;
|
||||||
|
|
||||||
@@ -739,10 +783,13 @@ public class ControlFlowInformationProvider {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (KotlinBuiltIns.isAnyOrNullableAny(expressionType)) {
|
if (KotlinBuiltIns.isAnyOrNullableAny(expressionType)) {
|
||||||
|
boolean isUsedAsResultOfLambda = BindingContextUtilsKt.isUsedAsResultOfLambda(expression, trace.getBindingContext());
|
||||||
for (KtExpression branchExpression : branchExpressions) {
|
for (KtExpression branchExpression : branchExpressions) {
|
||||||
if (branchExpression == null) continue;
|
if (branchExpression == null) continue;
|
||||||
KotlinType branchType = trace.getType(branchExpression);
|
KotlinType branchType = trace.getType(branchExpression);
|
||||||
if (branchType == null || KotlinBuiltIns.isAnyOrNullableAny(branchType)) {
|
if (branchType == null
|
||||||
|
|| KotlinBuiltIns.isAnyOrNullableAny(branchType)
|
||||||
|
|| (isUsedAsResultOfLambda && KotlinBuiltIns.isUnitOrNullableUnit(branchType))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -798,11 +845,7 @@ public class ControlFlowInformationProvider {
|
|||||||
KtWhenExpression whenExpression = (KtWhenExpression) element;
|
KtWhenExpression whenExpression = (KtWhenExpression) element;
|
||||||
|
|
||||||
if (BindingContextUtilsKt.isUsedAsExpression(whenExpression, trace.getBindingContext())) {
|
if (BindingContextUtilsKt.isUsedAsExpression(whenExpression, trace.getBindingContext())) {
|
||||||
List<KtExpression> branchExpressions = new ArrayList<KtExpression>(whenExpression.getEntries().size());
|
checkImplicitCastOnConditionalExpression(whenExpression);
|
||||||
for (KtWhenEntry whenEntry : whenExpression.getEntries()) {
|
|
||||||
branchExpressions.add(whenEntry.getExpression());
|
|
||||||
}
|
|
||||||
checkImplicitCastOnConditionalExpression(whenExpression, branchExpressions);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (whenExpression.getElseExpression() != null) continue;
|
if (whenExpression.getElseExpression() != null) continue;
|
||||||
|
|||||||
@@ -149,6 +149,7 @@ public interface BindingContext {
|
|||||||
*/
|
*/
|
||||||
WritableSlice<KtExpression, Boolean> PROCESSED = Slices.createSimpleSetSlice();
|
WritableSlice<KtExpression, Boolean> PROCESSED = Slices.createSimpleSetSlice();
|
||||||
WritableSlice<KtElement, Boolean> USED_AS_EXPRESSION = Slices.createSimpleSetSlice();
|
WritableSlice<KtElement, Boolean> USED_AS_EXPRESSION = Slices.createSimpleSetSlice();
|
||||||
|
WritableSlice<KtElement, Boolean> USED_AS_RESULT_OF_LAMBDA = Slices.createSimpleSetSlice();
|
||||||
WritableSlice<KtElement, Boolean> UNREACHABLE_CODE = Slices.createSimpleSetSlice();
|
WritableSlice<KtElement, Boolean> UNREACHABLE_CODE = Slices.createSimpleSetSlice();
|
||||||
|
|
||||||
WritableSlice<VariableDescriptor, CaptureKind> CAPTURED_IN_CLOSURE = new BasicWritableSlice<VariableDescriptor, CaptureKind>(DO_NOTHING);
|
WritableSlice<VariableDescriptor, CaptureKind> CAPTURED_IN_CLOSURE = new BasicWritableSlice<VariableDescriptor, CaptureKind>(DO_NOTHING);
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ fun KtReturnExpression.getTargetFunction(context: BindingContext): KtCallableDec
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun KtExpression.isUsedAsExpression(context: BindingContext): Boolean = context[BindingContext.USED_AS_EXPRESSION, this]!!
|
fun KtExpression.isUsedAsExpression(context: BindingContext): Boolean = context[BindingContext.USED_AS_EXPRESSION, this]!!
|
||||||
|
fun KtExpression.isUsedAsResultOfLambda(context: BindingContext): Boolean = context[BindingContext.USED_AS_RESULT_OF_LAMBDA, this]!!
|
||||||
fun KtExpression.isUsedAsStatement(context: BindingContext): Boolean = !isUsedAsExpression(context)
|
fun KtExpression.isUsedAsStatement(context: BindingContext): Boolean = !isUsedAsExpression(context)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+61
@@ -0,0 +1,61 @@
|
|||||||
|
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE
|
||||||
|
|
||||||
|
fun println() {}
|
||||||
|
fun foo(x: Any) {}
|
||||||
|
fun <T> fooGeneric(x: T) {}
|
||||||
|
|
||||||
|
fun testResultOfLambda1() =
|
||||||
|
run {
|
||||||
|
if (true) 42 else println()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testResultOfLambda2() =
|
||||||
|
run {
|
||||||
|
if (true) 42 else if (true) 42 else println()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testResultOfAnonFun1() =
|
||||||
|
run(fun () =
|
||||||
|
if (true) <!IMPLICIT_CAST_TO_ANY!>42<!>
|
||||||
|
else <!IMPLICIT_CAST_TO_ANY!>println()<!>
|
||||||
|
)
|
||||||
|
|
||||||
|
fun testResultOfAnonFun2() =
|
||||||
|
run(fun () {
|
||||||
|
if (true) <!UNUSED_EXPRESSION!>42<!> else println()
|
||||||
|
})
|
||||||
|
|
||||||
|
fun testReturnFromAnonFun() =
|
||||||
|
run(fun () {
|
||||||
|
return if (true) <!CONSTANT_EXPECTED_TYPE_MISMATCH!>42<!> else println()
|
||||||
|
})
|
||||||
|
|
||||||
|
fun <!IMPLICIT_NOTHING_RETURN_TYPE!>testReturn1<!>() =
|
||||||
|
run {
|
||||||
|
return if (true) <!IMPLICIT_CAST_TO_ANY!>42<!>
|
||||||
|
else <!IMPLICIT_CAST_TO_ANY!>println()<!>
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <!IMPLICIT_NOTHING_RETURN_TYPE!>testReturn2<!>() =
|
||||||
|
run {
|
||||||
|
return if (true) <!IMPLICIT_CAST_TO_ANY!>42<!>
|
||||||
|
else if (true) <!IMPLICIT_CAST_TO_ANY!>42<!>
|
||||||
|
else <!IMPLICIT_CAST_TO_ANY!>println()<!>
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testUsage1() =
|
||||||
|
if (true) <!IMPLICIT_CAST_TO_ANY!>42<!>
|
||||||
|
else <!IMPLICIT_CAST_TO_ANY!>println()<!>
|
||||||
|
|
||||||
|
fun testUsage2() =
|
||||||
|
foo(if (true) 42 else println())
|
||||||
|
|
||||||
|
fun testUsage2Generic() =
|
||||||
|
fooGeneric(if (true) 42 else println())
|
||||||
|
|
||||||
|
val testUsage3 =
|
||||||
|
if (true) <!IMPLICIT_CAST_TO_ANY!>42<!>
|
||||||
|
else <!IMPLICIT_CAST_TO_ANY!>println()<!>
|
||||||
|
|
||||||
|
val testUsage4: Any get() =
|
||||||
|
if (true) 42 else println()
|
||||||
+17
@@ -0,0 +1,17 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public val testUsage3: kotlin.Any
|
||||||
|
public val testUsage4: kotlin.Any
|
||||||
|
public fun foo(/*0*/ x: kotlin.Any): kotlin.Unit
|
||||||
|
public fun </*0*/ T> fooGeneric(/*0*/ x: T): kotlin.Unit
|
||||||
|
public fun println(): kotlin.Unit
|
||||||
|
public fun testResultOfAnonFun1(): kotlin.Any
|
||||||
|
public fun testResultOfAnonFun2(): kotlin.Unit
|
||||||
|
public fun testResultOfLambda1(): kotlin.Any
|
||||||
|
public fun testResultOfLambda2(): kotlin.Any
|
||||||
|
public fun testReturn1(): kotlin.Nothing
|
||||||
|
public fun testReturn2(): kotlin.Nothing
|
||||||
|
public fun testReturnFromAnonFun(): kotlin.Unit
|
||||||
|
public fun testUsage1(): kotlin.Any
|
||||||
|
public fun testUsage2(): kotlin.Unit
|
||||||
|
public fun testUsage2Generic(): kotlin.Unit
|
||||||
+31
@@ -0,0 +1,31 @@
|
|||||||
|
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE
|
||||||
|
|
||||||
|
fun println() {}
|
||||||
|
fun foo(x: Any) {}
|
||||||
|
fun <T> fooGeneric(x: T) {}
|
||||||
|
|
||||||
|
fun testMixedIfAndWhen() =
|
||||||
|
if (true)
|
||||||
|
when {
|
||||||
|
true -> if (true) <!IMPLICIT_CAST_TO_ANY!>42<!>
|
||||||
|
else <!IMPLICIT_CAST_TO_ANY!>1<!>
|
||||||
|
true -> if (true) <!IMPLICIT_CAST_TO_ANY!>42<!>
|
||||||
|
else <!IMPLICIT_CAST_TO_ANY!>println()<!>
|
||||||
|
else -> <!INVALID_IF_AS_EXPRESSION!>if (true) <!IMPLICIT_CAST_TO_ANY!>println()<!><!>
|
||||||
|
}
|
||||||
|
else <!IMPLICIT_CAST_TO_ANY!>println()<!>
|
||||||
|
|
||||||
|
fun testWrappedExpressions() =
|
||||||
|
if (true) {
|
||||||
|
println()
|
||||||
|
<!INVALID_IF_AS_EXPRESSION!>if (true) {
|
||||||
|
println()
|
||||||
|
if (true) {
|
||||||
|
<!IMPLICIT_CAST_TO_ANY!>println()<!>
|
||||||
|
}
|
||||||
|
else <!IMPLICIT_CAST_TO_ANY!>{}<!>
|
||||||
|
}<!>
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
(((<!IMPLICIT_CAST_TO_ANY!>((42)) + 1<!>)))
|
||||||
|
}
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun foo(/*0*/ x: kotlin.Any): kotlin.Unit
|
||||||
|
public fun </*0*/ T> fooGeneric(/*0*/ x: T): kotlin.Unit
|
||||||
|
public fun println(): kotlin.Unit
|
||||||
|
public fun testMixedIfAndWhen(): kotlin.Any
|
||||||
|
public fun testWrappedExpressions(): kotlin.Any
|
||||||
+2
-2
@@ -17,12 +17,12 @@ fun example() {
|
|||||||
}();
|
}();
|
||||||
|
|
||||||
{
|
{
|
||||||
if (true) <!IMPLICIT_CAST_TO_ANY!>{}<!> else <!IMPLICIT_CAST_TO_ANY!>false<!>
|
if (true) {} else false
|
||||||
}();
|
}();
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
if (true) <!IMPLICIT_CAST_TO_ANY!>true<!> else <!IMPLICIT_CAST_TO_ANY!>{}<!>
|
if (true) true else {}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
fun t(): Boolean {
|
fun t(): Boolean {
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
fun test1() {
|
fun test1() {
|
||||||
run {
|
run {
|
||||||
if (true) {
|
if (true) {
|
||||||
<!INVALID_IF_AS_EXPRESSION, IMPLICIT_CAST_TO_ANY!>if (true) {}<!>
|
<!INVALID_IF_AS_EXPRESSION!>if (true) {}<!>
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
<!IMPLICIT_CAST_TO_ANY!>1<!>
|
1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -20,10 +20,10 @@ fun foo() {
|
|||||||
var <!ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE!>z<!> = 2
|
var <!ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE!>z<!> = 2
|
||||||
val r = { // type fun(): Any is inferred
|
val r = { // type fun(): Any is inferred
|
||||||
if (true) {
|
if (true) {
|
||||||
<!IMPLICIT_CAST_TO_ANY!>2<!>
|
2
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
<!IMPLICIT_CAST_TO_ANY!>z = 34<!>
|
z = 34
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val <!UNUSED_VARIABLE!>f<!>: ()-> Int = <!TYPE_MISMATCH!>r<!>
|
val <!UNUSED_VARIABLE!>f<!>: ()-> Int = <!TYPE_MISMATCH!>r<!>
|
||||||
@@ -74,9 +74,9 @@ fun testCoercionToUnit() {
|
|||||||
var <!ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE!>x<!> = 43
|
var <!ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE!>x<!> = 43
|
||||||
val checkType = {
|
val checkType = {
|
||||||
if (true) {
|
if (true) {
|
||||||
<!IMPLICIT_CAST_TO_ANY!>x = 4<!>
|
x = 4
|
||||||
} else {
|
} else {
|
||||||
<!IMPLICIT_CAST_TO_ANY!>45<!>
|
45
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val <!UNUSED_VARIABLE!>f<!> : () -> String = <!TYPE_MISMATCH!>checkType<!>
|
val <!UNUSED_VARIABLE!>f<!> : () -> String = <!TYPE_MISMATCH!>checkType<!>
|
||||||
|
|||||||
+83
@@ -0,0 +1,83 @@
|
|||||||
|
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE
|
||||||
|
|
||||||
|
fun println() {}
|
||||||
|
fun foo(x: Any) {}
|
||||||
|
fun <T> fooGeneric(x: T) {}
|
||||||
|
|
||||||
|
fun testResultOfLambda1() =
|
||||||
|
run {
|
||||||
|
when {
|
||||||
|
true -> 42
|
||||||
|
else -> println()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testResultOfLambda2() =
|
||||||
|
run {
|
||||||
|
when {
|
||||||
|
true -> 42
|
||||||
|
else ->
|
||||||
|
when {
|
||||||
|
true -> 42
|
||||||
|
else -> println()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <!IMPLICIT_NOTHING_RETURN_TYPE!>testReturn1<!>() =
|
||||||
|
run {
|
||||||
|
return when {
|
||||||
|
true -> <!IMPLICIT_CAST_TO_ANY!>42<!>
|
||||||
|
else -> <!IMPLICIT_CAST_TO_ANY!>println()<!>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <!IMPLICIT_NOTHING_RETURN_TYPE!>testReturn2<!>() =
|
||||||
|
run {
|
||||||
|
return when {
|
||||||
|
true -> <!IMPLICIT_CAST_TO_ANY!>42<!>
|
||||||
|
else ->
|
||||||
|
when {
|
||||||
|
true -> <!IMPLICIT_CAST_TO_ANY!>42<!>
|
||||||
|
else -> <!IMPLICIT_CAST_TO_ANY!>println()<!>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testUsage1() =
|
||||||
|
when {
|
||||||
|
true -> <!IMPLICIT_CAST_TO_ANY!>42<!>
|
||||||
|
else -> <!IMPLICIT_CAST_TO_ANY!>println()<!>
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testUsage2() =
|
||||||
|
foo(when {
|
||||||
|
true -> 42
|
||||||
|
else -> println()
|
||||||
|
})
|
||||||
|
|
||||||
|
fun testUsage2Generic() =
|
||||||
|
fooGeneric(when {
|
||||||
|
true -> 42
|
||||||
|
else -> println()
|
||||||
|
})
|
||||||
|
|
||||||
|
val testUsage3 =
|
||||||
|
when {
|
||||||
|
true -> <!IMPLICIT_CAST_TO_ANY!>42<!>
|
||||||
|
else -> <!IMPLICIT_CAST_TO_ANY!>println()<!>
|
||||||
|
}
|
||||||
|
|
||||||
|
val testUsage4 =
|
||||||
|
when {
|
||||||
|
true -> <!IMPLICIT_CAST_TO_ANY!>42<!>
|
||||||
|
true -> <!IMPLICIT_CAST_TO_ANY!>42<!>
|
||||||
|
true -> <!IMPLICIT_CAST_TO_ANY!>42<!>
|
||||||
|
else -> <!IMPLICIT_CAST_TO_ANY!>println()<!>
|
||||||
|
}
|
||||||
|
|
||||||
|
val testUsage5: Any get() =
|
||||||
|
when {
|
||||||
|
true -> 42
|
||||||
|
else -> println()
|
||||||
|
}
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public val testUsage3: kotlin.Any
|
||||||
|
public val testUsage4: kotlin.Any
|
||||||
|
public val testUsage5: kotlin.Any
|
||||||
|
public fun foo(/*0*/ x: kotlin.Any): kotlin.Unit
|
||||||
|
public fun </*0*/ T> fooGeneric(/*0*/ x: T): kotlin.Unit
|
||||||
|
public fun println(): kotlin.Unit
|
||||||
|
public fun testResultOfLambda1(): kotlin.Any
|
||||||
|
public fun testResultOfLambda2(): kotlin.Any
|
||||||
|
public fun testReturn1(): kotlin.Nothing
|
||||||
|
public fun testReturn2(): kotlin.Nothing
|
||||||
|
public fun testUsage1(): kotlin.Any
|
||||||
|
public fun testUsage2(): kotlin.Unit
|
||||||
|
public fun testUsage2Generic(): kotlin.Unit
|
||||||
@@ -14,9 +14,19 @@ fun test1(word: String) =
|
|||||||
fun test2(word: String) =
|
fun test2(word: String) =
|
||||||
run {
|
run {
|
||||||
if (word.length > 4) {
|
if (word.length > 4) {
|
||||||
<!INVALID_IF_AS_EXPRESSION, IMPLICIT_CAST_TO_ANY!>if (word.startsWith("a")) longWords++<!>
|
<!INVALID_IF_AS_EXPRESSION!>if (word.startsWith("a")) <!IMPLICIT_CAST_TO_ANY!>longWords++<!><!>
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
<!IMPLICIT_CAST_TO_ANY!>smallWords.add(word)<!>
|
<!IMPLICIT_CAST_TO_ANY!>smallWords.add(word)<!>
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test3(word: String) =
|
||||||
|
run {
|
||||||
|
if (word.length > 4) {
|
||||||
|
longWords++
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
System.out?.println(word) // Unit?
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -4,3 +4,4 @@ public var longWords: kotlin.Int
|
|||||||
public val smallWords: java.util.HashSet<kotlin.String>
|
public val smallWords: java.util.HashSet<kotlin.String>
|
||||||
public fun test1(/*0*/ word: kotlin.String): kotlin.Any
|
public fun test1(/*0*/ word: kotlin.String): kotlin.Any
|
||||||
public fun test2(/*0*/ word: kotlin.String): kotlin.Any
|
public fun test2(/*0*/ word: kotlin.String): kotlin.Any
|
||||||
|
public fun test3(/*0*/ word: kotlin.String): kotlin.Any?
|
||||||
|
|||||||
@@ -3390,6 +3390,18 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("ifToAnyDiscriminatingUsages.kt")
|
||||||
|
public void testIfToAnyDiscriminatingUsages() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/controlStructures/ifToAnyDiscriminatingUsages.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("ifWhenToAnyComplexExpressions.kt")
|
||||||
|
public void testIfWhenToAnyComplexExpressions() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/controlStructures/ifWhenToAnyComplexExpressions.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("ifWhenWithoutElse.kt")
|
@TestMetadata("ifWhenWithoutElse.kt")
|
||||||
public void testIfWhenWithoutElse() throws Exception {
|
public void testIfWhenWithoutElse() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/controlStructures/ifWhenWithoutElse.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/controlStructures/ifWhenWithoutElse.kt");
|
||||||
@@ -3504,6 +3516,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("whenToAnyDiscriminatingUsages.kt")
|
||||||
|
public void testWhenToAnyDiscriminatingUsages() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/controlStructures/whenToAnyDiscriminatingUsages.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("when.kt234.kt973.kt")
|
@TestMetadata("when.kt234.kt973.kt")
|
||||||
public void testWhen_kt234_kt973() throws Exception {
|
public void testWhen_kt234_kt973() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/controlStructures/when.kt234.kt973.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/controlStructures/when.kt234.kt973.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user