diff --git a/src/main/kotlin/platform/mixin/expression/MEExpressionService.kt b/src/main/kotlin/platform/mixin/expression/MEExpressionService.kt index 5a3408652..473717217 100644 --- a/src/main/kotlin/platform/mixin/expression/MEExpressionService.kt +++ b/src/main/kotlin/platform/mixin/expression/MEExpressionService.kt @@ -22,9 +22,13 @@ package com.demonwav.mcdev.platform.mixin.expression import com.demonwav.mcdev.platform.mixin.util.toPsiType import com.demonwav.mcdev.util.descriptor -import com.intellij.psi.GenericsUtil +import com.intellij.openapi.project.Project import com.intellij.psi.JavaPsiFacade +import com.intellij.psi.PsiClass +import com.intellij.psi.PsiClassType +import com.intellij.psi.PsiElementFactory import com.intellij.psi.PsiManager +import com.intellij.psi.PsiType import com.llamalad7.mixinextras.expression.impl.ExpressionService import com.llamalad7.mixinextras.expression.impl.flow.FlowContext import org.objectweb.asm.Type @@ -34,11 +38,39 @@ object MEExpressionService : ExpressionService() { ctx as MEFlowContext val elementFactory = JavaPsiFacade.getElementFactory(ctx.project) return Type.getType( - GenericsUtil.getLeastUpperBound( - type1.toPsiType(elementFactory), - type2.toPsiType(elementFactory), - PsiManager.getInstance(ctx.project) - )?.descriptor ?: error("Failed to merge types $type1 and $type2!") + getCommonSuperClass( + ctx.project, + type1.toPsiType(elementFactory) as PsiClassType, + type2.toPsiType(elementFactory) as PsiClassType + )?.descriptor ?: error("Could not intersect types $type1 and $type2!") ) } + + // Copied from ClassInfo + private fun getCommonSuperClass( + project: Project, + type1: PsiType, + type2: PsiType + ): PsiClassType? { + val left = (type1 as? PsiClassType)?.resolve() ?: return null + val right = (type2 as? PsiClassType)?.resolve() ?: return null + + fun objectType() = PsiType.getJavaLangObject(PsiManager.getInstance(project), left.resolveScope) + fun PsiClass.type() = PsiElementFactory.getInstance(project).createType(this) + + if (left.isInheritor(right, true)) { + return right.type() + } + if (right.isInheritor(left, true)) { + return left.type() + } + if (left.isInterface || right.isInterface) { + return objectType() + } + + return generateSequence(left) { it.superClass } + .firstOrNull { right.isInheritor(it, true) } + ?.type() + ?: objectType() + } }