Skip to content

Commit 1934703

Browse files
committed
Remove old way to warn on returned None's
1 parent ccc1ccf commit 1934703

9 files changed

+31
-98
lines changed

mypy/checker.py

Lines changed: 14 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,7 @@ def get_generator_receive_type(self, return_type: Type, is_coroutine: bool) -> T
409409
else:
410410
# `return_type` is a supertype of Generator, so callers won't be able to send it
411411
# values. IOW, tc is None.
412-
return NoneTyp(is_ret_type=True)
412+
return NoneTyp()
413413

414414
def get_generator_return_type(self, return_type: Type, is_coroutine: bool) -> Type:
415415
"""Given the declared return type of a generator (t), return the type it returns (tr)."""
@@ -1543,10 +1543,7 @@ def is_definition(self, s: Lvalue) -> bool:
15431543
def infer_variable_type(self, name: Var, lvalue: Lvalue,
15441544
init_type: Type, context: Context) -> None:
15451545
"""Infer the type of initialized variables from initializer type."""
1546-
if self.is_unusable_type(init_type):
1547-
self.check_usable_type(init_type, context)
1548-
self.set_inference_error_fallback_type(name, lvalue, init_type, context)
1549-
elif isinstance(init_type, DeletedType):
1546+
if isinstance(init_type, DeletedType):
15501547
self.msg.deleted_as_rvalue(init_type, context)
15511548
elif not is_valid_inferred_type(init_type):
15521549
# We cannot use the type of the initialization expression for full type
@@ -1815,7 +1812,6 @@ def visit_if_stmt(self, s: IfStmt) -> None:
18151812
with self.binder.frame_context(can_skip=False, fall_through=0):
18161813
for e, b in zip(s.expr, s.body):
18171814
t = self.expr_checker.accept(e)
1818-
self.check_usable_type(t, e)
18191815

18201816
if isinstance(t, DeletedType):
18211817
self.msg.deleted_as_rvalue(t, s)
@@ -2055,8 +2051,6 @@ def analyze_async_iterable_item_type(self, expr: Expression) -> Type:
20552051
echk = self.expr_checker
20562052
iterable = echk.accept(expr)
20572053

2058-
self.check_usable_type(iterable, expr)
2059-
20602054
self.check_subtype(iterable,
20612055
self.named_generic_type('typing.AsyncIterable',
20622056
[AnyType()]),
@@ -2074,7 +2068,6 @@ def analyze_iterable_item_type(self, expr: Expression) -> Type:
20742068
echk = self.expr_checker
20752069
iterable = echk.accept(expr)
20762070

2077-
self.check_usable_type(iterable, expr)
20782071
if isinstance(iterable, TupleType):
20792072
joined = UninhabitedType() # type: Type
20802073
for item in iterable.items:
@@ -2242,21 +2235,18 @@ def check_subtype(self, subtype: Type, supertype: Type, context: Context,
22422235
if is_subtype(subtype, supertype):
22432236
return True
22442237
else:
2245-
if self.is_unusable_type(subtype):
2246-
self.msg.does_not_return_value(subtype, context)
2247-
else:
2248-
if self.should_suppress_optional_error([subtype]):
2249-
return False
2250-
extra_info = [] # type: List[str]
2251-
if subtype_label is not None or supertype_label is not None:
2252-
subtype_str, supertype_str = self.msg.format_distinctly(subtype, supertype)
2253-
if subtype_label is not None:
2254-
extra_info.append(subtype_label + ' ' + subtype_str)
2255-
if supertype_label is not None:
2256-
extra_info.append(supertype_label + ' ' + supertype_str)
2257-
if extra_info:
2258-
msg += ' (' + ', '.join(extra_info) + ')'
2259-
self.fail(msg, context)
2238+
if self.should_suppress_optional_error([subtype]):
2239+
return False
2240+
extra_info = [] # type: List[str]
2241+
if subtype_label is not None or supertype_label is not None:
2242+
subtype_str, supertype_str = self.msg.format_distinctly(subtype, supertype)
2243+
if subtype_label is not None:
2244+
extra_info.append(subtype_label + ' ' + subtype_str)
2245+
if supertype_label is not None:
2246+
extra_info.append(supertype_label + ' ' + supertype_str)
2247+
if extra_info:
2248+
msg += ' (' + ', '.join(extra_info) + ')'
2249+
self.fail(msg, context)
22602250
return False
22612251

22622252
def contains_none(self, t: Type) -> bool:
@@ -2376,18 +2366,6 @@ def find_partial_types(self, var: Var) -> Optional[Dict[Var, Context]]:
23762366
return partial_types
23772367
return None
23782368

2379-
def is_unusable_type(self, typ: Type) -> bool:
2380-
"""Is this type an unusable type?
2381-
2382-
The unusable type is NoneTyp(is_ret_type=True).
2383-
"""
2384-
return isinstance(typ, NoneTyp) and typ.is_ret_type
2385-
2386-
def check_usable_type(self, typ: Type, context: Context) -> None:
2387-
"""Generate an error if the type is not a usable type."""
2388-
if self.is_unusable_type(typ):
2389-
self.msg.does_not_return_value(typ, context)
2390-
23912369
def temp_node(self, t: Type, context: Context = None) -> TempNode:
23922370
"""Create a temporary node with the given, fixed type."""
23932371
temp = TempNode(t)

mypy/checkexpr.py

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ def visit_call_expr(self, e: CallExpr, allow_none_return: bool = False) -> Type:
194194
self.chk.binder.unreachable()
195195
if not allow_none_return and isinstance(ret_type, NoneTyp):
196196
self.chk.msg.does_not_return_value(callee_type, e)
197+
return AnyType(implicit=True)
197198
return ret_type
198199

199200
def check_typeddict_call(self, callee: TypedDictType,
@@ -835,9 +836,7 @@ def check_arg(self, caller_type: Type, original_caller_type: Type,
835836
callee_type: Type, n: int, m: int, callee: CallableType,
836837
context: Context, messages: MessageBuilder) -> None:
837838
"""Check the type of a single argument in a call."""
838-
if self.chk.is_unusable_type(caller_type):
839-
messages.does_not_return_value(caller_type, context)
840-
elif isinstance(caller_type, DeletedType):
839+
if isinstance(caller_type, DeletedType):
841840
messages.deleted_as_rvalue(caller_type, context)
842841
elif not is_subtype(caller_type, callee_type):
843842
if self.chk.should_suppress_optional_error([caller_type, callee_type]):
@@ -1191,7 +1190,6 @@ def visit_comparison_expr(self, e: ComparisonExpr) -> Type:
11911190
if result is None:
11921191
result = sub_result
11931192
else:
1194-
self.check_usable_type(sub_result, e)
11951193
result = join.join_types(result, sub_result)
11961194

11971195
return result
@@ -1342,9 +1340,6 @@ def check_boolean_op(self, e: OpExpr, context: Context) -> Type:
13421340

13431341
right_type = self.analyze_cond_branch(right_map, e.right, left_type)
13441342

1345-
self.check_usable_type(left_type, context)
1346-
self.check_usable_type(right_type, context)
1347-
13481343
if right_map is None:
13491344
# The boolean expression is statically known to be the left value
13501345
assert left_map is not None # find_isinstance_check guarantees this
@@ -1384,7 +1379,6 @@ def visit_unary_expr(self, e: UnaryExpr) -> Type:
13841379
operand_type = self.accept(e.expr)
13851380
op = e.op
13861381
if op == 'not':
1387-
self.check_usable_type(operand_type, e)
13881382
result = self.bool_type() # type: Type
13891383
elif op == '-':
13901384
method_type = self.analyze_external_member_access('__neg__',
@@ -1678,7 +1672,6 @@ def visit_tuple_expr(self, e: TupleExpr) -> Type:
16781672
# context? Counterargument: Why would anyone write
16791673
# (1, *(2, 3)) instead of (1, 2, 3) except in a test?
16801674
tt = self.accept(item.expr)
1681-
self.check_usable_type(tt, e)
16821675
if isinstance(tt, TupleType):
16831676
items.extend(tt.items)
16841677
j += len(tt.items)
@@ -1692,7 +1685,6 @@ def visit_tuple_expr(self, e: TupleExpr) -> Type:
16921685
else:
16931686
tt = self.accept(item, type_context_items[j])
16941687
j += 1
1695-
self.check_usable_type(tt, e)
16961688
items.append(tt)
16971689
fallback_item = join.join_type_list(items)
16981690
return TupleType(items, self.chk.named_generic_type('builtins.tuple', [fallback_item]))
@@ -1953,7 +1945,6 @@ def check_for_comp(self, e: Union[GeneratorExpr, DictionaryComprehension]) -> No
19531945

19541946
def visit_conditional_expr(self, e: ConditionalExpr) -> Type:
19551947
cond_type = self.accept(e.cond)
1956-
self.check_usable_type(cond_type, e)
19571948
if self.chk.options.strict_boolean:
19581949
is_bool = (isinstance(cond_type, Instance)
19591950
and cond_type.type.fullname() == 'builtins.bool')
@@ -2033,10 +2024,6 @@ def accept(self,
20332024
else:
20342025
return typ
20352026

2036-
def check_usable_type(self, typ: Type, context: Context) -> None:
2037-
"""Generate an error if type is not a usable type."""
2038-
self.chk.check_usable_type(typ, context)
2039-
20402027
def named_type(self, name: str) -> Instance:
20412028
"""Return an instance type with type given by the name and no type
20422029
arguments. Alias for TypeChecker.named_type.
@@ -2182,7 +2169,7 @@ def visit_yield_from_expr(self, e: YieldFromExpr) -> Type:
21822169
if isinstance(actual_item_type, AnyType):
21832170
return AnyType()
21842171
else:
2185-
return NoneTyp(is_ret_type=True)
2172+
return NoneTyp()
21862173

21872174
def visit_temp_node(self, e: TempNode) -> Type:
21882175
return e.type

mypy/erasetype.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ def visit_type_var(self, t: TypeVarType) -> Type:
6363

6464
def visit_callable_type(self, t: CallableType) -> Type:
6565
# We must preserve the fallback type for overload resolution to work.
66-
ret_type = NoneTyp(is_ret_type=True) # type: Type
66+
ret_type = NoneTyp() # type: Type
6767
return CallableType([], [], [], ret_type, t.fallback)
6868

6969
def visit_overloaded(self, t: Overloaded) -> Type:

mypy/fastparse.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -342,9 +342,6 @@ def do_func_def(self, n: Union[ast3.FunctionDef, ast3.AsyncFunctionDef],
342342
for arg, arg_type in zip(args, arg_types):
343343
self.set_type_optional(arg_type, arg.initializer)
344344

345-
if isinstance(return_type, UnboundType):
346-
return_type.is_ret_type = True
347-
348345
func_type = None
349346
if any(arg_types) or return_type:
350347
if len(arg_types) != 1 and any(isinstance(t, EllipsisType) for t in arg_types):

mypy/fastparse2.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -327,9 +327,6 @@ def visit_FunctionDef(self, n: ast27.FunctionDef) -> Statement:
327327
for arg, arg_type in zip(args, arg_types):
328328
self.set_type_optional(arg_type, arg.initializer)
329329

330-
if isinstance(return_type, UnboundType):
331-
return_type.is_ret_type = True
332-
333330
func_type = None
334331
if any(arg_types) or return_type:
335332
if len(arg_types) != 1 and any(isinstance(t, EllipsisType) for t in arg_types):

mypy/messages.py

Lines changed: 6 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -372,8 +372,6 @@ def has_no_attr(self, typ: Type, member: str, context: Context) -> Type:
372372
if (isinstance(typ, Instance) and
373373
typ.type.has_readable_member(member)):
374374
self.fail('Member "{}" is not assignable'.format(member), context)
375-
elif self.check_unusable_type(typ, context):
376-
pass
377375
elif member == '__contains__':
378376
self.fail('Unsupported right operand type for in ({})'.format(
379377
self.format(typ)), context)
@@ -438,9 +436,6 @@ def unsupported_operand_types(self, op: str, left_type: Any,
438436
439437
Types can be Type objects or strings.
440438
"""
441-
if (self.check_unusable_type(left_type, context) or
442-
self.check_unusable_type(right_type, context)):
443-
return
444439
left_str = ''
445440
if isinstance(left_type, str):
446441
left_str = left_type
@@ -462,13 +457,12 @@ def unsupported_operand_types(self, op: str, left_type: Any,
462457

463458
def unsupported_left_operand(self, op: str, typ: Type,
464459
context: Context) -> None:
465-
if not self.check_unusable_type(typ, context):
466-
if self.disable_type_names:
467-
msg = 'Unsupported left operand type for {} (some union)'.format(op)
468-
else:
469-
msg = 'Unsupported left operand type for {} ({})'.format(
470-
op, self.format(typ))
471-
self.fail(msg, context)
460+
if self.disable_type_names:
461+
msg = 'Unsupported left operand type for {} (some union)'.format(op)
462+
else:
463+
msg = 'Unsupported left operand type for {} ({})'.format(
464+
op, self.format(typ))
465+
self.fail(msg, context)
472466

473467
def not_callable(self, typ: Type, context: Context) -> Type:
474468
self.fail('{} not callable'.format(self.format(typ)), context)
@@ -738,17 +732,6 @@ def invalid_keyword_var_arg(self, typ: Type, context: Context) -> None:
738732
def undefined_in_superclass(self, member: str, context: Context) -> None:
739733
self.fail('"{}" undefined in superclass'.format(member), context)
740734

741-
def check_unusable_type(self, typ: Type, context: Context) -> bool:
742-
"""If type is a type which is not meant to be used (like
743-
NoneTyp(is_ret_type=True)), report an error such as '.. does not
744-
return a value' and return True. Otherwise, return False.
745-
"""
746-
if isinstance(typ, NoneTyp) and typ.is_ret_type:
747-
self.does_not_return_value(typ, context)
748-
return True
749-
else:
750-
return False
751-
752735
def too_few_string_formatting_arguments(self, context: Context) -> None:
753736
self.fail('Not enough arguments for format string', context)
754737

mypy/test/testtypes.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ def test_callable_type(self) -> None:
4545
AnyType(), self.function)
4646
assert_equal(str(c), 'def (X?, Y?) -> Any')
4747

48-
c2 = CallableType([], [], [], NoneTyp(is_ret_type=True), None)
48+
c2 = CallableType([], [], [], NoneTyp(), None)
4949
assert_equal(str(c2), 'def ()')
5050

5151
def test_callable_type_with_default_args(self) -> None:
@@ -87,7 +87,7 @@ def test_generic_function_type(self) -> None:
8787

8888
v = [TypeVarDef('Y', -1, None, self.fx.o),
8989
TypeVarDef('X', -2, None, self.fx.o)]
90-
c2 = CallableType([], [], [], NoneTyp(is_ret_type=True), self.function, name=None, variables=v)
90+
c2 = CallableType([], [], [], NoneTyp(), self.function, name=None, variables=v)
9191
assert_equal(str(c2), 'def [Y, X] ()')
9292

9393

mypy/typeanal.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ def visit_unbound_type(self, t: UnboundType) -> Type:
128128
assert sym.tvar_def is not None
129129
return TypeVarType(sym.tvar_def, t.line)
130130
elif fullname == 'builtins.None':
131-
return NoneTyp(is_ret_type=t.is_ret_type)
131+
return NoneTyp()
132132
elif fullname == 'typing.Any':
133133
return AnyType()
134134
elif fullname == 'typing.Tuple':

mypy/types.py

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -188,8 +188,6 @@ class UnboundType(Type):
188188
args = None # type: List[Type]
189189
# should this type be wrapped in an Optional?
190190
optional = False
191-
# is this type a return type?
192-
is_ret_type = False
193191

194192
# special case for X[()]
195193
empty_tuple_index = False
@@ -200,14 +198,12 @@ def __init__(self,
200198
line: int = -1,
201199
column: int = -1,
202200
optional: bool = False,
203-
is_ret_type: bool = False,
204201
empty_tuple_index: bool = False) -> None:
205202
if not args:
206203
args = []
207204
self.name = name
208205
self.args = args
209206
self.optional = optional
210-
self.is_ret_type = is_ret_type
211207
self.empty_tuple_index = empty_tuple_index
212208
super().__init__(line, column)
213209

@@ -319,29 +315,24 @@ def deserialize(cls, data: JsonDict) -> 'UninhabitedType':
319315
class NoneTyp(Type):
320316
"""The type of 'None'.
321317
322-
This type can be written by users as 'None'. When used as a return type,
323-
`is_ret_type` is set to true, which signifies the result should not be
324-
used.
318+
This type can be written by users as 'None'.
325319
"""
326320

327321
can_be_true = False
328322

329-
def __init__(self, is_ret_type: bool = False, line: int = -1, column: int = -1) -> None:
323+
def __init__(self, line: int = -1, column: int = -1) -> None:
330324
super().__init__(line, column)
331-
self.is_ret_type = is_ret_type
332325

333326
def accept(self, visitor: 'TypeVisitor[T]') -> T:
334327
return visitor.visit_none_type(self)
335328

336329
def serialize(self) -> JsonDict:
337-
return {'.class': 'NoneTyp',
338-
'is_ret_type': self.is_ret_type,
339-
}
330+
return {'.class': 'NoneTyp'}
340331

341332
@classmethod
342333
def deserialize(cls, data: JsonDict) -> 'NoneTyp':
343334
assert data['.class'] == 'NoneTyp'
344-
return NoneTyp(is_ret_type=data['is_ret_type'])
335+
return NoneTyp()
345336

346337

347338
class ErasedType(Type):

0 commit comments

Comments
 (0)