@@ -344,9 +344,19 @@ def fail(self,
344
344
msg : str ,
345
345
line : int ,
346
346
column : int ,
347
- blocker : bool = True ) -> None :
347
+ blocker : bool = True ,
348
+ code : codes .ErrorCode = codes .SYNTAX ) -> None :
348
349
if blocker or not self .options .ignore_errors :
349
- self .errors .report (line , column , msg , blocker = blocker , code = codes .SYNTAX )
350
+ self .errors .report (line , column , msg , blocker = blocker , code = code )
351
+
352
+ def fail_merge_overload (self , node : IfStmt ) -> None :
353
+ self .fail (
354
+ "Condition can't be inferred, unable to merge overloads" ,
355
+ line = node .line ,
356
+ column = node .column ,
357
+ blocker = False ,
358
+ code = codes .MISC ,
359
+ )
350
360
351
361
def visit (self , node : Optional [AST ]) -> Any :
352
362
if node is None :
@@ -479,10 +489,12 @@ def fix_function_overloads(self, stmts: List[Statement]) -> List[Statement]:
479
489
last_if_stmt : Optional [IfStmt ] = None
480
490
last_if_overload : Optional [Union [Decorator , FuncDef , OverloadedFuncDef ]] = None
481
491
last_if_stmt_overload_name : Optional [str ] = None
492
+ last_if_unknown_truth_value : Optional [IfStmt ] = None
482
493
skipped_if_stmts : List [IfStmt ] = []
483
494
for stmt in stmts :
484
495
if_overload_name : Optional [str ] = None
485
496
if_block_with_overload : Optional [Block ] = None
497
+ if_unknown_truth_value : Optional [IfStmt ] = None
486
498
if (
487
499
isinstance (stmt , IfStmt )
488
500
and len (stmt .body [0 ].body ) == 1
@@ -495,7 +507,8 @@ def fix_function_overloads(self, stmts: List[Statement]) -> List[Statement]:
495
507
# Check IfStmt block to determine if function overloads can be merged
496
508
if_overload_name = self ._check_ifstmt_for_overloads (stmt )
497
509
if if_overload_name is not None :
498
- if_block_with_overload = self ._get_executable_if_block_with_overloads (stmt )
510
+ if_block_with_overload , if_unknown_truth_value = \
511
+ self ._get_executable_if_block_with_overloads (stmt )
499
512
500
513
if (current_overload_name is not None
501
514
and isinstance (stmt , (Decorator , FuncDef ))
@@ -510,6 +523,9 @@ def fix_function_overloads(self, stmts: List[Statement]) -> List[Statement]:
510
523
else :
511
524
current_overload .append (last_if_overload )
512
525
last_if_stmt , last_if_overload = None , None
526
+ if last_if_unknown_truth_value :
527
+ self .fail_merge_overload (last_if_unknown_truth_value )
528
+ last_if_unknown_truth_value = None
513
529
current_overload .append (stmt )
514
530
elif (
515
531
current_overload_name is not None
@@ -522,6 +538,8 @@ def fix_function_overloads(self, stmts: List[Statement]) -> List[Statement]:
522
538
# or function definitions.
523
539
skipped_if_stmts .append (stmt )
524
540
if if_block_with_overload is None :
541
+ if if_unknown_truth_value is not None :
542
+ self .fail_merge_overload (if_unknown_truth_value )
525
543
continue
526
544
if last_if_overload is not None :
527
545
# Last stmt was an IfStmt with same overload name
@@ -542,6 +560,7 @@ def fix_function_overloads(self, stmts: List[Statement]) -> List[Statement]:
542
560
ret .append (last_if_stmt )
543
561
last_if_stmt_overload_name = current_overload_name
544
562
last_if_stmt , last_if_overload = None , None
563
+ last_if_unknown_truth_value = None
545
564
546
565
if current_overload and current_overload_name == last_if_stmt_overload_name :
547
566
# Remove last stmt (IfStmt) from ret if the overload names matched
@@ -580,6 +599,7 @@ def fix_function_overloads(self, stmts: List[Statement]) -> List[Statement]:
580
599
Union [Decorator , FuncDef , OverloadedFuncDef ],
581
600
if_block_with_overload .body [0 ]
582
601
)
602
+ last_if_unknown_truth_value = if_unknown_truth_value
583
603
else :
584
604
current_overload = []
585
605
current_overload_name = None
@@ -630,29 +650,40 @@ def _check_ifstmt_for_overloads(self, stmt: IfStmt) -> Optional[str]:
630
650
631
651
return None
632
652
633
- def _get_executable_if_block_with_overloads (self , stmt : IfStmt ) -> Optional [Block ]:
653
+ def _get_executable_if_block_with_overloads (
654
+ self , stmt : IfStmt
655
+ ) -> Tuple [Optional [Block ], Optional [IfStmt ]]:
634
656
"""Return block from IfStmt that will get executed.
635
657
636
- Only returns block if sure that alternative blocks are unreachable.
658
+ Return
659
+ 0 -> A block if sure that alternative blocks are unreachable.
660
+ 1 -> An IfStmt if the reachability of it can't be inferred,
661
+ i.e. the truth value is unknown.
637
662
"""
638
663
infer_reachability_of_if_statement (stmt , self .options )
664
+ if (
665
+ stmt .else_body is None
666
+ and stmt .body [0 ].is_unreachable is True
667
+ ):
668
+ # always False condition with no else
669
+ return None , None
639
670
if (
640
671
stmt .else_body is None
641
672
or stmt .body [0 ].is_unreachable is False
642
673
and stmt .else_body .is_unreachable is False
643
674
):
644
675
# The truth value is unknown, thus not conclusive
645
- return None
676
+ return None , stmt
646
677
if stmt .else_body .is_unreachable is True :
647
678
# else_body will be set unreachable if condition is always True
648
- return stmt .body [0 ]
679
+ return stmt .body [0 ], None
649
680
if stmt .body [0 ].is_unreachable is True :
650
681
# body will be set unreachable if condition is always False
651
682
# else_body can contain an IfStmt itself (for elif) -> do a recursive check
652
683
if isinstance (stmt .else_body .body [0 ], IfStmt ):
653
684
return self ._get_executable_if_block_with_overloads (stmt .else_body .body [0 ])
654
- return stmt .else_body
655
- return None
685
+ return stmt .else_body , None
686
+ return None , stmt
656
687
657
688
def _strip_contents_from_if_stmt (self , stmt : IfStmt ) -> None :
658
689
"""Remove contents from IfStmt.
0 commit comments