diff --git a/.travis.yml b/.travis.yml
index def0d930b..4139cc2b6 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -72,7 +72,7 @@ matrix:
     - arch: arm64
       python: "3.7"
       dist: xenial
-      env: ARM64=True
+      env: ARM64=True IPYTHON_TESTING_TIMEOUT_SCALE=2
       sudo: true
     - arch: amd64
       python: "3.8"
diff --git a/IPython/core/completer.py b/IPython/core/completer.py
index 0942798f3..9a81d637f 100644
--- a/IPython/core/completer.py
+++ b/IPython/core/completer.py
@@ -626,6 +626,8 @@ def __init__(self, namespace=None, global_namespace=None, **kwargs):
         else:
             self.global_namespace = global_namespace
 
+        self.custom_matchers = []
+
         super(Completer, self).__init__(**kwargs)
 
     def complete(self, text, state):
@@ -1122,12 +1124,14 @@ def matchers(self):
 
         if self.use_jedi:
             return [
+                *self.custom_matchers,
                 self.file_matches,
                 self.magic_matches,
                 self.dict_key_matches,
             ]
         else:
             return [
+                *self.custom_matchers,
                 self.python_matches,
                 self.file_matches,
                 self.magic_matches,
diff --git a/IPython/core/interactiveshell.py b/IPython/core/interactiveshell.py
index 4cbc885cb..848a14a48 100644
--- a/IPython/core/interactiveshell.py
+++ b/IPython/core/interactiveshell.py
@@ -2218,7 +2218,7 @@ def set_custom_completer(self, completer, pos=0):
         list where you want the completer to be inserted."""
 
         newcomp = types.MethodType(completer,self.Completer)
-        self.Completer.matchers.insert(pos,newcomp)
+        self.Completer.custom_matchers.insert(pos,newcomp)
 
     def set_completer_frame(self, frame=None):
         """Set the frame of the completer."""

set_custom_completer seems to be a no-op
In [interactive_shell.py](https://github.com/ipython/ipython/blob/a2685d78f2403f84e6cb915ae11a4f6033ccc5f6/IPython/core/interactiveshell.py#L2034), `set_custom_completer` does

    self.Completer.matchers.insert(pos,newcomp)

Looking at the source code of IPCompleter, though, [matchers](https://github.com/ipython/ipython/blob/eed56ba34aa3856b5726d60eedfe60a17e1c26c5/IPython/core/completer.py#L1114) seems to be a property returning an ephemeral list, so the insert is a no-op.

To reproduce:

    import IPython

    def foo(*args, **kwargs):
        pass

    print(len(IPython.get_ipython().Completer.matchers))
    IPython.get_ipython().set_custom_completer(foo, 0)
    print(len(IPython.get_ipython().Completer.matchers))

This should print the same number twice (in my version, 5, 5)

diff --git a/IPython/core/tests/test_interactiveshell.py b/IPython/core/tests/test_interactiveshell.py
index 578ef27d3..496e3bd02 100644
--- a/IPython/core/tests/test_interactiveshell.py
+++ b/IPython/core/tests/test_interactiveshell.py
@@ -998,3 +998,21 @@ def test_should_run_async():
     assert not ip.should_run_async("a = 5")
     assert ip.should_run_async("await x")
     assert ip.should_run_async("import asyncio; await asyncio.sleep(1)")
+
+
+def test_set_custom_completer():
+    num_completers = len(ip.Completer.matchers)
+
+    def foo(*args, **kwargs):
+        return "I'm a completer!"
+
+    ip.set_custom_completer(foo, 0)
+
+    # check that we've really added a new completer
+    assert len(ip.Completer.matchers) == num_completers + 1
+
+    # check that the first completer is the function we defined
+    assert ip.Completer.matchers[0]() == "I'm a completer!"
+
+    # clean up
+    ip.Completer.custom_matchers.pop()

pip install -e .[test]
parse_log_pytest
requirements.txt
pytest
3.6
requirements/base.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
asttokens==2.4.1
attrs==22.2.0
backcall==0.2.0
certifi==2021.5.30
charset-normalizer==2.0.12
decorator==5.1.1
entrypoints==0.4
executing==2.0.1
idna==3.10
importlib-metadata==4.8.3
iniconfig==1.1.1
ipykernel==5.5.6
-e git+https://github.com/ipython/ipython.git@201acc865abb92a6184b3c01d21c577e1ff07139#egg=ipython
ipython-genutils==0.2.0
jedi==0.19.2
jsonschema==3.2.0
jupyter-client==7.1.2
jupyter-core==4.9.2
nbformat==5.1.3
nest-asyncio==1.6.0
nose==1.3.7
numpy==1.19.5
packaging==21.3
parso==0.8.4
pexpect==4.9.0
pickleshare==0.7.5
pluggy==1.0.0
prompt-toolkit==3.0.36
ptyprocess==0.7.0
pure_eval==0.2.3
py==1.11.0
Pygments==2.14.0
pyparsing==3.1.4
pyrsistent==0.18.0
pytest==7.0.1
python-dateutil==2.9.0.post0
pyzmq==25.1.2
requests==2.27.1
six==1.17.0
stack-data==0.6.3
testpath==0.6.0
tomli==1.2.3
tornado==6.1
traitlets==4.3.3
typing_extensions==4.1.1
urllib3==1.26.20
wcwidth==0.2.13
zipp==3.6.0

name: ipython
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2021.5.30=py36h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.3=he6710b0_2
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=21.2.2=py36h06a4308_0
  - python=3.6.13=h12debd9_1
  - readline=8.2=h5eee18b_0
  - setuptools=58.0.4=py36h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.37.1=pyhd3eb1b0_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - asttokens==2.4.1
      - attrs==22.2.0
      - backcall==0.2.0
      - charset-normalizer==2.0.12
      - decorator==5.1.1
      - entrypoints==0.4
      - executing==2.0.1
      - idna==3.10
      - importlib-metadata==4.8.3
      - iniconfig==1.1.1
      - ipykernel==5.5.6
      - ipython-genutils==0.2.0
      - jedi==0.19.2
      - jsonschema==3.2.0
      - jupyter-client==7.1.2
      - jupyter-core==4.9.2
      - nbformat==5.1.3
      - nest-asyncio==1.6.0
      - nose==1.3.7
      - numpy==1.19.5
      - packaging==21.3
      - parso==0.8.4
      - pexpect==4.9.0
      - pickleshare==0.7.5
      - pluggy==1.0.0
      - prompt-toolkit==3.0.36
      - ptyprocess==0.7.0
      - pure-eval==0.2.3
      - py==1.11.0
      - pygments==2.14.0
      - pyparsing==3.1.4
      - pyrsistent==0.18.0
      - pytest==7.0.1
      - python-dateutil==2.9.0.post0
      - pyzmq==25.1.2
      - requests==2.27.1
      - six==1.17.0
      - stack-data==0.6.3
      - testpath==0.6.0
      - tomli==1.2.3
      - tornado==6.1
      - traitlets==4.3.3
      - typing-extensions==4.1.1
      - urllib3==1.26.20
      - wcwidth==0.2.13
      - zipp==3.6.0
prefix: /opt/conda/envs/ipython

IPython/core/tests/test_interactiveshell.py::test_set_custom_completer
IPython/core/tests/test_interactiveshell.py::InteractiveShellTestCase::test_In_variable IPython/core/tests/test_interactiveshell.py::InteractiveShellTestCase::test_bad_custom_tb IPython/core/tests/test_interactiveshell.py::InteractiveShellTestCase::test_bad_custom_tb_return IPython/core/tests/test_interactiveshell.py::InteractiveShellTestCase::test_bad_var_expand IPython/core/tests/test_interactiveshell.py::InteractiveShellTestCase::test_can_pickle IPython/core/tests/test_interactiveshell.py::InteractiveShellTestCase::test_custom_exception IPython/core/tests/test_interactiveshell.py::InteractiveShellTestCase::test_custom_syntaxerror_exception IPython/core/tests/test_interactiveshell.py::InteractiveShellTestCase::test_dont_cache_with_semicolon IPython/core/tests/test_interactiveshell.py::InteractiveShellTestCase::test_drop_by_id IPython/core/tests/test_interactiveshell.py::InteractiveShellTestCase::test_future_flags IPython/core/tests/test_interactiveshell.py::InteractiveShellTestCase::test_get_exception_only IPython/core/tests/test_interactiveshell.py::InteractiveShellTestCase::test_gh_597 IPython/core/tests/test_interactiveshell.py::InteractiveShellTestCase::test_global_ns IPython/core/tests/test_interactiveshell.py::InteractiveShellTestCase::test_inspect_text IPython/core/tests/test_interactiveshell.py::InteractiveShellTestCase::test_last_execution_result IPython/core/tests/test_interactiveshell.py::InteractiveShellTestCase::test_magic_names_in_string IPython/core/tests/test_interactiveshell.py::InteractiveShellTestCase::test_mktempfile IPython/core/tests/test_interactiveshell.py::InteractiveShellTestCase::test_multiline_string_cells IPython/core/tests/test_interactiveshell.py::InteractiveShellTestCase::test_naked_string_cells IPython/core/tests/test_interactiveshell.py::InteractiveShellTestCase::test_new_main_mod IPython/core/tests/test_interactiveshell.py::InteractiveShellTestCase::test_ofind_cell_magic IPython/core/tests/test_interactiveshell.py::InteractiveShellTestCase::test_ofind_line_magic IPython/core/tests/test_interactiveshell.py::InteractiveShellTestCase::test_ofind_multiple_attribute_lookups IPython/core/tests/test_interactiveshell.py::InteractiveShellTestCase::test_ofind_prefers_property_to_instance_level_attribute IPython/core/tests/test_interactiveshell.py::InteractiveShellTestCase::test_ofind_property_with_error IPython/core/tests/test_interactiveshell.py::InteractiveShellTestCase::test_ofind_slotted_attributes IPython/core/tests/test_interactiveshell.py::InteractiveShellTestCase::test_reset_aliasing IPython/core/tests/test_interactiveshell.py::InteractiveShellTestCase::test_run_cell_multiline IPython/core/tests/test_interactiveshell.py::InteractiveShellTestCase::test_run_empty_cell IPython/core/tests/test_interactiveshell.py::InteractiveShellTestCase::test_silent_noadvance IPython/core/tests/test_interactiveshell.py::InteractiveShellTestCase::test_silent_nodisplayhook IPython/core/tests/test_interactiveshell.py::InteractiveShellTestCase::test_silent_postexec IPython/core/tests/test_interactiveshell.py::InteractiveShellTestCase::test_syntax_error IPython/core/tests/test_interactiveshell.py::InteractiveShellTestCase::test_trailing_newline IPython/core/tests/test_interactiveshell.py::InteractiveShellTestCase::test_var_expand IPython/core/tests/test_interactiveshell.py::InteractiveShellTestCase::test_var_expand_local IPython/core/tests/test_interactiveshell.py::InteractiveShellTestCase::test_var_expand_self IPython/core/tests/test_interactiveshell.py::TestSafeExecfileNonAsciiPath::test_1 IPython/core/tests/test_interactiveshell.py::ExitCodeChecks::test_exit_code_error IPython/core/tests/test_interactiveshell.py::ExitCodeChecks::test_exit_code_ok IPython/core/tests/test_interactiveshell.py::ExitCodeChecks::test_exit_code_signal IPython/core/tests/test_interactiveshell.py::TestSystemRaw::test_1 IPython/core/tests/test_interactiveshell.py::TestSystemRaw::test_control_c IPython/core/tests/test_interactiveshell.py::TestSystemRaw::test_exit_code_error IPython/core/tests/test_interactiveshell.py::TestSystemRaw::test_exit_code_ok IPython/core/tests/test_interactiveshell.py::TestSystemRaw::test_exit_code_signal IPython/core/tests/test_interactiveshell.py::TestSystemPipedExitCode::test_exit_code_error IPython/core/tests/test_interactiveshell.py::TestSystemPipedExitCode::test_exit_code_ok IPython/core/tests/test_interactiveshell.py::TestSystemPipedExitCode::test_exit_code_signal IPython/core/tests/test_interactiveshell.py::TestModules::test_extraneous_loads IPython/core/tests/test_interactiveshell.py::TestAstTransform::test_macro IPython/core/tests/test_interactiveshell.py::TestAstTransform::test_run_cell IPython/core/tests/test_interactiveshell.py::TestAstTransform::test_time IPython/core/tests/test_interactiveshell.py::TestAstTransform::test_timeit IPython/core/tests/test_interactiveshell.py::TestAstTransform2::test_run_cell IPython/core/tests/test_interactiveshell.py::TestAstTransform2::test_timeit IPython/core/tests/test_interactiveshell.py::TestAstTransformError::test_unregistering IPython/core/tests/test_interactiveshell.py::TestAstTransformInputRejection::test_input_rejection IPython/core/tests/test_interactiveshell.py::test__IPYTHON__ IPython/core/tests/test_interactiveshell.py::test_user_variables IPython/core/tests/test_interactiveshell.py::test_user_expression IPython/core/tests/test_interactiveshell.py::TestSyntaxErrorTransformer::test_syntaxerror_input_transformer IPython/core/tests/test_interactiveshell.py::TestWarningSuppression::test_deprecation_warning IPython/core/tests/test_interactiveshell.py::TestWarningSuppression::test_warning_suppression IPython/core/tests/test_interactiveshell.py::TestImportNoDeprecate::test_no_dep IPython/core/tests/test_interactiveshell.py::test_custom_exc_count IPython/core/tests/test_interactiveshell.py::test_run_cell_async IPython/core/tests/test_interactiveshell.py::test_should_run_async
IPython/core/completer.py .travis.yml IPython/core/interactiveshell.py
IPython/core/completer.py .travis.yml IPython/core/interactiveshell.py