|
31 | 31 | use super::FnCtxt;
|
32 | 32 |
|
33 | 33 | use crate::type_error_struct;
|
34 |
| -use rustc_errors::{struct_span_err, Applicability, DelayDm, DiagnosticBuilder, ErrorGuaranteed}; |
| 34 | +use rustc_errors::{ |
| 35 | + struct_span_err, Applicability, DelayDm, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, |
| 36 | +}; |
35 | 37 | use rustc_hir as hir;
|
36 | 38 | use rustc_macros::{TypeFoldable, TypeVisitable};
|
37 | 39 | use rustc_middle::mir::Mutability;
|
@@ -270,6 +272,9 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
270 | 272 | }
|
271 | 273 | ));
|
272 | 274 | }
|
| 275 | + |
| 276 | + self.try_suggest_collection_to_bool(fcx, &mut err); |
| 277 | + |
273 | 278 | err.emit();
|
274 | 279 | }
|
275 | 280 | CastError::NeedViaInt => {
|
@@ -517,6 +522,9 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
517 | 522 | } else {
|
518 | 523 | err.span_label(self.span, "invalid cast");
|
519 | 524 | }
|
| 525 | + |
| 526 | + self.try_suggest_collection_to_bool(fcx, &mut err); |
| 527 | + |
520 | 528 | err.emit();
|
521 | 529 | }
|
522 | 530 | CastError::SizedUnsizedCast => {
|
@@ -1080,4 +1088,40 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
1080 | 1088 | },
|
1081 | 1089 | );
|
1082 | 1090 | }
|
| 1091 | + |
| 1092 | + /// Attempt to suggest using `.is_empty` when trying to cast from a |
| 1093 | + /// collection type to a boolean. |
| 1094 | + fn try_suggest_collection_to_bool(&self, fcx: &FnCtxt<'a, 'tcx>, err: &mut Diagnostic) { |
| 1095 | + if self.cast_ty.is_bool() { |
| 1096 | + let derefed = fcx |
| 1097 | + .autoderef(self.expr_span, self.expr_ty) |
| 1098 | + .silence_errors() |
| 1099 | + .find(|t| matches!(t.0.kind(), ty::Str | ty::Slice(..))); |
| 1100 | + |
| 1101 | + if let Some((deref_ty, _)) = derefed { |
| 1102 | + // Give a note about what the expr derefs to. |
| 1103 | + if deref_ty != self.expr_ty.peel_refs() { |
| 1104 | + err.span_note( |
| 1105 | + self.expr_span, |
| 1106 | + format!( |
| 1107 | + "this expression `Deref`s to `{}` which implements `is_empty`", |
| 1108 | + fcx.ty_to_string(deref_ty) |
| 1109 | + ), |
| 1110 | + ); |
| 1111 | + } |
| 1112 | + |
| 1113 | + // Create a multipart suggestion: add `!` and `.is_empty()` in |
| 1114 | + // place of the cast. |
| 1115 | + let suggestion = vec![ |
| 1116 | + (self.expr_span.shrink_to_lo(), "!".to_string()), |
| 1117 | + (self.span.with_lo(self.expr_span.hi()), ".is_empty()".to_string()), |
| 1118 | + ]; |
| 1119 | + |
| 1120 | + err.multipart_suggestion_verbose(format!( |
| 1121 | + "consider using the `is_empty` method on `{}` to determine if it contains anything", |
| 1122 | + fcx.ty_to_string(self.expr_ty), |
| 1123 | + ), suggestion, Applicability::MaybeIncorrect); |
| 1124 | + } |
| 1125 | + } |
| 1126 | + } |
1083 | 1127 | }
|
0 commit comments