@@ -513,19 +513,8 @@ pub fn infix_operand_type_rules(
513
513
514
514
use Type :: * ;
515
515
match ( lhs_type, rhs_type) {
516
- ( Integer ( comptime_x, sign_x, bit_width_x) , Integer ( comptime_y, sign_y, bit_width_y) ) => {
517
- if sign_x != sign_y {
518
- return Err ( make_error ( format ! ( "Integers must have the same signedness LHS is {sign_x:?}, RHS is {sign_y:?} " ) ) )
519
- }
520
- if bit_width_x != bit_width_y {
521
- return Err ( make_error ( format ! ( "Integers must have the same bit width LHS is {bit_width_x}, RHS is {bit_width_y} " ) ) )
522
- }
523
- let comptime = comptime_x. and ( comptime_y, op. location . span ) ;
524
- Ok ( Integer ( comptime, * sign_x, * bit_width_x) )
525
- }
526
- ( Integer ( ..) , FieldElement ( ..) ) | ( FieldElement ( ..) , Integer ( ..) ) => {
527
- Err ( make_error ( "Cannot use an integer and a Field in a binary operation, try converting the Field into an integer" . to_string ( ) ) )
528
- }
516
+ // Matches on PolymorphicInteger and TypeVariable must be first so that we follow any type
517
+ // bindings.
529
518
( PolymorphicInteger ( comptime, int) , other)
530
519
| ( other, PolymorphicInteger ( comptime, int) ) => {
531
520
if let TypeBinding :: Bound ( binding) = & * int. borrow ( ) {
@@ -555,6 +544,32 @@ pub fn infix_operand_type_rules(
555
544
Err ( make_error ( format ! ( "Types in a binary operation should match, but found {lhs_type} and {rhs_type}" ) ) )
556
545
}
557
546
}
547
+ ( TypeVariable ( var) , other)
548
+ | ( other, TypeVariable ( var) ) => {
549
+ if let TypeBinding :: Bound ( binding) = & * var. borrow ( ) {
550
+ return infix_operand_type_rules ( binding, op, other, span, interner, errors) ;
551
+ }
552
+
553
+ let comptime = CompTime :: No ( None ) ;
554
+ if other. try_bind_to_polymorphic_int ( var, & comptime, true , op. location . span ) . is_ok ( ) || other == & Type :: Error {
555
+ Ok ( other. clone ( ) )
556
+ } else {
557
+ Err ( make_error ( format ! ( "Types in a binary operation should match, but found {lhs_type} and {rhs_type}" ) ) )
558
+ }
559
+ }
560
+ ( Integer ( comptime_x, sign_x, bit_width_x) , Integer ( comptime_y, sign_y, bit_width_y) ) => {
561
+ if sign_x != sign_y {
562
+ return Err ( make_error ( format ! ( "Integers must have the same signedness LHS is {sign_x:?}, RHS is {sign_y:?} " ) ) )
563
+ }
564
+ if bit_width_x != bit_width_y {
565
+ return Err ( make_error ( format ! ( "Integers must have the same bit width LHS is {bit_width_x}, RHS is {bit_width_y} " ) ) )
566
+ }
567
+ let comptime = comptime_x. and ( comptime_y, op. location . span ) ;
568
+ Ok ( Integer ( comptime, * sign_x, * bit_width_x) )
569
+ }
570
+ ( Integer ( ..) , FieldElement ( ..) ) | ( FieldElement ( ..) , Integer ( ..) ) => {
571
+ Err ( make_error ( "Cannot use an integer and a Field in a binary operation, try converting the Field into an integer" . to_string ( ) ) )
572
+ }
558
573
( Integer ( ..) , typ) | ( typ, Integer ( ..) ) => {
559
574
Err ( make_error ( format ! ( "Integer cannot be used with type {typ}" ) ) )
560
575
}
@@ -578,20 +593,6 @@ pub fn infix_operand_type_rules(
578
593
579
594
( Bool ( comptime_x) , Bool ( comptime_y) ) => Ok ( Bool ( comptime_x. and ( comptime_y, op. location . span ) ) ) ,
580
595
581
- ( TypeVariable ( var) , other)
582
- | ( other, TypeVariable ( var) ) => {
583
- if let TypeBinding :: Bound ( binding) = & * var. borrow ( ) {
584
- return infix_operand_type_rules ( binding, op, other, span, interner, errors) ;
585
- }
586
-
587
- let comptime = CompTime :: No ( None ) ;
588
- if other. try_bind_to_polymorphic_int ( var, & comptime, true , op. location . span ) . is_ok ( ) || other == & Type :: Error {
589
- Ok ( other. clone ( ) )
590
- } else {
591
- Err ( make_error ( format ! ( "Types in a binary operation should match, but found {lhs_type} and {rhs_type}" ) ) )
592
- }
593
- }
594
-
595
596
( lhs, rhs) => Err ( make_error ( format ! ( "Unsupported types for binary operation: {lhs} and {rhs}" ) ) ) ,
596
597
}
597
598
}
@@ -722,6 +723,32 @@ pub fn comparator_operand_type_rules(
722
723
use crate :: BinaryOpKind :: { Equal , NotEqual } ;
723
724
use Type :: * ;
724
725
match ( lhs_type, rhs_type) {
726
+ // Matches on PolymorphicInteger and TypeVariable must be first to follow any type
727
+ // bindings.
728
+ ( PolymorphicInteger ( comptime, int) , other)
729
+ | ( other, PolymorphicInteger ( comptime, int) ) => {
730
+ if let TypeBinding :: Bound ( binding) = & * int. borrow ( ) {
731
+ return comparator_operand_type_rules ( other, binding, op, errors) ;
732
+ }
733
+ if other. try_bind_to_polymorphic_int ( int, comptime, true , op. location . span ) . is_ok ( ) || other == & Type :: Error {
734
+ Ok ( Bool ( comptime. clone ( ) ) )
735
+ } else {
736
+ Err ( format ! ( "Types in a binary operation should match, but found {lhs_type} and {rhs_type}" ) )
737
+ }
738
+ }
739
+ ( TypeVariable ( var) , other)
740
+ | ( other, TypeVariable ( var) ) => {
741
+ if let TypeBinding :: Bound ( binding) = & * var. borrow ( ) {
742
+ return comparator_operand_type_rules ( binding, other, op, errors) ;
743
+ }
744
+
745
+ let comptime = CompTime :: No ( None ) ;
746
+ if other. try_bind_to_polymorphic_int ( var, & comptime, true , op. location . span ) . is_ok ( ) || other == & Type :: Error {
747
+ Ok ( other. clone ( ) )
748
+ } else {
749
+ Err ( format ! ( "Types in a binary operation should match, but found {lhs_type} and {rhs_type}" ) )
750
+ }
751
+ }
725
752
( Integer ( comptime_x, sign_x, bit_width_x) , Integer ( comptime_y, sign_y, bit_width_y) ) => {
726
753
if sign_x != sign_y {
727
754
return Err ( format ! ( "Integers must have the same signedness LHS is {sign_x:?}, RHS is {sign_y:?} " ) )
@@ -735,17 +762,6 @@ pub fn comparator_operand_type_rules(
735
762
( Integer ( ..) , FieldElement ( ..) ) | ( FieldElement ( ..) , Integer ( ..) ) => {
736
763
Err ( "Cannot use an integer and a Field in a binary operation, try converting the Field into an integer first" . to_string ( ) )
737
764
}
738
- ( PolymorphicInteger ( comptime, int) , other)
739
- | ( other, PolymorphicInteger ( comptime, int) ) => {
740
- if let TypeBinding :: Bound ( binding) = & * int. borrow ( ) {
741
- return comparator_operand_type_rules ( other, binding, op, errors) ;
742
- }
743
- if other. try_bind_to_polymorphic_int ( int, comptime, true , op. location . span ) . is_ok ( ) || other == & Type :: Error {
744
- Ok ( Bool ( comptime. clone ( ) ) )
745
- } else {
746
- Err ( format ! ( "Types in a binary operation should match, but found {lhs_type} and {rhs_type}" ) )
747
- }
748
- }
749
765
( Integer ( ..) , typ) | ( typ, Integer ( ..) ) => {
750
766
Err ( format ! ( "Integer cannot be used with type {typ}" ) )
751
767
}
@@ -795,19 +811,6 @@ pub fn comparator_operand_type_rules(
795
811
}
796
812
Err ( format ! ( "Unsupported types for comparison: {name_a} and {name_b}" ) )
797
813
}
798
- ( TypeVariable ( var) , other)
799
- | ( other, TypeVariable ( var) ) => {
800
- if let TypeBinding :: Bound ( binding) = & * var. borrow ( ) {
801
- return comparator_operand_type_rules ( binding, other, op, errors) ;
802
- }
803
-
804
- let comptime = CompTime :: No ( None ) ;
805
- if other. try_bind_to_polymorphic_int ( var, & comptime, true , op. location . span ) . is_ok ( ) || other == & Type :: Error {
806
- Ok ( other. clone ( ) )
807
- } else {
808
- Err ( format ! ( "Types in a binary operation should match, but found {lhs_type} and {rhs_type}" ) )
809
- }
810
- }
811
814
( String ( x_size) , String ( y_size) ) => {
812
815
x_size. unify ( y_size, op. location . span , errors, || {
813
816
TypeCheckError :: Unstructured {
0 commit comments