Using `...` syntax and `--trim`

Hello,

I am working on a package for building c interfaces for an NLP solver packages and have run into something of an impasse regarding the --trim functionality and calling functions with keyword arguments which need to be populated at run time.

The situation is this: I have a options::T where T <: AbstractDict{Symbol, Union{<Some stuff>}}, populated by the c user at run time, which contains the keyword arguments I would like to pass to the constructor of the underlying options type. However, it seems that none of the obvious ways (that is ...) interact well with the --trim=safe flag in JuliaC.jl, and run into issues with unresolved calls to _apply_iterate (I assume related to Support resolving dispatch in `apply_iterate` for variable-length containers (`Tuple{Vararg{T}}` and `Vector{T}`) · Issue #57830 · JuliaLang/julia · GitHub).

Is there any way to use the ... syntax and retain the ability to use --trim? Am I missing something?

I am not an expert in AOT compilation but I suspect that the underlying issue is that splatting aka ... is oftentimes type unstable. Consider this:

function foo()
    vec = [1, 2, 3]
    +(vec...) # type unstable
end

Why is this type unstable? Because the vector does not carry its length as type parameter. So when Julia compiles this, fhe compiler has no idea how many arguments the function + will receive and thus does not know which method it needs to dispatch to. So it has to use a dynamic dispatch.

The matter is different when you use a tuple or StaticVector that carry size information in the type. Then splatting is type stable.

Basically no, because it is type-unstable.

I think your best bet is to explicitly get the options at the call site, something like

foo(
    # required option
    opt1=options[:opt1]::Int,
    # optional option with default
    opt2=get(options, :opt2, nothing)::Union{Float64,Nothing}
)
1 Like

@abraemer Thanks, I knew this is type unstable in cases of variadic numbers of parameters (like +(args...)) and it makes sense there is no way around this. It however does not make a lot of sense to me why it contributes to type instability in keyword arguments as, as far as I understand, these are not specialized on. Unfortunately your suggestions are not (easily) feasible for me as the creation of the options structure crosses the Julia-C boundary.

@cjdoris This is probably actually possible! Unfortunately it is quite annoying as there is no particularly sane way to get defaults (meta-)programmatically from a @kwdefed struct but this is a good direction to go in.

Thanks for the ideas!

You could make an instance and get its fields like

const MY_DEFAULTS = MyStruct()

foo(opt1=get(options, :opt1, MY_DEFAULTS.opt1), ...)