Repository: sphinx-doc/sphinx

Issue:
Reference target not found for typing.Literal with negative integer argument
### Describe the bug

Using a negative number as the value of a `typing.Literal` type hint causes sphinx to fail to resolve the reference.

### How to Reproduce

```python
# conf.py

nitpicky = True
extensions = ["sphinx.ext.intersphinx"]
intersphinx_mapping = {"python": ("https://docs.python.org/3", None)}
```

```rst
.. py:data:: test
    :type: ~typing.Literal[2]

    This one links to ``https://docs.python.org/3/library/typing.html#typing.Literal``

.. py:data:: test2
    :type: ~typing.Literal[-2]

    This one warns::

        WARNING: py:obj reference target not found: typing.Literal[-2]
```


### Environment Information

```text
Platform:              win32; (Windows-10-10.0.22621-SP0)
Python version:        3.11.4 (tags/v3.11.4:d2340ef, Jun  7 2023, 05:45:37) [MSC v.1934 64 bit (AMD64)])
Python implementation: CPython
Sphinx version:        7.2.6
Docutils version:      0.20.1
Jinja2 version:        3.1.2
Pygments version:      2.16.1
```


### Sphinx extensions

```python
["sphinx.ext.intersphinx"]
```


### Additional context

I'm calling sphinx as follows:
```
"C:\Program Files\Python311\python.exe" -m sphinx.cmd.build -b html -W -n --keep-going -d build/doctrees . build/html 
```


Discussion:
Well.. this is a weird thing. I'll investigate in a few weeks time if no one has looked at it. 



Patch:
diff --git a/sphinx/domains/python/_annotations.py b/sphinx/domains/python/_annotations.py
index dbd29213e1b..5d4803cfb60 100644
--- a/sphinx/domains/python/_annotations.py
+++ b/sphinx/domains/python/_annotations.py
@@ -109,6 +109,8 @@ def unparse(node: ast.AST) -> list[Node]:
             return unparse(node.value)
         if isinstance(node, ast.Invert):
             return [addnodes.desc_sig_punctuation('', '~')]
+        if isinstance(node, ast.USub):
+            return [addnodes.desc_sig_punctuation('', '-')]
         if isinstance(node, ast.List):
             result = [addnodes.desc_sig_punctuation('', '[')]
             if node.elts:


Test patch:
diff --git a/tests/roots/test-domain-py/module.rst b/tests/roots/test-domain-py/module.rst
index 4a280681207..70098f68752 100644
--- a/tests/roots/test-domain-py/module.rst
+++ b/tests/roots/test-domain-py/module.rst
@@ -58,3 +58,9 @@ module
 .. py:module:: object
 
 .. py:function:: sum()
+
+.. py:data:: test
+    :type: typing.Literal[2]
+
+.. py:data:: test2
+    :type: typing.Literal[-2]
diff --git a/tests/test_domains/test_domain_py.py b/tests/test_domains/test_domain_py.py
index f94d54382a9..e653c80fcb1 100644
--- a/tests/test_domains/test_domain_py.py
+++ b/tests/test_domains/test_domain_py.py
@@ -133,7 +133,9 @@ def assert_refnode(node, module_name, class_name, target, reftype=None,
     assert_refnode(refnodes[13], False, False, 'list', 'class')
     assert_refnode(refnodes[14], False, False, 'ModTopLevel', 'class')
     assert_refnode(refnodes[15], False, False, 'index', 'doc', domain='std')
-    assert len(refnodes) == 16
+    assert_refnode(refnodes[16], False, False, 'typing.Literal', 'obj', domain='py')
+    assert_refnode(refnodes[17], False, False, 'typing.Literal', 'obj', domain='py')
+    assert len(refnodes) == 18
 
     doctree = app.env.get_doctree('module_option')
     refnodes = list(doctree.findall(pending_xref))