@@ -10,8 +10,7 @@ use chalk_ir::{
1010} ;
1111use hir_def:: {
1212 expr:: {
13- ArithOp , Array , BinaryOp , ClosureKind , CmpOp , Expr , ExprId , LabelId , Literal , Statement ,
14- UnaryOp ,
13+ ArithOp , Array , BinaryOp , ClosureKind , Expr , ExprId , LabelId , Literal , Statement , UnaryOp ,
1514 } ,
1615 generics:: TypeOrConstParamData ,
1716 path:: { GenericArg , GenericArgs } ,
@@ -1017,11 +1016,21 @@ impl<'a> InferenceContext<'a> {
10171016 let ( trait_, func) = match trait_func {
10181017 Some ( it) => it,
10191018 None => {
1020- let rhs_ty = self . builtin_binary_op_rhs_expectation ( op, lhs_ty. clone ( ) ) ;
1021- let rhs_ty = self . infer_expr_coerce ( rhs, & Expectation :: from_option ( rhs_ty) ) ;
1022- return self
1023- . builtin_binary_op_return_ty ( op, lhs_ty, rhs_ty)
1024- . unwrap_or_else ( || self . err_ty ( ) ) ;
1019+ // HACK: `rhs_ty` is a general inference variable with no clue at all at this
1020+ // point. Passing `lhs_ty` as both operands just to check if `lhs_ty` is a builtin
1021+ // type applicable to `op`.
1022+ let ret_ty = if self . is_builtin_binop ( & lhs_ty, & lhs_ty, op) {
1023+ // Assume both operands are builtin so we can continue inference. No guarantee
1024+ // on the correctness, rustc would complain as necessary lang items don't seem
1025+ // to exist anyway.
1026+ self . enforce_builtin_binop_types ( & lhs_ty, & rhs_ty, op)
1027+ } else {
1028+ self . err_ty ( )
1029+ } ;
1030+
1031+ self . infer_expr_coerce ( rhs, & Expectation :: has_type ( rhs_ty) ) ;
1032+
1033+ return ret_ty;
10251034 }
10261035 } ;
10271036
@@ -1475,97 +1484,6 @@ impl<'a> InferenceContext<'a> {
14751484 indices
14761485 }
14771486
1478- fn builtin_binary_op_return_ty ( & mut self , op : BinaryOp , lhs_ty : Ty , rhs_ty : Ty ) -> Option < Ty > {
1479- let lhs_ty = self . resolve_ty_shallow ( & lhs_ty) ;
1480- let rhs_ty = self . resolve_ty_shallow ( & rhs_ty) ;
1481- match op {
1482- BinaryOp :: LogicOp ( _) | BinaryOp :: CmpOp ( _) => {
1483- Some ( TyKind :: Scalar ( Scalar :: Bool ) . intern ( Interner ) )
1484- }
1485- BinaryOp :: Assignment { .. } => Some ( TyBuilder :: unit ( ) ) ,
1486- BinaryOp :: ArithOp ( ArithOp :: Shl | ArithOp :: Shr ) => {
1487- // all integer combinations are valid here
1488- if matches ! (
1489- lhs_ty. kind( Interner ) ,
1490- TyKind :: Scalar ( Scalar :: Int ( _) | Scalar :: Uint ( _) )
1491- | TyKind :: InferenceVar ( _, TyVariableKind :: Integer )
1492- ) && matches ! (
1493- rhs_ty. kind( Interner ) ,
1494- TyKind :: Scalar ( Scalar :: Int ( _) | Scalar :: Uint ( _) )
1495- | TyKind :: InferenceVar ( _, TyVariableKind :: Integer )
1496- ) {
1497- Some ( lhs_ty)
1498- } else {
1499- None
1500- }
1501- }
1502- BinaryOp :: ArithOp ( _) => match ( lhs_ty. kind ( Interner ) , rhs_ty. kind ( Interner ) ) {
1503- // (int, int) | (uint, uint) | (float, float)
1504- ( TyKind :: Scalar ( Scalar :: Int ( _) ) , TyKind :: Scalar ( Scalar :: Int ( _) ) )
1505- | ( TyKind :: Scalar ( Scalar :: Uint ( _) ) , TyKind :: Scalar ( Scalar :: Uint ( _) ) )
1506- | ( TyKind :: Scalar ( Scalar :: Float ( _) ) , TyKind :: Scalar ( Scalar :: Float ( _) ) ) => {
1507- Some ( rhs_ty)
1508- }
1509- // ({int}, int) | ({int}, uint)
1510- (
1511- TyKind :: InferenceVar ( _, TyVariableKind :: Integer ) ,
1512- TyKind :: Scalar ( Scalar :: Int ( _) | Scalar :: Uint ( _) ) ,
1513- ) => Some ( rhs_ty) ,
1514- // (int, {int}) | (uint, {int})
1515- (
1516- TyKind :: Scalar ( Scalar :: Int ( _) | Scalar :: Uint ( _) ) ,
1517- TyKind :: InferenceVar ( _, TyVariableKind :: Integer ) ,
1518- ) => Some ( lhs_ty) ,
1519- // ({float} | float)
1520- (
1521- TyKind :: InferenceVar ( _, TyVariableKind :: Float ) ,
1522- TyKind :: Scalar ( Scalar :: Float ( _) ) ,
1523- ) => Some ( rhs_ty) ,
1524- // (float, {float})
1525- (
1526- TyKind :: Scalar ( Scalar :: Float ( _) ) ,
1527- TyKind :: InferenceVar ( _, TyVariableKind :: Float ) ,
1528- ) => Some ( lhs_ty) ,
1529- // ({int}, {int}) | ({float}, {float})
1530- (
1531- TyKind :: InferenceVar ( _, TyVariableKind :: Integer ) ,
1532- TyKind :: InferenceVar ( _, TyVariableKind :: Integer ) ,
1533- )
1534- | (
1535- TyKind :: InferenceVar ( _, TyVariableKind :: Float ) ,
1536- TyKind :: InferenceVar ( _, TyVariableKind :: Float ) ,
1537- ) => Some ( rhs_ty) ,
1538- _ => None ,
1539- } ,
1540- }
1541- }
1542-
1543- fn builtin_binary_op_rhs_expectation ( & mut self , op : BinaryOp , lhs_ty : Ty ) -> Option < Ty > {
1544- Some ( match op {
1545- BinaryOp :: LogicOp ( ..) => TyKind :: Scalar ( Scalar :: Bool ) . intern ( Interner ) ,
1546- BinaryOp :: Assignment { op : None } => {
1547- stdx:: never!( "Simple assignment operator is not binary op." ) ;
1548- return None ;
1549- }
1550- BinaryOp :: CmpOp ( CmpOp :: Eq { .. } ) => match self
1551- . resolve_ty_shallow ( & lhs_ty)
1552- . kind ( Interner )
1553- {
1554- TyKind :: Scalar ( _) | TyKind :: Str => lhs_ty,
1555- TyKind :: InferenceVar ( _, TyVariableKind :: Integer | TyVariableKind :: Float ) => lhs_ty,
1556- _ => return None ,
1557- } ,
1558- BinaryOp :: ArithOp ( ArithOp :: Shl | ArithOp :: Shr ) => return None ,
1559- BinaryOp :: CmpOp ( CmpOp :: Ord { .. } )
1560- | BinaryOp :: Assignment { op : Some ( _) }
1561- | BinaryOp :: ArithOp ( _) => match self . resolve_ty_shallow ( & lhs_ty) . kind ( Interner ) {
1562- TyKind :: Scalar ( Scalar :: Int ( _) | Scalar :: Uint ( _) | Scalar :: Float ( _) ) => lhs_ty,
1563- TyKind :: InferenceVar ( _, TyVariableKind :: Integer | TyVariableKind :: Float ) => lhs_ty,
1564- _ => return None ,
1565- } ,
1566- } )
1567- }
1568-
15691487 /// Dereferences a single level of immutable referencing.
15701488 fn deref_ty_if_possible ( & mut self , ty : & Ty ) -> Ty {
15711489 let ty = self . resolve_ty_shallow ( ty) ;
0 commit comments