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

assert_type() says an int is not an int #12923

Closed
jwodder opened this issue Jun 1, 2022 · 6 comments · Fixed by #15123
Closed

assert_type() says an int is not an int #12923

jwodder opened this issue Jun 1, 2022 · 6 comments · Fixed by #15123
Labels
assert-type assert_type() bug mypy got something wrong good-first-issue

Comments

@jwodder
Copy link

jwodder commented Jun 1, 2022

The following code:

from typing_extensions import assert_type

assert_type(42, int)

fails to typecheck with the following message:

assert-type01.py:3: error: Expression is of type "int", not "int"

Your Environment

  • Mypy version used: both 0.960 and commit 1636a05
  • Mypy command-line flags: none
  • Mypy configuration options from mypy.ini (and other config files): none
  • Python version used: 3.9.13
  • Operating system and version: macOS 11.6.6
@hauntsaninja
Copy link
Collaborator

Lol, it's probably Literal[42]. So bad error message, but there should probably still be an error? Jelle will confirm.

@hauntsaninja
Copy link
Collaborator

Yeah, pyright also gives an error error: "assert_type" mismatch: expected "int" but received "Literal[42]"

@AlexWaygood AlexWaygood added the assert-type assert_type() label Aug 5, 2022
@JukkaL
Copy link
Collaborator

JukkaL commented Apr 23, 2023

Implementation hints: 42 has type Instance with the last_known_value attribute set to the literal type. If the string representations of types in the assert_type error are the same, we can perhaps try again while using last_known_value if it exists.

@JelleZijlstra JelleZijlstra removed their assignment Apr 23, 2023
@JelleZijlstra
Copy link
Member

Looks like I self-assigned this but then forgot about it. I'm happy to leave this to a sprint contributor.

As the author of assert_type(), I think it's reasonable for a type checker to fail on assert_type(42, int) if it infers 42 to be of type Literal[42]. assert_type() is meant to check that the types are exactly the same.

mypy's current behavior is actually different from what this issue reports:

from typing_extensions import assert_type, Literal

assert_type(42, int)  # passes
assert_type(42, Literal[42]) # also passes

I think this behavior is wrong: exactly one of these two should succeed, but not both. Which of the two is up to the type checker to decide. For both pyanalyze and pyright, 42 is inferred as type Literal[42] and therefore the first assert_type fails. Mypy could choose to instead infer 42 as being of type int, which would make the second assert fail instead.

@CarlFK
Copy link
Contributor

CarlFK commented Apr 25, 2023

(venv) carl@x1:~/src/mypy$ python3 runtests.py self
run self: ['/home/carl/src/mypy/venv/bin/python3', '-m', 'mypy', '--config-file', 'mypy_self_check.ini', '-p', 'mypy']
mypy/checkexpr.py:3924: error: Never apply isinstance() to unexpanded types; use mypy.types.get_proper_type() first  [misc]
            if isinstance( source_type, mypy.types.Instance ) and not is_same_type(source_type.last_known_value, target_t...
               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mypy/checkexpr.py:3924: note: If you pass on the original type after the check, always use its unexpanded version
mypy/checkexpr.py:3924: error: Argument 1 to "is_same_type" has incompatible type "Optional[LiteralType]"; expected "Type" 
[arg-type]
            if isinstance( source_type, mypy.types.Instance ) and not is_same_type(source_type.last_known_value, target_t...
                                                                                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
mypy/checkexpr.py:3930: error: Argument 1 to "assert_type_fail" of "MessageBuilder" has incompatible type
"Optional[LiteralType]"; expected "Type"  [arg-type]
                self.msg.assert_type_fail(source_type.last_known_value, target_type, expr)
                                          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
Found 3 errors in 1 file (checked 170 source files)

working on it...

@CarlFK
Copy link
Contributor

CarlFK commented Apr 25, 2023

(venv) carl@x1:~/src/ck/mypy$ python3 runtests.py self 
run self: ['/home/carl/src/mypy/venv/bin/python3', '-m', 'mypy', '--config-file', 'mypy_self_check.ini', '-p', 'mypy']
mypy/checkexpr.py:3923: error: "Type" has no attribute "last_known_value"  [attr-defined]
                    and source_type.last_known_value is not None:
                        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~

+ and (hasattr(source_type, "last_known_value") and source_type.last_known_value is not None):

Success: no issues found in 170 source files

hauntsaninja added a commit that referenced this issue Apr 26, 2023
Fixes #12923

assert_type(42, int) ... had issues. #12923 was a bit of a mess as the
OP was or wasn't currently accurate.

Added two tests to repo the current problem, which now pass.

Co-authored-by: Shantanu <12621235+hauntsaninja@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
assert-type assert_type() bug mypy got something wrong good-first-issue
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants