我在以下 Julia 1.8 代码中收到红色警告
\nmutable struct S\n X::Int32\n const Children::Vector{Ref{S}}\nend\n\nfunction f2(s::Ref{S})\n x = Int32(0)\n \n chs = s[].Children\n for ch in chs\n add = ch[].X\n x += add\n end\n\n println("f2: $(x)")\nend\n\nfunction test()\n s = S(3, Vector{Ref{S}}())\n @code_warntype f2(Ref{S}(s))\nend\ntest()\nRun Code Online (Sandbox Code Playgroud)\n输出:
\nMethodInstance for f2(::Base.RefValue{S})\n from f2(s::Ref{S}) in Main at example.jl:7\nArguments\n #self#::Core.Const(f2)\n s::Base.RefValue{S}\nLocals\n @_3::Union{Nothing, Tuple{Ref{S}, Int64}} (green)\n chs::Vector{Ref{S}}\n x::Any (red)\n ch::Ref{S} (red)\n add::Any (red)\nBody::Nothing\n1 \xe2\x94\x80 (x = Main.Int32(0))\n\xe2\x94\x82 %2 = Base.getindex(s)::S \n\xe2\x94\x82 (chs = Base.getproperty(%2, :Children))\n\xe2\x94\x82 %4 = chs::Vector{Ref{S}}\n\xe2\x94\x82 (@_3 = Base.iterate(%4))\n\xe2\x94\x82 %6 = (@_3 === nothing)::Bool\n\xe2\x94\x82 %7 = Base.not_int(%6)::Bool\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 goto #4 if not %7\n2 \xe2\x94\x84 %9 = @_3::Tuple{Ref{S}, Int64} (red)\n\xe2\x94\x82 (ch = Core.getfield(%9, 1)) \n\xe2\x94\x82 %11 = Core.getfield(%9, 2)::Int64 \n\xe2\x94\x82 %12 = Base.getindex(ch)::Any (red)\n\xe2\x94\x82 (add = Base.getproperty(%12, :X))\n\xe2\x94\x82 (x = x + add)\n\xe2\x94\x82 (@_3 = Base.iterate(%4, %11)) \n\xe2\x94\x82 %16 = (@_3 === nothing)::Bool\n\xe2\x94\x82 %17 = Base.not_int(%16)::Bool\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 goto #4 if not %17\n3 \xe2\x94\x80 goto #2\n4 \xe2\x94\x84 %20 = Base.string("f2: ", x)::String \n\xe2\x94\x82 %21 = Main.println(%20)::Core.Const(nothing)\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 return %21\nRun Code Online (Sandbox Code Playgroud)\n据我所知, 的类型ch可以在编译时确定。\n应该没有歧义。
Ref是抽象的。使用Base.RefValue它的具体子类型,因为这可能是您想要的:
julia> mutable struct S\n X::Int32\n const Children::Vector{Base.RefValue{S}}\n end\n\njulia> function f2(s::Ref{S})\n x = Int32(0)\n\n chs = s[].Children\n for ch in chs\n add = ch[].X\n x += add\n end\n\n println("f2: $(x)")\n end\nf2 (generic function with 1 method)\n\njulia> function test()\n s = S(3, Vector{Ref{S}}())\n @code_warntype f2(Ref{S}(s))\n end\ntest (generic function with 1 method)\n\njulia> test()\nMethodInstance for f2(::Base.RefValue{S})\n from f2(s::Ref{S}) @ Main REPL[11]:1\nArguments\n #self#::Core.Const(f2)\n s::Base.RefValue{S}\nLocals\n @_3::Union{Nothing, Tuple{Base.RefValue{S}, Int64}}\n chs::Vector{Base.RefValue{S}}\n x::Int32\n ch::Base.RefValue{S}\n add::Int32\nBody::Nothing\n1 \xe2\x94\x80 (x = Main.Int32(0))\n\xe2\x94\x82 %2 = Base.getindex(s)::S\n\xe2\x94\x82 (chs = Base.getproperty(%2, :Children))\n\xe2\x94\x82 %4 = chs::Vector{Base.RefValue{S}}\n\xe2\x94\x82 (@_3 = Base.iterate(%4))\n\xe2\x94\x82 %6 = (@_3 === nothing)::Bool\n\xe2\x94\x82 %7 = Base.not_int(%6)::Bool\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 goto #4 if not %7\n2 \xe2\x94\x84 %9 = @_3::Tuple{Base.RefValue{S}, Int64}\n\xe2\x94\x82 (ch = Core.getfield(%9, 1))\n\xe2\x94\x82 %11 = Core.getfield(%9, 2)::Int64\n\xe2\x94\x82 %12 = Base.getindex(ch)::S\n\xe2\x94\x82 (add = Base.getproperty(%12, :X))\n\xe2\x94\x82 (x = x + add)\n\xe2\x94\x82 (@_3 = Base.iterate(%4, %11))\n\xe2\x94\x82 %16 = (@_3 === nothing)::Bool\n\xe2\x94\x82 %17 = Base.not_int(%16)::Bool\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 goto #4 if not %17\n3 \xe2\x94\x80 goto #2\n4 \xe2\x94\x84 %20 = Base.string("f2: ", x)::String\n\xe2\x94\x82 %21 = Main.println(%20)::Core.Const(nothing)\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 return %21\nRun Code Online (Sandbox Code Playgroud)\n