Pylance-release: Variable explicit type being ignored

Created on 26 Feb 2021  路  9Comments  路  Source: microsoft/pylance-release

Environment data

  • Pylance Type Checking Mode: basic
  • Language Server version: 2021.3.600354918-dev
  • OS and version: Windows 10 Pro Insider Preview Build 21313
  • Python version (& distribution if applicable, e.g. Anaconda): 3.8.7 64-bit

Expected behavior

As it was briefly discussed at https://github.com/microsoft/vscode-python/issues/15487, even though I have explicitly set guild: Optional[Guild] it is still interpreted as Any.

Actual behavior

Variable is being interpreted as Any. The same happens if I use guild: 'Guild | None'.

guild: Optional[Guild] = ctx.bot.get_guild(529775376721903617)
if guild is not None:
    guild # type is Any

Additional information

get_guild() is indeed untyped and returns Any | None, but I expected the interpreter to prioratize my explicitly set Guild type over Any.

issue

bug fixed in next version

Most helpful comment

My statement above ("An Any on the RHS causes the type of the assignment target to be narrowed to Any") was incorrect. I was confusing it with the case where the LHS contained an Any.

I found the cause of the inconsistency. It is triggered only in the case where the declared type of the assignment LHS is a union and the type of the expression on the assignment RHS is also a union that contains an Any 鈥斅爌recisely the situation in your example.

This will be fixed in the next release.

All 9 comments

FWIW I thought #822 meant that we'd be taking the left hand side as truth, but that doesn't appear to be what's happening.

Types are narrowed upon assignment. An Any on the RHS causes the type of the assignment target to be narrowed to Any.

If you want to explicitly cast an expression's type to a specified type, you need to use the typing.cast call.

But is it wrong to have it the other way? I only see it as an improvement. Using typing.cast means an additional import statement and less readable code.

Upon further investigation, we appear to be inconsistent here.

from typing import Any, List, Optional

def func1(a: Any, b: Optional[Any]):
    x: int = a
    reveal_type(x)  # int

    y: Optional[int] = b
    reveal_type(y)  # Optional[Any]

    z: List[int] = [a]
    reveal_type(z)  # List[int]

I'll investigate further.

My statement above ("An Any on the RHS causes the type of the assignment target to be narrowed to Any") was incorrect. I was confusing it with the case where the LHS contained an Any.

I found the cause of the inconsistency. It is triggered only in the case where the declared type of the assignment LHS is a union and the type of the expression on the assignment RHS is also a union that contains an Any 鈥斅爌recisely the situation in your example.

This will be fixed in the next release.

Hey, do you mind me asking when can I expect to see this fix in the Insider build?

We release new versions of Pylance once a week, typically on Wednesday. This fix will be enabled in the public version of the next release.

This issue has been fixed in version 2021.3.0, which we've just released. You can find the changelog here: https://github.com/microsoft/pylance-release/blob/main/CHANGELOG.md#202130-3-march-2021

SWEET, IT WORKS!

Was this page helpful?
0 / 5 - 0 ratings