@@ -2426,20 +2426,7 @@ def check_assignment(self, lvalue: Lvalue, rvalue: Expression, infer_lvalue_type
2426
2426
2427
2427
# Special case: only non-abstract non-protocol classes can be assigned to
2428
2428
# variables with explicit type Type[A], where A is protocol or abstract.
2429
- rvalue_type = get_proper_type (rvalue_type )
2430
- lvalue_type = get_proper_type (lvalue_type )
2431
- if (isinstance (rvalue_type , CallableType ) and rvalue_type .is_type_obj () and
2432
- (rvalue_type .type_object ().is_abstract or
2433
- rvalue_type .type_object ().is_protocol ) and
2434
- ((isinstance (lvalue_type , TypeType ) and
2435
- isinstance (lvalue_type .item , Instance ) and
2436
- (lvalue_type .item .type .is_abstract or
2437
- lvalue_type .item .type .is_protocol )) or
2438
- (isinstance (lvalue_type , CallableType ) and
2439
- isinstance (lvalue_type .ret_type , Instance ) and
2440
- (lvalue_type .ret_type .type .is_abstract or
2441
- lvalue_type .ret_type .type .is_protocol )))):
2442
- self .msg .concrete_only_assign (lvalue_type , rvalue )
2429
+ if not self .check_concrete_only_assign (lvalue_type , rvalue_type , rvalue ):
2443
2430
return
2444
2431
if rvalue_type and infer_lvalue_type and not isinstance (lvalue_type , PartialType ):
2445
2432
# Don't use type binder for definitions of special forms, like named tuples.
@@ -2457,6 +2444,38 @@ def check_assignment(self, lvalue: Lvalue, rvalue: Expression, infer_lvalue_type
2457
2444
self .infer_variable_type (inferred , lvalue , rvalue_type , rvalue )
2458
2445
self .check_assignment_to_slots (lvalue )
2459
2446
2447
+ def check_concrete_only_assign (self , lvalue_type : Optional [Type ],
2448
+ rvalue_type : Type , rvalue : Expression ) -> bool :
2449
+ rvalue_type = get_proper_type (rvalue_type )
2450
+ lvalue_type = get_proper_type (lvalue_type )
2451
+ if not (
2452
+ isinstance (rvalue_type , CallableType ) and
2453
+ rvalue_type .is_type_obj () and
2454
+ (rvalue_type .type_object ().is_abstract or
2455
+ rvalue_type .type_object ().is_protocol )):
2456
+ return True
2457
+
2458
+ lvalue_is_a_type = (
2459
+ isinstance (lvalue_type , TypeType ) and
2460
+ isinstance (lvalue_type .item , Instance ) and
2461
+ (lvalue_type .item .type .is_abstract or
2462
+ lvalue_type .item .type .is_protocol )
2463
+ )
2464
+
2465
+ lvalue_is_a_callable = False
2466
+ if isinstance (lvalue_type , CallableType ):
2467
+ ret_type = get_proper_type (lvalue_type .ret_type )
2468
+ lvalue_is_a_callable = (
2469
+ isinstance (ret_type , Instance ) and
2470
+ (ret_type .type .is_abstract or ret_type .type .is_protocol )
2471
+ )
2472
+
2473
+ if lvalue_is_a_type or lvalue_is_a_callable :
2474
+ # `lvalue_type` here is either `TypeType` or `CallableType`:
2475
+ self .msg .concrete_only_assign (cast (Type , lvalue_type ), rvalue )
2476
+ return False
2477
+ return True
2478
+
2460
2479
# (type, operator) tuples for augmented assignments supported with partial types
2461
2480
partial_type_augmented_ops : Final = {
2462
2481
('builtins.list' , '+' ),
0 commit comments