KT-315 I need list of FunctionDEscriptors to be taken from traits

This commit is contained in:
Andrey Breslav
2011-09-22 19:41:38 +04:00
parent 2b7f892c4a
commit 29470fa1d1
7 changed files with 215 additions and 151 deletions
@@ -165,4 +165,24 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements
return visitor.visitFunctionDescriptor(this, data); return visitor.visitFunctionDescriptor(this, data);
} }
// @Override
// public boolean equals(Object obj) {
// if (obj == null) return false;
// if (obj.getClass() != FunctionDescriptorImpl.class) return false;
// FunctionDescriptorImpl other = (FunctionDescriptorImpl) obj;
// if (!eq(this.getName(), other.getName())) return false;
// if (!eq(this.getContainingDeclaration(), other.getContainingDeclaration())) return false;
//
// }
//
// private static boolean eq(Object a, Object b) {
// if (a == null) return b == null;
// if (b == null) return false;
// return a.equals(b);
// }
//
// @Override
// public int hashCode() {
// return super.hashCode(); // TODO
// }
} }
@@ -1,8 +1,5 @@
package org.jetbrains.jet.lang.descriptors; package org.jetbrains.jet.lang.descriptors;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.Maps;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.BindingTrace;
@@ -112,125 +109,4 @@ public class FunctionDescriptorUtil {
return parameterScope; return parameterScope;
} }
public static class OverrideCompatibilityInfo {
private static final OverrideCompatibilityInfo SUCCESS = new OverrideCompatibilityInfo(false, "SUCCESS");
@NotNull
public static OverrideCompatibilityInfo nameMismatch() {
return new OverrideCompatibilityInfo(true, "nameMismatch"); // TODO
}
@NotNull
public static OverrideCompatibilityInfo typeParameterNumberMismatch() {
return new OverrideCompatibilityInfo(true, "typeParameterNumberMismatch"); // TODO
}
@NotNull
public static OverrideCompatibilityInfo valueParameterNumberMismatch() {
return new OverrideCompatibilityInfo(true, "valueParameterNumberMismatch"); // TODO
}
@NotNull
public static OverrideCompatibilityInfo boundsMismatch(TypeParameterDescriptor superTypeParameter, TypeParameterDescriptor subTypeParameter) {
return new OverrideCompatibilityInfo(true, "boundsMismatch"); // TODO
}
@NotNull
public static OverrideCompatibilityInfo valueParameterTypeMismatch(ValueParameterDescriptor superValueParameter, ValueParameterDescriptor subValueParameter) {
return new OverrideCompatibilityInfo(true, "valueParameterTypeMismatch"); // TODO
}
@NotNull
public static OverrideCompatibilityInfo returnTypeMismatch(JetType substitutedSuperReturnType, JetType unsubstitutedSubReturnType) {
return new OverrideCompatibilityInfo(true, "returnTypeMismatch: " + unsubstitutedSubReturnType + " >< " + substitutedSuperReturnType); // TODO
}
@NotNull
public static OverrideCompatibilityInfo success() {
return SUCCESS;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private final boolean isError;
private final String message;
public OverrideCompatibilityInfo(boolean error, String message) {
isError = error;
this.message = message;
}
public boolean isSuccess() {
return !isError;
}
public String getMessage() {
return message;
}
}
@NotNull
public static OverrideCompatibilityInfo isOverridableBy(@NotNull JetTypeChecker typeChecker, @NotNull FunctionDescriptor superFunction, @NotNull FunctionDescriptor subFunction) {
if (!superFunction.getName().equals(subFunction.getName())) {
return OverrideCompatibilityInfo.nameMismatch();
}
// TODO : Visibility
if (superFunction.getTypeParameters().size() != subFunction.getTypeParameters().size()) {
return OverrideCompatibilityInfo.typeParameterNumberMismatch();
}
if (superFunction.getValueParameters().size() != subFunction.getValueParameters().size()) {
return OverrideCompatibilityInfo.valueParameterNumberMismatch();
}
List<TypeParameterDescriptor> superTypeParameters = superFunction.getTypeParameters();
List<TypeParameterDescriptor> subTypeParameters = subFunction.getTypeParameters();
Map<TypeConstructor, TypeProjection> substitutionContext = Maps.newHashMap();
BiMap<TypeConstructor, TypeConstructor> axioms = HashBiMap.create();
for (int i = 0, typeParametersSize = superTypeParameters.size(); i < typeParametersSize; i++) {
TypeParameterDescriptor superTypeParameter = superTypeParameters.get(i);
TypeParameterDescriptor subTypeParameter = subTypeParameters.get(i);
substitutionContext.put(
superTypeParameter.getTypeConstructor(),
new TypeProjection(subTypeParameter.getDefaultType()));
axioms.put(superTypeParameter.getTypeConstructor(), subTypeParameter.getTypeConstructor());
}
for (int i = 0, typeParametersSize = superTypeParameters.size(); i < typeParametersSize; i++) {
TypeParameterDescriptor superTypeParameter = superTypeParameters.get(i);
TypeParameterDescriptor subTypeParameter = subTypeParameters.get(i);
if (!JetTypeImpl.equalTypes(superTypeParameter.getBoundsAsType(), subTypeParameter.getBoundsAsType(), axioms)) {
return OverrideCompatibilityInfo.boundsMismatch(superTypeParameter, subTypeParameter);
}
}
List<ValueParameterDescriptor> superValueParameters = superFunction.getValueParameters();
List<ValueParameterDescriptor> subValueParameters = subFunction.getValueParameters();
for (int i = 0, unsubstitutedValueParametersSize = superValueParameters.size(); i < unsubstitutedValueParametersSize; i++) {
ValueParameterDescriptor superValueParameter = superValueParameters.get(i);
ValueParameterDescriptor subValueParameter = subValueParameters.get(i);
if (!JetTypeImpl.equalTypes(superValueParameter.getOutType(), subValueParameter.getOutType(), axioms)) {
return OverrideCompatibilityInfo.valueParameterTypeMismatch(superValueParameter, subValueParameter);
}
}
// TODO : Default values, varargs etc
TypeSubstitutor typeSubstitutor = TypeSubstitutor.create(substitutionContext);
JetType substitutedSuperReturnType = typeSubstitutor.substitute(superFunction.getReturnType(), Variance.OUT_VARIANCE);
assert substitutedSuperReturnType != null;
if (!typeChecker.isSubtypeOf(subFunction.getReturnType(), substitutedSuperReturnType)) {
return OverrideCompatibilityInfo.returnTypeMismatch(substitutedSuperReturnType, subFunction.getReturnType());
}
return OverrideCompatibilityInfo.success();
}
} }
@@ -8,7 +8,6 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.JetTypeChecker;
import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.lexer.JetTokens;
import java.util.Collection; import java.util.Collection;
@@ -66,7 +65,7 @@ public class OverrideResolver {
private FunctionDescriptor findFunctionOverridableBy(@NotNull FunctionDescriptor declaredFunction, @NotNull JetType supertype) { private FunctionDescriptor findFunctionOverridableBy(@NotNull FunctionDescriptor declaredFunction, @NotNull JetType supertype) {
FunctionGroup functionGroup = supertype.getMemberScope().getFunctionGroup(declaredFunction.getName()); FunctionGroup functionGroup = supertype.getMemberScope().getFunctionGroup(declaredFunction.getName());
for (FunctionDescriptor functionDescriptor : functionGroup.getFunctionDescriptors()) { for (FunctionDescriptor functionDescriptor : functionGroup.getFunctionDescriptors()) {
if (FunctionDescriptorUtil.isOverridableBy(context.getSemanticServices().getTypeChecker(), functionDescriptor, declaredFunction).isSuccess()) { if (OverridingUtil.isOverridableBy(context.getSemanticServices().getTypeChecker(), functionDescriptor, declaredFunction).isSuccess()) {
return functionDescriptor; return functionDescriptor;
} }
} }
@@ -79,26 +78,12 @@ public class OverrideResolver {
if (property == null) { if (property == null) {
return null; return null;
} }
if (isOverridableBy(property, declaredProperty)) { if (OverridingUtil.isOverridableBy(context.getSemanticServices().getTypeChecker(), property, declaredProperty).isSuccess()) {
return property; return property;
} }
return null; return null;
} }
private boolean isOverridableBy(@NotNull PropertyDescriptor property, @NotNull PropertyDescriptor overrideCandidate) {
boolean var = property.isVar();
if (var && !overrideCandidate.isVar()) return false;
JetType propertyType = property.getReturnType();
JetType overrideType = overrideCandidate.getReturnType();
JetTypeChecker typeChecker = context.getSemanticServices().getTypeChecker();
if (var) {
return typeChecker.equalTypes(propertyType, overrideType);
}
else {
return typeChecker.isSubtypeOf(overrideType, propertyType);
}
}
private void checkOverrides() { private void checkOverrides() {
for (Map.Entry<JetClass, MutableClassDescriptor> entry : context.getClasses().entrySet()) { for (Map.Entry<JetClass, MutableClassDescriptor> entry : context.getClasses().entrySet()) {
checkOverridesInAClass(entry.getValue(), entry.getKey()); checkOverridesInAClass(entry.getValue(), entry.getKey());
@@ -109,6 +94,30 @@ public class OverrideResolver {
} }
protected void checkOverridesInAClass(MutableClassDescriptor classDescriptor, JetClassOrObject klass) { protected void checkOverridesInAClass(MutableClassDescriptor classDescriptor, JetClassOrObject klass) {
Set<FunctionDescriptor> inheritedFunctions = Sets.newLinkedHashSet();
Set<PropertyDescriptor> inheritedProperties = Sets.newLinkedHashSet();
for (JetType supertype : classDescriptor.getSupertypes()) {
for (DeclarationDescriptor descriptor : supertype.getMemberScope().getAllDescriptors()) {
if (descriptor instanceof FunctionDescriptor) {
FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor;
inheritedFunctions.add(functionDescriptor);
}
else if (descriptor instanceof PropertyDescriptor) {
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
inheritedProperties.add(propertyDescriptor);
}
}
}
OverridingUtil.filterOverrides(inheritedFunctions);
OverridingUtil.filterOverrides(inheritedProperties);
// System.out.println(classDescriptor);
// println(inheritedFunctions);
// println(inheritedProperties);
for (FunctionDescriptor declaredFunction : classDescriptor.getFunctions()) { for (FunctionDescriptor declaredFunction : classDescriptor.getFunctions()) {
checkOverrideForFunction(declaredFunction); checkOverrideForFunction(declaredFunction);
} }
@@ -151,6 +160,12 @@ public class OverrideResolver {
} }
} }
private void println(Set<? extends CallableDescriptor> inheritedProperties) {
for (CallableDescriptor inheritedProperty : inheritedProperties) {
System.out.println(" " + inheritedProperty);
}
}
private void checkOverrideForFunction(FunctionDescriptor declaredFunction) { private void checkOverrideForFunction(FunctionDescriptor declaredFunction) {
JetFunction function = (JetFunction) context.getTrace().get(BindingContext.DESCRIPTOR_TO_DECLARATION, declaredFunction); JetFunction function = (JetFunction) context.getTrace().get(BindingContext.DESCRIPTOR_TO_DECLARATION, declaredFunction);
@@ -1,10 +1,16 @@
package org.jetbrains.jet.lang.resolve; package org.jetbrains.jet.lang.resolve;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.types.*;
import java.util.Collection; import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
/** /**
@@ -17,21 +23,40 @@ public class OverridingUtil {
Set<CallableDescriptor> allMembers = Sets.newLinkedHashSet(); Set<CallableDescriptor> allMembers = Sets.newLinkedHashSet();
for (DeclarationDescriptor descriptor : allDescriptors) { for (DeclarationDescriptor descriptor : allDescriptors) {
assert !(descriptor instanceof ConstructorDescriptor); assert !(descriptor instanceof ConstructorDescriptor);
if (descriptor instanceof CallableDescriptor) { if (descriptor instanceof CallableDescriptor && descriptor instanceof MemberDescriptor) {
CallableDescriptor callableDescriptor = (CallableDescriptor) descriptor; CallableDescriptor callableDescriptor = (CallableDescriptor) descriptor;
allMembers.add(callableDescriptor); if (((MemberDescriptor) descriptor).getModality() != Modality.ABSTRACT) {
allMembers.add(callableDescriptor);
}
} }
} }
return filterOverrides(allMembers); return filterOverrides(allMembers);
} }
public static <D extends CallableDescriptor> Set<D> filterOverrides(Set<D> candidateSet) { public static <D extends CallableDescriptor> Set<D> filterOverrides(Set<D> candidateSet) {
Set<D> candidates = Sets.newLinkedHashSet(candidateSet); Set<D> candidates = Sets.newLinkedHashSet();
for (D descriptor : candidateSet) { outerLoop:
Set<CallableDescriptor> overriddenDescriptors = Sets.newHashSet(); for (D me : candidateSet) {
getAllOverriddenDescriptors(descriptor.getOriginal(), overriddenDescriptors); for (D other : candidateSet) {
candidates.removeAll(overriddenDescriptors); if (me == other) continue;
if (overrides(other, me)) {
continue outerLoop;
}
if (me.getOriginal() == other.getOriginal()
&& isOverridableBy(JetTypeChecker.INSTANCE, other, me).isSuccess()
&& isOverridableBy(JetTypeChecker.INSTANCE, me, other).isSuccess()) {
continue outerLoop;
}
}
// System.out.println(me);
candidates.add(me);
} }
// Set<D> candidates = Sets.newLinkedHashSet(candidateSet);
// for (D descriptor : candidateSet) {
// Set<CallableDescriptor> overriddenDescriptors = Sets.newHashSet();
// getAllOverriddenDescriptors(descriptor.getOriginal(), overriddenDescriptors);
// candidates.removeAll(overriddenDescriptors);
// }
return candidates; return candidates;
} }
@@ -52,4 +77,130 @@ public class OverridingUtil {
overriddenDescriptors.add(descriptor); overriddenDescriptors.add(descriptor);
} }
} }
@NotNull
public static OverrideCompatibilityInfo isOverridableBy(@NotNull JetTypeChecker typeChecker, @NotNull CallableDescriptor superDescriptor, @NotNull CallableDescriptor subDescriptor) {
if (!superDescriptor.getName().equals(subDescriptor.getName())) {
return OverrideCompatibilityInfo.nameMismatch();
}
// TODO : Visibility
if (superDescriptor.getTypeParameters().size() != subDescriptor.getTypeParameters().size()) {
return OverrideCompatibilityInfo.typeParameterNumberMismatch();
}
if (superDescriptor.getValueParameters().size() != subDescriptor.getValueParameters().size()) {
return OverrideCompatibilityInfo.valueParameterNumberMismatch();
}
List<TypeParameterDescriptor> superTypeParameters = superDescriptor.getTypeParameters();
List<TypeParameterDescriptor> subTypeParameters = subDescriptor.getTypeParameters();
Map<TypeConstructor, TypeProjection> substitutionContext = Maps.newHashMap();
BiMap<TypeConstructor, TypeConstructor> axioms = HashBiMap.create();
for (int i = 0, typeParametersSize = superTypeParameters.size(); i < typeParametersSize; i++) {
TypeParameterDescriptor superTypeParameter = superTypeParameters.get(i);
TypeParameterDescriptor subTypeParameter = subTypeParameters.get(i);
substitutionContext.put(
superTypeParameter.getTypeConstructor(),
new TypeProjection(subTypeParameter.getDefaultType()));
axioms.put(superTypeParameter.getTypeConstructor(), subTypeParameter.getTypeConstructor());
}
for (int i = 0, typeParametersSize = superTypeParameters.size(); i < typeParametersSize; i++) {
TypeParameterDescriptor superTypeParameter = superTypeParameters.get(i);
TypeParameterDescriptor subTypeParameter = subTypeParameters.get(i);
if (!JetTypeImpl.equalTypes(superTypeParameter.getBoundsAsType(), subTypeParameter.getBoundsAsType(), axioms)) {
return OverrideCompatibilityInfo.boundsMismatch(superTypeParameter, subTypeParameter);
}
}
List<ValueParameterDescriptor> superValueParameters = superDescriptor.getValueParameters();
List<ValueParameterDescriptor> subValueParameters = subDescriptor.getValueParameters();
for (int i = 0, unsubstitutedValueParametersSize = superValueParameters.size(); i < unsubstitutedValueParametersSize; i++) {
ValueParameterDescriptor superValueParameter = superValueParameters.get(i);
ValueParameterDescriptor subValueParameter = subValueParameters.get(i);
if (!JetTypeImpl.equalTypes(superValueParameter.getOutType(), subValueParameter.getOutType(), axioms)) {
return OverrideCompatibilityInfo.valueParameterTypeMismatch(superValueParameter, subValueParameter);
}
}
// TODO : Default values, varargs etc
TypeSubstitutor typeSubstitutor = TypeSubstitutor.create(substitutionContext);
JetType substitutedSuperReturnType = typeSubstitutor.substitute(superDescriptor.getReturnType(), Variance.OUT_VARIANCE);
assert substitutedSuperReturnType != null;
if (!typeChecker.isSubtypeOf(subDescriptor.getReturnType(), substitutedSuperReturnType)) {
return OverrideCompatibilityInfo.returnTypeMismatch(substitutedSuperReturnType, subDescriptor.getReturnType());
}
return OverrideCompatibilityInfo.success();
}
public static class OverrideCompatibilityInfo {
private static final OverrideCompatibilityInfo SUCCESS = new OverrideCompatibilityInfo(true, "SUCCESS");
@NotNull
public static OverrideCompatibilityInfo success() {
return SUCCESS;
}
@NotNull
public static OverrideCompatibilityInfo nameMismatch() {
return new OverrideCompatibilityInfo(false, "nameMismatch"); // TODO
}
@NotNull
public static OverrideCompatibilityInfo typeParameterNumberMismatch() {
return new OverrideCompatibilityInfo(false, "typeParameterNumberMismatch"); // TODO
}
@NotNull
public static OverrideCompatibilityInfo valueParameterNumberMismatch() {
return new OverrideCompatibilityInfo(false, "valueParameterNumberMismatch"); // TODO
}
@NotNull
public static OverrideCompatibilityInfo boundsMismatch(TypeParameterDescriptor superTypeParameter, TypeParameterDescriptor subTypeParameter) {
return new OverrideCompatibilityInfo(false, "boundsMismatch"); // TODO
}
@NotNull
public static OverrideCompatibilityInfo valueParameterTypeMismatch(ValueParameterDescriptor superValueParameter, ValueParameterDescriptor subValueParameter) {
return new OverrideCompatibilityInfo(false, "valueParameterTypeMismatch"); // TODO
}
@NotNull
public static OverrideCompatibilityInfo returnTypeMismatch(JetType substitutedSuperReturnType, JetType unsubstitutedSubReturnType) {
return new OverrideCompatibilityInfo(false, "returnTypeMismatch: " + unsubstitutedSubReturnType + " >< " + substitutedSuperReturnType); // TODO
}
@NotNull
public static OverrideCompatibilityInfo varOverriddenByVal() {
return new OverrideCompatibilityInfo(false, "varOverriddenByVal"); // TODO
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private final boolean isSuccess;
private final String message;
public OverrideCompatibilityInfo(boolean success, String message) {
isSuccess = success;
this.message = message;
}
public boolean isSuccess() {
return isSuccess;
}
public String getMessage() {
return message;
}
}
} }
@@ -19,7 +19,7 @@ import java.util.Map;
/** /**
* @author abreslav * @author abreslav
*/ */
/*package*/ class OverloadingConflictResolver { public class OverloadingConflictResolver {
private final JetSemanticServices semanticServices; private final JetSemanticServices semanticServices;
@@ -200,6 +200,7 @@ public class DescriptorRenderer {
@Override @Override
public Void visitFunctionDescriptor(FunctionDescriptor descriptor, StringBuilder builder) { public Void visitFunctionDescriptor(FunctionDescriptor descriptor, StringBuilder builder) {
renderModality(descriptor.getModality(), builder);
builder.append(renderKeyword("fun")).append(" "); builder.append(renderKeyword("fun")).append(" ");
renderTypeParameters(descriptor.getTypeParameters(), builder); renderTypeParameters(descriptor.getTypeParameters(), builder);
@@ -275,6 +276,7 @@ public class DescriptorRenderer {
} }
public void renderClassDescriptor(ClassDescriptor descriptor, StringBuilder builder, String keyword) { public void renderClassDescriptor(ClassDescriptor descriptor, StringBuilder builder, String keyword) {
renderModality(descriptor.getModality(), builder);
builder.append(renderKeyword(keyword)).append(" "); builder.append(renderKeyword(keyword)).append(" ");
renderName(descriptor, builder); renderName(descriptor, builder);
renderTypeParameters(descriptor.getTypeConstructor().getParameters(), builder); renderTypeParameters(descriptor.getTypeConstructor().getParameters(), builder);
@@ -5,11 +5,11 @@ import com.intellij.openapi.application.PathManager;
import org.jetbrains.jet.JetTestUtils; import org.jetbrains.jet.JetTestUtils;
import org.jetbrains.jet.lang.JetSemanticServices; import org.jetbrains.jet.lang.JetSemanticServices;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptorUtil;
import org.jetbrains.jet.lang.descriptors.ModuleDescriptor; import org.jetbrains.jet.lang.descriptors.ModuleDescriptor;
import org.jetbrains.jet.lang.psi.JetPsiFactory; import org.jetbrains.jet.lang.psi.JetPsiFactory;
import org.jetbrains.jet.lang.psi.JetNamedFunction; import org.jetbrains.jet.lang.psi.JetNamedFunction;
import org.jetbrains.jet.lang.resolve.ClassDescriptorResolver; import org.jetbrains.jet.lang.resolve.ClassDescriptorResolver;
import org.jetbrains.jet.lang.resolve.OverridingUtil;
import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.parsing.JetParsingTest; import org.jetbrains.jet.parsing.JetParsingTest;
@@ -139,7 +139,7 @@ public class JetOverridingTest extends LightDaemonAnalyzerTestCase {
private void assertOverridabilityRelation(String superFun, String subFun, boolean expectedIsError) { private void assertOverridabilityRelation(String superFun, String subFun, boolean expectedIsError) {
FunctionDescriptor a = makeFunction(superFun); FunctionDescriptor a = makeFunction(superFun);
FunctionDescriptor b = makeFunction(subFun); FunctionDescriptor b = makeFunction(subFun);
FunctionDescriptorUtil.OverrideCompatibilityInfo overridableWith = FunctionDescriptorUtil.isOverridableBy(semanticServices.getTypeChecker(), a, b); OverridingUtil.OverrideCompatibilityInfo overridableWith = OverridingUtil.isOverridableBy(semanticServices.getTypeChecker(), a, b);
assertEquals(overridableWith.getMessage(), expectedIsError, !overridableWith.isSuccess()); assertEquals(overridableWith.getMessage(), expectedIsError, !overridableWith.isSuccess());
} }