Skip to content

WYSIWYG reporting of generic type arguments default #2461

@jorenham

Description

@jorenham

In recent versions of NumPy, the two np.ndarray generic type parameters default to tuple[Any, ...] and numpy.dtype, respectively. The generic type parameter of numpy.dtype defaults to Any.
So writing _: np.ndarray is equivalent to writing _: np.ndarray[tuple[Any, ...], np.dtype[Any]]. And of course, the opposite is also the case, i.e., _: np.ndarray[tuple[Any, ...], np.dtype[Any]] can be written more compactly as _: np.ndarray.

When reporting types, it looks like pyrefly currently always chooses to "fill in" the defaults of type parameters that aren't provided. For example:

from typing import reveal_type

import numpy as np

def f(a: np.ndarray, /) -> None:
    reveal_type(a)
 INFO revealed type: ndarray[tuple[Any, ...], dtype[Any]] [reveal-type]

One obvious issue is that this is needlessly verbose: "ndarray[tuple[Any, ...], dtype[Any]]" counts 36 characters, while "ndarray" requires only 7; that's a factor of >5x.

It can also be confusing to users to see the type they explicitly wrote as ndarray to be printed as ndarray[tuple[Any, ...], dtype[Any]]. I can imagine that users new to typing in Python would not understand where the [tuple[Any, ...], dtype[Any]] came from.

There's also subjective loss of information: In natural language there are many synonyms, but even though they mean the same, there are often subtle context-dependent nuances that cause people to use them with specific intent, so that they can express themselves a little bit better. The way I see it, the same can be said about ndarray. For example, if one writes _: ndarray[tuple[Any, ...]] it highlights that the shape-type is unknown but relevant, whereas writing _: ndarray could mean that the shape-type isn't relevant.

So all things considered, I would like for pyrefly to report types as they are written. So with this WYSIWYG approach you'd have

def f(a: np.ndarray, /) -> None:
    reveal_type(a)  # revealed type: ndarray [reveal-type]

def f(a: np.ndarray[tuple[Any, ...]], /) -> None:
    reveal_type(a)  # revealed type: ndarray[tuple[Any, ...]] [reveal-type]

and so forth.

Metadata

Metadata

Assignees

No one assigned
    No fields configured for Feature.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions