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

Add more details for "Invalid type" errors #7166

Merged
merged 9 commits into from Jul 8, 2019

Conversation

@ilevkivskyi
Copy link
Collaborator

commented Jul 6, 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.

Please add ideas about how to improve these errors.

@JukkaL
Copy link
Collaborator

left a comment

Great! This improves one of the most common (and most confusing ) error messages.

This is the first part of my review: I left various suggestions about how to improve the error messages. I'll do another pass once the error messages are final.

import mock
from typing import Union

class A: ...
class B: ...

x: Union[mock, A] # E: Invalid type "mock"
x: Union[mock, A] # E: Invalid type "mock": Module cannot be used as type

This comment has been minimized.

Copy link
@JukkaL

JukkaL Jul 8, 2019

Collaborator

Bikeshedding: this error message could be shortened down to Module "mock" is not valid as a type without loss of clarity, I think.

import six
class M(type): pass
class A(object): pass
def f() -> type: return M
class C1(six.with_metaclass(M), object): pass # E: Invalid base class
class C2(C1, six.with_metaclass(M)): pass # E: Invalid base class
class C1(six.with_metaclass(M), object): pass # E: Invalid base class "six.with_metaclass": Unsupported dynamic base class

This comment has been minimized.

Copy link
@JukkaL

JukkaL Jul 8, 2019

Collaborator

Similar to above, this could be shortened to Unsupported dynamic base class "six.with_metaclass".

def f(x: bad): # E:10: Invalid type "__main__.bad"
y: bad # E:8: Invalid type "__main__.bad"
def f(x: bad): # E:10: Invalid type "__main__.bad": Cannot use variable as type
y: bad # E:8: Invalid type "__main__.bad": Cannot use variable as type

This comment has been minimized.

Copy link
@JukkaL

JukkaL Jul 8, 2019

Collaborator

Like above, this could be shortened to Variable "__main__.bad" is not valid as a type.

@@ -1737,12 +1738,12 @@ J = Callable[[VarArg(), KwArg()], int] # ok
K = Callable[[VarArg(), int], int] # E: Required positional args may not appear after default, named or var args
L = Callable[[Arg(name='x', type=int)], int] # ok
# I have commented out the following test because I don't know how to expect the "defined here" note part of the error.
# M = Callable[[Arg(gnome='x', type=int)], int] E: Invalid type alias E: Unexpected keyword argument "gnome" for "Arg"
# M = Callable[[Arg(gnome='x', type=int)], int] E: Invalid type alias: cannot interpret right hand side as a type E: Unexpected keyword argument "gnome" for "Arg"

This comment has been minimized.

Copy link
@JukkaL

JukkaL Jul 8, 2019

Collaborator

Bikeshedding: Invalid type alias: expression is not a valid type.

@@ -2195,9 +2196,9 @@ from b import x
1 + 1
[out]
[out2]
tmp/b.py:2: error: Invalid type "c.C"
tmp/b.py:2: error: Invalid type "c.C": Cannot use function as type, use Callable[...] or a protocol instead

This comment has been minimized.

Copy link
@JukkaL

JukkaL Jul 8, 2019

Collaborator

Again, the first part could be shortened to Function "c.C" is not valid as a type. I'd move the final part to a separate note and rephrase it, since it's not clear of Callable[...] or a protocol is actually what the user wants. Maybe something like this:

b.py:2: error: Function "c.C" is not a valid type
b.py:2: note: Perhaps you need Callable[...] or a callback protocol?
from typing_extensions import Literal
a: (1, 2, 3) # E: Syntax error in type annotation \
# N: Suggestion: Use Tuple[T1, ..., Tn] instead of (T1, ..., Tn)
b: Literal[[1, 2, 3]] # E: Parameter 1 of Literal[...] is invalid
c: [1, 2, 3] # E: Invalid type
c: [1, 2, 3] # E: Invalid type: Did you want to use "List[...]"?

This comment has been minimized.

Copy link
@JukkaL

JukkaL Jul 8, 2019

Collaborator

When we give a suggestion, we typically give it as a separate line. For example:

x.py:2: error: Expression "[...]" is not a valid type
x.py:2 note: Did you mean "List[t]"? 

We could do the same thing for x: (int, str) (Tuple[t1, ..., tN]), x: {int} (Set[t]) and x: {int: str} (Dict[kt, vt]).

This comment has been minimized.

Copy link
@ilevkivskyi

ilevkivskyi Jul 8, 2019

Author Collaborator

We already do this for tuples, dict and set are more tricky (and I think more rare) so I would leave this for a separate PR.

main:4: error: Invalid type "__main__.T"
main:4: error: Argument 2 to NewType(...) must be subclassable (got T?)
main:4: error: Invalid type "__main__.T": Can only use bound type variables as types
main:5: error: Invalid type "__main__.T": Can only use bound type variables as types

This comment has been minimized.

Copy link
@JukkaL

JukkaL Jul 8, 2019

Collaborator

Bikeshedding: Type variable "__main__.T" is unbound. Maybe also add a note about what this means, since unbound/bound can be confusing for new users. Idea:

main:4: error: Type variable "__main__.T" is unbound
main:4:note: (Hint: Use "Generic[T]" or "Protocol[T]" base class to bind "T" inside a class)
main:4:note: (Hint: Use "T" in function signature to bind "T" inside a function)
from typing import Union
class A:
def __enter__(self) -> int: pass
def __exit__(self, x, y, z): pass

with A(): # type: int # E: Invalid type comment
with A(): # type: int # E: Invalid type comment: `with` statement has no targets

This comment has been minimized.

Copy link
@JukkaL

JukkaL Jul 8, 2019

Collaborator

Style nit: use double quotes (... "with" statement ...).

Ivan Levkivskyi added some commits Jul 8, 2019

@JukkaL

JukkaL approved these changes Jul 8, 2019

Copy link
Collaborator

left a comment

Thanks for the updates! Looks good!

Ivan Levkivskyi added some commits Jul 8, 2019

Ivan Levkivskyi
Ivan Levkivskyi

@ilevkivskyi ilevkivskyi merged commit 0de5234 into python:master Jul 8, 2019

1 check passed

continuous-integration/appveyor/pr AppVeyor build succeeded
Details

@ilevkivskyi ilevkivskyi deleted the ilevkivskyi:invalid-type branch Jul 8, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.