3232from mypy .types import (
3333 Type , AnyType , CallableType , Void , FunctionLike , Overloaded , TupleType ,
3434 Instance , NoneTyp , ErrorType , strip_type ,
35- UnionType , TypeVarType , PartialType , DeletedType
35+ UnionType , TypeVarType , PartialType , DeletedType , UninhabitedType
3636)
3737from mypy .sametypes import is_same_type
3838from mypy .messages import MessageBuilder
5353from mypy .treetransform import TransformVisitor
5454from mypy .meet import meet_simple , nearest_builtin_ancestor , is_overlapping_types
5555
56+ from mypy import experiments
57+
5658
5759T = TypeVar ('T' )
5860
@@ -223,14 +225,14 @@ def get_declaration(self, expr: Any) -> Type:
223225 else :
224226 return self .frames [0 ].get (expr .literal_hash )
225227
226- def assign_type (self , expr : Node , type : Type ,
228+ def assign_type (self , expr : Node ,
229+ type : Type ,
230+ declared_type : Type ,
227231 restrict_any : bool = False ) -> None :
228232 if not expr .literal :
229233 return
230234 self .invalidate_dependencies (expr )
231235
232- declared_type = self .get_declaration (expr )
233-
234236 if declared_type is None :
235237 # Not sure why this happens. It seems to mainly happen in
236238 # member initialization.
@@ -1200,18 +1202,31 @@ def check_assignment(self, lvalue: Node, rvalue: Node, infer_lvalue_type: bool =
12001202 partial_types = self .find_partial_types (var )
12011203 if partial_types is not None :
12021204 if not self .current_node_deferred :
1203- var .type = rvalue_type
1205+ if experiments .STRICT_OPTIONAL :
1206+ var .type = UnionType .make_simplified_union (
1207+ [rvalue_type , NoneTyp ()])
1208+ else :
1209+ var .type = rvalue_type
12041210 else :
12051211 var .type = None
12061212 del partial_types [var ]
12071213 # Try to infer a partial type. No need to check the return value, as
12081214 # an error will be reported elsewhere.
12091215 self .infer_partial_type (lvalue_type .var , lvalue , rvalue_type )
12101216 return
1211- rvalue_type = self .check_simple_assignment (lvalue_type , rvalue , lvalue )
1217+ if (is_literal_none (rvalue ) and
1218+ isinstance (lvalue , NameExpr ) and
1219+ isinstance (lvalue .node , Var ) and
1220+ lvalue .node .is_initialized_in_class ):
1221+ # Allow None's to be assigned to class variables with non-Optional types.
1222+ rvalue_type = lvalue_type
1223+ else :
1224+ rvalue_type = self .check_simple_assignment (lvalue_type , rvalue , lvalue )
12121225
12131226 if rvalue_type and infer_lvalue_type :
1214- self .binder .assign_type (lvalue , rvalue_type ,
1227+ self .binder .assign_type (lvalue ,
1228+ rvalue_type ,
1229+ lvalue_type ,
12151230 self .typing_mode_weak ())
12161231 elif index_lvalue :
12171232 self .check_indexed_assignment (index_lvalue , rvalue , rvalue )
@@ -1444,7 +1459,7 @@ def infer_variable_type(self, name: Var, lvalue: Node,
14441459 """Infer the type of initialized variables from initializer type."""
14451460 if self .typing_mode_weak ():
14461461 self .set_inferred_type (name , lvalue , AnyType ())
1447- self .binder .assign_type (lvalue , init_type , True )
1462+ self .binder .assign_type (lvalue , init_type , self . binder . get_declaration ( lvalue ), True )
14481463 elif isinstance (init_type , Void ):
14491464 self .check_not_void (init_type , context )
14501465 self .set_inference_error_fallback_type (name , lvalue , init_type , context )
@@ -1467,16 +1482,16 @@ def infer_variable_type(self, name: Var, lvalue: Node,
14671482 self .set_inferred_type (name , lvalue , init_type )
14681483
14691484 def infer_partial_type (self , name : Var , lvalue : Node , init_type : Type ) -> bool :
1470- if isinstance (init_type , NoneTyp ):
1471- partial_type = PartialType (None , name )
1485+ if isinstance (init_type , ( NoneTyp , UninhabitedType ) ):
1486+ partial_type = PartialType (None , name , [ init_type ] )
14721487 elif isinstance (init_type , Instance ):
14731488 fullname = init_type .type .fullname ()
1474- if (( fullname == 'builtins.list' or fullname == 'builtins.set' or
1475- fullname == 'builtins.dict' )
1476- and isinstance ( init_type . args [ 0 ], NoneTyp )
1477- and ( fullname != 'builtins.dict' or isinstance ( init_type . args [ 1 ], NoneTyp ))
1478- and isinstance (lvalue , NameExpr )):
1479- partial_type = PartialType (init_type .type , name )
1489+ if (isinstance ( lvalue , NameExpr ) and
1490+ ( fullname == 'builtins.list' or
1491+ fullname == 'builtins.set' or
1492+ fullname == 'builtins.dict' ) and
1493+ all ( isinstance (t , ( NoneTyp , UninhabitedType )) for t in init_type . args )):
1494+ partial_type = PartialType (init_type .type , name , init_type . args )
14801495 else :
14811496 return False
14821497 else :
@@ -1559,8 +1574,8 @@ def try_infer_partial_type_from_indexed_assignment(
15591574 self , lvalue : IndexExpr , rvalue : Node ) -> None :
15601575 # TODO: Should we share some of this with try_infer_partial_type?
15611576 if isinstance (lvalue .base , RefExpr ) and isinstance (lvalue .base .node , Var ):
1562- var = cast ( Var , lvalue .base .node )
1563- if var is not None and isinstance (var .type , PartialType ):
1577+ var = lvalue .base .node
1578+ if isinstance (var .type , PartialType ):
15641579 type_type = var .type .type
15651580 if type_type is None :
15661581 return # The partial type is None.
@@ -1572,10 +1587,15 @@ def try_infer_partial_type_from_indexed_assignment(
15721587 # TODO: Don't infer things twice.
15731588 key_type = self .accept (lvalue .index )
15741589 value_type = self .accept (rvalue )
1575- if is_valid_inferred_type (key_type ) and is_valid_inferred_type (value_type ):
1590+ full_key_type = UnionType .make_simplified_union (
1591+ [key_type , var .type .inner_types [0 ]])
1592+ full_value_type = UnionType .make_simplified_union (
1593+ [value_type , var .type .inner_types [1 ]])
1594+ if (is_valid_inferred_type (full_key_type ) and
1595+ is_valid_inferred_type (full_value_type )):
15761596 if not self .current_node_deferred :
15771597 var .type = self .named_generic_type ('builtins.dict' ,
1578- [key_type , value_type ])
1598+ [full_key_type , full_value_type ])
15791599 del partial_types [var ]
15801600
15811601 def visit_expression_stmt (self , s : ExpressionStmt ) -> Type :
@@ -1881,7 +1901,10 @@ def analyze_iterable_item_type(self, expr: Node) -> Type:
18811901
18821902 self .check_not_void (iterable , expr )
18831903 if isinstance (iterable , TupleType ):
1884- joined = NoneTyp () # type: Type
1904+ if experiments .STRICT_OPTIONAL :
1905+ joined = UninhabitedType () # type: Type
1906+ else :
1907+ joined = NoneTyp ()
18851908 for item in iterable .items :
18861909 joined = join_types (joined , item )
18871910 if isinstance (joined , ErrorType ):
@@ -1932,7 +1955,9 @@ def flatten(t: Node) -> List[Node]:
19321955 s .expr .accept (self )
19331956 for elt in flatten (s .expr ):
19341957 if isinstance (elt , NameExpr ):
1935- self .binder .assign_type (elt , DeletedType (source = elt .name ),
1958+ self .binder .assign_type (elt ,
1959+ DeletedType (source = elt .name ),
1960+ self .binder .get_declaration (elt ),
19361961 self .typing_mode_weak ())
19371962 return None
19381963
@@ -2311,8 +2336,12 @@ def leave_partial_types(self) -> None:
23112336 partial_types = self .partial_types .pop ()
23122337 if not self .current_node_deferred :
23132338 for var , context in partial_types .items ():
2314- self .msg .fail (messages .NEED_ANNOTATION_FOR_VAR , context )
2315- var .type = AnyType ()
2339+ if experiments .STRICT_OPTIONAL and cast (PartialType , var .type ).type is None :
2340+ # None partial type: assume variable is intended to have type None
2341+ var .type = NoneTyp ()
2342+ else :
2343+ self .msg .fail (messages .NEED_ANNOTATION_FOR_VAR , context )
2344+ var .type = AnyType ()
23162345
23172346 def find_partial_types (self , var : Var ) -> Optional [Dict [Var , Context ]]:
23182347 for partial_types in reversed (self .partial_types ):
@@ -2356,11 +2385,48 @@ def method_type(self, func: FuncBase) -> FunctionLike:
23562385 return method_type_with_fallback (func , self .named_type ('builtins.function' ))
23572386
23582387
2388+ def conditional_type_map (expr : Node ,
2389+ current_type : Optional [Type ],
2390+ proposed_type : Optional [Type ],
2391+ * ,
2392+ weak : bool = False
2393+ ) -> Tuple [Optional [Dict [Node , Type ]], Optional [Dict [Node , Type ]]]:
2394+ """Takes in an expression, the current type of the expression, and a
2395+ proposed type of that expression.
2396+
2397+ Returns a 2-tuple: The first element is a map from the expression to
2398+ the proposed type, if the expression can be the proposed type. The
2399+ second element is a map from the expression to the type it would hold
2400+ if it was not the proposed type, if any."""
2401+ if proposed_type :
2402+ if current_type :
2403+ if is_proper_subtype (current_type , proposed_type ):
2404+ return {expr : proposed_type }, None
2405+ elif not is_overlapping_types (current_type , proposed_type ):
2406+ return None , {expr : current_type }
2407+ else :
2408+ remaining_type = restrict_subtype_away (current_type , proposed_type )
2409+ return {expr : proposed_type }, {expr : remaining_type }
2410+ else :
2411+ return {expr : proposed_type }, {}
2412+ else :
2413+ # An isinstance check, but we don't understand the type
2414+ if weak :
2415+ return {expr : AnyType ()}, {expr : current_type }
2416+ else :
2417+ return {}, {}
2418+
2419+
2420+ def is_literal_none (n : Node ) -> bool :
2421+ return isinstance (n , NameExpr ) and n .fullname == 'builtins.None'
2422+
2423+
23592424def find_isinstance_check (node : Node ,
23602425 type_map : Dict [Node , Type ],
2361- weak : bool = False ) \
2362- -> Tuple [Optional [Dict [Node , Type ]], Optional [Dict [Node , Type ]]]:
2363- """Find any isinstance checks (within a chain of ands).
2426+ weak : bool = False
2427+ ) -> Tuple [Optional [Dict [Node , Type ]], Optional [Dict [Node , Type ]]]:
2428+ """Find any isinstance checks (within a chain of ands). Includes
2429+ implicit and explicit checks for None.
23642430
23652431 Return value is a map of variables to their types if the condition
23662432 is true and a map of variables to their types if the condition is false.
@@ -2376,20 +2442,31 @@ def find_isinstance_check(node: Node,
23762442 if expr .literal == LITERAL_TYPE :
23772443 vartype = type_map [expr ]
23782444 type = get_isinstance_type (node .args [1 ], type_map )
2379- if type :
2380- elsetype = vartype
2381- if vartype :
2382- if is_proper_subtype (vartype , type ):
2383- return {expr : type }, None
2384- elif not is_overlapping_types (vartype , type ):
2385- return None , {expr : elsetype }
2386- else :
2387- elsetype = restrict_subtype_away (vartype , type )
2388- return {expr : type }, {expr : elsetype }
2389- else :
2390- # An isinstance check, but we don't understand the type
2391- if weak :
2392- return {expr : AnyType ()}, {expr : vartype }
2445+ return conditional_type_map (expr , vartype , type , weak = weak )
2446+ elif (isinstance (node , ComparisonExpr ) and any (is_literal_none (n ) for n in node .operands ) and
2447+ experiments .STRICT_OPTIONAL ):
2448+ # Check for `x is None` and `x is not None`.
2449+ is_not = node .operators == ['is not' ]
2450+ if is_not or node .operators == ['is' ]:
2451+ if_vars = {} # type: Dict[Node, Type]
2452+ else_vars = {} # type: Dict[Node, Type]
2453+ for expr in node .operands :
2454+ if expr .literal == LITERAL_TYPE and not is_literal_none (expr ) and expr in type_map :
2455+ # This should only be true at most once: there should be
2456+ # two elements in node.operands, and at least one of them
2457+ # should represent a None.
2458+ vartype = type_map [expr ]
2459+ if_vars , else_vars = conditional_type_map (expr , vartype , NoneTyp (), weak = weak )
2460+ break
2461+
2462+ if is_not :
2463+ if_vars , else_vars = else_vars , if_vars
2464+ return if_vars , else_vars
2465+ elif isinstance (node , RefExpr ) and experiments .STRICT_OPTIONAL :
2466+ # The type could be falsy, so we can't deduce anything new about the else branch
2467+ vartype = type_map [node ]
2468+ _ , if_vars = conditional_type_map (node , vartype , NoneTyp (), weak = weak )
2469+ return if_vars , {}
23932470 elif isinstance (node , OpExpr ) and node .op == 'and' :
23942471 left_if_vars , right_else_vars = find_isinstance_check (
23952472 node .left ,
@@ -2571,6 +2648,12 @@ def is_valid_inferred_type(typ: Type) -> bool:
25712648 Examples of invalid types include the None type or a type with a None component.
25722649 """
25732650 if is_same_type (typ , NoneTyp ()):
2651+ # With strict Optional checking, we *may* eventually infer NoneTyp, but
2652+ # we only do that if we can't infer a specific Optional type. This
2653+ # resolution happens in leave_partial_types when we pop a partial types
2654+ # scope.
2655+ return False
2656+ if is_same_type (typ , UninhabitedType ()):
25742657 return False
25752658 elif isinstance (typ , Instance ):
25762659 for arg in typ .args :
0 commit comments