sphinx-doc / sphinx

The Sphinx documentation generator
https://www.sphinx-doc.org/
Other
6.6k stars 2.12k forks source link

py domain: All `:py:*` roles can refer python objects even if objtype not matched. #7243

Closed tk0miya closed 4 years ago

tk0miya commented 4 years ago

Describe the bug py domain: All :py:* roles can refer python objects even if objtype not matched.

To Reproduce

Both :py:meth: and :py:class: are converted into hyperlinks to .. py:function:: foo.

.. py:function:: foo

:py:meth:`foo`
:py:class:`foo`

Expected behavior They fails to create hyperlinks for python object when objtype is different.

Your project N/A

Screenshots N/A

Environment info

tk0miya commented 4 years ago

I found same problem in C domain:

.. c:function:: hello()

:c:member:`hello`
:c:macro:`hello`
:c:func:`hello`
jakobandersen commented 4 years ago

First: @tk0miya, thanks for all the work and maintenance! It's really nice.

I'll look more closely at the C domain soon(TM), but just a few semi-relevant comments for now.

This is definitely an issue that should be resolve in each domain, though I'm not entirely sure it should be solved in the same style everywhere, nor that it shouldn't be. Different languages/domains may have different semantics that begs for different resolutions. In general, for the programming language domains, I believe that xref roles should resolve almost* independent of object types. Once resolved, then if there is a mismatch of role type and object type, a warning should be issued. E.g., for the example:

.. py:function:: foo

:py:meth:`foo`, great, role type matches the object it resolves to
:py:class:`foo`, warning, target ``foo`` is a function but the xref role is a class

That is, the second xref becomes the exact same link** as the first. This is the scheme I implemented in the C++ domain. From a brief view, PR #7256 implements the alternative where the second link triggers a warning about foo not found, which I personally find misleading.***

* Different roles may parse their argument with differently. E.g., the cpp:func role allows for specifying a specific function overload. This parsing option is not enabled in the other roles. ** Different roles may transform the link text in different ways. Notably, the function roles in multiple (all?) domains has the fix_parens option enabled, which ensures that the link text ends with (), e.g., :py:meth:`foo` becomes a link with text foo(). *** When time allows I can make the necessary fixes in the C domain, though it may be some more weeks before I get to it.

tk0miya commented 4 years ago

Agreed. I don't think all domains are fixed as same. Now I wonder this fix is really helpful to Python. For example, we have a discussion about attributes and properties (refs: #7068). They are different in implementation, but behave almost same. Other case, we received a post about typing.Any in sphinx-users form. Usually it is used like a type. But it is a variable, not a class.

In python, everything is an object. Variables, functions and classes are all objects. And we don't need to know the some object is either a function, a class or an instance. For example, int is a class. But somebody might consider it as a function which converts string to integer like int("1"). I also did not know staticmethod is a class, not a function (decorator). In my understanding, the behavior of the objects is determined by special methods (dunder methods). So all instances, functions, classes and other all objects having __call__() methods behave like "callable".

Therefore, my proposal in this issue would be correct. But it would also be uncomfortable restriction for python developers. I reconsider again what we should do for python domain especially.

Note: On the other hand, I feel no problem for C domain to fix this.

tk0miya commented 4 years ago

Closing this now. I think this will harm users. Thanks,