Optimize external overridability conditions
- Skip ones that can lead only to success after first success - And vice versa
This commit is contained in:
+6
-5
@@ -46,15 +46,16 @@ public class SamAdapterOverridabilityCondition implements ExternalOverridability
|
||||
return subOriginal == null ? Result.UNKNOWN : Result.INCOMPATIBLE; // DECLARATION can override anything
|
||||
}
|
||||
|
||||
OverridingUtil.OverrideCompatibilityInfo basicResult = OverridingUtil.DEFAULT
|
||||
.isOverridableByWithoutExternalConditions(superDescriptor, subDescriptor, /* checkReturnType = */ false);
|
||||
|
||||
if (basicResult.getResult() != OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE) return Result.UNKNOWN;
|
||||
|
||||
// inheritor if SYNTHESIZED can override inheritor of SYNTHESIZED if their originals have same erasure
|
||||
return equalErasure(superOriginal, subOriginal) ? Result.UNKNOWN : Result.INCOMPATIBLE;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Contract getContract() {
|
||||
return Contract.CONFLICTS_ONLY;
|
||||
}
|
||||
|
||||
private static boolean equalErasure(@NotNull FunctionDescriptor fun1, @NotNull FunctionDescriptor fun2) {
|
||||
List<ValueParameterDescriptor> parameters1 = fun1.getValueParameters();
|
||||
List<ValueParameterDescriptor> parameters2 = fun2.getValueParameters();
|
||||
|
||||
+2
@@ -64,4 +64,6 @@ class BuiltinOverridabilityCondition : ExternalOverridabilityCondition {
|
||||
// incompatible override
|
||||
return Result.INCOMPATIBLE
|
||||
}
|
||||
|
||||
override fun getContract() = ExternalOverridabilityCondition.Contract.CONFLICTS_ONLY
|
||||
}
|
||||
|
||||
+2
@@ -43,4 +43,6 @@ class ErasedOverridabilityCondition : ExternalOverridabilityCondition {
|
||||
else -> Result.UNKNOWN
|
||||
}
|
||||
}
|
||||
|
||||
override fun getContract() = ExternalOverridabilityCondition.Contract.SUCCESS_ONLY
|
||||
}
|
||||
|
||||
+2
@@ -33,4 +33,6 @@ class FieldOverridabilityCondition : ExternalOverridabilityCondition {
|
||||
|
||||
return Result.UNKNOWN
|
||||
}
|
||||
|
||||
override fun getContract() = ExternalOverridabilityCondition.Contract.BOTH
|
||||
}
|
||||
|
||||
@@ -26,10 +26,17 @@ public interface ExternalOverridabilityCondition {
|
||||
OVERRIDABLE, CONFLICT, INCOMPATIBLE, UNKNOWN
|
||||
}
|
||||
|
||||
enum Contract {
|
||||
CONFLICTS_ONLY, SUCCESS_ONLY, BOTH
|
||||
}
|
||||
|
||||
@NotNull
|
||||
Result isOverridable(
|
||||
@NotNull CallableDescriptor superDescriptor,
|
||||
@NotNull CallableDescriptor subDescriptor,
|
||||
@Nullable ClassDescriptor subClassDescriptor
|
||||
);
|
||||
|
||||
@NotNull
|
||||
Contract getContract();
|
||||
}
|
||||
|
||||
@@ -84,13 +84,20 @@ public class OverridingUtil {
|
||||
@Nullable ClassDescriptor subClassDescriptor,
|
||||
boolean checkReturnType
|
||||
) {
|
||||
boolean wasSuccessfulExternalCondition = false;
|
||||
OverrideCompatibilityInfo basicResult = isOverridableByWithoutExternalConditions(superDescriptor, subDescriptor, checkReturnType);
|
||||
boolean wasSuccess = basicResult.getResult() == OVERRIDABLE;
|
||||
|
||||
for (ExternalOverridabilityCondition externalCondition : EXTERNAL_CONDITIONS) {
|
||||
// Do not run CONFLICTS_ONLY while there was no success
|
||||
if (externalCondition.getContract() == ExternalOverridabilityCondition.Contract.CONFLICTS_ONLY) continue;
|
||||
if (wasSuccess && externalCondition.getContract() == ExternalOverridabilityCondition.Contract.SUCCESS_ONLY) continue;
|
||||
|
||||
ExternalOverridabilityCondition.Result result =
|
||||
externalCondition.isOverridable(superDescriptor, subDescriptor, subClassDescriptor);
|
||||
|
||||
switch (result) {
|
||||
case OVERRIDABLE:
|
||||
wasSuccessfulExternalCondition = true;
|
||||
wasSuccess = true;
|
||||
break;
|
||||
case CONFLICT:
|
||||
return OverrideCompatibilityInfo.conflict("External condition failed");
|
||||
@@ -102,11 +109,32 @@ public class OverridingUtil {
|
||||
}
|
||||
}
|
||||
|
||||
if (wasSuccessfulExternalCondition) {
|
||||
return OverrideCompatibilityInfo.success();
|
||||
if (!wasSuccess) {
|
||||
return basicResult;
|
||||
}
|
||||
|
||||
return isOverridableByWithoutExternalConditions(superDescriptor, subDescriptor, checkReturnType);
|
||||
// Search for conflicts from external conditions
|
||||
for (ExternalOverridabilityCondition externalCondition : EXTERNAL_CONDITIONS) {
|
||||
// Run all conditions that was not run before (i.e. CONFLICTS_ONLY)
|
||||
if (externalCondition.getContract() != ExternalOverridabilityCondition.Contract.CONFLICTS_ONLY) continue;
|
||||
|
||||
ExternalOverridabilityCondition.Result result =
|
||||
externalCondition.isOverridable(superDescriptor, subDescriptor, subClassDescriptor);
|
||||
switch (result) {
|
||||
case CONFLICT:
|
||||
return OverrideCompatibilityInfo.conflict("External condition failed");
|
||||
case INCOMPATIBLE:
|
||||
return OverrideCompatibilityInfo.incompatible("External condition");
|
||||
case OVERRIDABLE:
|
||||
throw new IllegalStateException(
|
||||
"Contract violation in " + externalCondition.getClass().getName() + " condition. It's not supposed to end with success");
|
||||
case UNKNOWN:
|
||||
// do nothing
|
||||
// go to the next external condition or default override check
|
||||
}
|
||||
}
|
||||
|
||||
return OverrideCompatibilityInfo.success();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
Reference in New Issue
Block a user