Jvm Codegen: do not throw on malformed delegation to a type parameter
Fix exception on light class building See KT-15931
This commit is contained in:
@@ -1105,9 +1105,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
private final Map<KtDelegatedSuperTypeEntry, Field> fields = new HashMap<>();
|
||||
|
||||
@NotNull
|
||||
@Nullable
|
||||
public Field getInfo(KtDelegatedSuperTypeEntry specifier) {
|
||||
return fields.get(specifier);
|
||||
Field field = fields.get(specifier);
|
||||
assert field != null || state.getClassBuilderMode() == ClassBuilderMode.LIGHT_CLASSES : "No field for " + specifier.getText();
|
||||
return field;
|
||||
}
|
||||
|
||||
private void addField(KtDelegatedSuperTypeEntry specifier, PropertyDescriptor propertyDescriptor) {
|
||||
@@ -1127,22 +1129,24 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
for (KtSuperTypeListEntry specifier : delegationSpecifiers) {
|
||||
if (specifier instanceof KtDelegatedSuperTypeEntry) {
|
||||
KtExpression expression = ((KtDelegatedSuperTypeEntry) specifier).getDelegateExpression();
|
||||
PropertyDescriptor propertyDescriptor = expression != null
|
||||
? CodegenUtil.getDelegatePropertyIfAny(expression, descriptor, bindingContext)
|
||||
: null;
|
||||
if (expression == null) continue;
|
||||
|
||||
PropertyDescriptor propertyDescriptor = CodegenUtil.getDelegatePropertyIfAny(expression, descriptor, bindingContext);
|
||||
|
||||
|
||||
if (CodegenUtil.isFinalPropertyWithBackingField(propertyDescriptor, bindingContext)) {
|
||||
result.addField((KtDelegatedSuperTypeEntry) specifier, propertyDescriptor);
|
||||
}
|
||||
else {
|
||||
KotlinType expressionType = expression != null
|
||||
? bindingContext.getType(expression)
|
||||
: null;
|
||||
KotlinType expressionType = bindingContext.getType(expression);
|
||||
ClassDescriptor superClass = getSuperClass(specifier);
|
||||
if (superClass != null) {
|
||||
Type asmType = expressionType != null ? typeMapper.mapType(expressionType) : typeMapper.mapType(superClass);
|
||||
result.addField((KtDelegatedSuperTypeEntry) specifier, asmType, JvmAbi.DELEGATE_SUPER_FIELD_PREFIX + n);
|
||||
}
|
||||
Type asmType =
|
||||
expressionType != null ? typeMapper.mapType(expressionType) :
|
||||
superClass != null ? typeMapper.mapType(superClass) : null;
|
||||
|
||||
if (asmType == null) continue;
|
||||
|
||||
result.addField((KtDelegatedSuperTypeEntry) specifier, asmType, JvmAbi.DELEGATE_SUPER_FIELD_PREFIX + n);
|
||||
}
|
||||
n++;
|
||||
}
|
||||
@@ -1152,7 +1156,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
@Nullable
|
||||
private ClassDescriptor getSuperClass(@NotNull KtSuperTypeListEntry specifier) {
|
||||
return CodegenUtil.getSuperClassBySuperTypeListEntry(specifier, bindingContext);
|
||||
ClassDescriptor superClass = CodegenUtil.getSuperClassBySuperTypeListEntry(specifier, bindingContext);
|
||||
|
||||
assert superClass != null || state.getClassBuilderMode() == ClassBuilderMode.LIGHT_CLASSES
|
||||
: "ClassDescriptor should not be null:" + specifier.getText();
|
||||
return superClass;
|
||||
}
|
||||
|
||||
private void genCallToDelegatorByExpressionSpecifier(
|
||||
@@ -1164,6 +1172,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
KtExpression expression = specifier.getDelegateExpression();
|
||||
|
||||
DelegationFieldsInfo.Field fieldInfo = fieldsInfo.getInfo(specifier);
|
||||
if (fieldInfo == null) return;
|
||||
|
||||
if (fieldInfo.generateField) {
|
||||
iv.load(0, classAsmType);
|
||||
fieldInfo.getStackValue().store(codegen.gen(expression), iv);
|
||||
@@ -1609,10 +1619,15 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
for (KtSuperTypeListEntry specifier : myClass.getSuperTypeListEntries()) {
|
||||
if (specifier instanceof KtDelegatedSuperTypeEntry) {
|
||||
DelegationFieldsInfo.Field field = delegationFieldsInfo.getInfo((KtDelegatedSuperTypeEntry) specifier);
|
||||
if (field == null) continue;
|
||||
|
||||
generateDelegateField(field);
|
||||
KtExpression delegateExpression = ((KtDelegatedSuperTypeEntry) specifier).getDelegateExpression();
|
||||
KotlinType delegateExpressionType = delegateExpression != null ? bindingContext.getType(delegateExpression) : null;
|
||||
generateDelegates(getSuperClass(specifier), delegateExpressionType, field);
|
||||
ClassDescriptor superClass = getSuperClass(specifier);
|
||||
if (superClass == null) continue;
|
||||
|
||||
generateDelegates(superClass, delegateExpressionType, field);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package c
|
||||
|
||||
class C<T>: <error>T</error> by <error>{
|
||||
}</error>
|
||||
|
||||
class D<T>: <error>T</error> by<EOLError></EOLError>
|
||||
|
||||
class G<T> : <error>T</error> by <error>{
|
||||
|
||||
val c = 3
|
||||
}</error>
|
||||
|
||||
interface I
|
||||
|
||||
class A<T : I>(a: T) : <error>T</error> by a
|
||||
@@ -551,6 +551,12 @@ public class PsiCheckerTestGenerated extends AbstractPsiCheckerTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("IncompleteClassDelegation.kt")
|
||||
public void testIncompleteClassDelegation() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/checker/regression/IncompleteClassDelegation.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("InitializerInInterface.kt")
|
||||
public void testInitializerInInterface() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/checker/regression/InitializerInInterface.kt");
|
||||
|
||||
+1
@@ -94,6 +94,7 @@ class DelegationTranslator(
|
||||
|
||||
private fun getSuperClass(specifier: KtSuperTypeListEntry): ClassDescriptor? =
|
||||
CodegenUtil.getSuperClassBySuperTypeListEntry(specifier, bindingContext())
|
||||
?: error("ClassDescriptor of superType should not be null: ${specifier.text}")
|
||||
|
||||
private fun generateDelegates(specifier: KtSuperTypeListEntry, toClass: ClassDescriptor, field: Field) {
|
||||
for ((descriptor, overriddenDescriptor) in DelegationResolver.getDelegates(classDescriptor, toClass)) {
|
||||
|
||||
Reference in New Issue
Block a user