Skip to content

Commit

Permalink
Improve type inference for @something
Browse files Browse the repository at this point in the history
`@something` eagerly unwraps any `Some` given to it,
while keeping the variable between its arguments the same.
This can be an issue if a previously unpacked value is used as input
to `@something`, leading to a type instability on more than two arguments
(e.g. because of a fallback to `Some(nothing)`). By using different
variables for each argument, type inference has an easier time handling
these cases that are isolated to single branches anyway.
  • Loading branch information
Seelengrab committed Dec 3, 2023
1 parent 0c46852 commit 81038d3
Showing 1 changed file with 25 additions and 4 deletions.
29 changes: 25 additions & 4 deletions base/some.jl
Original file line number Diff line number Diff line change
Expand Up @@ -138,10 +138,31 @@ true
This macro is available as of Julia 1.7.
"""
macro something(args...)
expr = :(nothing)
noth = GlobalRef(Base, :nothing)
something = GlobalRef(Base, :something)

# This preserves existing semantics of throwing on `nothing`
expr = :($something($noth))

#=
We go through the arguments in reverse
because we're building a nested if/else
expression from the inside out.
The innermost thing to check is the last argument,
which is why we need the last argument first
when building the final expression.
=#
for arg in reverse(args)
expr = :(val = $(esc(arg)); val !== nothing ? val : ($expr))
val = gensym()
expr = quote
$val = $(esc(arg))
if !isnothing($val)
# unwrap eagerly to help type inference
$something($val)
else
$expr
end
end
end
something = GlobalRef(Base, :something)
return :($something($expr))
return expr
end

0 comments on commit 81038d3

Please sign in to comment.