@@ -380,20 +380,21 @@ impl<'a, 'tcx> CastCheck<'tcx> {
380
380
err.span_label(self.span, "invalid cast");
381
381
if self.expr_ty.is_numeric() {
382
382
if self.expr_ty == fcx.tcx.types.u32 {
383
- match fcx.tcx.sess.source_map().span_to_snippet(self.expr.span) {
384
- Ok(snippet) => err.span_suggestion(
385
- self.span,
386
- "try `char::from_u32` instead",
387
- format!("char::from_u32({snippet})"),
388
- Applicability::MachineApplicable,
389
- ),
390
-
391
- Err(_) => err.span_help(self.span, "try `char::from_u32` instead"),
392
- };
383
+ err.multipart_suggestion(
384
+ "consider using `char::from_u32` instead",
385
+ vec![
386
+ (self.expr_span.shrink_to_lo(), "char::from_u32(".to_string()),
387
+ (self.expr_span.shrink_to_hi().to(self.cast_span), ")".to_string()),
388
+ ],
389
+ Applicability::MachineApplicable,
390
+ );
393
391
} else if self.expr_ty == fcx.tcx.types.i8 {
394
- err.span_help(self.span, "try casting from `u8` instead");
392
+ err.span_help(self.span, "consider casting from `u8` instead");
395
393
} else {
396
- err.span_help(self.span, "try `char::from_u32` instead (via a `u32`)");
394
+ err.span_help(
395
+ self.span,
396
+ "consider using `char::from_u32` instead (via a `u32`)",
397
+ );
397
398
};
398
399
}
399
400
err.emit();
@@ -494,38 +495,31 @@ impl<'a, 'tcx> CastCheck<'tcx> {
494
495
self.cast_ty.kind(),
495
496
ty::FnDef(..) | ty::FnPtr(..) | ty::Closure(..)
496
497
) {
497
- let mut label = true;
498
498
// Check `impl From<self.expr_ty> for self.cast_ty {}` for accurate suggestion:
499
- if let Ok(snippet) = fcx.tcx.sess.source_map().span_to_snippet(self.expr_span)
500
- && let Some(from_trait) = fcx.tcx.get_diagnostic_item(sym::From)
501
- {
499
+ if let Some(from_trait) = fcx.tcx.get_diagnostic_item(sym::From) {
502
500
let ty = fcx.resolve_vars_if_possible(self.cast_ty);
503
501
let expr_ty = fcx.resolve_vars_if_possible(self.expr_ty);
504
502
if fcx
505
503
.infcx
506
504
.type_implements_trait(from_trait, [ty, expr_ty], fcx.param_env)
507
505
.must_apply_modulo_regions()
508
506
{
509
- label = false;
510
- if let ty::Adt(def, args) = self.cast_ty.kind() {
511
- err.span_suggestion_verbose(
512
- self.span,
513
- "consider using the `From` trait instead",
514
- format!(
515
- "{}::from({})",
516
- fcx.tcx.value_path_str_with_args(def.did(), args),
517
- snippet
518
- ),
519
- Applicability::MaybeIncorrect,
520
- );
507
+ let to_ty = if let ty::Adt(def, args) = self.cast_ty.kind() {
508
+ fcx.tcx.value_path_str_with_args(def.did(), args)
521
509
} else {
522
- err.span_suggestion(
523
- self.span,
524
- "consider using the `From` trait instead",
525
- format!("{}::from({})", self.cast_ty, snippet),
526
- Applicability::MaybeIncorrect,
527
- );
510
+ self.cast_ty.to_string()
528
511
};
512
+ err.multipart_suggestion(
513
+ "consider using the `From` trait instead",
514
+ vec![
515
+ (self.expr_span.shrink_to_lo(), format!("{to_ty}::from(")),
516
+ (
517
+ self.expr_span.shrink_to_hi().to(self.cast_span),
518
+ ")".to_string(),
519
+ ),
520
+ ],
521
+ Applicability::MaybeIncorrect,
522
+ );
529
523
}
530
524
}
531
525
@@ -548,11 +542,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
548
542
)
549
543
};
550
544
551
- if label {
552
- err.span_label(self.span, msg);
553
- } else {
554
- err.note(msg);
555
- }
545
+ err.span_label(self.span, msg);
556
546
557
547
if let Some(note) = note {
558
548
err.note(note);
@@ -654,38 +644,22 @@ impl<'a, 'tcx> CastCheck<'tcx> {
654
644
match self.expr_ty.kind() {
655
645
ty::Ref(_, _, mt) => {
656
646
let mtstr = mt.prefix_str();
657
- match fcx.tcx.sess.source_map().span_to_snippet(self.cast_span) {
658
- Ok(s) => {
659
- err.span_suggestion(
660
- self.cast_span,
661
- "try casting to a reference instead",
662
- format!("&{mtstr}{s}"),
663
- Applicability::MachineApplicable,
664
- );
665
- }
666
- Err(_) => {
667
- let msg = format!("did you mean `&{mtstr}{tstr}`?");
668
- err.span_help(self.cast_span, msg);
669
- }
670
- }
647
+ err.span_suggestion_verbose(
648
+ self.cast_span.shrink_to_lo(),
649
+ "consider casting to a reference instead",
650
+ format!("&{mtstr}"),
651
+ Applicability::MachineApplicable,
652
+ );
671
653
}
672
654
ty::Adt(def, ..) if def.is_box() => {
673
- match fcx.tcx.sess.source_map().span_to_snippet(self.cast_span) {
674
- Ok(s) => {
675
- err.span_suggestion(
676
- self.cast_span,
677
- "you can cast to a `Box` instead",
678
- format!("Box<{s}>"),
679
- Applicability::MachineApplicable,
680
- );
681
- }
682
- Err(_) => {
683
- err.span_help(
684
- self.cast_span,
685
- format!("you might have meant `Box<{tstr}>`"),
686
- );
687
- }
688
- }
655
+ err.multipart_suggestion(
656
+ "you can cast to a `Box` instead",
657
+ vec![
658
+ (self.cast_span.shrink_to_lo(), "Box<".to_string()),
659
+ (self.cast_span.shrink_to_hi(), ">".to_string()),
660
+ ],
661
+ Applicability::MachineApplicable,
662
+ );
689
663
}
690
664
_ => {
691
665
err.span_help(self.expr_span, "consider using a box or reference as appropriate");
0 commit comments