NI: introduce warning about implicitly inferred Nothing with existing non-Nothing expected type

^KT-35406 Fixed
This commit is contained in:
Victor Petukhov
2020-02-13 16:09:50 +03:00
parent e3184e407d
commit 51edf2b351
18 changed files with 414 additions and 42 deletions
@@ -23347,9 +23347,14 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte
runTest("compiler/testData/diagnostics/tests/typeParameters/functionTypeAsUpperBound.kt");
}
@TestMetadata("implicitNothingAsTypeParameter.kt")
public void testImplicitNothingAsTypeParameter() throws Exception {
runTest("compiler/testData/diagnostics/tests/typeParameters/implicitNothingAsTypeParameter.kt");
@TestMetadata("implicitNothingAgainstNotNothingExpectedType.kt")
public void testImplicitNothingAgainstNotNothingExpectedType() throws Exception {
runTest("compiler/testData/diagnostics/tests/typeParameters/implicitNothingAgainstNotNothingExpectedType.kt");
}
@TestMetadata("implicitNothingInReturnPosition.kt")
public void testImplicitNothingInReturnPosition() throws Exception {
runTest("compiler/testData/diagnostics/tests/typeParameters/implicitNothingInReturnPosition.kt");
}
@TestMetadata("implicitNothingOnDelegates.kt")
@@ -780,7 +780,8 @@ public interface Errors {
DiagnosticFactory0<KtExpression> TYPE_INFERENCE_FAILED_ON_SPECIAL_CONSTRUCT = DiagnosticFactory0.create(ERROR, SPECIAL_CONSTRUCT_TOKEN);
DiagnosticFactory0<PsiElement> IMPLICIT_NOTHING_AS_TYPE_PARAMETER = DiagnosticFactory0.create(WARNING);
DiagnosticFactory0<PsiElement> IMPLICIT_NOTHING_TYPE_ARGUMENT_IN_RETURN_POSITION = DiagnosticFactory0.create(WARNING);
DiagnosticFactory0<PsiElement> IMPLICIT_NOTHING_TYPE_ARGUMENT_AGAINST_NOT_NOTHING_EXPECTED_TYPE = DiagnosticFactory0.create(WARNING);
// Reflection
@@ -117,6 +117,18 @@ fun BindingTrace.reportDiagnosticOnce(diagnostic: Diagnostic) {
report(diagnostic)
}
fun BindingTrace.reportDiagnosticOnceWrtDiagnosticFactoryList(
diagnosticToReport: Diagnostic,
vararg diagnosticFactories: DiagnosticFactory<*>,
) {
val hasAlreadyReportedDiagnosticFromListOrSameType = bindingContext.diagnostics.forElement(diagnosticToReport.psiElement)
.any { diagnostic -> diagnostic.factory == diagnosticToReport.factory || diagnosticFactories.any { it == diagnostic.factory } }
if (hasAlreadyReportedDiagnosticFromListOrSameType) return
report(diagnosticToReport)
}
class TypeMismatchDueToTypeProjectionsData(
val expectedType: KotlinType,
val expressionType: KotlinType,
@@ -1001,7 +1001,8 @@ public class DefaultErrorMessages {
MAP.put(ILLEGAL_SUSPEND_PROPERTY_ACCESS, "Suspend property ''{0}'' should be accessed only from a coroutine or suspend function", NAME);
MAP.put(ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL, "Restricted suspending functions can only invoke member or extension suspending functions on their restricted coroutine scope");
MAP.put(NON_MODIFIER_FORM_FOR_BUILT_IN_SUSPEND, "''suspend'' function can only be called in a form of modifier of a lambda: suspend { ... }");
MAP.put(IMPLICIT_NOTHING_AS_TYPE_PARAMETER, "One of the type variables was implicitly inferred to Nothing. Please, specify type arguments explicitly to hide this warning.");
MAP.put(IMPLICIT_NOTHING_TYPE_ARGUMENT_IN_RETURN_POSITION, "Returning type parameter has been inferred to Nothing implicitly. Please, specify type arguments explicitly to hide this warning. Nothing can produce an exception at runtime.");
MAP.put(IMPLICIT_NOTHING_TYPE_ARGUMENT_AGAINST_NOT_NOTHING_EXPECTED_TYPE, "Returning type parameter has been inferred to Nothing implicitly because Nothing is more specific than specified expected type. Please specify type arguments explicitly in accordance with expected type to hide this warning. Nothing can produce an exception at runtime.");
MAP.put(RETURN_FOR_BUILT_IN_SUSPEND, "Using implicit label for this lambda is prohibited");
MAP.put(MODIFIER_FORM_FOR_NON_BUILT_IN_SUSPEND, "Calls having a form of ''suspend {}'' are deprecated because ''suspend'' in the context will have a meaning of a modifier. Add empty argument list to the call: ''suspend() { ... }''");
@@ -9,12 +9,20 @@ import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.builtins.isBuiltinFunctionalType
import org.jetbrains.kotlin.builtins.isFunctionOrSuspendFunctionType
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.diagnostics.reportDiagnosticOnceWrtDiagnosticFactoryList
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.SPECIAL_FUNCTION_NAMES
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.callUtil.getParameterForArgument
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.calls.tower.NewResolvedCallImpl
import org.jetbrains.kotlin.resolve.calls.tower.psiExpression
import org.jetbrains.kotlin.resolve.calls.tower.psiKotlinCall
import org.jetbrains.kotlin.types.DeferredType
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.expressions.ControlStructureTypingUtils
import org.jetbrains.kotlin.types.typeUtil.isNothing
import org.jetbrains.kotlin.types.typeUtil.isNothingOrNullableNothing
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
object ImplicitNothingAsTypeParameterCallChecker : CallChecker {
@@ -34,27 +42,131 @@ object ImplicitNothingAsTypeParameterCallChecker : CallChecker {
* return inv()
* }
*/
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
private fun checkByReturnPositionWithoutExpected(
resolvedCall: ResolvedCall<*>,
reportOn: PsiElement,
context: CallCheckerContext,
): Boolean {
val resultingDescriptor = resolvedCall.resultingDescriptor
val expectedType = context.resolutionContext.expectedType
val inferredReturnType = resultingDescriptor.returnType
val isBuiltinFunctionalType =
resolvedCall.resultingDescriptor.dispatchReceiverParameter?.value?.type?.isBuiltinFunctionalType == true
if (inferredReturnType is DeferredType || isBuiltinFunctionalType)
return
if (resultingDescriptor.name !in SPECIAL_FUNCTION_NAMES && resolvedCall.call.typeArguments.isEmpty()) {
val lambdasFromArgumentsReturnTypes =
resolvedCall.candidateDescriptor.valueParameters.filter { it.type.isFunctionOrSuspendFunctionType }
.map { it.returnType?.arguments?.last()?.type }.toSet()
val unsubstitutedReturnType = resultingDescriptor.original.returnType
val expectedType = context.resolutionContext.expectedType
val hasImplicitNothing = inferredReturnType?.isNothing() == true &&
unsubstitutedReturnType?.isTypeParameter() == true &&
(TypeUtils.noExpectedType(expectedType) || !expectedType.isNothing())
if (inferredReturnType is DeferredType || isBuiltinFunctionalType) return false
if (resultingDescriptor.name in SPECIAL_FUNCTION_NAMES || resolvedCall.call.typeArguments.isNotEmpty()) return false
if (hasImplicitNothing && unsubstitutedReturnType !in lambdasFromArgumentsReturnTypes) {
context.trace.report(Errors.IMPLICIT_NOTHING_AS_TYPE_PARAMETER.on(reportOn))
val lambdasFromArgumentsReturnTypes =
resolvedCall.candidateDescriptor.valueParameters.filter { it.type.isFunctionOrSuspendFunctionType }
.map { it.returnType?.arguments?.last()?.type }.toSet()
val unsubstitutedReturnType = resultingDescriptor.original.returnType
val hasImplicitNothing = inferredReturnType?.isNothing() == true &&
unsubstitutedReturnType?.isTypeParameter() == true &&
(TypeUtils.noExpectedType(expectedType) || !expectedType.isNothing())
if (hasImplicitNothing && unsubstitutedReturnType !in lambdasFromArgumentsReturnTypes) {
context.trace.reportDiagnosticOnceWrtDiagnosticFactoryList(
Errors.IMPLICIT_NOTHING_TYPE_ARGUMENT_IN_RETURN_POSITION.on(reportOn),
Errors.IMPLICIT_NOTHING_TYPE_ARGUMENT_AGAINST_NOT_NOTHING_EXPECTED_TYPE,
)
return true
}
return false
}
private fun ResolvedAtom.getResolvedCallAtom(bindingContext: BindingContext): ResolvedCallAtom? {
if (this is SingleCallResolutionResult) return resultCallAtom
val resolutionAtom = atom as? KotlinCallArgument ?: return null
val resolvedCall = resolutionAtom.psiExpression.getResolvedCall(bindingContext)
return if (resolvedCall is NewResolvedCallImpl) resolvedCall.resolvedCallAtom else null
}
private fun findFunctionsWithImplicitNothingAndReport(resolvedAtoms: List<ResolvedAtom>, context: CallCheckerContext): Boolean {
var hasAlreadyReportedAtDepth = false
for (resolvedAtom in resolvedAtoms) {
val subResolveAtoms = resolvedAtom.subResolvedAtoms
if (!subResolveAtoms.isNullOrEmpty() && findFunctionsWithImplicitNothingAndReport(subResolveAtoms, context)) {
hasAlreadyReportedAtDepth = true
continue
}
val resolvedCallAtom = resolvedAtom.getResolvedCallAtom(context.trace.bindingContext) ?: continue
val candidateDescriptor = resolvedCallAtom.candidateDescriptor
val isReturnTypeOwnTypeParameter = candidateDescriptor.typeParameters.any { it.defaultType == candidateDescriptor.returnType }
val isSpecialCall = candidateDescriptor.name in SPECIAL_FUNCTION_NAMES
val hasExplicitTypeArguments = resolvedCallAtom.atom.psiKotlinCall.typeArguments.isNotEmpty() // not required
if (!isSpecialCall && isReturnTypeOwnTypeParameter && !hasExplicitTypeArguments) {
context.trace.reportDiagnosticOnceWrtDiagnosticFactoryList(
Errors.IMPLICIT_NOTHING_TYPE_ARGUMENT_AGAINST_NOT_NOTHING_EXPECTED_TYPE.on(
resolvedCallAtom.atom.psiKotlinCall.psiCall.run { calleeExpression ?: callElement },
),
Errors.IMPLICIT_NOTHING_TYPE_ARGUMENT_IN_RETURN_POSITION,
)
hasAlreadyReportedAtDepth = true
}
}
return hasAlreadyReportedAtDepth
}
private fun getSubResolvedAtomsToAnalyze(
resolvedCall: ResolvedCall<*>,
expectedType: KotlinType,
bindingContext: BindingContext,
): List<ResolvedAtom>? {
if (resolvedCall !is NewResolvedCallImpl) return null
val hasNotNothingExpectedType = !TypeUtils.noExpectedType(expectedType) && !expectedType.isNothingOrNullableNothing()
val hasNothingReturnType = resolvedCall.resultingDescriptor.returnType?.isNothingOrNullableNothing() == true
val isSubResolvedAtomsNotEmpty = !resolvedCall.resolvedCallAtom.subResolvedAtoms.isNullOrEmpty()
if (hasNotNothingExpectedType && hasNothingReturnType && isSubResolvedAtomsNotEmpty) {
return resolvedCall.resolvedCallAtom.subResolvedAtoms
}
val resolvedAtomsFromArguments = resolvedCall.valueArguments.values.mapNotNull { argument ->
if (argument !is ExpressionValueArgument) return@mapNotNull null
val resolvedCallForArgument =
argument.valueArgument?.getArgumentExpression()?.getResolvedCall(bindingContext) as? NewResolvedCallImpl
?: return@mapNotNull null
val expectedTypeForArgument = resolvedCall.getParameterForArgument(argument.valueArgument)?.type ?: return@mapNotNull null
getSubResolvedAtomsToAnalyze(resolvedCallForArgument, expectedTypeForArgument, bindingContext)
}.flatten()
val extensionReceiver = resolvedCall.resolvedCallAtom.extensionReceiverArgument?.psiExpression
val resolvedAtomsFromExtensionReceiver = extensionReceiver?.run {
val extensionReceiverResolvedCall = getResolvedCall(bindingContext)
// It's needed to exclude invoke with extension (when resolved call for extension equals to common resolved call)
if (extensionReceiverResolvedCall == resolvedCall) return@run null
getSubResolvedAtomsToAnalyze(
getResolvedCall(bindingContext) ?: return@run null,
resolvedCall.resultingDescriptor.extensionReceiverParameter?.type ?: return@run null,
bindingContext,
)
}
return if (resolvedAtomsFromExtensionReceiver != null) {
resolvedAtomsFromArguments + resolvedAtomsFromExtensionReceiver
} else resolvedAtomsFromArguments
}
private fun checkAgainstNotNothingExpectedType(resolvedCall: ResolvedCall<*>, context: CallCheckerContext): Boolean {
val subResolvedAtoms =
getSubResolvedAtomsToAnalyze(resolvedCall, context.resolutionContext.expectedType, context.trace.bindingContext) ?: return false
return findFunctionsWithImplicitNothingAndReport(subResolvedAtoms, context)
}
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
checkByReturnPositionWithoutExpected(resolvedCall, reportOn, context) || checkAgainstNotNothingExpectedType(resolvedCall, context)
}
}
@@ -30,7 +30,7 @@ fun <T> test(x: T) {
<!REIFIED_TYPE_FORBIDDEN_SUBSTITUTION, REIFIED_TYPE_FORBIDDEN_SUBSTITUTION!>baz<!>(null, null, ::foo)
val s3: Pair<Int, String?> = <!NI;TYPE_MISMATCH, OI;TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH!>bar(null, null, ::<!OI;TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo<!>)<!>
val s4: Pair<Int?, String> = <!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, OI;TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH!>bar(null, null, ::<!NI;IMPLICIT_NOTHING_AS_TYPE_PARAMETER, OI;TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo<!>)<!>
val s4: Pair<Int?, String> = <!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, OI;TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH!>bar(null, null, ::<!NI;IMPLICIT_NOTHING_TYPE_ARGUMENT_IN_RETURN_POSITION, OI;TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo<!>)<!>
val s5: Pair<Int, String> = <!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, OI;TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH!>bar(1, "", ::foo)<!>
val (a1: Int, b1: String) = <!COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH!>bar(1, "", ::foo)<!>
@@ -13,7 +13,7 @@ fun <E4, F : E4> noSmartCast4(arg: E4?, fn: F): E4 = TODO()
fun testSmartCast(s: String?) {
id(
if (s != null) ""
else <!IMPLICIT_NOTHING_AS_TYPE_PARAMETER!>smartCast<!>(null) { "" }
else <!IMPLICIT_NOTHING_TYPE_ARGUMENT_IN_RETURN_POSITION!>smartCast<!>(null) { "" }
)
<!DEBUG_INFO_SMARTCAST!>s<!>.length
}
@@ -46,7 +46,7 @@ fun testNoSmartCast3(s: String?) {
fun testNoSmartCast4(s: String?) {
id(
if (s != null) ( {""} )
else <!IMPLICIT_NOTHING_AS_TYPE_PARAMETER, IMPLICIT_NOTHING_AS_TYPE_PARAMETER!>noSmartCast4<!>(null) <!TYPE_MISMATCH!>{ <!TYPE_MISMATCH!>""<!> }<!>
else <!IMPLICIT_NOTHING_TYPE_ARGUMENT_IN_RETURN_POSITION!>noSmartCast4<!>(null) <!TYPE_MISMATCH!>{ <!TYPE_MISMATCH!>""<!> }<!>
)
s<!UNSAFE_CALL!>.<!>length
}
@@ -9,5 +9,5 @@ fun <K> invOut(y: K?): Inv<Out<K>> = TODO()
fun <R> test(x: Inv<Out<R>>): R = TODO()
fun testNothing() {
<!IMPLICIT_NOTHING_AS_TYPE_PARAMETER!>test<!>(invOut(null)) checkType { _<Nothing>() }
<!IMPLICIT_NOTHING_TYPE_ARGUMENT_IN_RETURN_POSITION!>test<!>(invOut(null)) checkType { _<Nothing>() }
}
@@ -14,7 +14,7 @@ inline fun <reified M> materializeReifiedUnbound(): M = TODO()
fun <T> select(a: T, b: T): T = TODO()
fun test1() {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!><!IMPLICIT_NOTHING_AS_TYPE_PARAMETER!>take<!>(null)<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!><!IMPLICIT_NOTHING_TYPE_ARGUMENT_IN_RETURN_POSITION!>take<!>(null)<!>
}
fun test2() {
@@ -22,20 +22,20 @@ fun test2() {
}
fun test3() {
<!IMPLICIT_NOTHING_AS_TYPE_PARAMETER, REIFIED_TYPE_FORBIDDEN_SUBSTITUTION!>takeReifiedUnbound<!>(null)
<!IMPLICIT_NOTHING_TYPE_ARGUMENT_IN_RETURN_POSITION, REIFIED_TYPE_FORBIDDEN_SUBSTITUTION!>takeReifiedUnbound<!>(null)
}
fun test4(): Bound = <!DEBUG_INFO_EXPRESSION_TYPE("Bound")!>takeReifiedUnbound(null)<!>
fun test5(): Bound? = select(
null,
<!IMPLICIT_NOTHING_AS_TYPE_PARAMETER, IMPLICIT_NOTHING_AS_TYPE_PARAMETER!>materialize<!>()
<!IMPLICIT_NOTHING_TYPE_ARGUMENT_IN_RETURN_POSITION!>materialize<!>()
)
fun test6() {
select(
null,
<!IMPLICIT_NOTHING_AS_TYPE_PARAMETER, IMPLICIT_NOTHING_AS_TYPE_PARAMETER, REIFIED_TYPE_FORBIDDEN_SUBSTITUTION, REIFIED_TYPE_FORBIDDEN_SUBSTITUTION!>materializeReified<!>()
<!IMPLICIT_NOTHING_TYPE_ARGUMENT_IN_RETURN_POSITION, REIFIED_TYPE_FORBIDDEN_SUBSTITUTION, REIFIED_TYPE_FORBIDDEN_SUBSTITUTION!>materializeReified<!>()
)
}
@@ -0,0 +1,105 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE -UNCHECKED_CAST -UNUSED_EXPRESSION -UNREACHABLE_CODE
// !LANGUAGE: +NewInference
fun <K> materialize(): K = null as K
fun <K, T> materializeWithGenericArg(x: T): K = null as K
fun <K> id(x: K): K = null as K
fun <K> K.idFromReceiver(): K = null as K
fun <K> K.idFromReceiverWithArg(x: String): K = null as K
fun <S> select(x: S, y: S): S = x
class Foo<T> {
fun idFromClassTypeArg(): T = null as T
fun <K> idFromClassTypeArgWithAnotherTypeArg(): T = null as T
fun <K> materialize(): K = null as K
}
fun test() {
if (true) materialize() else null
val x1: String? = if (true) materialize() else null
val x2: String? = if (true) materializeWithGenericArg("") else null
val x3: String? = if (true) {
if (true) materialize() else null
} else null
val x4: String? = if (true) {
select(materialize(), null)
} else null
val x5: String? = select(if (true) materialize() else null, null)
val x6: String? = select(materialize(), null)
val x7: String? = select(null.idFromReceiver(), null)
val x8: String? = select(null.idFromReceiverWithArg(""), null)
val foo = Foo<Nothing?>()
val x9: String? = select(foo.materialize(), null)
val x10: String? = select(foo.idFromClassTypeArgWithAnotherTypeArg(), null)
val x11: String? = select(foo.idFromClassTypeArg(), null)
foo.run {
val x12: String? = select(materialize(), null)
val x13: String? = select(idFromClassTypeArgWithAnotherTypeArg(), null)
val x14: String? = select(idFromClassTypeArg(), null)
}
val boolean: Boolean? = true
val x15: String? = when (boolean) {
true -> select(materialize(), null)
false -> select(materialize(), null)
null -> null
}
val x16: String? = when (boolean) {
true -> null
false -> materialize()
null -> null
}
val x17: String? = when (boolean) {
true -> if (true) null else materialize()
false -> if (true) materialize() else null
null -> if (true) null else null
}
val x18: String? = try {
materialize()
} catch (e: Exception) {
null
}
val x19: String? = if (true) materialize<Nothing?>() else null
val x20: String? = if (true) materialize<String?>() else null
val x21: String? = if (true) materialize() else TODO()
val x22: String? = if (true) return else materialize()
val x23: String? = if (true) id(null) else null
foo1(if (true) materialize() else null)
val x24 = id(foo1(if (true) materialize() else null))
val x25 = select(materialize(), null).foo2()
// TODO
val x26 = select(materialize(), null).run { foo2() }
val x27: () -> String? = {
id(id(if (true) materialize() else null))
}
}
fun foo1(x: String?) {}
fun String?.foo2() {}
@@ -0,0 +1,105 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE -UNCHECKED_CAST -UNUSED_EXPRESSION -UNREACHABLE_CODE
// !LANGUAGE: +NewInference
fun <K> materialize(): K = null as K
fun <K, T> materializeWithGenericArg(x: T): K = null as K
fun <K> id(x: K): K = null as K
fun <K> K.idFromReceiver(): K = null as K
fun <K> K.idFromReceiverWithArg(x: String): K = null as K
fun <S> select(x: S, y: S): S = x
class Foo<T> {
fun idFromClassTypeArg(): T = null as T
fun <K> idFromClassTypeArgWithAnotherTypeArg(): T = null as T
fun <K> materialize(): K = null as K
}
fun test() {
if (true) materialize() else null
val x1: String? = if (true) <!IMPLICIT_NOTHING_TYPE_ARGUMENT_AGAINST_NOT_NOTHING_EXPECTED_TYPE!>materialize<!>() else null
val x2: String? = if (true) <!IMPLICIT_NOTHING_TYPE_ARGUMENT_AGAINST_NOT_NOTHING_EXPECTED_TYPE!>materializeWithGenericArg<!>("") else null
val x3: String? = if (true) {
if (true) <!IMPLICIT_NOTHING_TYPE_ARGUMENT_AGAINST_NOT_NOTHING_EXPECTED_TYPE!>materialize<!>() else null
} else null
val x4: String? = if (true) {
select(<!IMPLICIT_NOTHING_TYPE_ARGUMENT_AGAINST_NOT_NOTHING_EXPECTED_TYPE!>materialize<!>(), null)
} else null
val x5: String? = select(if (true) <!IMPLICIT_NOTHING_TYPE_ARGUMENT_AGAINST_NOT_NOTHING_EXPECTED_TYPE!>materialize<!>() else null, null)
val x6: String? = select(<!IMPLICIT_NOTHING_TYPE_ARGUMENT_AGAINST_NOT_NOTHING_EXPECTED_TYPE!>materialize<!>(), null)
val x7: String? = select(null.<!IMPLICIT_NOTHING_TYPE_ARGUMENT_AGAINST_NOT_NOTHING_EXPECTED_TYPE!>idFromReceiver<!>(), null)
val x8: String? = select(null.<!IMPLICIT_NOTHING_TYPE_ARGUMENT_AGAINST_NOT_NOTHING_EXPECTED_TYPE!>idFromReceiverWithArg<!>(""), null)
val foo = Foo<Nothing?>()
val x9: String? = select(foo.<!IMPLICIT_NOTHING_TYPE_ARGUMENT_AGAINST_NOT_NOTHING_EXPECTED_TYPE!>materialize<!>(), null)
val x10: String? = select(foo.<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>idFromClassTypeArgWithAnotherTypeArg<!>(), null)
val x11: String? = select(foo.idFromClassTypeArg(), null)
foo.run {
val x12: String? = select(<!IMPLICIT_NOTHING_TYPE_ARGUMENT_AGAINST_NOT_NOTHING_EXPECTED_TYPE!>materialize<!>(), null)
val x13: String? = select(<!NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>idFromClassTypeArgWithAnotherTypeArg<!>(), null)
val x14: String? = select(idFromClassTypeArg(), null)
}
val boolean: Boolean? = true
val x15: String? = when (boolean) {
true -> select(<!IMPLICIT_NOTHING_TYPE_ARGUMENT_AGAINST_NOT_NOTHING_EXPECTED_TYPE!>materialize<!>(), null)
false -> select(<!IMPLICIT_NOTHING_TYPE_ARGUMENT_AGAINST_NOT_NOTHING_EXPECTED_TYPE!>materialize<!>(), null)
null -> null
}
val x16: String? = when (boolean) {
true -> null
false -> <!IMPLICIT_NOTHING_TYPE_ARGUMENT_AGAINST_NOT_NOTHING_EXPECTED_TYPE!>materialize<!>()
null -> null
}
val x17: String? = when (boolean) {
true -> if (true) null else <!IMPLICIT_NOTHING_TYPE_ARGUMENT_AGAINST_NOT_NOTHING_EXPECTED_TYPE!>materialize<!>()
false -> if (true) <!IMPLICIT_NOTHING_TYPE_ARGUMENT_AGAINST_NOT_NOTHING_EXPECTED_TYPE!>materialize<!>() else null
null -> if (true) null else null
}
val x18: String? = try {
<!IMPLICIT_NOTHING_TYPE_ARGUMENT_AGAINST_NOT_NOTHING_EXPECTED_TYPE!>materialize<!>()
} catch (e: Exception) {
null
}
val x19: String? = if (true) materialize<Nothing?>() else null
val x20: String? = if (true) materialize<String?>() else null
val x21: String? = if (true) <!IMPLICIT_NOTHING_TYPE_ARGUMENT_IN_RETURN_POSITION!>materialize<!>() else TODO()
val x22: String? = if (true) return else <!IMPLICIT_NOTHING_TYPE_ARGUMENT_IN_RETURN_POSITION!>materialize<!>()
val x23: String? = if (true) <!IMPLICIT_NOTHING_TYPE_ARGUMENT_AGAINST_NOT_NOTHING_EXPECTED_TYPE!>id<!>(null) else null
foo1(if (true) <!IMPLICIT_NOTHING_TYPE_ARGUMENT_AGAINST_NOT_NOTHING_EXPECTED_TYPE!>materialize<!>() else null)
val x24 = id(foo1(if (true) <!IMPLICIT_NOTHING_TYPE_ARGUMENT_AGAINST_NOT_NOTHING_EXPECTED_TYPE!>materialize<!>() else null))
val x25 = select(<!IMPLICIT_NOTHING_TYPE_ARGUMENT_AGAINST_NOT_NOTHING_EXPECTED_TYPE!>materialize<!>(), null).foo2()
// TODO
val x26 = select(materialize(), null).run { foo2() }
val x27: () -> String? = {
id(id(if (true) <!IMPLICIT_NOTHING_TYPE_ARGUMENT_AGAINST_NOT_NOTHING_EXPECTED_TYPE!>materialize<!>() else null))
}
}
fun foo1(x: String?) {}
fun String?.foo2() {}
@@ -0,0 +1,21 @@
package
public fun foo1(/*0*/ x: kotlin.String?): kotlin.Unit
public fun </*0*/ K> id(/*0*/ x: K): K
public fun </*0*/ K> materialize(): K
public fun </*0*/ K, /*1*/ T> materializeWithGenericArg(/*0*/ x: T): K
public fun </*0*/ S> select(/*0*/ x: S, /*1*/ y: S): S
public fun test(): kotlin.Unit
public fun kotlin.String?.foo2(): kotlin.Unit
public fun </*0*/ K> K.idFromReceiver(): K
public fun </*0*/ K> K.idFromReceiverWithArg(/*0*/ x: kotlin.String): K
public final class Foo</*0*/ T> {
public constructor Foo</*0*/ T>()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public final fun idFromClassTypeArg(): T
public final fun </*0*/ K> idFromClassTypeArgWithAnotherTypeArg(): T
public final fun </*0*/ K> materialize(): K
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -40,7 +40,7 @@ class Context<T>
fun <T> Any.decodeIn(typeFrom: Context<in T>): T = something()
fun <T> Any?.decodeOut1(typeFrom: Context<out T>): T {
return <!NI;TYPE_MISMATCH!>this?.<!IMPLICIT_NOTHING_AS_TYPE_PARAMETER, NI;IMPLICIT_NOTHING_AS_TYPE_PARAMETER!>decodeIn<!>(typeFrom) ?: <!OI;TYPE_MISMATCH!>kotlin.Unit<!><!>
return <!NI;TYPE_MISMATCH!>this?.<!IMPLICIT_NOTHING_TYPE_ARGUMENT_IN_RETURN_POSITION!>decodeIn<!>(typeFrom) ?: <!OI;TYPE_MISMATCH!>kotlin.Unit<!><!>
}
fun <T> Any.decodeOut2(typeFrom: Context<out T>): T {
@@ -48,11 +48,11 @@ fun <T> Any.decodeOut2(typeFrom: Context<out T>): T {
}
fun <T> Any.decodeOut3(typeFrom: Context<out T>): T {
<!UNREACHABLE_CODE!>val x =<!> this.<!IMPLICIT_NOTHING_AS_TYPE_PARAMETER!>decodeIn<!>(typeFrom)
<!UNREACHABLE_CODE!>val x =<!> this.<!IMPLICIT_NOTHING_TYPE_ARGUMENT_IN_RETURN_POSITION!>decodeIn<!>(typeFrom)
}
fun <T> Any.decodeOut4(typeFrom: Context<out T>): T {
<!UNREACHABLE_CODE!>val x: Any =<!> this.<!IMPLICIT_NOTHING_AS_TYPE_PARAMETER!>decodeIn<!>(typeFrom)
<!UNREACHABLE_CODE!>val x: Any =<!> this.<!IMPLICIT_NOTHING_TYPE_ARGUMENT_IN_RETURN_POSITION!>decodeIn<!>(typeFrom)
}
class TrieNode<out E> {
@@ -91,7 +91,7 @@ interface Worker<out T>
interface RenderContext<StateT, in OutputT : Any>
val emptyOrNull: List<Nothing>? = null
val x = emptyOrNull?.<!IMPLICIT_NOTHING_AS_TYPE_PARAMETER!>get<!>(0)
val x = emptyOrNull?.<!IMPLICIT_NOTHING_TYPE_ARGUMENT_IN_RETURN_POSITION!>get<!>(0)
val errorCompletion = { <!UNUSED_ANONYMOUS_PARAMETER!>e<!>: Throwable -> throw Exception() }
@@ -18,6 +18,6 @@ private object Scope {
fun <T> materialize(): T = Any() as T
fun test(i: Inv<out Number>) {
val <!UNUSED_VARIABLE!>p<!>: Int by <!IMPLICIT_NOTHING_AS_TYPE_PARAMETER!>Scope.Delegate(i)<!>
val <!UNUSED_VARIABLE!>p<!>: Int by <!IMPLICIT_NOTHING_TYPE_ARGUMENT_IN_RETURN_POSITION!>Scope.Delegate(i)<!>
}
}
@@ -3831,12 +3831,12 @@ fun Nothing.case_63() {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing"), DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>this<!>.hashCode()
hashCode()
<!IMPLICIT_NOTHING_AS_TYPE_PARAMETER!>apply<!> {
<!IMPLICIT_NOTHING_TYPE_ARGUMENT_IN_RETURN_POSITION!>apply<!> {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing"), DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>this<!>
<!UNREACHABLE_CODE!>hashCode()<!>
<!UNREACHABLE_CODE!><!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing"), DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>this<!>.hashCode()<!>
}
<!IMPLICIT_NOTHING_AS_TYPE_PARAMETER!>also<!> {
<!IMPLICIT_NOTHING_TYPE_ARGUMENT_IN_RETURN_POSITION!>also<!> {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!>
<!UNREACHABLE_CODE!><!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>it<!>.hashCode()<!>
}
@@ -23429,9 +23429,14 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
runTest("compiler/testData/diagnostics/tests/typeParameters/functionTypeAsUpperBound.kt");
}
@TestMetadata("implicitNothingAsTypeParameter.kt")
public void testImplicitNothingAsTypeParameter() throws Exception {
runTest("compiler/testData/diagnostics/tests/typeParameters/implicitNothingAsTypeParameter.kt");
@TestMetadata("implicitNothingAgainstNotNothingExpectedType.kt")
public void testImplicitNothingAgainstNotNothingExpectedType() throws Exception {
runTest("compiler/testData/diagnostics/tests/typeParameters/implicitNothingAgainstNotNothingExpectedType.kt");
}
@TestMetadata("implicitNothingInReturnPosition.kt")
public void testImplicitNothingInReturnPosition() throws Exception {
runTest("compiler/testData/diagnostics/tests/typeParameters/implicitNothingInReturnPosition.kt");
}
@TestMetadata("implicitNothingOnDelegates.kt")
@@ -23349,9 +23349,14 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
runTest("compiler/testData/diagnostics/tests/typeParameters/functionTypeAsUpperBound.kt");
}
@TestMetadata("implicitNothingAsTypeParameter.kt")
public void testImplicitNothingAsTypeParameter() throws Exception {
runTest("compiler/testData/diagnostics/tests/typeParameters/implicitNothingAsTypeParameter.kt");
@TestMetadata("implicitNothingAgainstNotNothingExpectedType.kt")
public void testImplicitNothingAgainstNotNothingExpectedType() throws Exception {
runTest("compiler/testData/diagnostics/tests/typeParameters/implicitNothingAgainstNotNothingExpectedType.kt");
}
@TestMetadata("implicitNothingInReturnPosition.kt")
public void testImplicitNothingInReturnPosition() throws Exception {
runTest("compiler/testData/diagnostics/tests/typeParameters/implicitNothingInReturnPosition.kt");
}
@TestMetadata("implicitNothingOnDelegates.kt")