@@ -1008,49 +1008,33 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
1008
1008
let mut prev_ty = self . resolve_vars_if_possible (
1009
1009
typeck. expr_ty_adjusted_opt ( expr) . unwrap_or ( Ty :: new_misc_error ( self . tcx ) ) ,
1010
1010
) ;
1011
- let mut annotate_expr = |span : Span , prev_ty : Ty < ' tcx > , self_ty : Ty < ' tcx > | -> bool {
1012
- // We always look at the `E` type, because that's the only one affected by `?`. If the
1013
- // incorrect `Result<T, E>` is because of the `T`, we'll get an E0308 on the whole
1014
- // expression, after the `?` has "unwrapped" the `T`.
1011
+
1012
+ // We always look at the `E` type, because that's the only one affected by `?`. If the
1013
+ // incorrect `Result<T, E>` is because of the `T`, we'll get an E0308 on the whole
1014
+ // expression, after the `?` has "unwrapped" the `T`.
1015
+ let get_e_type = |prev_ty : Ty < ' tcx > | -> Option < Ty < ' tcx > > {
1015
1016
let ty:: Adt ( def, args) = prev_ty. kind ( ) else {
1016
- return false ;
1017
+ return None ;
1017
1018
} ;
1018
1019
let Some ( arg) = args. get ( 1 ) else {
1019
- return false ;
1020
+ return None ;
1020
1021
} ;
1021
1022
if !self . tcx . is_diagnostic_item ( sym:: Result , def. did ( ) ) {
1022
- return false ;
1023
+ return None ;
1023
1024
}
1024
- let can = if self
1025
- . infcx
1026
- . type_implements_trait (
1027
- self . tcx . get_diagnostic_item ( sym:: From ) . unwrap ( ) ,
1028
- [ self_ty. into ( ) , * arg] ,
1029
- obligation. param_env ,
1030
- )
1031
- . must_apply_modulo_regions ( )
1032
- {
1033
- "can"
1034
- } else {
1035
- "can't"
1036
- } ;
1037
- err. span_label (
1038
- span,
1039
- format ! ( "this {can} be annotated with `?` because it has type `{prev_ty}`" ) ,
1040
- ) ;
1041
- true
1025
+ Some ( arg. as_type ( ) ?)
1042
1026
} ;
1043
1027
1028
+ let mut chain = vec ! [ ] ;
1029
+
1044
1030
// The following logic is simlar to `point_at_chain`, but that's focused on associated types
1045
1031
let mut expr = expr;
1046
1032
while let hir:: ExprKind :: MethodCall ( _path_segment, rcvr_expr, _args, span) = expr. kind {
1047
1033
// Point at every method call in the chain with the `Result` type.
1048
1034
// let foo = bar.iter().map(mapper)?;
1049
1035
// ------ -----------
1050
1036
expr = rcvr_expr;
1051
- if !annotate_expr ( span, prev_ty, self_ty) {
1052
- break ;
1053
- }
1037
+ chain. push ( ( span, prev_ty) ) ;
1054
1038
1055
1039
prev_ty = self . resolve_vars_if_possible (
1056
1040
typeck. expr_ty_adjusted_opt ( expr) . unwrap_or ( Ty :: new_misc_error ( self . tcx ) ) ,
@@ -1078,7 +1062,41 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
1078
1062
prev_ty = self . resolve_vars_if_possible (
1079
1063
typeck. expr_ty_adjusted_opt ( expr) . unwrap_or ( Ty :: new_misc_error ( self . tcx ) ) ,
1080
1064
) ;
1081
- annotate_expr ( expr. span , prev_ty, self_ty) ;
1065
+ chain. push ( ( expr. span , prev_ty) ) ;
1066
+
1067
+ let mut prev = None ;
1068
+ for ( span, err_ty) in chain. into_iter ( ) . rev ( ) {
1069
+ let err_ty = get_e_type ( err_ty) ;
1070
+ let err_ty = match ( err_ty, prev) {
1071
+ ( Some ( err_ty) , Some ( prev) ) if !self . can_eq ( obligation. param_env , err_ty, prev) => {
1072
+ err_ty
1073
+ }
1074
+ ( Some ( err_ty) , None ) => err_ty,
1075
+ _ => {
1076
+ prev = err_ty;
1077
+ continue ;
1078
+ }
1079
+ } ;
1080
+ if self
1081
+ . infcx
1082
+ . type_implements_trait (
1083
+ self . tcx . get_diagnostic_item ( sym:: From ) . unwrap ( ) ,
1084
+ [ self_ty, err_ty] ,
1085
+ obligation. param_env ,
1086
+ )
1087
+ . must_apply_modulo_regions ( )
1088
+ {
1089
+ err. span_label ( span, format ! ( "this has type `Result<_, {err_ty}>`" ) ) ;
1090
+ } else {
1091
+ err. span_label (
1092
+ span,
1093
+ format ! (
1094
+ "this can't be annotated with `?` because it has type `Result<_, {err_ty}>`" ,
1095
+ ) ,
1096
+ ) ;
1097
+ }
1098
+ prev = Some ( err_ty) ;
1099
+ }
1082
1100
}
1083
1101
1084
1102
fn report_const_param_not_wf (
0 commit comments