@@ -11,6 +11,7 @@ use rustc_infer::traits::ObligationCauseCode;
11
11
use rustc_middle:: ty:: adjustment:: {
12
12
Adjust , Adjustment , AllowTwoPhase , AutoBorrow , AutoBorrowMutability ,
13
13
} ;
14
+ use rustc_middle:: ty:: print:: with_no_trimmed_paths;
14
15
use rustc_middle:: ty:: {
15
16
self , Ty , TyCtxt , TypeFolder , TypeSuperFoldable , TypeSuperVisitable , TypeVisitable , TypeVisitor ,
16
17
} ;
@@ -313,7 +314,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
313
314
// error types are considered "builtin"
314
315
Err ( _) if lhs_ty. references_error ( ) || rhs_ty. references_error ( ) => self . tcx . ty_error ( ) ,
315
316
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 {
317
321
IsAssign :: Yes => {
318
322
let mut err = struct_span_err ! (
319
323
self . tcx. sess,
@@ -327,112 +331,60 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
327
331
lhs_expr. span ,
328
332
format ! ( "cannot use `{}=` on type `{}`" , op. node. as_str( ) , lhs_ty) ,
329
333
) ;
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
- } ;
343
334
self . note_unmet_impls_on_type ( & mut err, errors) ;
344
- ( err, missing_trait , false )
335
+ ( err, false )
345
336
}
346
337
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
427
373
) ,
428
374
} ;
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
+ } ) ;
429
381
let mut err = struct_span_err ! ( self . tcx. sess, op. span, E0369 , "{message}" ) ;
430
382
if !lhs_expr. span . eq ( & rhs_expr. span ) {
431
383
err. span_label ( lhs_expr. span , lhs_ty. to_string ( ) ) ;
432
384
err. span_label ( rhs_expr. span , rhs_ty. to_string ( ) ) ;
433
385
}
434
386
self . note_unmet_impls_on_type ( & mut err, errors) ;
435
- ( err, missing_trait , use_output)
387
+ ( err, use_output)
436
388
}
437
389
} ;
438
390
@@ -773,64 +725,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
773
725
op : Op ,
774
726
expected : Expectation < ' tcx > ,
775
727
) -> Result < MethodCallee < ' tcx > , Vec < FulfillmentError < ' tcx > > > {
776
- let lang = self . tcx . lang_items ( ) ;
777
-
778
728
let span = match op {
779
729
Op :: Binary ( op, _) => op. span ,
780
730
Op :: Unary ( _, span) => span,
781
731
} ;
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) ;
834
733
835
734
debug ! (
836
735
"lookup_op_method(lhs_ty={:?}, op={:?}, opname={:?}, trait_did={:?})" ,
@@ -891,6 +790,66 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
891
790
}
892
791
}
893
792
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
+
894
853
// Binary operator categories. These categories summarize the behavior
895
854
// with respect to the builtin operations supported.
896
855
enum BinOpCategory {
0 commit comments