@@ -2012,14 +2012,18 @@ def check_method_call_by_name(self,
2012
2012
arg_kinds : List [int ],
2013
2013
context : Context ,
2014
2014
local_errors : Optional [MessageBuilder ] = None ,
2015
+ original_type : Optional [Type ] = None
2015
2016
) -> Tuple [Type , Type ]:
2016
2017
"""Type check a call to a named method on an object.
2017
2018
2018
- Return tuple (result type, inferred method type).
2019
+ Return tuple (result type, inferred method type). The 'original_type'
2020
+ is used for error messages.
2019
2021
"""
2020
2022
local_errors = local_errors or self .msg
2023
+ original_type = original_type or base_type
2021
2024
method_type = analyze_member_access (method , base_type , context , False , False , True ,
2022
- local_errors , original_type = base_type , chk = self .chk ,
2025
+ local_errors , original_type = original_type ,
2026
+ chk = self .chk ,
2023
2027
in_literal_context = self .is_literal_context ())
2024
2028
return self .check_method_call (
2025
2029
method , base_type , method_type , args , arg_kinds , context , local_errors )
@@ -2441,18 +2445,31 @@ def visit_index_expr_helper(self, e: IndexExpr) -> Type:
2441
2445
# It's actually a type application.
2442
2446
return self .accept (e .analyzed )
2443
2447
left_type = self .accept (e .base )
2444
- if isinstance (left_type , TupleType ) and self .chk .in_checked_function ():
2448
+ return self .visit_index_with_type (left_type , e )
2449
+
2450
+ def visit_index_with_type (self , left_type : Type , e : IndexExpr ,
2451
+ original_type : Optional [Type ] = None ) -> Type :
2452
+ """Analyze type of an index expression for a given type of base expression.
2453
+
2454
+ The 'original_type' is used for error messages (currently used for union types).
2455
+ """
2456
+ index = e .index
2457
+ if isinstance (left_type , UnionType ):
2458
+ original_type = original_type or left_type
2459
+ return UnionType .make_simplified_union ([self .visit_index_with_type (typ , e ,
2460
+ original_type )
2461
+ for typ in left_type .relevant_items ()])
2462
+ elif isinstance (left_type , TupleType ) and self .chk .in_checked_function ():
2445
2463
# Special case for tuples. They return a more specific type when
2446
2464
# indexed by an integer literal.
2447
- index = e .index
2448
2465
if isinstance (index , SliceExpr ):
2449
2466
return self .visit_tuple_slice_helper (left_type , index )
2450
2467
2451
2468
n = self ._get_value (index )
2452
2469
if n is not None :
2453
2470
if n < 0 :
2454
2471
n += len (left_type .items )
2455
- if n >= 0 and n < len (left_type .items ):
2472
+ if 0 <= n < len (left_type .items ):
2456
2473
return left_type .items [n ]
2457
2474
else :
2458
2475
self .chk .fail (message_registry .TUPLE_INDEX_OUT_OF_RANGE , e )
@@ -2466,7 +2483,8 @@ def visit_index_expr_helper(self, e: IndexExpr) -> Type:
2466
2483
return self .visit_enum_index_expr (left_type .type_object (), e .index , e )
2467
2484
else :
2468
2485
result , method_type = self .check_method_call_by_name (
2469
- '__getitem__' , left_type , [e .index ], [ARG_POS ], e )
2486
+ '__getitem__' , left_type , [e .index ], [ARG_POS ], e ,
2487
+ original_type = original_type )
2470
2488
e .method_type = method_type
2471
2489
return result
2472
2490
0 commit comments