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

Forward reference to a type alias results in an "Invalid type ..." error #2241

Closed
jstasiak opened this issue Oct 11, 2016 · 9 comments · Fixed by #3952
Closed

Forward reference to a type alias results in an "Invalid type ..." error #2241

jstasiak opened this issue Oct 11, 2016 · 9 comments · Fixed by #3952
Labels
bug mypy got something wrong priority-1-normal

Comments

@jstasiak
Copy link
Contributor

mypy 0.4.5 and 0.4.4, CPython 3.5.1 and 3.5.2.

Code:

# code.py
def f(p: 'Alias') -> None:
    print(p)

Alias = int

Expected result:

% mypy code.py
%

Actual result:

% mypy code.py
code.py: note: In function "f":
code.py:1: error: Invalid type "code.Alias"
%
@gvanrossum
Copy link
Member

gvanrossum commented Oct 11, 2016 via email

@JukkaL
Copy link
Collaborator

JukkaL commented Oct 11, 2016

I think that type aliases also don't work reliably across different modules in import cycles.

@gvanrossum gvanrossum added the bug mypy got something wrong label Oct 13, 2016
@gvanrossum gvanrossum added this to the 0.5 milestone Oct 13, 2016
@TRManderson
Copy link
Contributor

TRManderson commented Dec 1, 2016

As far as I can tell, it is currently not possible to represent the output of json.load/s with types due to this.

JSON = Union[None, str, int, float, bool, List['JSON'], Dict[str, 'JSON']]

Adding newtypes in various bits didn't help the situation, I'm still getting 'Invalid type'

@JelleZijlstra
Copy link
Member

Here's another example I ran into:

from typing import List

class A(object):
    b: 'B'  # E: Invalid type "recurse.B"

B = List[A]

@linclelinkpart5
Copy link

I'm also seeing this occur with new Python 3.6-style NamedTuple type hint declarations.

import typing as typ

class EdgeDef(typ.NamedTuple):
    id: int
    stack_cmd: 'StackCommand' # ERROR: Invalid type "test.StackCommand"

# Other defs that depend on `EdgeDef`

StackCommand = typ.Tuple[bool, int]

@gvanrossum
Copy link
Member

I think we have enough examples at this point. :-)

@refi64
Copy link
Contributor

refi64 commented May 31, 2017

@ThatsGobbles Is that the same issue though? This issue is with recursive type aliases, but your example doesn't actually have any recursion, just and out-of-order alias.

@ilevkivskyi
Copy link
Member

@kirbyfan64

This issue is with recursive type aliases

The original example does not have any recursion. Moreover, I am quite sure that there is no big difference between recursive and non-recursive situations with classes. The problem is very simple: type aliases are not analysed during first pass, but solution is not easy and requires refactoring semantic analyser (see roadmap).

@refi64
Copy link
Contributor

refi64 commented May 31, 2017

cough I...uhh... totally knew that... cough

JukkaL pushed a commit that referenced this issue Sep 27, 2017
Forward references didn't work with anything apart from classes, for example 
this didn't work:

```
x: A
A = NamedTuple('A', [('x', int)])
```

The same situation was with `TypedDict`, `NewType`, and type aliases. The 
root problem is that these synthetic types are neither detected in first pass, 
nor fixed in third pass. In certain cases this can lead to crashes (first six issues 
below are various crash scenarios). This fixes these crashes by applying some 
additional patches after third pass.

Here is the summary of the PR:

* New simple wrapper type `ForwardRef` with only one field `link` is introduced 
  (with updates to type visitors)
* When an unknown type is found in second pass, the corresponding 
  `UnboundType` is wrapped in `ForwardRef`, it is given a "second chance" in 
  third pass.
* After third pass I record the "suspicious" nodes, where forward references and 
  synthetic types have been encountered and append patches (callbacks) to fix 
  them after third pass. Patches use the new visitor `TypeReplacer` (which is the 
  core of this PR).

Fixes #3340
Fixes #3419
Fixes #3674
Fixes #3685
Fixes #3799
Fixes #3836
Fixes #3881
Fixes #867
Fixes #2241
Fixes #2399
Fixes #1701
Fixes #3016
Fixes #3054
Fixes #2762
Fixes #3575
Fixes #3990
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong priority-1-normal
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants