Skip to content

Conversation

@elazarg
Copy link
Contributor

@elazarg elazarg commented Oct 18, 2016

Remove a cast to Any and some others, and assert-guard many casts.

The patch for each file is independent of the others. I think the only non-immediate change is in semanal.py.

Copy link
Collaborator

@ddfisher ddfisher left a comment

Choose a reason for hiding this comment

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

Thanks for these changes! They look largely good. There's an additional fixup to be made here, though: mypy understands assert isinstance(...), so basically all the casts made after the assert guards you added can be removed. Could you make that change?

# A property cannot have an overloaded type => the cast
# is fine.
assert isinstance(signature, CallableType)
return cast(CallableType, signature).ret_type
Copy link
Collaborator

Choose a reason for hiding this comment

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

I checked this cast -- we can remove it.

mypy/semanal.py Outdated
if defn.type:
functype = cast(CallableType, defn.type)
typevars = self.infer_type_variables(functype)
if isinstance(defn.type, CallableType):
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think this might be cleaner with an assert instead. This changes the meaning a bit.

mypy/semanal.py Outdated
node = self.lookup_qualified(name, type)
if node and node.kind == UNBOUND_TVAR:
assert isinstance(node.node, TypeVarExpr)
result.append((name, cast(TypeVarExpr, node.node)))
Copy link
Collaborator

Choose a reason for hiding this comment

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

This cast can be removed.

mypy/semanal.py Outdated
b = self.globals.get('__builtins__', None)
if b:
assert isinstance(b.node, MypyFile)
table = cast(MypyFile, b.node).names
Copy link
Collaborator

Choose a reason for hiding this comment

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

This cast can likely be removed.

@elazarg
Copy link
Contributor Author

elazarg commented Oct 18, 2016

Thanks for the review. I left some casts thinking they may serve as a warning sign to the reader, but of course asserts can also be grepped.

assert isinstance(node.node, TypeInfo)
return Instance(node.node, [])

def lookup_fully_qualified(self, name: str) -> SymbolTableNode:
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 refactoring is not really related to the casts, but why not?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Actually, this PR is pretty big already (and is not without risk of breakage -- changing casts to asserts potentially changes runtime behavior), so I'd prefer to keep it as focused as possible. If you'd like to make this refactor, could you submit it as a separate small PR?

@elazarg
Copy link
Contributor Author

elazarg commented Oct 18, 2016

@ddfisher I think it's done. Please notice the change in how errors are reported in apply_generic_arguments, the removal of apply_generic_arguments2, and the refactoring of lookup_fully_qualified.

Copy link
Collaborator

@ddfisher ddfisher left a comment

Choose a reason for hiding this comment

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

Thanks for fixing that up. The refactor of apply_generic_arguments doesn't look correct to me -- it looks like mypy actually depends on that cast for some error conditions. For that reason, the casts involving that call should not have asserts. The behavior is hacky, but is a larger project to clean up, which should not be part of this PR.

In general, it's a lot easier to review PRs if they stay focused, even though it's tempting to fix other problems discovered while writing the PR. It's better to put those in a separate follow-up PR instead. Thanks!

assert isinstance(node.node, TypeInfo)
return Instance(node.node, [])

def lookup_fully_qualified(self, name: str) -> SymbolTableNode:
Copy link
Collaborator

Choose a reason for hiding this comment

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

Actually, this PR is pretty big already (and is not without risk of breakage -- changing casts to asserts potentially changes runtime behavior), so I'd prefer to keep it as focused as possible. If you'd like to make this refactor, could you submit it as a separate small PR?

@elazarg
Copy link
Contributor Author

elazarg commented Oct 20, 2016

@ddfisher I don't understand your comment about apply_generic_arguments. Sorry. Can you elaborate?

mypy/subtypes.py Outdated
msg = messages.temp_message_builder()
applied = mypy.applytype.apply_generic_arguments(type, inferred_vars, msg, context=target)
if msg.is_errors() or not isinstance(applied, CallableType):
if applied is None or msg.is_errors():
Copy link
Contributor Author

Choose a reason for hiding this comment

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

not isinstance(applied, CallableType) before if and only if applied is None now.
not msg.iserrors() also implies not isinstance(applied, AnyType) and therefore isinstance(applied, CallableType).
Am I wrong?

@gvanrossum
Copy link
Member

Could you split this up in smaller portions, e.g. one PR per file?

@elazarg
Copy link
Contributor Author

elazarg commented Oct 27, 2016

Working on it

@elazarg
Copy link
Contributor Author

elazarg commented Oct 27, 2016

Changes to 9 files remain in this PR, but each file has 1-2 uncomplicated changes.

@gvanrossum
Copy link
Member

Waiting for @ddfisher to finish the review.

mypy/checker.py Outdated
assert isinstance(inferred, Var)
else:
m = cast(MemberExpr, lvalue)
assert isinstance(m, MemberExpr)
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't these lines be reversed to get rid of a cast?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes. I missed these.

mypy/typeanal.py Outdated
def builtin_type(self, fully_qualified_name: str, args: List[Type] = None) -> Instance:
node = self.lookup_fqn_func(fully_qualified_name)
assert isinstance(node.node, TypeInfo)
info = cast(TypeInfo, node.node)
Copy link
Contributor

Choose a reason for hiding this comment

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

You should be able to get rid of this cast (and could get rid of info entirely).

gvanrossum pushed a commit that referenced this pull request Oct 27, 2016
Part of #2272.

The only place where the number of type arguments in type application might not match is when the user does that; this is explicitly checked in visit_type_application. Other places involve type inference, which must be correct "by construction" and if it isn't, that's a bug we want to catch, instead of returning AnyType.

It also allows us to remove casts.
@ddfisher
Copy link
Collaborator

This looks good now, thanks! It looks like there's a small merge conflict to fix, though.

@elazarg
Copy link
Contributor Author

elazarg commented Oct 27, 2016

Fixed. Thanks.

@gvanrossum gvanrossum merged commit 66c7148 into python:master Oct 28, 2016
@gvanrossum
Copy link
Member

Thanks! I liked all of these improvements. Death to casts!

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.

4 participants