@@ -11,6 +11,7 @@ use rustc_infer::traits::ObligationCauseCode;
1111use rustc_middle:: ty:: adjustment:: {
1212 Adjust , Adjustment , AllowTwoPhase , AutoBorrow , AutoBorrowMutability ,
1313} ;
14+ use rustc_middle:: ty:: print:: with_no_trimmed_paths;
1415use rustc_middle:: ty:: {
1516 self , Ty , TyCtxt , TypeFolder , TypeSuperFoldable , TypeSuperVisitable , TypeVisitable , TypeVisitor ,
1617} ;
@@ -313,7 +314,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
313314 // error types are considered "builtin"
314315 Err ( _) if lhs_ty. references_error ( ) || rhs_ty. references_error ( ) => self . tcx . ty_error ( ) ,
315316 Err ( errors) => {
316- let ( mut err, missing_trait, use_output) = match is_assign {
317+ let ( _, item) = lang_item_for_op ( self . tcx , Op :: Binary ( op, is_assign) , op. span ) ;
318+ let missing_trait =
319+ item. map ( |def_id| with_no_trimmed_paths ! ( self . tcx. def_path_str( def_id) ) ) ;
320+ let ( mut err, use_output) = match is_assign {
317321 IsAssign :: Yes => {
318322 let mut err = struct_span_err ! (
319323 self . tcx. sess,
@@ -327,112 +331,60 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
327331 lhs_expr. span ,
328332 format ! ( "cannot use `{}=` on type `{}`" , op. node. as_str( ) , lhs_ty) ,
329333 ) ;
330- let missing_trait = match op. node {
331- hir:: BinOpKind :: Add => Some ( "std::ops::AddAssign" ) ,
332- hir:: BinOpKind :: Sub => Some ( "std::ops::SubAssign" ) ,
333- hir:: BinOpKind :: Mul => Some ( "std::ops::MulAssign" ) ,
334- hir:: BinOpKind :: Div => Some ( "std::ops::DivAssign" ) ,
335- hir:: BinOpKind :: Rem => Some ( "std::ops::RemAssign" ) ,
336- hir:: BinOpKind :: BitAnd => Some ( "std::ops::BitAndAssign" ) ,
337- hir:: BinOpKind :: BitXor => Some ( "std::ops::BitXorAssign" ) ,
338- hir:: BinOpKind :: BitOr => Some ( "std::ops::BitOrAssign" ) ,
339- hir:: BinOpKind :: Shl => Some ( "std::ops::ShlAssign" ) ,
340- hir:: BinOpKind :: Shr => Some ( "std::ops::ShrAssign" ) ,
341- _ => None ,
342- } ;
343334 self . note_unmet_impls_on_type ( & mut err, errors) ;
344- ( err, missing_trait , false )
335+ ( err, false )
345336 }
346337 IsAssign :: No => {
347- let ( message, missing_trait, use_output) = match op. node {
348- hir:: BinOpKind :: Add => (
349- format ! ( "cannot add `{rhs_ty}` to `{lhs_ty}`" ) ,
350- Some ( "std::ops::Add" ) ,
351- true ,
352- ) ,
353- hir:: BinOpKind :: Sub => (
354- format ! ( "cannot subtract `{rhs_ty}` from `{lhs_ty}`" ) ,
355- Some ( "std::ops::Sub" ) ,
356- true ,
357- ) ,
358- hir:: BinOpKind :: Mul => (
359- format ! ( "cannot multiply `{lhs_ty}` by `{rhs_ty}`" ) ,
360- Some ( "std::ops::Mul" ) ,
361- true ,
362- ) ,
363- hir:: BinOpKind :: Div => (
364- format ! ( "cannot divide `{lhs_ty}` by `{rhs_ty}`" ) ,
365- Some ( "std::ops::Div" ) ,
366- true ,
367- ) ,
368- hir:: BinOpKind :: Rem => (
369- format ! ( "cannot mod `{lhs_ty}` by `{rhs_ty}`" ) ,
370- Some ( "std::ops::Rem" ) ,
371- true ,
372- ) ,
373- hir:: BinOpKind :: BitAnd => (
374- format ! ( "no implementation for `{lhs_ty} & {rhs_ty}`" ) ,
375- Some ( "std::ops::BitAnd" ) ,
376- true ,
377- ) ,
378- hir:: BinOpKind :: BitXor => (
379- format ! ( "no implementation for `{lhs_ty} ^ {rhs_ty}`" ) ,
380- Some ( "std::ops::BitXor" ) ,
381- true ,
382- ) ,
383- hir:: BinOpKind :: BitOr => (
384- format ! ( "no implementation for `{lhs_ty} | {rhs_ty}`" ) ,
385- Some ( "std::ops::BitOr" ) ,
386- true ,
387- ) ,
388- hir:: BinOpKind :: Shl => (
389- format ! ( "no implementation for `{lhs_ty} << {rhs_ty}`" ) ,
390- Some ( "std::ops::Shl" ) ,
391- true ,
392- ) ,
393- hir:: BinOpKind :: Shr => (
394- format ! ( "no implementation for `{lhs_ty} >> {rhs_ty}`" ) ,
395- Some ( "std::ops::Shr" ) ,
396- true ,
397- ) ,
398- hir:: BinOpKind :: Eq | hir:: BinOpKind :: Ne => (
399- format ! (
400- "binary operation `{}` cannot be applied to type `{}`" ,
401- op. node. as_str( ) ,
402- lhs_ty
403- ) ,
404- Some ( "std::cmp::PartialEq" ) ,
405- false ,
406- ) ,
407- hir:: BinOpKind :: Lt
408- | hir:: BinOpKind :: Le
409- | hir:: BinOpKind :: Gt
410- | hir:: BinOpKind :: Ge => (
411- format ! (
412- "binary operation `{}` cannot be applied to type `{}`" ,
413- op. node. as_str( ) ,
414- lhs_ty
415- ) ,
416- Some ( "std::cmp::PartialOrd" ) ,
417- false ,
418- ) ,
419- _ => (
420- format ! (
421- "binary operation `{}` cannot be applied to type `{}`" ,
422- op. node. as_str( ) ,
423- lhs_ty
424- ) ,
425- None ,
426- false ,
338+ let message = match op. node {
339+ hir:: BinOpKind :: Add => {
340+ format ! ( "cannot add `{rhs_ty}` to `{lhs_ty}`" )
341+ }
342+ hir:: BinOpKind :: Sub => {
343+ format ! ( "cannot subtract `{rhs_ty}` from `{lhs_ty}`" )
344+ }
345+ hir:: BinOpKind :: Mul => {
346+ format ! ( "cannot multiply `{lhs_ty}` by `{rhs_ty}`" )
347+ }
348+ hir:: BinOpKind :: Div => {
349+ format ! ( "cannot divide `{lhs_ty}` by `{rhs_ty}`" )
350+ }
351+ hir:: BinOpKind :: Rem => {
352+ format ! ( "cannot mod `{lhs_ty}` by `{rhs_ty}`" )
353+ }
354+ hir:: BinOpKind :: BitAnd => {
355+ format ! ( "no implementation for `{lhs_ty} & {rhs_ty}`" )
356+ }
357+ hir:: BinOpKind :: BitXor => {
358+ format ! ( "no implementation for `{lhs_ty} ^ {rhs_ty}`" )
359+ }
360+ hir:: BinOpKind :: BitOr => {
361+ format ! ( "no implementation for `{lhs_ty} | {rhs_ty}`" )
362+ }
363+ hir:: BinOpKind :: Shl => {
364+ format ! ( "no implementation for `{lhs_ty} << {rhs_ty}`" )
365+ }
366+ hir:: BinOpKind :: Shr => {
367+ format ! ( "no implementation for `{lhs_ty} >> {rhs_ty}`" )
368+ }
369+ _ => format ! (
370+ "binary operation `{}` cannot be applied to type `{}`" ,
371+ op. node. as_str( ) ,
372+ lhs_ty
427373 ) ,
428374 } ;
375+ let use_output = item. map_or ( false , |def_id| {
376+ self . tcx . associated_item_def_ids ( def_id) . iter ( ) . any ( |item_def_id| {
377+ self . tcx . opt_associated_item ( * item_def_id) . unwrap ( ) . name
378+ == sym:: Output
379+ } )
380+ } ) ;
429381 let mut err = struct_span_err ! ( self . tcx. sess, op. span, E0369 , "{message}" ) ;
430382 if !lhs_expr. span . eq ( & rhs_expr. span ) {
431383 err. span_label ( lhs_expr. span , lhs_ty. to_string ( ) ) ;
432384 err. span_label ( rhs_expr. span , rhs_ty. to_string ( ) ) ;
433385 }
434386 self . note_unmet_impls_on_type ( & mut err, errors) ;
435- ( err, missing_trait , use_output)
387+ ( err, use_output)
436388 }
437389 } ;
438390
@@ -773,64 +725,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
773725 op : Op ,
774726 expected : Expectation < ' tcx > ,
775727 ) -> Result < MethodCallee < ' tcx > , Vec < FulfillmentError < ' tcx > > > {
776- let lang = self . tcx . lang_items ( ) ;
777-
778728 let span = match op {
779729 Op :: Binary ( op, _) => op. span ,
780730 Op :: Unary ( _, span) => span,
781731 } ;
782- let ( opname, trait_did) = if let Op :: Binary ( op, IsAssign :: Yes ) = op {
783- match op. node {
784- hir:: BinOpKind :: Add => ( sym:: add_assign, lang. add_assign_trait ( ) ) ,
785- hir:: BinOpKind :: Sub => ( sym:: sub_assign, lang. sub_assign_trait ( ) ) ,
786- hir:: BinOpKind :: Mul => ( sym:: mul_assign, lang. mul_assign_trait ( ) ) ,
787- hir:: BinOpKind :: Div => ( sym:: div_assign, lang. div_assign_trait ( ) ) ,
788- hir:: BinOpKind :: Rem => ( sym:: rem_assign, lang. rem_assign_trait ( ) ) ,
789- hir:: BinOpKind :: BitXor => ( sym:: bitxor_assign, lang. bitxor_assign_trait ( ) ) ,
790- hir:: BinOpKind :: BitAnd => ( sym:: bitand_assign, lang. bitand_assign_trait ( ) ) ,
791- hir:: BinOpKind :: BitOr => ( sym:: bitor_assign, lang. bitor_assign_trait ( ) ) ,
792- hir:: BinOpKind :: Shl => ( sym:: shl_assign, lang. shl_assign_trait ( ) ) ,
793- hir:: BinOpKind :: Shr => ( sym:: shr_assign, lang. shr_assign_trait ( ) ) ,
794- hir:: BinOpKind :: Lt
795- | hir:: BinOpKind :: Le
796- | hir:: BinOpKind :: Ge
797- | hir:: BinOpKind :: Gt
798- | hir:: BinOpKind :: Eq
799- | hir:: BinOpKind :: Ne
800- | hir:: BinOpKind :: And
801- | hir:: BinOpKind :: Or => {
802- span_bug ! ( span, "impossible assignment operation: {}=" , op. node. as_str( ) )
803- }
804- }
805- } else if let Op :: Binary ( op, IsAssign :: No ) = op {
806- match op. node {
807- hir:: BinOpKind :: Add => ( sym:: add, lang. add_trait ( ) ) ,
808- hir:: BinOpKind :: Sub => ( sym:: sub, lang. sub_trait ( ) ) ,
809- hir:: BinOpKind :: Mul => ( sym:: mul, lang. mul_trait ( ) ) ,
810- hir:: BinOpKind :: Div => ( sym:: div, lang. div_trait ( ) ) ,
811- hir:: BinOpKind :: Rem => ( sym:: rem, lang. rem_trait ( ) ) ,
812- hir:: BinOpKind :: BitXor => ( sym:: bitxor, lang. bitxor_trait ( ) ) ,
813- hir:: BinOpKind :: BitAnd => ( sym:: bitand, lang. bitand_trait ( ) ) ,
814- hir:: BinOpKind :: BitOr => ( sym:: bitor, lang. bitor_trait ( ) ) ,
815- hir:: BinOpKind :: Shl => ( sym:: shl, lang. shl_trait ( ) ) ,
816- hir:: BinOpKind :: Shr => ( sym:: shr, lang. shr_trait ( ) ) ,
817- hir:: BinOpKind :: Lt => ( sym:: lt, lang. partial_ord_trait ( ) ) ,
818- hir:: BinOpKind :: Le => ( sym:: le, lang. partial_ord_trait ( ) ) ,
819- hir:: BinOpKind :: Ge => ( sym:: ge, lang. partial_ord_trait ( ) ) ,
820- hir:: BinOpKind :: Gt => ( sym:: gt, lang. partial_ord_trait ( ) ) ,
821- hir:: BinOpKind :: Eq => ( sym:: eq, lang. eq_trait ( ) ) ,
822- hir:: BinOpKind :: Ne => ( sym:: ne, lang. eq_trait ( ) ) ,
823- hir:: BinOpKind :: And | hir:: BinOpKind :: Or => {
824- span_bug ! ( span, "&& and || are not overloadable" )
825- }
826- }
827- } else if let Op :: Unary ( hir:: UnOp :: Not , _) = op {
828- ( sym:: not, lang. not_trait ( ) )
829- } else if let Op :: Unary ( hir:: UnOp :: Neg , _) = op {
830- ( sym:: neg, lang. neg_trait ( ) )
831- } else {
832- bug ! ( "lookup_op_method: op not supported: {:?}" , op)
833- } ;
732+ let ( opname, trait_did) = lang_item_for_op ( self . tcx , op, span) ;
834733
835734 debug ! (
836735 "lookup_op_method(lhs_ty={:?}, op={:?}, opname={:?}, trait_did={:?})" ,
@@ -891,6 +790,66 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
891790 }
892791}
893792
793+ fn lang_item_for_op (
794+ tcx : TyCtxt < ' _ > ,
795+ op : Op ,
796+ span : Span ,
797+ ) -> ( rustc_span:: Symbol , Option < hir:: def_id:: DefId > ) {
798+ let lang = tcx. lang_items ( ) ;
799+ if let Op :: Binary ( op, IsAssign :: Yes ) = op {
800+ match op. node {
801+ hir:: BinOpKind :: Add => ( sym:: add_assign, lang. add_assign_trait ( ) ) ,
802+ hir:: BinOpKind :: Sub => ( sym:: sub_assign, lang. sub_assign_trait ( ) ) ,
803+ hir:: BinOpKind :: Mul => ( sym:: mul_assign, lang. mul_assign_trait ( ) ) ,
804+ hir:: BinOpKind :: Div => ( sym:: div_assign, lang. div_assign_trait ( ) ) ,
805+ hir:: BinOpKind :: Rem => ( sym:: rem_assign, lang. rem_assign_trait ( ) ) ,
806+ hir:: BinOpKind :: BitXor => ( sym:: bitxor_assign, lang. bitxor_assign_trait ( ) ) ,
807+ hir:: BinOpKind :: BitAnd => ( sym:: bitand_assign, lang. bitand_assign_trait ( ) ) ,
808+ hir:: BinOpKind :: BitOr => ( sym:: bitor_assign, lang. bitor_assign_trait ( ) ) ,
809+ hir:: BinOpKind :: Shl => ( sym:: shl_assign, lang. shl_assign_trait ( ) ) ,
810+ hir:: BinOpKind :: Shr => ( sym:: shr_assign, lang. shr_assign_trait ( ) ) ,
811+ hir:: BinOpKind :: Lt
812+ | hir:: BinOpKind :: Le
813+ | hir:: BinOpKind :: Ge
814+ | hir:: BinOpKind :: Gt
815+ | hir:: BinOpKind :: Eq
816+ | hir:: BinOpKind :: Ne
817+ | hir:: BinOpKind :: And
818+ | hir:: BinOpKind :: Or => {
819+ span_bug ! ( span, "impossible assignment operation: {}=" , op. node. as_str( ) )
820+ }
821+ }
822+ } else if let Op :: Binary ( op, IsAssign :: No ) = op {
823+ match op. node {
824+ hir:: BinOpKind :: Add => ( sym:: add, lang. add_trait ( ) ) ,
825+ hir:: BinOpKind :: Sub => ( sym:: sub, lang. sub_trait ( ) ) ,
826+ hir:: BinOpKind :: Mul => ( sym:: mul, lang. mul_trait ( ) ) ,
827+ hir:: BinOpKind :: Div => ( sym:: div, lang. div_trait ( ) ) ,
828+ hir:: BinOpKind :: Rem => ( sym:: rem, lang. rem_trait ( ) ) ,
829+ hir:: BinOpKind :: BitXor => ( sym:: bitxor, lang. bitxor_trait ( ) ) ,
830+ hir:: BinOpKind :: BitAnd => ( sym:: bitand, lang. bitand_trait ( ) ) ,
831+ hir:: BinOpKind :: BitOr => ( sym:: bitor, lang. bitor_trait ( ) ) ,
832+ hir:: BinOpKind :: Shl => ( sym:: shl, lang. shl_trait ( ) ) ,
833+ hir:: BinOpKind :: Shr => ( sym:: shr, lang. shr_trait ( ) ) ,
834+ hir:: BinOpKind :: Lt => ( sym:: lt, lang. partial_ord_trait ( ) ) ,
835+ hir:: BinOpKind :: Le => ( sym:: le, lang. partial_ord_trait ( ) ) ,
836+ hir:: BinOpKind :: Ge => ( sym:: ge, lang. partial_ord_trait ( ) ) ,
837+ hir:: BinOpKind :: Gt => ( sym:: gt, lang. partial_ord_trait ( ) ) ,
838+ hir:: BinOpKind :: Eq => ( sym:: eq, lang. eq_trait ( ) ) ,
839+ hir:: BinOpKind :: Ne => ( sym:: ne, lang. eq_trait ( ) ) ,
840+ hir:: BinOpKind :: And | hir:: BinOpKind :: Or => {
841+ span_bug ! ( span, "&& and || are not overloadable" )
842+ }
843+ }
844+ } else if let Op :: Unary ( hir:: UnOp :: Not , _) = op {
845+ ( sym:: not, lang. not_trait ( ) )
846+ } else if let Op :: Unary ( hir:: UnOp :: Neg , _) = op {
847+ ( sym:: neg, lang. neg_trait ( ) )
848+ } else {
849+ bug ! ( "lookup_op_method: op not supported: {:?}" , op)
850+ }
851+ }
852+
894853// Binary operator categories. These categories summarize the behavior
895854// with respect to the builtin operations supported.
896855enum BinOpCategory {
0 commit comments