11use super :: FnCtxt ;
22
3- use crate :: errors:: {
4- AddReturnTypeSuggestion , ExpectedReturnTypeLabel , SuggestBoxing , SuggestConvertViaMethod ,
5- } ;
3+ use crate :: errors;
64use crate :: fluent_generated as fluent;
75use crate :: method:: probe:: { IsSuggestion , Mode , ProbeScope } ;
86use rustc_ast:: util:: parser:: { ExprPrecedence , PREC_POSTFIX } ;
@@ -434,7 +432,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
434432 // FIXME: This could/should be extended to suggest `as_mut` and `as_deref_mut`,
435433 // but those checks need to be a bit more delicate and the benefit is diminishing.
436434 if self . can_eq ( self . param_env , found_ty_inner, peeled) && error_tys_equate_as_ref {
437- err. subdiagnostic ( SuggestConvertViaMethod {
435+ err. subdiagnostic ( errors :: SuggestConvertViaMethod {
438436 span : expr. span . shrink_to_hi ( ) ,
439437 sugg : ".as_ref()" ,
440438 expected,
@@ -447,7 +445,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
447445 && self . can_eq ( self . param_env , deref_ty, peeled)
448446 && error_tys_equate_as_ref
449447 {
450- err. subdiagnostic ( SuggestConvertViaMethod {
448+ err. subdiagnostic ( errors :: SuggestConvertViaMethod {
451449 span : expr. span . shrink_to_hi ( ) ,
452450 sugg : ".as_deref()" ,
453451 expected,
@@ -521,17 +519,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
521519 if self . can_coerce ( Ty :: new_box ( self . tcx , found) , expected) {
522520 let suggest_boxing = match found. kind ( ) {
523521 ty:: Tuple ( tuple) if tuple. is_empty ( ) => {
524- SuggestBoxing :: Unit { start : span. shrink_to_lo ( ) , end : span }
522+ errors :: SuggestBoxing :: Unit { start : span. shrink_to_lo ( ) , end : span }
525523 }
526524 ty:: Generator ( def_id, ..)
527525 if matches ! (
528526 self . tcx. generator_kind( def_id) ,
529527 Some ( GeneratorKind :: Async ( AsyncGeneratorKind :: Closure ) )
530528 ) =>
531529 {
532- SuggestBoxing :: AsyncBody
530+ errors :: SuggestBoxing :: AsyncBody
533531 }
534- _ => SuggestBoxing :: Other { start : span. shrink_to_lo ( ) , end : span. shrink_to_hi ( ) } ,
532+ _ => errors:: SuggestBoxing :: Other {
533+ start : span. shrink_to_lo ( ) ,
534+ end : span. shrink_to_hi ( ) ,
535+ } ,
535536 } ;
536537 err. subdiagnostic ( suggest_boxing) ;
537538
@@ -756,23 +757,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
756757 match & fn_decl. output {
757758 & hir:: FnRetTy :: DefaultReturn ( span) if expected. is_unit ( ) && !can_suggest => {
758759 // `fn main()` must return `()`, do not suggest changing return type
759- err. subdiagnostic ( ExpectedReturnTypeLabel :: Unit { span } ) ;
760+ err. subdiagnostic ( errors :: ExpectedReturnTypeLabel :: Unit { span } ) ;
760761 return true ;
761762 }
762763 & hir:: FnRetTy :: DefaultReturn ( span) if expected. is_unit ( ) => {
763764 if let Some ( found) = found. make_suggestable ( self . tcx , false ) {
764- err. subdiagnostic ( AddReturnTypeSuggestion :: Add { span, found : found. to_string ( ) } ) ;
765+ err. subdiagnostic ( errors :: AddReturnTypeSuggestion :: Add { span, found : found. to_string ( ) } ) ;
765766 return true ;
766767 } else if let ty:: Closure ( _, args) = found. kind ( )
767768 // FIXME(compiler-errors): Get better at printing binders...
768769 && let closure = args. as_closure ( )
769770 && closure. sig ( ) . is_suggestable ( self . tcx , false )
770771 {
771- err. subdiagnostic ( AddReturnTypeSuggestion :: Add { span, found : closure. print_as_impl_trait ( ) . to_string ( ) } ) ;
772+ err. subdiagnostic ( errors :: AddReturnTypeSuggestion :: Add { span, found : closure. print_as_impl_trait ( ) . to_string ( ) } ) ;
772773 return true ;
773774 } else {
774775 // FIXME: if `found` could be `impl Iterator` we should suggest that.
775- err. subdiagnostic ( AddReturnTypeSuggestion :: MissingHere { span } ) ;
776+ err. subdiagnostic ( errors :: AddReturnTypeSuggestion :: MissingHere { span } ) ;
776777 return true
777778 }
778779 }
@@ -794,10 +795,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
794795 debug ! ( ?found) ;
795796 if found. is_suggestable ( self . tcx , false ) {
796797 if term. span . is_empty ( ) {
797- err. subdiagnostic ( AddReturnTypeSuggestion :: Add { span, found : found. to_string ( ) } ) ;
798+ err. subdiagnostic ( errors :: AddReturnTypeSuggestion :: Add { span, found : found. to_string ( ) } ) ;
798799 return true ;
799800 } else {
800- err. subdiagnostic ( ExpectedReturnTypeLabel :: Other { span, expected } ) ;
801+ err. subdiagnostic ( errors :: ExpectedReturnTypeLabel :: Other { span, expected } ) ;
801802 }
802803 }
803804 }
@@ -813,7 +814,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
813814 let ty = self . normalize ( span, ty) ;
814815 let ty = self . tcx . erase_late_bound_regions ( ty) ;
815816 if self . can_coerce ( expected, ty) {
816- err. subdiagnostic ( ExpectedReturnTypeLabel :: Other { span, expected } ) ;
817+ err. subdiagnostic ( errors :: ExpectedReturnTypeLabel :: Other { span, expected } ) ;
817818 self . try_suggest_return_impl_trait ( err, expected, ty, fn_id) ;
818819 return true ;
819820 }
@@ -1103,65 +1104,46 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11031104 return false ;
11041105 }
11051106
1106- let mut suggest_copied_cloned_or_as_ref = || {
1107+ if Some ( adt_def. did ( ) ) == self . tcx . get_diagnostic_item ( sym:: Result )
1108+ && self . can_eq ( self . param_env , args. type_at ( 1 ) , expected_args. type_at ( 1 ) )
1109+ || Some ( adt_def. did ( ) ) == self . tcx . get_diagnostic_item ( sym:: Option )
1110+ {
11071111 let expr_inner_ty = args. type_at ( 0 ) ;
11081112 let expected_inner_ty = expected_args. type_at ( 0 ) ;
1109- if let & ty:: Ref ( _, ty, hir:: Mutability :: Not ) = expr_inner_ty. kind ( )
1110- && self . can_eq ( self . param_env , ty, expected_inner_ty)
1111- {
1112- let def_path = self . tcx . def_path_str ( adt_def. did ( ) ) ;
1113- if self . type_is_copy_modulo_regions ( self . param_env , ty) {
1114- diag. span_suggestion_verbose (
1115- expr. span . shrink_to_hi ( ) ,
1116- format ! (
1117- "use `{def_path}::copied` to copy the value inside the `{def_path}`"
1118- ) ,
1119- ".copied()" ,
1120- Applicability :: MachineApplicable ,
1121- ) ;
1122- return true ;
1123- } else if let Some ( expected_ty_expr) = expected_ty_expr {
1124- diag. span_suggestion_verbose (
1125- expected_ty_expr. span . shrink_to_hi ( ) ,
1126- format ! (
1127- "use `{def_path}::as_ref()` to convert `{expected_ty}` to `{expr_ty}`"
1128- ) ,
1129- ".as_ref()" ,
1130- Applicability :: MachineApplicable ,
1131- ) ;
1132- return true ;
1133- } else if let Some ( clone_did) = self . tcx . lang_items ( ) . clone_trait ( )
1134- && rustc_trait_selection:: traits:: type_known_to_meet_bound_modulo_regions (
1135- self ,
1136- self . param_env ,
1137- ty,
1138- clone_did,
1139- )
1113+ if let & ty:: Ref ( _, ty, mutability) = expr_inner_ty. kind ( )
1114+ && self . can_eq ( self . param_env , ty, expected_inner_ty)
11401115 {
1141- diag. span_suggestion_verbose (
1142- expr. span . shrink_to_hi ( ) ,
1143- format ! (
1144- "use `{def_path}::cloned` to clone the value inside the `{def_path}`"
1145- ) ,
1146- ".cloned()" ,
1147- Applicability :: MachineApplicable ,
1148- ) ;
1116+ let def_path = self . tcx . def_path_str ( adt_def. did ( ) ) ;
1117+ let span = expr. span . shrink_to_hi ( ) ;
1118+ let subdiag = if self . type_is_copy_modulo_regions ( self . param_env , ty) {
1119+ errors:: OptionResultRefMismatch :: Copied {
1120+ span, def_path
1121+ }
1122+ } else if let Some ( expected_ty_expr) = expected_ty_expr
1123+ // FIXME: suggest changes to both expressions to convert both to
1124+ // Option/Result<&T>
1125+ && mutability. is_not ( )
1126+ {
1127+ errors:: OptionResultRefMismatch :: AsRef {
1128+ span : expected_ty_expr. span . shrink_to_hi ( ) , expected_ty, expr_ty, def_path
1129+ }
1130+ } else if let Some ( clone_did) = self . tcx . lang_items ( ) . clone_trait ( )
1131+ && rustc_trait_selection:: traits:: type_known_to_meet_bound_modulo_regions (
1132+ self ,
1133+ self . param_env ,
1134+ ty,
1135+ clone_did,
1136+ )
1137+ {
1138+ errors:: OptionResultRefMismatch :: Cloned {
1139+ span, def_path
1140+ }
1141+ } else {
1142+ return false ;
1143+ } ;
1144+ diag. subdiagnostic ( subdiag) ;
11491145 return true ;
11501146 }
1151- }
1152- false
1153- } ;
1154-
1155- if let Some ( result_did) = self . tcx . get_diagnostic_item ( sym:: Result )
1156- && adt_def. did ( ) == result_did
1157- // Check that the error types are equal
1158- && self . can_eq ( self . param_env , args. type_at ( 1 ) , expected_args. type_at ( 1 ) )
1159- {
1160- return suggest_copied_cloned_or_as_ref ( ) ;
1161- } else if let Some ( option_did) = self . tcx . get_diagnostic_item ( sym:: Option )
1162- && adt_def. did ( ) == option_did
1163- {
1164- return suggest_copied_cloned_or_as_ref ( ) ;
11651147 }
11661148
11671149 false
0 commit comments