Skip to content

Commit d2b1bb8

Browse files
use find_ancestor_inside to get right span in CastCheck
1 parent 18f32b7 commit d2b1bb8

File tree

3 files changed

+42
-18
lines changed

3 files changed

+42
-18
lines changed

compiler/rustc_typeck/src/check/cast.rs

+19-18
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ use rustc_trait_selection::traits::error_reporting::report_object_safety_error;
5555
pub struct CastCheck<'tcx> {
5656
expr: &'tcx hir::Expr<'tcx>,
5757
expr_ty: Ty<'tcx>,
58+
expr_span: Span,
5859
cast_ty: Ty<'tcx>,
5960
cast_span: Span,
6061
span: Span,
@@ -207,7 +208,8 @@ impl<'a, 'tcx> CastCheck<'tcx> {
207208
cast_span: Span,
208209
span: Span,
209210
) -> Result<CastCheck<'tcx>, ErrorGuaranteed> {
210-
let check = CastCheck { expr, expr_ty, cast_ty, cast_span, span };
211+
let expr_span = expr.span.find_ancestor_inside(span).unwrap_or(expr.span);
212+
let check = CastCheck { expr, expr_ty, expr_span, cast_ty, cast_span, span };
211213

212214
// For better error messages, check for some obviously unsized
213215
// cases now. We do a more thorough check at the end, once
@@ -240,15 +242,15 @@ impl<'a, 'tcx> CastCheck<'tcx> {
240242
error_span,
241243
format!("cannot cast `{}` as `{}`", fcx.ty_to_string(self.expr_ty), cast_ty),
242244
);
243-
if let Ok(snippet) = fcx.sess().source_map().span_to_snippet(self.expr.span) {
245+
if let Ok(snippet) = fcx.sess().source_map().span_to_snippet(self.expr_span) {
244246
err.span_suggestion(
245-
self.expr.span,
247+
self.expr_span,
246248
"dereference the expression",
247249
format!("*{}", snippet),
248250
Applicability::MaybeIncorrect,
249251
);
250252
} else {
251-
err.span_help(self.expr.span, "dereference the expression with `*`");
253+
err.span_help(self.expr_span, "dereference the expression with `*`");
252254
}
253255
err.emit();
254256
}
@@ -315,7 +317,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
315317
struct_span_err!(fcx.tcx.sess, self.span, E0054, "cannot cast as `bool`");
316318

317319
if self.expr_ty.is_numeric() {
318-
match fcx.tcx.sess.source_map().span_to_snippet(self.expr.span) {
320+
match fcx.tcx.sess.source_map().span_to_snippet(self.expr_span) {
319321
Ok(snippet) => {
320322
err.span_suggestion(
321323
self.span,
@@ -440,7 +442,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
440442
}
441443
if sugg_mutref {
442444
err.span_label(self.span, "invalid cast");
443-
err.span_note(self.expr.span, "this reference is immutable");
445+
err.span_note(self.expr_span, "this reference is immutable");
444446
err.span_note(self.cast_span, "trying to cast to a mutable reference type");
445447
} else if let Some((sugg, remove_cast)) = sugg {
446448
err.span_label(self.span, "invalid cast");
@@ -449,7 +451,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
449451
.tcx
450452
.sess
451453
.source_map()
452-
.span_to_snippet(self.expr.span)
454+
.span_to_snippet(self.expr_span)
453455
.map_or(false, |snip| snip.starts_with('('));
454456

455457
// Very crude check to see whether the expression must be wrapped
@@ -458,14 +460,14 @@ impl<'a, 'tcx> CastCheck<'tcx> {
458460
let needs_parens =
459461
!has_parens && matches!(self.expr.kind, hir::ExprKind::Cast(..));
460462

461-
let mut suggestion = vec![(self.expr.span.shrink_to_lo(), sugg)];
463+
let mut suggestion = vec![(self.expr_span.shrink_to_lo(), sugg)];
462464
if needs_parens {
463465
suggestion[0].1 += "(";
464-
suggestion.push((self.expr.span.shrink_to_hi(), ")".to_string()));
466+
suggestion.push((self.expr_span.shrink_to_hi(), ")".to_string()));
465467
}
466468
if remove_cast {
467469
suggestion.push((
468-
self.expr.span.shrink_to_hi().to(self.cast_span),
470+
self.expr_span.shrink_to_hi().to(self.cast_span),
469471
String::new(),
470472
));
471473
}
@@ -481,7 +483,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
481483
) {
482484
let mut label = true;
483485
// Check `impl From<self.expr_ty> for self.cast_ty {}` for accurate suggestion:
484-
if let Ok(snippet) = fcx.tcx.sess.source_map().span_to_snippet(self.expr.span) {
486+
if let Ok(snippet) = fcx.tcx.sess.source_map().span_to_snippet(self.expr_span) {
485487
if let Some(from_trait) = fcx.tcx.get_diagnostic_item(sym::From) {
486488
let ty = fcx.resolve_vars_if_possible(self.cast_ty);
487489
// Erase regions to avoid panic in `prove_value` when calling
@@ -550,7 +552,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
550552

551553
if fcx.tcx.sess.is_nightly_build() {
552554
err.span_label(
553-
self.expr.span,
555+
self.expr_span,
554556
"consider casting this expression to `*const ()`, \
555557
then using `core::ptr::from_raw_parts`",
556558
);
@@ -651,7 +653,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
651653
}
652654
}
653655
_ => {
654-
err.span_help(self.expr.span, "consider using a box or reference as appropriate");
656+
err.span_help(self.expr_span, "consider using a box or reference as appropriate");
655657
}
656658
}
657659
err.emit()
@@ -685,7 +687,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
685687

686688
#[instrument(skip(fcx), level = "debug")]
687689
pub fn check(mut self, fcx: &FnCtxt<'a, 'tcx>) {
688-
self.expr_ty = fcx.structurally_resolved_type(self.expr.span, self.expr_ty);
690+
self.expr_ty = fcx.structurally_resolved_type(self.expr_span, self.expr_ty);
689691
self.cast_ty = fcx.structurally_resolved_type(self.cast_span, self.cast_ty);
690692

691693
debug!("check_cast({}, {:?} as {:?})", self.expr.hir_id, self.expr_ty, self.cast_ty);
@@ -741,7 +743,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
741743
ty::FnDef(..) => {
742744
// Attempt a coercion to a fn pointer type.
743745
let f = fcx.normalize_associated_types_in(
744-
self.expr.span,
746+
self.expr_span,
745747
self.expr_ty.fn_sig(fcx.tcx),
746748
);
747749
let res = fcx.try_coerce(
@@ -997,7 +999,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
997999
));
9981000

9991001
let msg = "use `.addr()` to obtain the address of a pointer";
1000-
if let Ok(snippet) = fcx.tcx.sess.source_map().span_to_snippet(self.expr.span) {
1002+
if let Ok(snippet) = fcx.tcx.sess.source_map().span_to_snippet(self.expr_span) {
10011003
let scalar_cast = match t_c {
10021004
ty::cast::IntTy::U(ty::UintTy::Usize) => String::new(),
10031005
_ => format!(" as {}", self.cast_ty),
@@ -1027,13 +1029,12 @@ impl<'a, 'tcx> CastCheck<'tcx> {
10271029
self.expr.hir_id,
10281030
self.span,
10291031
|err| {
1030-
10311032
let mut err = err.build(&format!(
10321033
"strict provenance disallows casting integer `{}` to pointer `{}`",
10331034
self.expr_ty, self.cast_ty
10341035
));
10351036
let msg = "use `.with_addr()` to adjust a valid pointer in the same allocation, to this address";
1036-
if let Ok(snippet) = fcx.tcx.sess.source_map().span_to_snippet(self.expr.span) {
1037+
if let Ok(snippet) = fcx.tcx.sess.source_map().span_to_snippet(self.expr_span) {
10371038
err.span_suggestion(
10381039
self.span,
10391040
msg,

src/test/ui/cast/cast-macro-lhs.rs

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Test to make sure we suggest "consider casting" on the right span
2+
3+
macro_rules! foo {
4+
() => { 0 }
5+
}
6+
7+
fn main() {
8+
let x = foo!() as *const [u8];
9+
//~^ ERROR cannot cast `usize` to a pointer that is wide
10+
//~| NOTE creating a `*const [u8]` requires both an address and a length
11+
//~| NOTE consider casting this expression to `*const ()`, then using `core::ptr::from_raw_parts`
12+
}
+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0606]: cannot cast `usize` to a pointer that is wide
2+
--> $DIR/cast-macro-lhs.rs:8:23
3+
|
4+
LL | let x = foo!() as *const [u8];
5+
| ------ ^^^^^^^^^^^ creating a `*const [u8]` requires both an address and a length
6+
| |
7+
| consider casting this expression to `*const ()`, then using `core::ptr::from_raw_parts`
8+
9+
error: aborting due to previous error
10+
11+
For more information about this error, try `rustc --explain E0606`.

0 commit comments

Comments
 (0)