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

Internal Error with forward references #3881

Closed
garrettheel opened this issue Aug 26, 2017 · 5 comments · Fixed by #3952
Closed

Internal Error with forward references #3881

garrettheel opened this issue Aug 26, 2017 · 5 comments · Fixed by #3952

Comments

@garrettheel
Copy link
Contributor

Reporting a bug I found.

$ mypy mypy_bug.py --show-traceback
mypy_bug.py:15: error: INTERNAL ERROR -- please report a bug at https://github.com/python/mypy/issues version: 0.521
Traceback (most recent call last):
  File "/Users/gheel/.virtualenvs/mypy/bin/mypy", line 11, in <module>
    sys.exit(console_entry())
  File "/Users/gheel/.virtualenvs/mypy/lib/python3.6/site-packages/mypy/__main__.py", line 7, in console_entry
    main(None)
  File "/Users/gheel/.virtualenvs/mypy/lib/python3.6/site-packages/mypy/main.py", line 50, in main
    res = type_check_only(sources, bin_dir, options)
  File "/Users/gheel/.virtualenvs/mypy/lib/python3.6/site-packages/mypy/main.py", line 97, in type_check_only
    options=options)
  File "/Users/gheel/.virtualenvs/mypy/lib/python3.6/site-packages/mypy/build.py", line 196, in build
    graph = dispatch(sources, manager)
  File "/Users/gheel/.virtualenvs/mypy/lib/python3.6/site-packages/mypy/build.py", line 1801, in dispatch
    process_graph(graph, manager)
  File "/Users/gheel/.virtualenvs/mypy/lib/python3.6/site-packages/mypy/build.py", line 2044, in process_graph
    process_stale_scc(graph, scc, manager)
  File "/Users/gheel/.virtualenvs/mypy/lib/python3.6/site-packages/mypy/build.py", line 2147, in process_stale_scc
    graph[id].type_check_first_pass()
  File "/Users/gheel/.virtualenvs/mypy/lib/python3.6/site-packages/mypy/build.py", line 1716, in type_check_first_pass
    self.type_checker.check_first_pass()
  File "/Users/gheel/.virtualenvs/mypy/lib/python3.6/site-packages/mypy/checker.py", line 185, in check_first_pass
    self.accept(d)
  File "/Users/gheel/.virtualenvs/mypy/lib/python3.6/site-packages/mypy/checker.py", line 273, in accept
    stmt.accept(self)
  File "/Users/gheel/.virtualenvs/mypy/lib/python3.6/site-packages/mypy/nodes.py", line 754, in accept
    return visitor.visit_class_def(self)
  File "/Users/gheel/.virtualenvs/mypy/lib/python3.6/site-packages/mypy/checker.py", line 1109, in visit_class_def
    self.accept(defn.defs)
  File "/Users/gheel/.virtualenvs/mypy/lib/python3.6/site-packages/mypy/checker.py", line 273, in accept
    stmt.accept(self)
  File "/Users/gheel/.virtualenvs/mypy/lib/python3.6/site-packages/mypy/nodes.py", line 815, in accept
    return visitor.visit_block(self)
  File "/Users/gheel/.virtualenvs/mypy/lib/python3.6/site-packages/mypy/checker.py", line 1202, in visit_block
    self.accept(s)
  File "/Users/gheel/.virtualenvs/mypy/lib/python3.6/site-packages/mypy/checker.py", line 273, in accept
    stmt.accept(self)
  File "/Users/gheel/.virtualenvs/mypy/lib/python3.6/site-packages/mypy/nodes.py", line 565, in accept
    return visitor.visit_func_def(self)
  File "/Users/gheel/.virtualenvs/mypy/lib/python3.6/site-packages/mypy/checker.py", line 519, in visit_func_def
    self.check_func_item(defn, name=defn.name())
  File "/Users/gheel/.virtualenvs/mypy/lib/python3.6/site-packages/mypy/checker.py", line 578, in check_func_item
    self.check_func_def(defn, typ, name)
  File "/Users/gheel/.virtualenvs/mypy/lib/python3.6/site-packages/mypy/checker.py", line 738, in check_func_def
    self.accept(item.body)
  File "/Users/gheel/.virtualenvs/mypy/lib/python3.6/site-packages/mypy/checker.py", line 273, in accept
    stmt.accept(self)
  File "/Users/gheel/.virtualenvs/mypy/lib/python3.6/site-packages/mypy/nodes.py", line 815, in accept
    return visitor.visit_block(self)
  File "/Users/gheel/.virtualenvs/mypy/lib/python3.6/site-packages/mypy/checker.py", line 1202, in visit_block
    self.accept(s)
  File "/Users/gheel/.virtualenvs/mypy/lib/python3.6/site-packages/mypy/checker.py", line 273, in accept
    stmt.accept(self)
  File "/Users/gheel/.virtualenvs/mypy/lib/python3.6/site-packages/mypy/nodes.py", line 859, in accept
    return visitor.visit_assignment_stmt(self)
  File "/Users/gheel/.virtualenvs/mypy/lib/python3.6/site-packages/mypy/checker.py", line 1209, in visit_assignment_stmt
    self.check_assignment(s.lvalues[-1], s.rvalue, s.type is None, s.new_syntax)
  File "/Users/gheel/.virtualenvs/mypy/lib/python3.6/site-packages/mypy/checker.py", line 1301, in check_assignment
    rvalue)
  File "/Users/gheel/.virtualenvs/mypy/lib/python3.6/site-packages/mypy/checker.py", line 1692, in infer_variable_type
    elif not is_valid_inferred_type(init_type):
  File "/Users/gheel/.virtualenvs/mypy/lib/python3.6/site-packages/mypy/checker.py", line 3113, in is_valid_inferred_type
    if is_same_type(typ, NoneTyp()):
  File "/Users/gheel/.virtualenvs/mypy/lib/python3.6/site-packages/mypy/sametypes.py", line 25, in is_same_type
    left = simplify_union(left)
  File "/Users/gheel/.virtualenvs/mypy/lib/python3.6/site-packages/mypy/sametypes.py", line 33, in simplify_union
    return UnionType.make_simplified_union(t.items)
  File "/Users/gheel/.virtualenvs/mypy/lib/python3.6/site-packages/mypy/types.py", line 1096, in make_simplified_union
    if (i != j and is_proper_subtype(tj, ti)):
  File "/Users/gheel/.virtualenvs/mypy/lib/python3.6/site-packages/mypy/subtypes.py", line 569, in is_proper_subtype
    return left.accept(ProperSubtypeVisitor(right))
  File "/Users/gheel/.virtualenvs/mypy/lib/python3.6/site-packages/mypy/types.py", line 435, in accept
    return visitor.visit_instance(self)
  File "/Users/gheel/.virtualenvs/mypy/lib/python3.6/site-packages/mypy/subtypes.py", line 605, in visit_instance
    for base in left.type.mro:
TypeError: 'NoneType' object is not iterable
mypy_bug.py:15: note: use --pdb to drop into pdb

Reproducible case:

from typing import NamedTuple, Union

AOrB = Union['A', 'B']

class A(NamedTuple):
    lat: float
    lng: float

class B(object):

    def __init__(self, a: AOrB) -> None:
        self.a = a

    @property
    def lat(self) -> float:
        return self.a.lat

    @property
    def lng(self) -> float:
        return self.a.lng

Note that moving the definition of AOrB after the definition of A works fine. This seems only to happen when all of the types are forward references. Making the constructor of B use a forward reference to AOrB does not fix the issue either.

@gvanrossum
Copy link
Member

Confirmed. But could be a duplicate of #3836.

@ilevkivskyi
Copy link
Member

Yes, this is very similar to #3836, but 100% identical. We currently have half a dozen of crashes with the same root cause: forward references to "synthetic" types are not processed correctly during semantic analysis.

@JukkaL are you working on this? If not, then I could take care of this. I think we can fix all these crashes and other issues simply by adding few callbacks after semantic passes, as we discussed some time ago.

@gvanrossum
Copy link
Member

Yes, this is very similar to #3836, but 100% identical.

Did you mean "but not 100% identical?

I just heard from @JukkaL, he's not working on this, it's not trivial, we'd love it if you could take care of it.

@ilevkivskyi
Copy link
Member

@gvanrossum Yes, sorry, I meant not 100% identical. OK, I will give it a try, this is not a very small task, but since I was thinking about it for some time already I think there is a good chance it will be straightforward to solve.

@ilevkivskyi ilevkivskyi self-assigned this Aug 29, 2017
@JukkaL
Copy link
Collaborator

JukkaL commented Aug 30, 2017

@ilevkivskyi Thanks! As a first step it's fine to focus on fixing the crashes. Mypy would still generate an error when trying to use a forward reference. This should be easier than making the forward references work correctly. Our current plan is to get at least the crashes fixed by around mid September, before the next mypy release.

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
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants