about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2022-04-10 22:15:31 -0700
committerMichael Goulet <michael@errs.io>2022-04-10 22:15:31 -0700
commitd2b1bb8a9b7a0a73b8da36d12798f4e848ed7171 (patch)
treea63ecd2792e4bb26faf38491932fed96a163550b
parent18f32b73bdb3833c18c73fe3062bde8e1721ccca (diff)
downloadrust-d2b1bb8a9b7a0a73b8da36d12798f4e848ed7171.tar.gz
rust-d2b1bb8a9b7a0a73b8da36d12798f4e848ed7171.zip
use find_ancestor_inside to get right span in CastCheck
-rw-r--r--compiler/rustc_typeck/src/check/cast.rs37
-rw-r--r--src/test/ui/cast/cast-macro-lhs.rs12
-rw-r--r--src/test/ui/cast/cast-macro-lhs.stderr11
3 files changed, 42 insertions, 18 deletions
diff --git a/compiler/rustc_typeck/src/check/cast.rs b/compiler/rustc_typeck/src/check/cast.rs
index 6091b8fee00..88100fcc453 100644
--- a/compiler/rustc_typeck/src/check/cast.rs
+++ b/compiler/rustc_typeck/src/check/cast.rs
@@ -55,6 +55,7 @@ use rustc_trait_selection::traits::error_reporting::report_object_safety_error;
 pub struct CastCheck<'tcx> {
     expr: &'tcx hir::Expr<'tcx>,
     expr_ty: Ty<'tcx>,
+    expr_span: Span,
     cast_ty: Ty<'tcx>,
     cast_span: Span,
     span: Span,
@@ -207,7 +208,8 @@ impl<'a, 'tcx> CastCheck<'tcx> {
         cast_span: Span,
         span: Span,
     ) -> Result<CastCheck<'tcx>, ErrorGuaranteed> {
-        let check = CastCheck { expr, expr_ty, cast_ty, cast_span, span };
+        let expr_span = expr.span.find_ancestor_inside(span).unwrap_or(expr.span);
+        let check = CastCheck { expr, expr_ty, expr_span, cast_ty, cast_span, span };
 
         // For better error messages, check for some obviously unsized
         // cases now. We do a more thorough check at the end, once
@@ -240,15 +242,15 @@ impl<'a, 'tcx> CastCheck<'tcx> {
                     error_span,
                     format!("cannot cast `{}` as `{}`", fcx.ty_to_string(self.expr_ty), cast_ty),
                 );
-                if let Ok(snippet) = fcx.sess().source_map().span_to_snippet(self.expr.span) {
+                if let Ok(snippet) = fcx.sess().source_map().span_to_snippet(self.expr_span) {
                     err.span_suggestion(
-                        self.expr.span,
+                        self.expr_span,
                         "dereference the expression",
                         format!("*{}", snippet),
                         Applicability::MaybeIncorrect,
                     );
                 } else {
-                    err.span_help(self.expr.span, "dereference the expression with `*`");
+                    err.span_help(self.expr_span, "dereference the expression with `*`");
                 }
                 err.emit();
             }
@@ -315,7 +317,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
                     struct_span_err!(fcx.tcx.sess, self.span, E0054, "cannot cast as `bool`");
 
                 if self.expr_ty.is_numeric() {
-                    match fcx.tcx.sess.source_map().span_to_snippet(self.expr.span) {
+                    match fcx.tcx.sess.source_map().span_to_snippet(self.expr_span) {
                         Ok(snippet) => {
                             err.span_suggestion(
                                 self.span,
@@ -440,7 +442,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
                 }
                 if sugg_mutref {
                     err.span_label(self.span, "invalid cast");
-                    err.span_note(self.expr.span, "this reference is immutable");
+                    err.span_note(self.expr_span, "this reference is immutable");
                     err.span_note(self.cast_span, "trying to cast to a mutable reference type");
                 } else if let Some((sugg, remove_cast)) = sugg {
                     err.span_label(self.span, "invalid cast");
@@ -449,7 +451,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
                         .tcx
                         .sess
                         .source_map()
-                        .span_to_snippet(self.expr.span)
+                        .span_to_snippet(self.expr_span)
                         .map_or(false, |snip| snip.starts_with('('));
 
                     // Very crude check to see whether the expression must be wrapped
@@ -458,14 +460,14 @@ impl<'a, 'tcx> CastCheck<'tcx> {
                     let needs_parens =
                         !has_parens && matches!(self.expr.kind, hir::ExprKind::Cast(..));
 
-                    let mut suggestion = vec![(self.expr.span.shrink_to_lo(), sugg)];
+                    let mut suggestion = vec![(self.expr_span.shrink_to_lo(), sugg)];
                     if needs_parens {
                         suggestion[0].1 += "(";
-                        suggestion.push((self.expr.span.shrink_to_hi(), ")".to_string()));
+                        suggestion.push((self.expr_span.shrink_to_hi(), ")".to_string()));
                     }
                     if remove_cast {
                         suggestion.push((
-                            self.expr.span.shrink_to_hi().to(self.cast_span),
+                            self.expr_span.shrink_to_hi().to(self.cast_span),
                             String::new(),
                         ));
                     }
@@ -481,7 +483,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
                 ) {
                     let mut label = true;
                     // Check `impl From<self.expr_ty> for self.cast_ty {}` for accurate suggestion:
-                    if let Ok(snippet) = fcx.tcx.sess.source_map().span_to_snippet(self.expr.span) {
+                    if let Ok(snippet) = fcx.tcx.sess.source_map().span_to_snippet(self.expr_span) {
                         if let Some(from_trait) = fcx.tcx.get_diagnostic_item(sym::From) {
                             let ty = fcx.resolve_vars_if_possible(self.cast_ty);
                             // Erase regions to avoid panic in `prove_value` when calling
@@ -550,7 +552,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
 
                 if fcx.tcx.sess.is_nightly_build() {
                     err.span_label(
-                        self.expr.span,
+                        self.expr_span,
                         "consider casting this expression to `*const ()`, \
                         then using `core::ptr::from_raw_parts`",
                     );
@@ -651,7 +653,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
                 }
             }
             _ => {
-                err.span_help(self.expr.span, "consider using a box or reference as appropriate");
+                err.span_help(self.expr_span, "consider using a box or reference as appropriate");
             }
         }
         err.emit()
@@ -685,7 +687,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
 
     #[instrument(skip(fcx), level = "debug")]
     pub fn check(mut self, fcx: &FnCtxt<'a, 'tcx>) {
-        self.expr_ty = fcx.structurally_resolved_type(self.expr.span, self.expr_ty);
+        self.expr_ty = fcx.structurally_resolved_type(self.expr_span, self.expr_ty);
         self.cast_ty = fcx.structurally_resolved_type(self.cast_span, self.cast_ty);
 
         debug!("check_cast({}, {:?} as {:?})", self.expr.hir_id, self.expr_ty, self.cast_ty);
@@ -741,7 +743,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
                     ty::FnDef(..) => {
                         // Attempt a coercion to a fn pointer type.
                         let f = fcx.normalize_associated_types_in(
-                            self.expr.span,
+                            self.expr_span,
                             self.expr_ty.fn_sig(fcx.tcx),
                         );
                         let res = fcx.try_coerce(
@@ -997,7 +999,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
                 ));
 
                 let msg = "use `.addr()` to obtain the address of a pointer";
-                if let Ok(snippet) = fcx.tcx.sess.source_map().span_to_snippet(self.expr.span) {
+                if let Ok(snippet) = fcx.tcx.sess.source_map().span_to_snippet(self.expr_span) {
                     let scalar_cast = match t_c {
                         ty::cast::IntTy::U(ty::UintTy::Usize) => String::new(),
                         _ => format!(" as {}", self.cast_ty),
@@ -1027,13 +1029,12 @@ impl<'a, 'tcx> CastCheck<'tcx> {
             self.expr.hir_id,
             self.span,
             |err| {
-
                 let mut err = err.build(&format!(
                     "strict provenance disallows casting integer `{}` to pointer `{}`",
                     self.expr_ty, self.cast_ty
                 ));
                 let msg = "use `.with_addr()` to adjust a valid pointer in the same allocation, to this address";
-                if let Ok(snippet) = fcx.tcx.sess.source_map().span_to_snippet(self.expr.span) {
+                if let Ok(snippet) = fcx.tcx.sess.source_map().span_to_snippet(self.expr_span) {
                     err.span_suggestion(
                         self.span,
                         msg,
diff --git a/src/test/ui/cast/cast-macro-lhs.rs b/src/test/ui/cast/cast-macro-lhs.rs
new file mode 100644
index 00000000000..b509b3239bc
--- /dev/null
+++ b/src/test/ui/cast/cast-macro-lhs.rs
@@ -0,0 +1,12 @@
+// Test to make sure we suggest "consider casting" on the right span
+
+macro_rules! foo {
+    () => { 0 }
+}
+
+fn main() {
+    let x = foo!() as *const [u8];
+    //~^ ERROR cannot cast `usize` to a pointer that is wide
+    //~| NOTE creating a `*const [u8]` requires both an address and a length
+    //~| NOTE consider casting this expression to `*const ()`, then using `core::ptr::from_raw_parts`
+}
diff --git a/src/test/ui/cast/cast-macro-lhs.stderr b/src/test/ui/cast/cast-macro-lhs.stderr
new file mode 100644
index 00000000000..db7ce57e150
--- /dev/null
+++ b/src/test/ui/cast/cast-macro-lhs.stderr
@@ -0,0 +1,11 @@
+error[E0606]: cannot cast `usize` to a pointer that is wide
+  --> $DIR/cast-macro-lhs.rs:8:23
+   |
+LL |     let x = foo!() as *const [u8];
+   |             ------    ^^^^^^^^^^^ creating a `*const [u8]` requires both an address and a length
+   |             |
+   |             consider casting this expression to `*const ()`, then using `core::ptr::from_raw_parts`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0606`.