Skip to content

Commit 8d46f9c

Browse files
authored
Rollup merge of #95920 - compiler-errors:cast-suggestion-span, r=oli-obk
use `Span::find_ancestor_inside` to get right span in CastCheck This is a quick fix. This bad suggestion likely lives in other places... but thought it would be useful to fix all of the CastCheck ones first. Let me know if reviewer would prefer I add more tests for each of the diagnostics in CastCheck, or would like to do a more thorough review of other suggestions that use spans in typeck. I would also be open to further suggestions on how to better expose an API that gives us the "best" span for a diagnostic suggestion. Fixed #95919
2 parents 1b364ae + d2b1bb8 commit 8d46f9c

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)