Skip to content

Commit c8a4fd2

Browse files
mbaumanKristofferC
authored andcommitted
Re-enable tab completion of kwargs for large method tables (#58012)
while testing to ensure that ~~absurdly large method tables~~ tab completing over an abstract function call doesn't tank the performance of the REPL Fixes #57836 (cherry picked from commit 6f12957)
1 parent 31151e5 commit c8a4fd2

File tree

2 files changed

+36
-1
lines changed

2 files changed

+36
-1
lines changed

stdlib/REPL/src/REPLCompletions.jl

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -883,7 +883,13 @@ function complete_keyword_argument!(suggestions::Vector{Completion},
883883
kwargs_flag == 2 && false # one of the previous kwargs is invalid
884884

885885
methods = Completion[]
886-
complete_methods!(methods, funct, Any[Vararg{Any}], kwargs_ex, shift ? -1 : MAX_METHOD_COMPLETIONS, kwargs_flag == 1)
886+
# Limit kwarg completions to cases when function is concretely known; looking up
887+
# matching methods for abstract functions — particularly `Any` or `Function` — can
888+
# take many seconds to run over the thousands of possible methods. Note that
889+
# isabstracttype would return naively return true for common constructor calls
890+
# like Array, but the REPL's introspection here may know their Type{T}.
891+
isconcretetype(funct) || return false
892+
complete_methods!(methods, funct, Any[Vararg{Any}], kwargs_ex, -1, arg_pos == :kwargs)
887893
# TODO: use args_ex instead of Any[Vararg{Any}] and only provide kwarg completion for
888894
# method calls compatible with the current arguments.
889895

stdlib/REPL/test/replcompletions.jl

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2632,6 +2632,35 @@ const issue57780_orig = copy(issue57780)
26322632
test_complete_context("empty!(issue57780).", Main)
26332633
@test issue57780 == issue57780_orig
26342634

2635+
function g54131 end
2636+
for i in 1:498
2637+
@eval g54131(::Val{$i}) = i
2638+
end
2639+
g54131(::Val{499}; kwarg=true) = 499*kwarg
2640+
struct F54131; end
2641+
Base.getproperty(::F54131, ::Symbol) = Any[cos, sin, g54131][rand(1:3)]
2642+
f54131 = F54131()
2643+
@testset "performance of kwarg completion with large method tables" begin
2644+
# The goal here is to simply ensure we aren't hitting catestrophically bad
2645+
# behaviors when shift isn't pressed. The difference between good and bad
2646+
# is on the order of tens of milliseconds vs tens of seconds; using 1 sec as
2647+
# a very rough canary that is hopefully robust even in the noisy CI coalmines
2648+
s = "g54131(kwa"
2649+
a, b, c = completions(s, lastindex(s), @__MODULE__, #= shift =# false)
2650+
@test REPLCompletions.KeywordArgumentCompletion("kwarg") in a
2651+
@test (@elapsed completions(s, lastindex(s), @__MODULE__, false)) < 1
2652+
2653+
s = "f54131.x("
2654+
a, b, c = completions(s, lastindex(s), @__MODULE__, false)
2655+
@test only(a) isa REPLCompletions.TextCompletion
2656+
@test (@elapsed completions(s, lastindex(s), @__MODULE__, false)) < 1
2657+
2658+
s = "f54131.x(kwa"
2659+
a, b, c = completions(s, lastindex(s), @__MODULE__, false)
2660+
@test_broken REPLCompletions.KeywordArgumentCompletion("kwarg") in a
2661+
@test (@elapsed completions(s, lastindex(s), @__MODULE__, false)) < 1
2662+
end
2663+
26352664
# Completion inside string interpolation
26362665
let s = "\"example: \$varflo"
26372666
c, r = test_complete_foo(s)

0 commit comments

Comments
 (0)