@@ -453,16 +453,16 @@ def get_generator_yield_type(self, return_type: Type) -> Type:
453
453
if isinstance (return_type , AnyType ):
454
454
return AnyType ()
455
455
elif not self .is_generator_return_type (return_type ):
456
- # if the function doesn't have a proper Generator (or superclass)
457
- # return type, anything is permissible
456
+ # If the function doesn't have a proper Generator (or superclass) return type, anything
457
+ # is permissible.
458
458
return AnyType ()
459
459
elif not isinstance (return_type , Instance ):
460
- # same as above, but written as a separate branch so the typechecker can understand
460
+ # Same as above, but written as a separate branch so the typechecker can understand.
461
461
return AnyType ()
462
462
elif return_type .args :
463
463
return return_type .args [0 ]
464
464
else :
465
- # if the function's declared supertype of Generator has no type
465
+ # If the function's declared supertype of Generator has no type
466
466
# parameters (i.e. is `object`), then the yielded values can't
467
467
# be accessed so any type is acceptable.
468
468
return AnyType ()
@@ -471,35 +471,37 @@ def get_generator_receive_type(self, return_type: Type) -> Type:
471
471
if isinstance (return_type , AnyType ):
472
472
return AnyType ()
473
473
elif not self .is_generator_return_type (return_type ):
474
- # if the function doesn't have a proper Generator (or superclass)
475
- # return type, anything is permissible
474
+ # If the function doesn't have a proper Generator (or superclass) return type, anything
475
+ # is permissible.
476
476
return AnyType ()
477
477
elif not isinstance (return_type , Instance ):
478
- # same as above, but written as a separate branch so the typechecker can understand
478
+ # Same as above, but written as a separate branch so the typechecker can understand.
479
479
return AnyType ()
480
480
elif return_type .type .fullname () == 'typing.Generator' :
481
- # Generator is the only type which specifies the type of values it can receive
481
+ # Generator is the only type which specifies the type of values it can receive.
482
482
return return_type .args [1 ]
483
483
else :
484
- # it's a supertype of Generator, so callers won't be able to see send it values
484
+ # `return_type` is a supertype of Generator, so callers won't be able to send it
485
+ # values.
485
486
return Void ()
486
487
487
488
def get_generator_return_type (self , return_type : Type ) -> Type :
488
489
if isinstance (return_type , AnyType ):
489
490
return AnyType ()
490
491
elif not self .is_generator_return_type (return_type ):
491
- # if the function doesn't have a proper Generator (or superclass)
492
- # return type, anything is permissible
492
+ # If the function doesn't have a proper Generator (or superclass) return type, anything
493
+ # is permissible.
493
494
return AnyType ()
494
495
elif not isinstance (return_type , Instance ):
495
- # same as above, but written as a separate branch so the typechecker can understand
496
+ # Same as above, but written as a separate branch so the typechecker can understand.
496
497
return AnyType ()
497
498
elif return_type .type .fullname () == 'typing.Generator' :
498
- # Generator is the only type which specifies the type of values it
499
- # returns into `yield from` expressions
499
+ # Generator is the only type which specifies the type of values it returns into
500
+ # `yield from` expressions.
500
501
return return_type .args [2 ]
501
502
else :
502
- # it's a supertype of Generator, so callers won't be able to see the return type
503
+ # `return_type` is supertype of Generator, so callers won't be able to see the return
504
+ # type when used in a `yield from` expression.
503
505
return AnyType ()
504
506
505
507
def visit_func_def (self , defn : FuncDef ) -> Type :
@@ -612,12 +614,12 @@ def check_func_def(self, defn: FuncItem, typ: CallableType, name: str) -> None:
612
614
self .fail (messages .RETURN_TYPE_CANNOT_BE_CONTRAVARIANT ,
613
615
typ .ret_type )
614
616
615
- # check that Generator functions have the appropriate return type
617
+ # Check that Generator functions have the appropriate return type.
616
618
if defn .is_generator :
617
619
if not self .is_generator_return_type (typ .ret_type ):
618
620
self .fail (messages .INVALID_RETURN_TYPE_FOR_GENERATOR , typ )
619
621
620
- # Python 2 generators aren't allowed to return values
622
+ # Python 2 generators aren't allowed to return values.
621
623
if (self .pyversion [0 ] == 2 and
622
624
isinstance (typ .ret_type , Instance ) and
623
625
typ .ret_type .type .fullname () == 'typing.Generator' ):
@@ -1484,11 +1486,10 @@ def visit_return_stmt(self, s: ReturnStmt) -> Type:
1484
1486
return None
1485
1487
1486
1488
if isinstance (return_type , Void ):
1487
- # FuncExpr (lambda) may have a Void return.
1488
- # Function returning a value of type None may have a Void return.
1489
+ # Lambdas are allowed to have a Void return.
1490
+ # Functions returning a value of type None are allowed to have a Void return.
1489
1491
if isinstance (self .function_stack [- 1 ], FuncExpr ) or isinstance (typ , NoneTyp ):
1490
1492
return None
1491
-
1492
1493
self .fail (messages .NO_RETURN_VALUE_EXPECTED , s )
1493
1494
else :
1494
1495
self .check_subtype (
@@ -1497,7 +1498,7 @@ def visit_return_stmt(self, s: ReturnStmt) -> Type:
1497
1498
+ ": expected {}, got {}" .format (return_type , typ )
1498
1499
)
1499
1500
else :
1500
- # empty returns are valid in Generators with Any typed returns
1501
+ # Empty returns are valid in Generators with Any typed returns.
1501
1502
if (self .function_stack [- 1 ].is_generator and isinstance (return_type , AnyType )):
1502
1503
return None
1503
1504
@@ -1861,9 +1862,11 @@ def visit_yield_from_expr(self, e: YieldFromExpr) -> Type:
1861
1862
return_type = self .return_types [- 1 ]
1862
1863
subexpr_type = self .accept (e .expr , return_type )
1863
1864
1864
- # check that the expr is an instance of Iterable and get the type of
1865
- # the iterator produced by __iter__
1866
- if (isinstance (subexpr_type , Instance ) and
1865
+ # Check that the expr is an instance of Iterable and get the type of the iterator produced
1866
+ # by __iter__.
1867
+ if isinstance (subexpr_type , AnyType ):
1868
+ iter_type = AnyType ()
1869
+ elif (isinstance (subexpr_type , Instance ) and
1867
1870
is_subtype (subexpr_type , self .named_type ('typing.Iterable' ))):
1868
1871
iter_method_type = self .expr_checker .analyze_external_member_access (
1869
1872
'__iter__' ,
@@ -1874,27 +1877,25 @@ def visit_yield_from_expr(self, e: YieldFromExpr) -> Type:
1874
1877
[AnyType (), AnyType (), AnyType ()])
1875
1878
iter_type , _ = self .expr_checker .check_call (iter_method_type , [], [],
1876
1879
context = generic_generator_type )
1877
- elif isinstance (subexpr_type , AnyType ):
1878
- iter_type = AnyType ()
1879
1880
else :
1880
1881
self .msg .yield_from_invalid_operand_type (subexpr_type , e )
1881
1882
iter_type = AnyType ()
1882
1883
1883
- # check that the iterator's item type matches the type yielded by the
1884
- # Generator function containing this yield from
1884
+ # Check that the iterator's item type matches the type yielded by the Generator function
1885
+ # containing this ` yield from` expression.
1885
1886
expected_item_type = self .get_generator_yield_type (return_type )
1886
1887
actual_item_type = self .get_generator_yield_type (iter_type )
1887
1888
1888
1889
self .check_subtype (actual_item_type , expected_item_type , e ,
1889
1890
messages .INCOMPATIBLE_TYPES_IN_YIELD_FROM ,
1890
1891
'actual type' , 'expected type' )
1891
1892
1892
- # determine the type of the entire yield from expression
1893
+ # Determine the type of the entire yield from expression.
1893
1894
if (isinstance (iter_type , Instance ) and
1894
1895
iter_type .type .fullname () == 'typing.Generator' ):
1895
1896
return self .get_generator_return_type (iter_type )
1896
1897
else :
1897
- # non -Generators don't return anything from " yield from" expressions
1898
+ # Non -Generators don't return anything from ` yield from` expressions.
1898
1899
return Void ()
1899
1900
1900
1901
def visit_member_expr (self , e : MemberExpr ) -> Type :
0 commit comments