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

Better error message for "Invalid type" #4030

Closed
ilevkivskyi opened this issue Sep 29, 2017 · 5 comments · Fixed by #7166
Closed

Better error message for "Invalid type" #4030

ilevkivskyi opened this issue Sep 29, 2017 · 5 comments · Fixed by #7166

Comments

@ilevkivskyi
Copy link
Member

There several situations where a quite terse error message is given: Invalid type "__main__.T" -- this could be an attempt to use a variable as a type, attempt to use function as a type, unsupported forward reference, maybe some other. I propose to make this error message more specific, or add a note:

error: Invalid type "__main__.f"
note: Functions can't be used as a type

and

error: Invalid type "__main__.Alias"
note: Variables can't be used as a type

The second can be also useful if someone accidentally created a variable instead of an alias. In this case we can even append a link to docs, if we detect that variable has type Type[...].

Another similar terse error message is Invalid base class. We can say which base is invalid, this will be useful in case of multiple bases on the same line, and maybe also add a note in some cases explaining why it is invalid, like note: Union types can't be subclassed, so that it is clear what went wrong.

@gvanrossum
Copy link
Member

Also e.g.

class C:
  A = int

a: C.A  # error: Invalid type "_.C.A"

@ilevkivskyi
Copy link
Member Author

ilevkivskyi commented Jan 24, 2018

This case is actually quite important, especially while #3494 (document variables vs aliases) is not fixed.

Michael0x2a added a commit to Michael0x2a/mypy that referenced this issue Dec 31, 2018
This diff changes how we track raw literal types in the semantic
analysis phase. It makes the following changes:

1.  Removes the `RawLiteralType` synthetic type.

2.  Adds a new `TypeOfAny`: `TypeOfAny.invalid_type` as suggested
    in python#4030.

3.  Modifies `AnyType` so it can optionally contain a new
    `RawLiteral` class. This class contains information
    about the underlying literal that produced that particular
    `TypeOfAny`.

4.  Adjusts mypy to stop recommending using `Literal[...]` when
    doing `A = NewType('A', 4)` or `T = TypeVar('T', bound=4)`.

    (The former suggestion is a bad one: you can't create a NewType of a
    Literal[...] type. The latter suggestion is a valid but stupid one:
    `T = TypeVar('T', bound=Literal[4])` is basically the same thing as
    `T = Literal[4]`.)

    This resolves python#5989.

The net effect of this diff is that:

1.  RawLiteralTypes no longer leak during fine-grained mode,
    which should partially help unblock
    python#6075.

2.  The way mypy handles literal expressions in types is "inverted".

    Previously, we by default assumed literal expressions would belong
    inside `Literal[...]` and tacked on some logic to make them convert
    into error `AnyTypes`. Now, we do the reverse: we start with an
    error `AnyType` and convert those into `Literal[...]`s as needed.

    This more closely mirrors the way mypy *used* to work before we
    started work on Literal types. It should also hopefully help reduce
    some of the cognitive burden of working on other parts of the
    semantic analysis code, since we no longer need to worry about the
    `RawLiteralType` synthetic type.

3.  We now have more flexibility in how we choose to handle invalid
    types: since they're just `Anys`, we have more opportunities to
    intercept and customize the exact way in which we handle errors.

    Also see python#4030 for additional
    context. (This diff lays out some of the foundation work for that
    diff).
@ilevkivskyi
Copy link
Member Author

A rare case where adding "Invalid type" would be actually helpful is the error message for using subscriptable metaclasses in type context, see #6313.

@ilevkivskyi
Copy link
Member Author

A similar example where we should give a better error message is (recently closed) #2477

@ilevkivskyi
Copy link
Member Author

One more example is cast targets, see #6862

@gvanrossum gvanrossum changed the title Better error messge for "Invalid type" Better error message for "Invalid type" May 20, 2019
ilevkivskyi added a commit that referenced this issue Jul 8, 2019
Fixes #4030

This adds some more details to various `Invalid type` errors, and similar such as `Invalid type alias`, and `Invalid base class`. Unfortunately, `MessageBuilder` is not available in `typeanal.py`, so I put some error message formatting logic there.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants