Itβs not because of mutable type declarations.
1) Meta.@lower x -> y -> x = y
:($(Expr(:thunk, CodeInfo(
@ none within `top-level scope'
1 β $(Expr(:thunk, CodeInfo(
@ none within `top-level scope'
1 β global var"#38#40"
β const var"#38#40"
β %3 = Core._structtype(Main, Symbol("#38#40"), Core.svec(), Core.svec(:x), false, 1)
β var"#38#40" = %3
β Core._setsuper!(var"#38#40", Core.Function)
β Core._typebody!(var"#38#40", Core.svec(Core.Box))
βββ return
)))
β $(Expr(:thunk, CodeInfo(
@ none within `top-level scope'
1 β global var"#37#39"
β const var"#37#39"
β %3 = Core._structtype(Main, Symbol("#37#39"), Core.svec(), Core.svec(), false, 0)
β var"#37#39" = %3
β Core._setsuper!(var"#37#39", Core.Function)
β Core._typebody!(var"#37#39", Core.svec())
βββ return
)))
β %3 = Core.svec(var"#38#40", Core.Any)
β %4 = Core.svec()
β %5 = Core.svec(%3, %4, $(QuoteNode(:(#= REPL[20]:1 =#))))
β $(Expr(:method, false, :(%5), CodeInfo(quote
y
Core.getfield(#self#, :x)
Core.setfield!(%2, :contents, %1)
return %1
end)))
β %7 = Core.svec(var"#37#39", Core.Any)
β %8 = Core.svec()
β %9 = Core.svec(%7, %8, $(QuoteNode(:(#= REPL[20]:1 =#))))
β $(Expr(:method, false, :(%9), CodeInfo(quote
x@_4 = x@_2
x@_4 = Core.Box(x@_4)
#38 = %new(var"#38#40", x@_4)
return #38
end)))
β #37 = %new(var"#37#39")
βββ return #37
))))
2) Meta.@lower x -> y -> x+y
julia> Meta.@lower x -> y -> x + y
:($(Expr(:thunk, CodeInfo(
@ none within `top-level scope'
1 β $(Expr(:thunk, CodeInfo(
@ none within `top-level scope'
1 β global var"#42#44"
β const var"#42#44"
β Core.TypeVar(:x, Core.Any)
β %4 = Core._structtype(Main, Symbol("#42#44"), Core.svec(%3), Core.svec(:x), false, 1)
β var"#42#44" = %4
β Core._setsuper!(var"#42#44", Core.Function)
β Core._typebody!(var"#42#44", Core.svec(%3))
βββ return
)))
β $(Expr(:thunk, CodeInfo(
@ none within `top-level scope'
1 β global var"#41#43"
β const var"#41#43"
β %3 = Core._structtype(Main, Symbol("#41#43"), Core.svec(), Core.svec(), false, 0)
β var"#41#43" = %3
β Core._setsuper!(var"#41#43", Core.Function)
β Core._typebody!(var"#41#43", Core.svec())
βββ return
)))
β %3 = Core.svec(var"#42#44", Core.Any)
β %4 = Core.svec()
β %5 = Core.svec(%3, %4, $(QuoteNode(:(#= REPL[21]:1 =#))))
β $(Expr(:method, false, :(%5), CodeInfo(quote
Core.getfield(#self#, :x)
%1 + y
return %2
end)))
β %7 = Core.svec(var"#41#43", Core.Any)
β %8 = Core.svec()
β %9 = Core.svec(%7, %8, $(QuoteNode(:(#= REPL[21]:1 =#))))
β $(Expr(:method, false, :(%9), CodeInfo(quote
var"#42#44"
Core.typeof(x)
Core.apply_type(%1, %2)
#42 = %new(%3, x)
return #42
end)))
β #41 = %new(var"#41#43")
βββ return #41
))))
3) Meta.@lower mutable struct A end
julia> Meta.@lower mutable struct A end
:($(Expr(:thunk, CodeInfo(
@ none within `top-level scope'
1 β global A
β const A
β %3 = Core.svec()
β %4 = Core.svec()
β #16#A = Core._structtype(Main, :A, %3, %4, true, 0)
β Core._setsuper!(#16#A, Core.Any)
β %7 = $(Expr(:isdefined, :A))
βββ goto #6 if not %7
2 β %9 = A
β %10 = Core._equiv_typedef(%9, #16#A)
βββ goto #4 if not %10
3 β #16#A = %9
βββ goto #5
4 β A = #16#A
5 β goto #7
6 β A = #16#A
7 β %17 = #16#A
β %18 = Core.svec()
β Core._typebody!(%17, %18)
β global A
β $(Expr(:method, :A))
β %22 = Core.Typeof(A)
β %23 = Core.svec(%22)
β %24 = Core.svec()
β %25 = Core.svec(%23, %24, $(QuoteNode(:(#= REPL[22]:1 =#))))
β $(Expr(:method, :A, :(%25), CodeInfo(quote
A
%new(%1)
return %2
end)))
βββ return
))))
4) Meta.@lower struct A end
julia> Meta.@lower struct A end
:($(Expr(:thunk, CodeInfo(
@ none within `top-level scope'
1 β global A
β const A
β %3 = Core.svec()
β %4 = Core.svec()
β #17#A = Core._structtype(Main, :A, %3, %4, false, 0)
β Core._setsuper!(#17#A, Core.Any)
β %7 = $(Expr(:isdefined, :A))
βββ goto #6 if not %7
2 β %9 = A
β %10 = Core._equiv_typedef(%9, #17#A)
βββ goto #4 if not %10
3 β #17#A = %9
βββ goto #5
4 β A = #17#A
5 β goto #7
6 β A = #17#A
7 β %17 = #17#A
β %18 = Core.svec()
β Core._typebody!(%17, %18)
β global A
β $(Expr(:method, :A))
β %22 = Core.Typeof(A)
β %23 = Core.svec(%22)
β %24 = Core.svec()
β %25 = Core.svec(%23, %24, $(QuoteNode(:(#= REPL[23]:1 =#))))
β $(Expr(:method, :A, :(%25), CodeInfo(quote
A
%new(%1)
return %2
end)))
βββ return
))))
Note the difference between 3 & 4 - itβs just the fifth field of the call to Core._structtype
, which (I think) stands for mutability. Neither 1 nor 2 have that set to true, so theyβre not mutable structs (ismutable
works on instances, thatβs the reason for the call):
julia> f = x -> y -> x + y
#45 (generic function with 1 method)
julia> ismutable(f(1))
false
julia> g = x -> y -> x = y
#49 (generic function with 1 method)
julia> ismutable(g(1))
false
The Box the second one is capturing is though:
julia> f(1) |> dump
#46 (function of type var"#46#48"{Int64})
x: Int64 1
julia> f(1).x |> ismutable
false
julia> g(1) |> dump
#50 (function of type var"#50#52")
x: Core.Box
contents: Int64 1
julia> g(1).x |> ismutable
true