diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index 6e843f460ac5d..93ead3207fce2 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -2823,7 +2823,7 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState) @assert !frame.inferred frame.dont_work_on_me = true # mark that this function is currently on the stack W = frame.ip - nargs = narguments(frame) + nargs = narguments(frame, #=include_va=#false) slottypes = frame.slottypes ssavaluetypes = frame.ssavaluetypes bbs = frame.cfg.blocks diff --git a/base/compiler/inferencestate.jl b/base/compiler/inferencestate.jl index df7bb67d625e8..e3f4cb2866aa3 100644 --- a/base/compiler/inferencestate.jl +++ b/base/compiler/inferencestate.jl @@ -607,9 +607,11 @@ get_curr_ssaflag(sv::InferenceState) = sv.src.ssaflags[sv.currpc] add_curr_ssaflag!(sv::InferenceState, flag::UInt8) = sv.src.ssaflags[sv.currpc] |= flag sub_curr_ssaflag!(sv::InferenceState, flag::UInt8) = sv.src.ssaflags[sv.currpc] &= ~flag -function narguments(sv::InferenceState) +function narguments(sv::InferenceState, include_va::Bool=true) def = sv.linfo.def - isva = isa(def, Method) && def.isva - nargs = length(sv.result.argtypes) - isva + nargs = length(sv.result.argtypes) + if !include_va + nargs -= isa(def, Method) && def.isva + end return nargs end diff --git a/base/compiler/typeinfer.jl b/base/compiler/typeinfer.jl index 35a2e25e62d11..ab7ca4b56a9bd 100644 --- a/base/compiler/typeinfer.jl +++ b/base/compiler/typeinfer.jl @@ -444,7 +444,7 @@ function adjust_effects(sv::InferenceState) # always throwing an error counts or never returning both count as consistent ipo_effects = Effects(ipo_effects; consistent=ALWAYS_TRUE) end - if is_inaccessiblemem_or_argmemonly(ipo_effects) && all(1:narguments(sv)) do i::Int + if is_inaccessiblemem_or_argmemonly(ipo_effects) && all(1:narguments(sv, #=include_va=#true)) do i::Int return is_mutation_free_argtype(sv.slottypes[i]) end ipo_effects = Effects(ipo_effects; inaccessiblememonly=ALWAYS_TRUE) diff --git a/test/compiler/effects.jl b/test/compiler/effects.jl index dceb737ed6ae7..33420efc91d3c 100644 --- a/test/compiler/effects.jl +++ b/test/compiler/effects.jl @@ -603,6 +603,21 @@ global inconsistent_condition_ref = Ref{Bool}(false) end end |> !Core.Compiler.is_consistent +# should handle va-method properly +callgetfield1(xs...) = getfield(getfield(xs, 1), 1) +@test !Core.Compiler.is_inaccessiblememonly(Base.infer_effects(callgetfield1, (Base.RefValue{Symbol},))) +const GLOBAL_XS = Ref(:julia) +global_getfield() = callgetfield1(GLOBAL_XS) +@test let + Base.Experimental.@force_compile + global_getfield() +end === :julia +GLOBAL_XS[] = :julia2 +@test let + Base.Experimental.@force_compile + global_getfield() +end === :julia2 + # the `:inaccessiblememonly` helper effect allows us to prove `:effect_free`-ness of frames # including `setfield!` modifying local mutable object