Revision 2a406b243730a0a50aa99355786b3ac41340a386 authored by Keno Fischer on 06 July 2023, 21:20:40 UTC, committed by GitHub on 06 July 2023, 21:20:40 UTC
* Add pattern matching for `typeof` into field type tparam

This PR allows full elimination of the following, even in
ill-typed code.
```
struct TParamTypeofTest{T}
    x::T
    @eval TParamTypeofTest(x) = $(Expr(:new, :(TParamTypeofTest{typeof(x)}), :x))
end
function tparam_typeof_test_elim(x)
    TParamTypeofTest(x).x
end
```

Before this PR, we would get:
```
julia> code_typed(tparam_typeof_test_elim, Tuple{Any})
1-element Vector{Any}:
 CodeInfo(
1 ─ %1 = Main.typeof(x)::DataType
│   %2 = Core.apply_type(Main.TParamTypeofTest, %1)::Type{TParamTypeofTest{_A}} where _A
│        %new(%2, x)::TParamTypeofTest
└──      return x
```

Where the `new` is non-eliminable, because the compiler did not know that
`x::_A`. Fix this by pattern matching this particular pattern (where the
condition is guaranteed, because we computed `_A` by `typeof`).
This is not particularly general, but this pattern comes up a lot,
so it's surprisingly effective.

* add test case for optimizing multiple abstract fields

* improve robustness

---------

Co-authored-by: Shuhei Kadowaki <aviatesk@gmail.com>
1 parent 46477cc
Raw File
osutils.jl
# This file is a part of Julia. License is MIT: https://julialang.org/license

"""
    @static

Partially evaluate an expression at parse time.

For example, `@static Sys.iswindows() ? foo : bar` will evaluate `Sys.iswindows()` and insert
either `foo` or `bar` into the expression.
This is useful in cases where a construct would be invalid on other platforms,
such as a `ccall` to a non-existent function.
`@static if Sys.isapple() foo end` and `@static foo <&&,||> bar` are also valid syntax.
"""
macro static(ex)
    if isa(ex, Expr)
        @label loop
        hd = ex.head
        if hd ∈ (:if, :elseif, :&&, :||)
            cond = Core.eval(__module__, ex.args[1])::Bool
            if xor(cond, hd === :||)
                return esc(ex.args[2])
            elseif length(ex.args) == 3
                br = ex.args[3]
                if br isa Expr && br.head === :elseif
                    ex = br
                    @goto loop
                else
                    return esc(ex.args[3])
                end
            elseif hd ∈ (:if, :elseif)
                return nothing
            else
                return cond
            end
        end
    end
    throw(ArgumentError("invalid @static macro"))
end
back to top