[NI] Use alternative to intersection type in public declarations

The new inference uses inferred intersection types normally, unlike the old inference.
However, intersection types in public declarations are approximated to supertype, which
potentially may give a less presice type, then it would be with the OI.
For non-related T1, T2 the NI approximates {T1 & T2} to Any in public declarations,
and if the OI was inferring T1 instead of the intersection type, it may lead to
less precise declaration type and related errors.

The solution is to remember an alternative for an intersection type when present.
Before approximation the alternative replaces the intersection type.

^KT-36249 Fixed
This commit is contained in:
Pavel Kirpichenkov
2020-02-20 19:55:13 +03:00
parent 4038c758ca
commit dc42b20ae3
67 changed files with 2120 additions and 30 deletions
@@ -0,0 +1,18 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER UNUSED_VARIABLE -UNUSED_EXPRESSION
import kotlin.reflect.KClass
fun <T : PsiElement> select(vararg classes: KClass<out T>): T? {
return null
}
interface PomRenameableTarget
interface PsiElement
interface PsiMethod : PsiElement, PomRenameableTarget
interface PsiClass : PsiElement, PomRenameableTarget
class A {
val inv get() = select(PsiMethod::class, PsiClass::class)
}
fun main() {
A().inv
}
@@ -0,0 +1,18 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER UNUSED_VARIABLE -UNUSED_EXPRESSION
import kotlin.reflect.KClass
fun <T : PsiElement> select(vararg classes: KClass<out T>): T? {
return null
}
interface PomRenameableTarget
interface PsiElement
interface PsiMethod : PsiElement, PomRenameableTarget
interface PsiClass : PsiElement, PomRenameableTarget
class A {
val inv get() = select(PsiMethod::class, PsiClass::class)
}
fun main() {
<!DEBUG_INFO_EXPRESSION_TYPE("PsiElement?")!>A().inv<!>
}
@@ -0,0 +1,36 @@
package
public fun main(): kotlin.Unit
public fun </*0*/ T : PsiElement> select(/*0*/ vararg classes: kotlin.reflect.KClass<out T> /*kotlin.Array<out kotlin.reflect.KClass<out T>>*/): T?
public final class A {
public constructor A()
public final val inv: PsiElement?
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 open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface PomRenameableTarget {
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 open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface PsiClass : PsiElement, PomRenameableTarget {
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface PsiElement {
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 open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface PsiMethod : PsiElement, PomRenameableTarget {
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
}