diff --git a/mypy/messages.py b/mypy/messages.py index 70d79384c1a9d..f82625530fae6 100644 --- a/mypy/messages.py +++ b/mypy/messages.py @@ -1975,10 +1975,12 @@ def [T <: int] f(self, x: int, y: T) -> None s += ' = ...' # If we got a "special arg" (i.e: self, cls, etc...), prepend it to the arg list - if isinstance(tp.definition, FuncDef) and tp.definition.name is not None: + if isinstance(tp.definition, FuncDef) and \ + tp.definition.name is not None and \ + tp.definition.arguments: definition_args = [arg.variable.name for arg in tp.definition.arguments] if definition_args and tp.arg_names != definition_args \ - and len(definition_args) > 0 and definition_args[0]: + and len(definition_args) > 0 and definition_args[0]: if s: s = ', ' + s s = definition_args[0] + s diff --git a/mypy/nodes.py b/mypy/nodes.py index d510cbeeec620..6a29eb0c813b1 100644 --- a/mypy/nodes.py +++ b/mypy/nodes.py @@ -649,7 +649,7 @@ def set_line(self, class FuncItem(FuncBase): """Base class for nodes usable as overloaded function items.""" - __slots__ = ('arguments', # Note that can be None if deserialized (type is a lie!) + __slots__ = ('arguments', # Note that can be empty if deserialized 'arg_names', # Names of arguments 'arg_kinds', # Kinds of arguments 'min_args', # Minimum number of arguments @@ -665,7 +665,7 @@ class FuncItem(FuncBase): 'expanded', # Variants of function with type variables with values expanded ) - __deletable__ = ('arguments', 'max_pos', 'min_args') + __deletable__ = ('max_pos', 'min_args') def __init__(self, arguments: Optional[List[Argument]] = None, @@ -780,7 +780,6 @@ def deserialize(cls, data: JsonDict) -> 'FuncDef': ret.arg_names = data['arg_names'] ret.arg_kinds = [ArgKind(x) for x in data['arg_kinds']] # Leave these uninitialized so that future uses will trigger an error - del ret.arguments del ret.max_pos del ret.min_args return ret diff --git a/mypy/suggestions.py b/mypy/suggestions.py index d311d0edde638..8b7c0987a04b8 100644 --- a/mypy/suggestions.py +++ b/mypy/suggestions.py @@ -345,6 +345,7 @@ def get_args(self, is_method: bool, return types def get_default_arg_types(self, fdef: FuncDef) -> List[Optional[Type]]: + assert fdef.arguments is not None return [ self.manager.all_types[arg.initializer] if arg.initializer else None for arg in fdef.arguments diff --git a/mypy/types.py b/mypy/types.py index f0f7add2d92fb..dc78fdbdd9317 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -1524,16 +1524,13 @@ def __init__(self, # after serialization, but it is useful in error messages. # TODO: decide how to add more info here (file, line, column) # without changing interface hash. - self.def_extras = { - 'first_arg': ( - definition.arguments[0].variable.name - if (getattr(definition, 'arguments', None) - and definition.arg_names - and definition.info - and not definition.is_static) - else None - ), - } + first_arg: Optional[str] = None + if definition.info and not definition.is_static: + if definition.arguments: + first_arg = definition.arguments[0].variable.name + elif definition.arg_names: + first_arg = definition.arg_names[0] + self.def_extras = {'first_arg': first_arg} else: self.def_extras = {} self.type_guard = type_guard diff --git a/mypyc/irbuild/mapper.py b/mypyc/irbuild/mapper.py index 576eacc141df1..181479066b7ba 100644 --- a/mypyc/irbuild/mapper.py +++ b/mypyc/irbuild/mapper.py @@ -145,7 +145,7 @@ def fdef_to_sig(self, fdef: FuncDef) -> FuncSignature: # deserialized FuncDef that lacks arguments. We won't ever # need to use those inside of a FuncIR, so we just make up # some crap. - if hasattr(fdef, 'arguments'): + if fdef.arguments: arg_names = [arg.variable.name for arg in fdef.arguments] else: arg_names = [name or '' for name in fdef.arg_names]