Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The docs for the typing stdlib module use the phrase "bound type var" to mean two distinct things #126543

Open
fofoni opened this issue Nov 7, 2024 · 6 comments
Labels
docs Documentation in the Doc dir topic-typing

Comments

@fofoni
Copy link

fofoni commented Nov 7, 2024

Documentation

Follow-up of: https://discuss.python.org/t/a-typevar-with-a-bound-is-a-bounded-typevar-or-a-bound-typevar/69966

As discussed above, in some places the stdlib docs for the typing module use the phrase "bound type var" to mean a TypeVar created using the bound keyword argument. This keyword argument, however, establishes a boundary for that type variable, instead of binding it---the binding happens when we instantiate a generic function or class.

I proposed changing "bound type var" to "bounded type var" in such contexts. @hauntsaninja expressed a concern that distinguishing between "bound" and "bounded" could be too subtle, and suggested using "type var with upper bound" instead, and "hope that PEP 695 means we all end up talking about bound or unbound type variables less often." Two other people commented agreeing that there is an issue, but expressing no preference for "bounded" vs "with upper bound".

I'd like to make a case for "bounded":

  1. The expression "upper bound" is used in the typing spec and in mypy's documentation (links in the Discourse thread), but it is not currently used in the stdlib docs. Introducing this expression would require a little refactoring of the text.
  2. In a few places in the text, the stdlib docs focuses on distinguishing bound (i.e. bounded) type vars from constrained type vars, and the text makes use of the fact that both "bound" and "constrinained" can be used as single-word adjectives to make parallell arguments clear. I believe that, for the resulting text to feel netural, changing "bound" to "with upper bound" would also require a little bit of refactoring.
  3. @hauntsaninja hoped that "PEP 695 means we all end up talking about bound or unbound type variables less often." I don't really see why this would be the case. Take this docs snippet (which by the way is the first use of the word "bound" to mean "bounded"):
   This syntax can also be used to create bound and constrained type
   variables::

      class StrSequence[S: str]:  # S is a TypeVar bound to str
          ...


      class StrOrBytesSequence[A: (str, bytes)]:  # A is a TypeVar constrained to str or bytes
          ...

PEP 695 introduces the [S: str] syntax so that the user can still explicitly declare that that type var has an upper bound (even though the word "bound" is not used anymore). Since this is a decision the user has to make, I believe the docs will still need to distinguish bounded type vars from unbounded type vars.

I'll play around with the text, but before submitting a PR I'll wait until we reach a consensus on "bounded" vs "with upper bound". Of course, if we end up deciding in favor of "with upper bound", I'll be happy to introduce the expression "upper bound" and make the small text refactorings required.

@fofoni fofoni added the docs Documentation in the Doc dir label Nov 7, 2024
@carljm
Copy link
Member

carljm commented Nov 7, 2024

I would be happy with switching from "bound" to "bounded" where we mean "a typevar with a (n upper) bound"; to me that seems like clearly an improvement in clarity and precision compared to the current text (which just uses "bound" for everything) and doesn't require any more invasive rewordings. I don't see "with upper bound" as a better option; I agree that looks like it would be quite awkward in many usages. And I also agree that PEP 695 won't reduce our need to discuss TypeVars which have an upper bound.

To me the biggest issue is that the keyword argument to TypeVar et al is named bound. This is not wrong, but it's confusing, since it means we will still have multiple meanings of bound used in the text (at least to the extent that function signatures are part of "the text"). But this is a problem that PEP 695 should help with over time, since it should reduce usage of that keyword argument.

@picnixz
Copy link
Contributor

picnixz commented Nov 7, 2024

As I said on the thread, I don't have a preferrence for either of the two options, though I would have personally used "bounded TypeVar". I would use "upper bound" only if I need to mention the upper bound in question, for instance, A TypeVar with a str upper bound instead of a str-bounded TypeVar.

@JelleZijlstra
Copy link
Member

I agree with using "bounded" over "bound" for TypeVars with upper bounds. However, the docs also once use "bound" to refer to the operation of setting a TypeVar to a specific type: "# T is bound to int, Ts is bound to ()". For clarity, it might be better if we pick a different term for that.

@carljm
Copy link
Member

carljm commented Nov 7, 2024

I agree with using "bounded" over "bound" for TypeVars with upper bounds. However, the docs also once use "bound" to refer to the operation of setting a TypeVar to a specific type: "# T is bound to int, Ts is bound to ()". For clarity, it might be better if we pick a different term for that.

I noticed this usage also; I guess I assumed that switching to "bounded" where we mean "has an upper bound" was in order to disambiguate from this usage.

I'm not necessarily opposed to finding a different term, but I don't have a suggestion; I think that "binding" is the most common term here, and anything else we pick may be confusing just because it's not commonly used, rather than due to the possible confusion with typevar bounds.

@hauntsaninja
Copy link
Contributor

hauntsaninja commented Nov 7, 2024

hauntsaninja hoped that "PEP 695 means we all end up talking about bound or unbound type variables less often." I don't really see why this would be the case.

Sorry, I should have been clearer about what I meant by unbound. mypy + the typing specification + maybe also pyright often use bound-as-in-binding to refer to the act of attaching a type variable to a scope (in this sense, "unbound type variables" are an error). PEP 695 syntax makes it hard to use an unbound-as-in-binding type variable because it won't be defined.

@carljm
Copy link
Member

carljm commented Nov 7, 2024

Oh no, we have two different meanings even for bound-as-in-binding 😆 It could mean "bound to a scope" (in this sense, PEP695 type variables can never be unbound), but it can also mean "bound to a type", as in the docs usage @JelleZijlstra mentioned above. In the latter sense, I think this PEP 695 code uses an unbound type variable:

def f[T]() -> T: ...

Both mypy and pyright error on this, though neither refer to the type variable as "unbound" in their error message.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs Documentation in the Doc dir topic-typing
Projects
Status: Todo
Development

No branches or pull requests

6 participants