Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

@which and @code_warntype don't show ^Val{p} lowering #21014

Closed
rdeits opened this issue Mar 14, 2017 · 9 comments · Fixed by #53713
Closed

@which and @code_warntype don't show ^Val{p} lowering #21014

rdeits opened this issue Mar 14, 2017 · 9 comments · Fixed by #53713
Labels
compiler:lowering Syntax lowering (compiler front end, 2nd stage)

Comments

@rdeits
Copy link
Contributor

rdeits commented Mar 14, 2017

Cross-posting from discourse: https://discourse.julialang.org/t/incorrect-results-from-which-and-code-warntype-for-literal-powers/2630

I'm trying to use the new literal exponent behavior introduced in #20530 and #20889. I think I'm correctly overloading literal_pow, but various macros like @which, @code_warntype and others all seem to be showing me the wrong behavior.

julia> versioninfo()
Julia Version 0.6.0-pre.alpha.136
Commit 6eeabd8 (2017-03-13 00:18 UTC)
Platform Info:
  OS: macOS (x86_64-apple-darwin13.4.0)
  CPU: Intel(R) Core(TM) i7-2860QM CPU @ 2.50GHz
  WORD_SIZE: 64
  BLAS: libopenblas (USE64BITINT DYNAMIC_ARCH NO_AFFINITY Sandybridge)
  LAPACK: libopenblas64_
  LIBM: libopenlibm
  LLVM: libLLVM-3.9.1 (ORCJIT, sandybridge)

julia> immutable MyType
           x::Int
       end

julia> import Base: literal_pow

julia> literal_pow(^, m::MyType, ::Type{Val{p}}) where p = m.x + p
literal_pow (generic function with 6 methods)

julia> m = MyType(1)
MyType(1)

julia> m^2
3

That's all good so far. But none of the introspection macros seem to work for m^2:

julia> @which m^2
^(x, p::Integer) in Base at intfuncs.jl:196

julia> @code_warntype m^2
Variables:
  #self#::Base.#^
  x::MyType
  p::Int64

Body:
  begin
      return $(Expr(:invoke, MethodInstance for power_by_squaring(::MyType, ::Int64), :(Base.power_by_squaring), :(x), :(p)))
  end::Any

julia> @code_lowered m^2
CodeInfo(:(begin
        nothing
        return (Base.power_by_squaring)(x, p)
    end))

julia> using Base.Test

julia> @inferred m^2
ERROR: MethodError: no method matching *(::MyType, ::MyType)
Closest candidates are:
  *(::Any, ::Any, ::Any, ::Any...) at operators.jl:424
Stacktrace:
 [1] power_by_squaring(::MyType, ::Int64) at ./intfuncs.jl:166
 [2] ^(::MyType, ::Int64) at ./intfuncs.jl:196

are the special lowering rules not being applied inside these macros?

@ararslan ararslan added the compiler:lowering Syntax lowering (compiler front end, 2nd stage) label Mar 14, 2017
@TotalVerb
Copy link
Contributor

Duplicate (mostly) of #20620. Maybe we can leave this open as a reminder in case literal power and dot operator end up being treated separately.

@rdeits
Copy link
Contributor Author

rdeits commented Mar 14, 2017

Ah, I see, thanks. So is the workaround to use eval with expand like this?

julia> eval(:(@which $(expand(:(m^2)))))
literal_pow(^, m::MyType, ::Type{Val{p}}) where p in Main at REPL[3]:1

julia> eval(:(@code_warntype $(expand(:(m^2)))))
Variables:
  #self#::Base.#literal_pow
  ^::Base.#^
  m::MyType
  #unused#::Any

Body:
  begin
      return (Base.add_int)((Core.getfield)(m::MyType, :x)::Int64, $(Expr(:static_parameter, 1)))::Int64
  end::Int64

@TotalVerb
Copy link
Contributor

Yes, or the alternative but equivalent syntax

julia> @eval @which $(expand(:(1^2)))
literal_pow(::Base.#^, x::Union{Complex{#s37} where #s37<:Union{Float32, Float64, Int16, Int32, Int64, Int8, UInt16, UInt32, UInt64, UInt8}, Float32, Float64, Int16, Int32, Int64, Int8, Rational{#s23} where #s23<:Union{Float32, Float64, Int16, Int32, Int64, Int8, UInt16, UInt32, UInt64, UInt8}, UInt16, UInt32, UInt64, UInt8}, ::Type{Val{2}}) in Base at intfuncs.jl:218

@thofma
Copy link
Contributor

thofma commented Nov 21, 2017

Would be nice if this is fixed in 0.7. The new literal power stuff breaks existing code and it is quite difficuelt to find out how to fix it. Overload literal_pow?

@fredrikekre
Copy link
Member

Do you have an example of code that is broken by this?

@thofma
Copy link
Contributor

thofma commented Nov 21, 2017

For my type, in ^(x::mytype, ::Int) I throw a domain error for negative exponents. On 0.7 it gives me (as expected)

julia> a = -1;

julia> x^a
ERROR: DomainError with nothing:

Stacktrace:
 [1] ^(::Nemo.nmod_poly, ::Int64) at /home/thofmann/.julia/v0.7/Nemo/src/flint/nmod_poly.jl:295
 [2] top-level scope

But for literals it gives me:

julia> x^-1
ERROR: MethodError: no method matching inv(::Nemo.nmod_poly)
Closest candidates are:
  inv(::Complex{Float64}) at complex.jl:391
  inv(::Nemo.Generic.perm) at /home/thofmann/.julia/v0.7/Nemo/src/generic/PermGroups.jl:243
  inv(::Nemo.nmod) at /home/thofmann/.julia/v0.7/Nemo/src/flint/nmod.jl:256
  ...
Stacktrace:
 [1] @generated body at ./none:0 [inlined]
 [2] literal_pow(::typeof(^), ::Nemo.nmod_poly, ::Val{-1}) at ./<missing>:0
 [3] top-level scope

I cannot define inv, because the elements are not invertible. Also why should I need to define inv if I want to have literal powers? I already defined powering for exponents of type Int.

This is very intransparent for custom types.

@fredrikekre
Copy link
Member

That would be #24240 then, I suppose that inv transformation should only be done on types that are defined in base.

@stevengj
Copy link
Member

stevengj commented Nov 21, 2017

You don't need to define inv if you don't have an inverse. It will just throw a MethodError instead of a DomainError for negative literal powers.

(If it's crucial that you throw a DomainError, you could define an inv method that throws a DomainError, which is not so unreasonable: if you want a DomainError for x^-1, why wouldn't you want a DomainError for inv(x) too?)

@thofma
Copy link
Contributor

thofma commented Nov 22, 2017

See #24699

mbauman added a commit that referenced this issue Apr 3, 2024
…w` case. (#53713)

The macros `@which`, `@edit`, `@functionloc`, `@less` from `InteractiveUtils`, if
applied to the case of literal powers, like `a^12` or `2^-1` used to direct the
user to function `^`, while the compiler generates code for `Base.literal_pow`.

Now the user is shown the code the compiler generates.

Fixes #53691
Fixes #43337
Fixes #21014

Co-authored-by: Matt Bauman <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler:lowering Syntax lowering (compiler front end, 2nd stage)
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants