presto-main/src/main/java/io/prestosql/operator/scalar/annotations/ParametricScalarImplementation.java/ParametricScalarImplementation/ParametricScalarImplementation
class ParametricScalarImplementation:    private ParametricScalarImplementation(
            Signature signature,
            List<Optional<Class<?>>> argumentNativeContainerTypes,
            Map<String, Class<?>> specializedTypeParameters,
            List<ParametricScalarImplementationChoice> choices,
            Class<?> returnContainerType)
    {
        this.signature = requireNonNull(signature, "signature is null");
        this.argumentNativeContainerTypes = ImmutableList.copyOf(requireNonNull(argumentNativeContainerTypes, "argumentNativeContainerTypes is null"));
        this.specializedTypeParameters = ImmutableMap.copyOf(requireNonNull(specializedTypeParameters, "specializedTypeParameters is null"));
        this.choices = requireNonNull(choices, "choices is null");
        checkArgument(!choices.isEmpty(), "choices is empty");
        this.returnNativeContainerType = requireNonNull(returnContainerType, "return native container type is null");

        for (Class<?> specializedJavaType : specializedTypeParameters.values()) {
            checkArgument(specializedJavaType != Object.class, "specializedTypeParameter must not contain Object.class entries");
            checkArgument(!Primitives.isWrapperType(specializedJavaType), "specializedTypeParameter must not contain boxed primitive types");
        }

        ParametricScalarImplementationChoice defaultChoice = choices.get(0);
        boolean expression = defaultChoice.getArgumentProperties().stream()
                .noneMatch(argumentProperty -> argumentProperty.getArgumentType() == VALUE_TYPE && argumentProperty.getNullConvention() == BLOCK_AND_POSITION);
        checkArgument(expression, "default choice can not use the BLOCK_AND_POSITION calling convention: %s", signature);

        this.nullable = defaultChoice.isNullable();
        checkArgument(choices.stream().allMatch(choice -> choice.isNullable() == nullable), "all choices must have the same nullable flag: %s", signature);

        argumentDefinitions = defaultChoice.getArgumentProperties().stream()
                .map(argumentProperty -> argumentProperty.getArgumentType() == VALUE_TYPE && argumentProperty.getNullConvention() != RETURN_NULL_ON_NULL)
                .map(FunctionArgumentDefinition::new)
                .collect(toImmutableList());
        checkArgument(
                choices.stream().allMatch(choice -> matches(argumentDefinitions, choice.getArgumentProperties())),
                "all choices must have the same nullable parameter flags: %s",
                signature);
    }