@@ -971,32 +971,39 @@ impl<'db> TypeInferenceBuilder<'db> {
971
971
/// Raise a diagnostic if the given type cannot be divided by zero.
972
972
///
973
973
/// Expects the resolved type of the left side of the binary expression.
974
- fn check_division_by_zero ( & mut self , expr : & ast:: ExprBinOp , left : Type < ' db > ) {
974
+ fn check_division_by_zero (
975
+ & mut self ,
976
+ node : AnyNodeRef < ' _ > ,
977
+ op : ast:: Operator ,
978
+ left : Type < ' db > ,
979
+ ) -> bool {
975
980
match left {
976
981
Type :: BooleanLiteral ( _) | Type :: IntLiteral ( _) => { }
977
982
Type :: Instance ( instance)
978
983
if matches ! (
979
984
instance. class( ) . known( self . db( ) ) ,
980
985
Some ( KnownClass :: Float | KnownClass :: Int | KnownClass :: Bool )
981
986
) => { }
982
- _ => return ,
987
+ _ => return false ,
983
988
} ;
984
989
985
- let ( op, by_zero) = match expr . op {
990
+ let ( op, by_zero) = match op {
986
991
ast:: Operator :: Div => ( "divide" , "by zero" ) ,
987
992
ast:: Operator :: FloorDiv => ( "floor divide" , "by zero" ) ,
988
993
ast:: Operator :: Mod => ( "reduce" , "modulo zero" ) ,
989
- _ => return ,
994
+ _ => return false ,
990
995
} ;
991
996
992
997
self . context . report_lint (
993
998
& DIVISION_BY_ZERO ,
994
- expr ,
999
+ node ,
995
1000
format_args ! (
996
1001
"Cannot {op} object of type `{}` {by_zero}" ,
997
1002
left. display( self . db( ) )
998
1003
) ,
999
1004
) ;
1005
+
1006
+ true
1000
1007
}
1001
1008
1002
1009
fn add_binding ( & mut self , node : AnyNodeRef , binding : Definition < ' db > , ty : Type < ' db > ) {
@@ -2858,7 +2865,7 @@ impl<'db> TypeInferenceBuilder<'db> {
2858
2865
2859
2866
// Fall back to non-augmented binary operator inference.
2860
2867
let mut binary_return_ty = || {
2861
- self . infer_binary_expression_type ( target_type, value_type, op)
2868
+ self . infer_binary_expression_type ( assignment . into ( ) , false , target_type, value_type, op)
2862
2869
. unwrap_or_else ( || {
2863
2870
report_unsupported_augmented_op ( & mut self . context ) ;
2864
2871
Type :: unknown ( )
@@ -4495,19 +4502,7 @@ impl<'db> TypeInferenceBuilder<'db> {
4495
4502
let left_ty = self . infer_expression ( left) ;
4496
4503
let right_ty = self . infer_expression ( right) ;
4497
4504
4498
- // Check for division by zero; this doesn't change the inferred type for the expression, but
4499
- // may emit a diagnostic
4500
- if matches ! (
4501
- ( op, right_ty) ,
4502
- (
4503
- ast:: Operator :: Div | ast:: Operator :: FloorDiv | ast:: Operator :: Mod ,
4504
- Type :: IntLiteral ( 0 ) | Type :: BooleanLiteral ( false )
4505
- )
4506
- ) {
4507
- self . check_division_by_zero ( binary, left_ty) ;
4508
- }
4509
-
4510
- self . infer_binary_expression_type ( left_ty, right_ty, * op)
4505
+ self . infer_binary_expression_type ( binary. into ( ) , false , left_ty, right_ty, * op)
4511
4506
. unwrap_or_else ( || {
4512
4507
self . context . report_lint (
4513
4508
& UNSUPPORTED_OPERATOR ,
@@ -4524,23 +4519,51 @@ impl<'db> TypeInferenceBuilder<'db> {
4524
4519
4525
4520
fn infer_binary_expression_type (
4526
4521
& mut self ,
4522
+ node : AnyNodeRef < ' _ > ,
4523
+ mut emitted_division_by_zero_diagnostic : bool ,
4527
4524
left_ty : Type < ' db > ,
4528
4525
right_ty : Type < ' db > ,
4529
4526
op : ast:: Operator ,
4530
4527
) -> Option < Type < ' db > > {
4528
+ // Check for division by zero; this doesn't change the inferred type for the expression, but
4529
+ // may emit a diagnostic
4530
+ if !emitted_division_by_zero_diagnostic
4531
+ && matches ! (
4532
+ ( op, right_ty) ,
4533
+ (
4534
+ ast:: Operator :: Div | ast:: Operator :: FloorDiv | ast:: Operator :: Mod ,
4535
+ Type :: IntLiteral ( 0 ) | Type :: BooleanLiteral ( false )
4536
+ )
4537
+ )
4538
+ {
4539
+ emitted_division_by_zero_diagnostic = self . check_division_by_zero ( node, op, left_ty) ;
4540
+ }
4541
+
4531
4542
match ( left_ty, right_ty, op) {
4532
4543
( Type :: Union ( lhs_union) , rhs, _) => {
4533
4544
let mut union = UnionBuilder :: new ( self . db ( ) ) ;
4534
4545
for lhs in lhs_union. elements ( self . db ( ) ) {
4535
- let result = self . infer_binary_expression_type ( * lhs, rhs, op) ?;
4546
+ let result = self . infer_binary_expression_type (
4547
+ node,
4548
+ emitted_division_by_zero_diagnostic,
4549
+ * lhs,
4550
+ rhs,
4551
+ op,
4552
+ ) ?;
4536
4553
union = union. add ( result) ;
4537
4554
}
4538
4555
Some ( union. build ( ) )
4539
4556
}
4540
4557
( lhs, Type :: Union ( rhs_union) , _) => {
4541
4558
let mut union = UnionBuilder :: new ( self . db ( ) ) ;
4542
4559
for rhs in rhs_union. elements ( self . db ( ) ) {
4543
- let result = self . infer_binary_expression_type ( lhs, * rhs, op) ?;
4560
+ let result = self . infer_binary_expression_type (
4561
+ node,
4562
+ emitted_division_by_zero_diagnostic,
4563
+ lhs,
4564
+ * rhs,
4565
+ op,
4566
+ ) ?;
4544
4567
union = union. add ( result) ;
4545
4568
}
4546
4569
Some ( union. build ( ) )
@@ -4659,13 +4682,19 @@ impl<'db> TypeInferenceBuilder<'db> {
4659
4682
}
4660
4683
4661
4684
( Type :: BooleanLiteral ( bool_value) , right, op) => self . infer_binary_expression_type (
4685
+ node,
4686
+ emitted_division_by_zero_diagnostic,
4662
4687
Type :: IntLiteral ( i64:: from ( bool_value) ) ,
4663
4688
right,
4664
4689
op,
4665
4690
) ,
4666
- ( left, Type :: BooleanLiteral ( bool_value) , op) => {
4667
- self . infer_binary_expression_type ( left, Type :: IntLiteral ( i64:: from ( bool_value) ) , op)
4668
- }
4691
+ ( left, Type :: BooleanLiteral ( bool_value) , op) => self . infer_binary_expression_type (
4692
+ node,
4693
+ emitted_division_by_zero_diagnostic,
4694
+ left,
4695
+ Type :: IntLiteral ( i64:: from ( bool_value) ) ,
4696
+ op,
4697
+ ) ,
4669
4698
4670
4699
( Type :: Tuple ( lhs) , Type :: Tuple ( rhs) , ast:: Operator :: Add ) => {
4671
4700
// Note: this only works on heterogeneous tuples.
0 commit comments