diff --git a/core/src/main/java/org/projectnessie/cel/checker/Checker.java b/core/src/main/java/org/projectnessie/cel/checker/Checker.java index 56bed6f8..70892363 100644 --- a/core/src/main/java/org/projectnessie/cel/checker/Checker.java +++ b/core/src/main/java/org/projectnessie/cel/checker/Checker.java @@ -408,6 +408,10 @@ OverloadResolution resolveOverload( // not a compatible call style. continue; } + if (overload.getParamsCount() != argTypes.size()) { + // not a compatible arity. + continue; + } Type overloadType = Decls.newFunctionType(overload.getResultType(), overload.getParamsList()); if (overload.getTypeParamsCount() > 0) { diff --git a/core/src/main/java/org/projectnessie/cel/checker/CheckerEnv.java b/core/src/main/java/org/projectnessie/cel/checker/CheckerEnv.java index 55c3077a..6ed4258e 100644 --- a/core/src/main/java/org/projectnessie/cel/checker/CheckerEnv.java +++ b/core/src/main/java/org/projectnessie/cel/checker/CheckerEnv.java @@ -170,19 +170,28 @@ public Decl lookupFunction(String name) { */ Decl addOverload(Decl f, Overload overload, List errMsgs) { FunctionDecl function = f.getFunction(); - Mapping emptyMappings = newMapping(); - Type overloadFunction = - Decls.newFunctionType(overload.getResultType(), overload.getParamsList()); - Type overloadErased = substitute(emptyMappings, overloadFunction, true); + Mapping emptyMappings = null; + Type overloadFunction = null; + Type overloadErased = null; boolean hasErr = false; for (Overload existing : function.getOverloadsList()) { + if (overload.getIsInstanceFunction() != existing.getIsInstanceFunction() + || overload.getParamsCount() != existing.getParamsCount()) { + continue; + } + if (emptyMappings == null) { + emptyMappings = newMapping(); + overloadFunction = + Decls.newFunctionType(overload.getResultType(), overload.getParamsList()); + overloadErased = substitute(emptyMappings, overloadFunction, true); + } Type existingFunction = Decls.newFunctionType(existing.getResultType(), existing.getParamsList()); Type existingErased = substitute(emptyMappings, existingFunction, true); boolean overlap = isAssignable(emptyMappings, overloadErased, existingErased) != null || isAssignable(emptyMappings, existingErased, overloadErased) != null; - if (overlap && overload.getIsInstanceFunction() == existing.getIsInstanceFunction()) { + if (overlap) { errMsgs.add( overlappingOverloadError( f.getName(), diff --git a/core/src/test/java/org/projectnessie/cel/checker/CheckerEnvTest.java b/core/src/test/java/org/projectnessie/cel/checker/CheckerEnvTest.java index 5ffe755b..f7bb0e47 100644 --- a/core/src/test/java/org/projectnessie/cel/checker/CheckerEnvTest.java +++ b/core/src/test/java/org/projectnessie/cel/checker/CheckerEnvTest.java @@ -20,6 +20,7 @@ import static org.projectnessie.cel.common.types.pb.ProtoTypeRegistry.newRegistry; import com.google.api.expr.v1alpha1.Type; +import java.util.Arrays; import java.util.List; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; @@ -61,4 +62,20 @@ Overloads.ToDyn, singletonList(paramA), Decls.Dyn, typeParamAList)))) .hasMessage( "overlapping overload for name 'dyn' (type '(type_param: \"A\") -> dyn' with overloadId: 'to_dyn' cannot be distinguished from '(type_param: \"A\") -> dyn' with overloadId: 'to_dyn')"); } + + @Test + void overloadsWithDifferentArityOrStyleDoNotOverlap() { + CheckerEnv env = newStandardCheckerEnv(Container.defaultContainer, newRegistry()); + + env.add( + Decls.newFunction( + "custom", + Decls.newOverload("custom_string", singletonList(Decls.String), Decls.String), + Decls.newOverload( + "custom_string_string", Arrays.asList(Decls.String, Decls.String), Decls.String), + Decls.newInstanceOverload( + "custom_receiver_string", + Arrays.asList(Decls.String, Decls.String), + Decls.String))); + } }