diff --git a/AUTHORS.rst b/AUTHORS.rst
index fd129bb8f72..c798657ff21 100644
--- a/AUTHORS.rst
+++ b/AUTHORS.rst
@@ -70,6 +70,7 @@ Contributors
* Ian Lee -- quickstart improvements
* Jacob Mason -- websupport library (GSOC project)
* James Addison -- linkcheck and HTML search improvements
+* Jens H. Nielsen -- Small fixes for incorrect xref resolution
* Jeppe Pihl -- literalinclude improvements
* Jeremy Maitin-Shepard -- C++ domain improvements
* Joel Wurtz -- cellspanning support in LaTeX
diff --git a/sphinx/domains/python/__init__.py b/sphinx/domains/python/__init__.py
index a23207ea3c2..7e6baccc3ac 100644
--- a/sphinx/domains/python/__init__.py
+++ b/sphinx/domains/python/__init__.py
@@ -945,11 +945,12 @@ def resolve_xref(
if not matches and type == 'class':
# fallback to data/attr (for type aliases)
# type aliases are documented as data/attr but referenced as class
- matches = self.find_obj(env, modname, clsname, target, 'data', searchmode)
+ # Use searchmode=0 (exact match only) to avoid fuzzy matching
+ # that could incorrectly match class attributes (e.g. D.list)
+ # when resolving builtin type annotations (e.g. list[int]).
+ matches = self.find_obj(env, modname, clsname, target, 'data', 0)
if not matches:
- matches = self.find_obj(
- env, modname, clsname, target, 'attr', searchmode
- )
+ matches = self.find_obj(env, modname, clsname, target, 'attr', 0)
if not matches and type == 'attr':
# fallback to meth (for property; Sphinx 2.4.x)
# this ensures that `:attr:` role continues to refer to the old property entry
diff --git a/tests/roots/test-domain-py-xref-type-alias-builtin/conf.py b/tests/roots/test-domain-py-xref-type-alias-builtin/conf.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/tests/roots/test-domain-py-xref-type-alias-builtin/index.rst b/tests/roots/test-domain-py-xref-type-alias-builtin/index.rst
new file mode 100644
index 00000000000..60b0cdec92c
--- /dev/null
+++ b/tests/roots/test-domain-py-xref-type-alias-builtin/index.rst
@@ -0,0 +1,28 @@
+Builtin Type Alias False Positive Test
+=======================================
+
+This tests that builtin types like ``list`` in function signatures do not
+incorrectly link to class attributes with the same name.
+
+
+.. py:module:: mymodule
+
+ Module to test builtin type cross-reference false positives.
+
+
+.. py:class:: MyClass
+
+ A class with an attribute that shadows a builtin type name.
+
+ .. py:attribute:: list
+ :value: [1, 2, 3]
+
+ An attribute named ``list`` that shadows the builtin.
+
+
+.. py:function:: process(items: list) -> None
+ :module: mymodule
+
+ Process a list of items.
+
+ The ``list`` type annotation here should NOT link to ``MyClass.list``.
diff --git a/tests/test_domains/test_domain_py.py b/tests/test_domains/test_domain_py.py
index 19e92eca7a6..d5cf0e855d6 100644
--- a/tests/test_domains/test_domain_py.py
+++ b/tests/test_domains/test_domain_py.py
@@ -1900,3 +1900,40 @@ def test_type_alias_xref_resolution(app: SphinxTestApp) -> None:
' None:
+ """Test that builtin type annotations don't falsely link to class attributes.
+
+ Regression test for a bug where ``def process(items: list)`` combined with
+ ``class MyClass`` having a ``list`` attribute would cause the ``list`` type
+ annotation to incorrectly resolve to ``MyClass.list`` via the class→data/attr
+ fallback in PythonDomain.resolve_xref (searchmode must be 0 for exact match).
+ """
+ app.build()
+
+ html_content = (app.outdir / 'index.html').read_text(encoding='utf8')
+
+ # The MyClass.list attribute should still be properly documented
+ assert 'id="mymodule.MyClass.list"' in html_content, (
+ 'MyClass.list attribute anchor not found in HTML'
+ )
+
+ # Find the process() function signature
+ process_match = re.search(
+ r'process.*?', html_content, re.DOTALL
+ )
+ assert process_match is not None, 'Could not find process function signature'
+ process_signature = process_match.group(0)
+
+ # The critical assertion: ``list`` in the function signature must NOT link
+ # to MyClass.list. If the fallback used fuzzy matching (searchmode=1),
+ # "list" would match "MyClass.list" and produce a false-positive link.
+ assert (
+ '