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

[WIP] Improvement of mismatching type variable error message #3911

Closed
wants to merge 11 commits into from

Conversation

OddBloke
Copy link
Contributor

@OddBloke OddBloke commented Sep 2, 2017

This is attempting to address #963; it's WIP, and pushed up only as a basis for discussion.

@OddBloke
Copy link
Contributor Author

OddBloke commented Sep 2, 2017

As a sample of the output this now produces:

Expected:
  main:8: error: Value of type variable "X" of "A" cannot be "object" (diff)
Actual:
  main:8: error: Argument types for type variable "X" are incompatible in call to "A" (diff)
  main:8: note: All arguments for type variable "X" must be of the same type (one of "int", "str") (diff)


Expected:
  main:6: error: Value of type variable "T" of "f" cannot be "object" (diff)
Actual:
  main:6: error: Argument types for type variable "T" are incompatible in call to "f" (diff)
  main:6: note: All arguments for type variable "T" must be of the same type (one of "int", "str") (diff)


Expected:
  main:9: error: Value of type variable "Y" of "f" cannot be "A" (diff)
  main:10: error: Value of type variable "X" of "f" cannot be "int" (diff)
Actual:
  main:9: error: Argument types for type variable "Y" are incompatible in call to "f" (diff)
  main:9: note: All arguments for type variable "Y" must be of the same type (one of "int", "str") (diff)
  main:10: error: Argument types for type variable "X" are incompatible in call to "f" (diff)
  main:10: note: All arguments for type variable "X" must be of the same type (one of "A", "B") (diff)


Expected:
  main:9: error: Value of type variable "T" of "f" cannot be "object" (diff)
Actual:
  main:9: error: Argument types for type variable "T" are incompatible in call to "f" (diff)
  main:9: note: All arguments for type variable "T" must be of the same type (one of "int", "str") (diff)


Expected:
  main:9:7: error: Value of type variable "T" of "A" cannot be "str"
  main:13: error: Value of type variable "T" of "A" cannot be "str" (diff)
  main:13: error: Value of type variable "S" of "A" cannot be "str" (diff)
Actual:
  main:9:7: error: Value of type variable "T" of "A" cannot be "str"
  main:9:7: error: Argument types for type variable "T" are incompatible in call to "A" (diff)
  main:9:7: note: All arguments for type variable "T" must be of the same type (one of "int", "list") (diff)
  main:13: error: Value of type variable "T" of "A" cannot be "str" (diff)
  main:13: error: Value of type variable "S" of "A" cannot be "str" (diff)


Expected:
  main:6: error: Value of type variable "AnyStr" of "f" cannot be "object" (diff)
  main:9: error: Value of type variable "AnyStr" of "f" cannot be "object" (diff)
Actual:
  main:6: error: Argument types for type variable "AnyStr" are incompatible in call to "f" (diff)
  main:6: note: All arguments for type variable "AnyStr" must be of the same type (one of "bytes", "str") (diff)
  main:9: error: Argument types for type variable "AnyStr" are incompatible in call to "f" (diff)
  main:9: note: All arguments for type variable "AnyStr" must be of the same type (one of "bytes", "str") (diff)


Expected:
  ...
  main:15: error: Revealed type is 'builtins.int*'
  main:16: error: Argument 1 to "fun1" has incompatible type "int"; expected ...
  main:17: error: Cannot infer type argument 1 of "fun1"
  main:19: error: Revealed type is 'builtins.list[Tuple[builtins.int*, builti...
  main:20: error: Value of type variable "T" of "fun2" cannot be "str" (diff)
Actual:
  ...
  main:15: error: Revealed type is 'builtins.int*'
  main:16: error: Argument 1 to "fun1" has incompatible type "int"; expected ...
  main:17: error: Cannot infer type argument 1 of "fun1"
  main:19: error: Revealed type is 'builtins.list[Tuple[builtins.int*, builti...
  main:20: error: Argument types for type variable "T" are incompatible in call to "fun2" (diff)
  main:20: note: All arguments for type variable "T" must be of the same type (one of "int", "bool") (diff)


Expected:
  tmp/foo.pyi:9: error: "int" not callable
  tmp/foo.pyi:10: error: "str" not callable
  tmp/foo.pyi:11: error: "str" not callable
  tmp/foo.pyi:12: error: No overload variant of "f" matches argument types [b...
  tmp/foo.pyi:21: error: Value of type variable "AnyStr" of "g" cannot be "object" (diff)
  tmp/foo.pyi:24: error: Value of type variable "AnyStr" of "g" cannot be "object" (diff)
Actual:
  tmp/foo.pyi:9: error: "int" not callable
  tmp/foo.pyi:10: error: "str" not callable
  tmp/foo.pyi:11: error: "str" not callable
  tmp/foo.pyi:12: error: No overload variant of "f" matches argument types [b...
  tmp/foo.pyi:21: error: Argument types for type variable "AnyStr" are incompatible in call to "g" (diff)
  tmp/foo.pyi:21: note: All arguments for type variable "AnyStr" must be of the same type (one of "bytes", "str") (diff)
  tmp/foo.pyi:24: error: Argument types for type variable "AnyStr" are incompatible in call to "g" (diff)
  tmp/foo.pyi:24: note: All arguments for type variable "AnyStr" must be of the same type (one of "bytes", "str") (diff)


Expected:
  main:8: error: Value of type variable "Y" of "C" cannot be "X" (diff)
  main:9: error: Incompatible types in assignment (expression has type "X", variable has type "int") (diff)
  main:10: error: Incompatible types in assignment (expression has type "str", variable has type "int") (diff)
  main:11: error: "int" has no attribute "foo"  (diff)
  main:11: error: "str" has no attribute "foo"  (diff)
Actual:
  main:8: error: Argument types for type variable "Y" are incompatible in call to "C" (diff)
  main:8: note: All arguments for type variable "Y" must be of the same type (one of "int", "str") (diff)
  main:9: error: Incompatible types in assignment (expression has type "X", variable has type "int") (diff)
  main:10: error: Incompatible types in assignment (expression has type "str", variable has type "int") (diff)
  main:11: error: "int" has no attribute "foo"  (diff)
  main:11: error: "str" has no attribute "foo"  (diff)


Expected:
  _testReModuleBytes.py:7: error: Value of type variable "AnyStr" of "search" cannot be "object" (diff)
  _testReModuleBytes.py:9: error: Cannot infer type argument 1 of "search" (diff)
Actual:
  _testReModuleBytes.py:7: error: Argument types for type variable "AnyStr" are incompatible in call to "search" (diff)
  _testReModuleBytes.py:7: note: All arguments for type variable "AnyStr" must be of the same type (one of "str", "bytes") (diff)
  _testReModuleBytes.py:9: error: Cannot infer type argument 1 of "search" (diff)


Expected:
  _testReModuleString.py:7: error: Value of type variable "AnyStr" of "search" cannot be "object" (diff)
  _testReModuleString.py:9: error: Cannot infer type argument 1 of "search" (diff)
Actual:
  _testReModuleString.py:7: error: Argument types for type variable "AnyStr" are incompatible in call to "search" (diff)
  _testReModuleString.py:7: note: All arguments for type variable "AnyStr" must be of the same type (one of "str", "bytes") (diff)
  _testReModuleString.py:9: error: Cannot infer type argument 1 of "search" (diff)

are all the actual/expected parts from tests that now fail.

@OddBloke
Copy link
Contributor Author

OddBloke commented Sep 2, 2017

@ilevkivskyi I have to run to catch a train, but does this look along the right lines?

I'd like to include more type information about the call (i.e. what the problematic types were), but I can't work out a good way to get access to that info from where this error message is emitted.

@ilevkivskyi
Copy link
Member

Ideally, the new error message should look like this:

def func(num: int, a: AnyStr, b: AnyStr) -> AnyStr:
    ...
fun(1, 'a', b'b')
error: Argument types for type variable "AnyStr" are incompatible in call to "func"
note: Arguments 2 and 3 for "func" must be all of the same type: (one of "str", "bytes")
note: Got:
note:     type of argument 2: "str"
note:     type of argument 3: "bytes"

You could try to check up the call stack and maybe pass the original argument types. If this is too hard, then at least show the numbers of the arguments involved.

@OddBloke
Copy link
Contributor Author

OddBloke commented Sep 2, 2017 via email

Daniel Watkins added 10 commits September 3, 2017 15:59
Previously, we weren't listing arguments which had their typevar nested
(e.g. List[Tuple[T, T]]).
This is the case where someone has simply passed the wrong type in for a
single type variable argument.
The code path will sometimes be exercised for generic type application
(and there may be other times it will be exercised that the tests don't
currently cover).  As the new error message only makes sense in the
context of a call, only use it in that case.
@@ -852,7 +852,8 @@ fun1(1) # E: Argument 1 to "fun1" has incompatible type "int"; expected "List[Tu
fun1([(1, 'x')]) # E: Cannot infer type argument 1 of "fun1"

reveal_type(fun2([(1, 1)], 1)) # E: Revealed type is 'builtins.list[Tuple[builtins.int*, builtins.int*]]'
fun2([('x', 'x')], 'x') # E: Value of type variable "T" of "fun2" cannot be "str"
fun2([('x', 'x')], 'x') # E: Argument types for type variable "T" are incompatible in call to "fun2" \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Taking into account that positional arguments are more often used than keyword arguments, it is much more convenient to see the position of the argument, not its name at call site.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Understood; I'll look at making this switch as when I start passing the arguments through the call stack.

@@ -852,7 +852,8 @@ fun1(1) # E: Argument 1 to "fun1" has incompatible type "int"; expected "List[Tu
fun1([(1, 'x')]) # E: Cannot infer type argument 1 of "fun1"

reveal_type(fun2([(1, 1)], 1)) # E: Revealed type is 'builtins.list[Tuple[builtins.int*, builtins.int*]]'
fun2([('x', 'x')], 'x') # E: Value of type variable "T" of "fun2" cannot be "str"
fun2([('x', 'x')], 'x') # E: Argument types for type variable "T" are incompatible in call to "fun2" \
# N: Arguments "v" and "scale" in call to "fun2" must all have the same type for "T" (one of "int", "bool")
Copy link
Member

@ilevkivskyi ilevkivskyi Sep 3, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In understand why you formulate the note this way (because of, e.g., T and List[T] argument types). But maybe you can show the note only if there are three or less constraints so that in this case you could propose valid variants, like:

note: Acceptable combinations of types for arguments 1 and 2 of "fun":
note:    "str" and "List[str]"
note:    "bytes" and "List[bytes]"
note: Got: "bytes" and "List[str]"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels like it might be an enhancement on top of this change (which should end up displaying what we expected to see, and what was actually passed in).

@ilevkivskyi ilevkivskyi self-assigned this Sep 17, 2017
@ilevkivskyi
Copy link
Member

@OddBloke Are you still working on this? It is an important issue.

@OddBloke
Copy link
Contributor Author

OddBloke commented Nov 8, 2017 via email

@emmatyping emmatyping closed this Nov 14, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants