Skip to content

Commit 16592f6

Browse files
committed
Suggest removing ? to resolve type errors.
This commit adds a suggestion to remove the `?` from expressions if removing the `?` would resolve a type error.
1 parent 77bdb35 commit 16592f6

File tree

8 files changed

+59
-4
lines changed

8 files changed

+59
-4
lines changed

src/librustc/infer/error_reporting/mod.rs

+27-1
Original file line numberDiff line numberDiff line change
@@ -604,13 +604,39 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
604604
source,
605605
ref prior_arms,
606606
last_ty,
607+
discrim_hir_id,
607608
..
608609
} => match source {
609610
hir::MatchSource::IfLetDesugar { .. } => {
610611
let msg = "`if let` arms have incompatible types";
611612
err.span_label(cause.span, msg);
612613
}
613-
hir::MatchSource::TryDesugar => {}
614+
hir::MatchSource::TryDesugar => {
615+
if let Some(ty::error::ExpectedFound { expected, .. }) = exp_found {
616+
let discrim_expr = self.tcx.hir().expect_expr_by_hir_id(discrim_hir_id);
617+
let discrim_ty = if let hir::ExprKind::Call(_, args) = &discrim_expr.node {
618+
let arg_expr = args.first().expect("try desugaring call w/out arg");
619+
self.in_progress_tables.and_then(|tables| {
620+
tables.borrow().expr_ty_opt(arg_expr)
621+
})
622+
} else {
623+
bug!("try desugaring w/out call expr as discriminant");
624+
};
625+
626+
match discrim_ty {
627+
Some(ty) if expected == ty => {
628+
let source_map = self.tcx.sess.source_map();
629+
err.span_suggestion(
630+
source_map.end_point(cause.span),
631+
"try removing this `?`",
632+
"".to_string(),
633+
Applicability::MachineApplicable,
634+
);
635+
},
636+
_ => {},
637+
}
638+
}
639+
}
614640
_ => {
615641
let msg = "`match` arms have incompatible types";
616642
err.span_label(cause.span, msg);

src/librustc/traits/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,7 @@ pub enum ObligationCauseCode<'tcx> {
227227
source: hir::MatchSource,
228228
prior_arms: Vec<Span>,
229229
last_ty: Ty<'tcx>,
230+
discrim_hir_id: hir::HirId,
230231
},
231232

232233
/// Computing common supertype in the pattern guard for the arms of a match expression

src/librustc/traits/structural_impls.rs

+2
Original file line numberDiff line numberDiff line change
@@ -519,13 +519,15 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
519519
source,
520520
ref prior_arms,
521521
last_ty,
522+
discrim_hir_id,
522523
} => {
523524
tcx.lift(&last_ty).map(|last_ty| {
524525
super::MatchExpressionArm {
525526
arm_span,
526527
source,
527528
prior_arms: prior_arms.clone(),
528529
last_ty,
530+
discrim_hir_id,
529531
}
530532
})
531533
}

src/librustc_typeck/check/_match.rs

+1
Original file line numberDiff line numberDiff line change
@@ -732,6 +732,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
732732
source: match_src,
733733
prior_arms: other_arms.clone(),
734734
last_ty: prior_arm_ty.unwrap(),
735+
discrim_hir_id: discrim.hir_id,
735736
})
736737
};
737738
coercion.coerce(self, &cause, &arm.body, arm_ty);

src/test/ui/issue-59756.fixed

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// run-rustfix
2+
3+
#![allow(warnings)]
4+
5+
struct A;
6+
struct B;
7+
8+
fn foo() -> Result<A, B> {
9+
Ok(A)
10+
}
11+
12+
fn bar() -> Result<A, B> {
13+
foo()
14+
//~^ ERROR try expression alternatives have incompatible types [E0308]
15+
}
16+
17+
fn main() {}

src/test/ui/issue-59756.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// run-rustfix
2+
13
#![allow(warnings)]
24

35
struct A;

src/test/ui/issue-59756.stderr

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
error[E0308]: try expression alternatives have incompatible types
2-
--> $DIR/issue-59756.rs:11:5
2+
--> $DIR/issue-59756.rs:13:5
33
|
44
LL | foo()?
5-
| ^^^^^^ expected enum `std::result::Result`, found struct `A`
5+
| ^^^^^-
6+
| | |
7+
| | help: try removing this `?`
8+
| expected enum `std::result::Result`, found struct `A`
69
|
710
= note: expected type `std::result::Result<A, B>`
811
found type `A`

src/test/ui/issues/issue-51632-try-desugar-incompatible-types.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ error[E0308]: try expression alternatives have incompatible types
22
--> $DIR/issue-51632-try-desugar-incompatible-types.rs:8:5
33
|
44
LL | missing_discourses()?
5-
| ^^^^^^^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found isize
5+
| ^^^^^^^^^^^^^^^^^^^^-
6+
| | |
7+
| | help: try removing this `?`
8+
| expected enum `std::result::Result`, found isize
69
|
710
= note: expected type `std::result::Result<isize, ()>`
811
found type `isize`

0 commit comments

Comments
 (0)