report conflicting overloads in functions with same parameters different type parameters
test case:
===
class Aaa() {
fun f() = 1
fun <P> f() = 1
}
===
This commit is contained in:
@@ -28,7 +28,7 @@ public class OverloadUtil {
|
||||
*/
|
||||
public static OverloadCompatibilityInfo isOverloadble(FunctionDescriptor a, FunctionDescriptor b) {
|
||||
OverridingUtil.OverrideCompatibilityInfo overrideCompatibilityInfo = OverridingUtil.isOverridableByImpl(a, b, false);
|
||||
if (overrideCompatibilityInfo.isSuccess()) {
|
||||
if (!overrideCompatibilityInfo.isOverloadable()) {
|
||||
return OverloadCompatibilityInfo.someError();
|
||||
} else {
|
||||
return OverloadCompatibilityInfo.success();
|
||||
|
||||
@@ -147,14 +147,14 @@ public class OverrideResolver {
|
||||
boolean overrides = false;
|
||||
|
||||
for (NamedFunctionDescriptor functionFromCurrent : functionsFromCurrent) {
|
||||
if (OverridingUtil.isOverridableBy(functionFromSupertype, functionFromCurrent).isSuccess()) {
|
||||
if (OverridingUtil.isOverridableBy(functionFromSupertype, functionFromCurrent).isOverridable()) {
|
||||
((FunctionDescriptorImpl) functionFromCurrent).addOverriddenFunction(functionFromSupertype);
|
||||
overrides = true;
|
||||
}
|
||||
}
|
||||
|
||||
for (NamedFunctionDescriptor fakeOverride : fakeOverrides) {
|
||||
if (OverridingUtil.isOverridableBy(functionFromSupertype, fakeOverride).isSuccess()) {
|
||||
if (OverridingUtil.isOverridableBy(functionFromSupertype, fakeOverride).isOverridable()) {
|
||||
((FunctionDescriptorImpl) fakeOverride).addOverriddenFunction(functionFromSupertype);
|
||||
overrides = true;
|
||||
}
|
||||
@@ -183,14 +183,14 @@ public class OverrideResolver {
|
||||
for (PropertyDescriptor propertyFromSupertype : propertiesFromSupertypes) {
|
||||
boolean overrides = false;
|
||||
for (PropertyDescriptor propertyFromCurrent : propertiesFromCurrent) {
|
||||
if (OverridingUtil.isOverridableBy(propertyFromSupertype, propertyFromCurrent).isSuccess()) {
|
||||
if (OverridingUtil.isOverridableBy(propertyFromSupertype, propertyFromCurrent).isOverridable()) {
|
||||
propertyFromCurrent.addOverriddenDescriptor(propertyFromSupertype);
|
||||
overrides = true;
|
||||
}
|
||||
}
|
||||
|
||||
for (PropertyDescriptor fakeOverride : fakeOverrides) {
|
||||
if (OverridingUtil.isOverridableBy(propertyFromSupertype, fakeOverride).isSuccess()) {
|
||||
if (OverridingUtil.isOverridableBy(propertyFromSupertype, fakeOverride).isOverridable()) {
|
||||
((PropertyDescriptor) fakeOverride).addOverriddenDescriptor(propertyFromSupertype);
|
||||
overrides = true;
|
||||
}
|
||||
@@ -243,7 +243,7 @@ public class OverrideResolver {
|
||||
List<FunctionDescriptor> result2 = Lists.newArrayList();
|
||||
Set<FunctionDescriptor> functionGroup = supertype.getMemberScope().getFunctions(declaredFunction.getName());
|
||||
for (FunctionDescriptor functionDescriptor : functionGroup) {
|
||||
if (OverridingUtil.isOverridableBy(functionDescriptor, declaredFunction).isSuccess()) {
|
||||
if (OverridingUtil.isOverridableBy(functionDescriptor, declaredFunction).isOverridable()) {
|
||||
result.add(functionDescriptor);
|
||||
} else {
|
||||
result2.add(functionDescriptor);
|
||||
@@ -258,7 +258,7 @@ public class OverrideResolver {
|
||||
Set<VariableDescriptor> properties = supertype.getMemberScope().getProperties(declaredProperty.getName());
|
||||
for (VariableDescriptor property : properties) {
|
||||
assert property instanceof PropertyDescriptor;
|
||||
if (OverridingUtil.isOverridableBy(property, declaredProperty).isSuccess()) {
|
||||
if (OverridingUtil.isOverridableBy(property, declaredProperty).isOverridable()) {
|
||||
result.add((PropertyDescriptor) property);
|
||||
}
|
||||
}
|
||||
@@ -402,8 +402,8 @@ public class OverrideResolver {
|
||||
for (CallableMemberDescriptor another : filteredMembers) {
|
||||
// if (one == another) continue;
|
||||
factoredMembers.put(one, one);
|
||||
if (OverridingUtil.isOverridableBy(one, another).isSuccess()
|
||||
|| OverridingUtil.isOverridableBy(another, one).isSuccess()) {
|
||||
if (OverridingUtil.isOverridableBy(one, another).isOverridable()
|
||||
|| OverridingUtil.isOverridableBy(another, one).isOverridable()) {
|
||||
factoredMembers.put(one, another);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,8 +56,8 @@ public class OverridingUtil {
|
||||
for (D otherD : candidates) {
|
||||
CallableDescriptor other = transform.fun(otherD);
|
||||
if (me.getOriginal() == other.getOriginal()
|
||||
&& isOverridableBy(other, me).isSuccess()
|
||||
&& isOverridableBy(me, other).isSuccess()) {
|
||||
&& isOverridableBy(other, me).isOverridable()
|
||||
&& isOverridableBy(me, other).isOverridable()) {
|
||||
continue outerLoop;
|
||||
}
|
||||
}
|
||||
@@ -129,45 +129,60 @@ public class OverridingUtil {
|
||||
/**
|
||||
* @param forOverride true for override, false for overload
|
||||
*/
|
||||
static OverrideCompatibilityInfo isOverridableByImpl(CallableDescriptor superDescriptor, CallableDescriptor subDescriptor, boolean forOverride) {
|
||||
static OverrideCompatibilityInfo isOverridableByImpl(@NotNull CallableDescriptor superDescriptor, @NotNull CallableDescriptor subDescriptor, boolean forOverride) {
|
||||
|
||||
// TODO : Visibility
|
||||
|
||||
if (superDescriptor.getTypeParameters().size() != subDescriptor.getTypeParameters().size()) {
|
||||
return OverrideCompatibilityInfo.typeParameterNumberMismatch();
|
||||
if (forOverride) {
|
||||
if (superDescriptor.getTypeParameters().size() != subDescriptor.getTypeParameters().size()) {
|
||||
return OverrideCompatibilityInfo.typeParameterNumberMismatch();
|
||||
}
|
||||
}
|
||||
|
||||
if (compiledValueParameterCount(superDescriptor) != compiledValueParameterCount(subDescriptor)) {
|
||||
return OverrideCompatibilityInfo.valueParameterNumberMismatch();
|
||||
}
|
||||
|
||||
List<TypeParameterDescriptor> superTypeParameters = superDescriptor.getTypeParameters();
|
||||
List<TypeParameterDescriptor> subTypeParameters = subDescriptor.getTypeParameters();
|
||||
|
||||
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);
|
||||
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 (!JetTypeChecker.INSTANCE.equalTypes(superTypeParameter.getUpperBoundsAsType(), subTypeParameter.getUpperBoundsAsType(), axioms)) {
|
||||
return OverrideCompatibilityInfo.boundsMismatch(superTypeParameter, subTypeParameter);
|
||||
}
|
||||
}
|
||||
|
||||
List<JetType> superValueParameters = compiledValueParameters(superDescriptor);
|
||||
List<JetType> subValueParameters = compiledValueParameters(subDescriptor);
|
||||
for (int i = 0, unsubstitutedValueParametersSize = superValueParameters.size(); i < unsubstitutedValueParametersSize; i++) {
|
||||
JetType superValueParameter = superValueParameters.get(i);
|
||||
JetType subValueParameter = subValueParameters.get(i);
|
||||
|
||||
if (!JetTypeChecker.INSTANCE.equalTypes(superValueParameter, subValueParameter, axioms)) {
|
||||
return OverrideCompatibilityInfo.valueParameterTypeMismatch(superValueParameter, subValueParameter);
|
||||
if (forOverride) {
|
||||
|
||||
List<TypeParameterDescriptor> superTypeParameters = superDescriptor.getTypeParameters();
|
||||
List<TypeParameterDescriptor> subTypeParameters = subDescriptor.getTypeParameters();
|
||||
|
||||
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);
|
||||
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 (!JetTypeChecker.INSTANCE.equalTypes(superTypeParameter.getUpperBoundsAsType(), subTypeParameter.getUpperBoundsAsType(), axioms)) {
|
||||
return OverrideCompatibilityInfo.boundsMismatch(superTypeParameter, subTypeParameter);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0, unsubstitutedValueParametersSize = superValueParameters.size(); i < unsubstitutedValueParametersSize; i++) {
|
||||
JetType superValueParameter = superValueParameters.get(i);
|
||||
JetType subValueParameter = subValueParameters.get(i);
|
||||
|
||||
if (!JetTypeChecker.INSTANCE.equalTypes(superValueParameter, subValueParameter, axioms)) {
|
||||
return OverrideCompatibilityInfo.valueParameterTypeMismatch(superValueParameter, subValueParameter);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < superValueParameters.size(); ++i) {
|
||||
JetType superValueParameterType = getUpperBound(superValueParameters.get(i));
|
||||
JetType subValueParameterType = getUpperBound(subValueParameters.get(i));
|
||||
// TODO: compare erasure
|
||||
if (!JetTypeChecker.INSTANCE.equalTypes(superValueParameterType, subValueParameterType)) {
|
||||
return OverrideCompatibilityInfo.valueParameterTypeMismatch(superValueParameterType, subValueParameterType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,6 +190,16 @@ public class OverridingUtil {
|
||||
|
||||
return OverrideCompatibilityInfo.success();
|
||||
}
|
||||
|
||||
private static JetType getUpperBound(JetType type) {
|
||||
if (type.getConstructor().getDeclarationDescriptor() instanceof ClassDescriptor) {
|
||||
return type;
|
||||
} else if (type.getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptor) {
|
||||
return ((TypeParameterDescriptor) type.getConstructor().getDeclarationDescriptor()).getUpperBoundsAsType();
|
||||
} else {
|
||||
throw new IllegalStateException("unknown type constructor: " + type.getConstructor().getClass().getName());
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isReturnTypeOkForOverride(@NotNull JetTypeChecker typeChecker, @NotNull CallableDescriptor superDescriptor, @NotNull CallableDescriptor subDescriptor) {
|
||||
List<TypeParameterDescriptor> superTypeParameters = superDescriptor.getTypeParameters();
|
||||
@@ -274,16 +299,20 @@ public class OverridingUtil {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private final boolean isSuccess;
|
||||
private final boolean overridable;
|
||||
private final String message;
|
||||
|
||||
public OverrideCompatibilityInfo(boolean success, String message) {
|
||||
isSuccess = success;
|
||||
this.overridable = success;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public boolean isSuccess() {
|
||||
return isSuccess;
|
||||
public boolean isOverridable() {
|
||||
return overridable;
|
||||
}
|
||||
|
||||
public boolean isOverloadable() {
|
||||
return !overridable;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
class Aaa() {
|
||||
<!CONFLICTING_OVERLOADS!>fun f()<!> = 1
|
||||
<!CONFLICTING_OVERLOADS!>fun <P> f()<!> = 1
|
||||
}
|
||||
@@ -96,16 +96,16 @@ public class JetOverloadTest extends JetLiteFixture {
|
||||
"fun a(a : Int?) : Int",
|
||||
"fun a(a : Int) : Int");
|
||||
|
||||
// XXX: different from overridable
|
||||
/*
|
||||
assertNotOverloadable(
|
||||
"fun a<T>(a : Int) : Int",
|
||||
"fun a(a : Int) : Int");
|
||||
*/
|
||||
|
||||
// TODO
|
||||
/*
|
||||
assertOverloadable(
|
||||
"fun a<T1, X : T1>(a : T1) : T1",
|
||||
"fun a<T, Y>(a : T) : T");
|
||||
*/
|
||||
|
||||
assertOverloadable(
|
||||
"fun a<T1, X : T1>(a : T1) : T1",
|
||||
@@ -115,9 +115,12 @@ public class JetOverloadTest extends JetLiteFixture {
|
||||
"fun a<T1, X : T1>(a : T1) : X",
|
||||
"fun a<T, Y : T>(a : T) : T");
|
||||
|
||||
// TODO
|
||||
/*
|
||||
assertNotOverloadable(
|
||||
"fun a<T1, X : Array<out T1>>(a : Array<in T1>) : T1",
|
||||
"fun a<T, Y : Array<out T>>(a : Array<in T>) : T");
|
||||
*/
|
||||
|
||||
assertOverloadable(
|
||||
"fun a<T1, X : Array<T1>>(a : Array<in T1>) : T1",
|
||||
|
||||
@@ -156,7 +156,7 @@ public class JetOverridingTest extends JetLiteFixture {
|
||||
FunctionDescriptor a = makeFunction(superFun);
|
||||
FunctionDescriptor b = makeFunction(subFun);
|
||||
OverridingUtil.OverrideCompatibilityInfo overridableWith = OverridingUtil.isOverridableBy(a, b);
|
||||
assertEquals(overridableWith.getMessage(), expectedIsError, !overridableWith.isSuccess());
|
||||
assertEquals(overridableWith.getMessage(), expectedIsError, !overridableWith.isOverridable());
|
||||
}
|
||||
|
||||
private FunctionDescriptor makeFunction(String funDecl) {
|
||||
|
||||
Reference in New Issue
Block a user