1
1
use super :: FnCtxt ;
2
2
3
- use crate :: errors:: {
4
- AddReturnTypeSuggestion , ExpectedReturnTypeLabel , SuggestBoxing , SuggestConvertViaMethod ,
5
- } ;
3
+ use crate :: errors;
6
4
use crate :: fluent_generated as fluent;
7
5
use crate :: method:: probe:: { IsSuggestion , Mode , ProbeScope } ;
8
6
use rustc_ast:: util:: parser:: { ExprPrecedence , PREC_POSTFIX } ;
@@ -434,7 +432,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
434
432
// FIXME: This could/should be extended to suggest `as_mut` and `as_deref_mut`,
435
433
// but those checks need to be a bit more delicate and the benefit is diminishing.
436
434
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 {
438
436
span : expr. span . shrink_to_hi ( ) ,
439
437
sugg : ".as_ref()" ,
440
438
expected,
@@ -447,7 +445,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
447
445
&& self . can_eq ( self . param_env , deref_ty, peeled)
448
446
&& error_tys_equate_as_ref
449
447
{
450
- err. subdiagnostic ( SuggestConvertViaMethod {
448
+ err. subdiagnostic ( errors :: SuggestConvertViaMethod {
451
449
span : expr. span . shrink_to_hi ( ) ,
452
450
sugg : ".as_deref()" ,
453
451
expected,
@@ -521,17 +519,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
521
519
if self . can_coerce ( Ty :: new_box ( self . tcx , found) , expected) {
522
520
let suggest_boxing = match found. kind ( ) {
523
521
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 }
525
523
}
526
524
ty:: Generator ( def_id, ..)
527
525
if matches ! (
528
526
self . tcx. generator_kind( def_id) ,
529
527
Some ( GeneratorKind :: Async ( AsyncGeneratorKind :: Closure ) )
530
528
) =>
531
529
{
532
- SuggestBoxing :: AsyncBody
530
+ errors :: SuggestBoxing :: AsyncBody
533
531
}
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
+ } ,
535
536
} ;
536
537
err. subdiagnostic ( suggest_boxing) ;
537
538
@@ -756,23 +757,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
756
757
match & fn_decl. output {
757
758
& hir:: FnRetTy :: DefaultReturn ( span) if expected. is_unit ( ) && !can_suggest => {
758
759
// `fn main()` must return `()`, do not suggest changing return type
759
- err. subdiagnostic ( ExpectedReturnTypeLabel :: Unit { span } ) ;
760
+ err. subdiagnostic ( errors :: ExpectedReturnTypeLabel :: Unit { span } ) ;
760
761
return true ;
761
762
}
762
763
& hir:: FnRetTy :: DefaultReturn ( span) if expected. is_unit ( ) => {
763
764
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 ( ) } ) ;
765
766
return true ;
766
767
} else if let ty:: Closure ( _, args) = found. kind ( )
767
768
// FIXME(compiler-errors): Get better at printing binders...
768
769
&& let closure = args. as_closure ( )
769
770
&& closure. sig ( ) . is_suggestable ( self . tcx , false )
770
771
{
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 ( ) } ) ;
772
773
return true ;
773
774
} else {
774
775
// FIXME: if `found` could be `impl Iterator` we should suggest that.
775
- err. subdiagnostic ( AddReturnTypeSuggestion :: MissingHere { span } ) ;
776
+ err. subdiagnostic ( errors :: AddReturnTypeSuggestion :: MissingHere { span } ) ;
776
777
return true
777
778
}
778
779
}
@@ -794,10 +795,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
794
795
debug ! ( ?found) ;
795
796
if found. is_suggestable ( self . tcx , false ) {
796
797
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 ( ) } ) ;
798
799
return true ;
799
800
} else {
800
- err. subdiagnostic ( ExpectedReturnTypeLabel :: Other { span, expected } ) ;
801
+ err. subdiagnostic ( errors :: ExpectedReturnTypeLabel :: Other { span, expected } ) ;
801
802
}
802
803
}
803
804
}
@@ -813,7 +814,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
813
814
let ty = self . normalize ( span, ty) ;
814
815
let ty = self . tcx . erase_late_bound_regions ( ty) ;
815
816
if self . can_coerce ( expected, ty) {
816
- err. subdiagnostic ( ExpectedReturnTypeLabel :: Other { span, expected } ) ;
817
+ err. subdiagnostic ( errors :: ExpectedReturnTypeLabel :: Other { span, expected } ) ;
817
818
self . try_suggest_return_impl_trait ( err, expected, ty, fn_id) ;
818
819
return true ;
819
820
}
@@ -1103,65 +1104,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1103
1104
return false ;
1104
1105
}
1105
1106
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
+ {
1107
1111
let expr_inner_ty = args. type_at ( 0 ) ;
1108
1112
let expected_inner_ty = expected_args. type_at ( 0 ) ;
1109
1113
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
- )
1114
+ && self . can_eq ( self . param_env , ty, expected_inner_ty)
1140
1115
{
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
+ errors:: OptionResultRefMismatch :: AsRef {
1124
+ span : expected_ty_expr. span . shrink_to_hi ( ) , expected_ty, expr_ty, def_path
1125
+ }
1126
+ } else if let Some ( clone_did) = self . tcx . lang_items ( ) . clone_trait ( )
1127
+ && rustc_trait_selection:: traits:: type_known_to_meet_bound_modulo_regions (
1128
+ self ,
1129
+ self . param_env ,
1130
+ ty,
1131
+ clone_did,
1132
+ )
1133
+ {
1134
+ errors:: OptionResultRefMismatch :: Cloned {
1135
+ span, def_path
1136
+ }
1137
+ } else {
1138
+ return false ;
1139
+ } ;
1140
+ diag. subdiagnostic ( subdiag) ;
1149
1141
return true ;
1150
1142
}
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 ( ) ;
1165
1143
}
1166
1144
1167
1145
false
0 commit comments