Skip to content

Commit

Permalink
suggest unwrap/expect for let binding type mismatch
Browse files Browse the repository at this point in the history
  • Loading branch information
chenyukang committed Oct 17, 2023
1 parent a483969 commit da907ec
Show file tree
Hide file tree
Showing 6 changed files with 161 additions and 1 deletion.
50 changes: 49 additions & 1 deletion compiler/rustc_hir_typeck/src/demand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|| self.suggest_into(err, expr, expr_ty, expected)
|| self.suggest_floating_point_literal(err, expr, expected)
|| self.suggest_null_ptr_for_literal_zero_given_to_ptr_arg(err, expr, expected)
|| self.suggest_coercing_result_via_try_operator(err, expr, expected, expr_ty);
|| self.suggest_coercing_result_via_try_operator(err, expr, expected, expr_ty)
|| self.suggest_missing_unwrap_expect(err, expr, expected, expr_ty);

if !suggested {
self.note_source_of_type_mismatch_constraint(
Expand Down Expand Up @@ -954,6 +955,53 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
}

pub(crate) fn suggest_missing_unwrap_expect(
&self,
err: &mut Diagnostic,
expr: &hir::Expr<'tcx>,
expected: Ty<'tcx>,
found: Ty<'tcx>,
) -> bool {
if let ty::Adt(adt, args) = found.kind() {
if self.tcx.is_diagnostic_item(sym::Option, adt.did())
|| self.tcx.is_diagnostic_item(sym::Result, adt.did())
{
// don't suggest anything like `Ok(ok_val).unwrap()` , `Some(some_val).unwrap()`, `None.unwrap()` etc.
let is_ctor = match expr.kind {
hir::ExprKind::Call(
hir::Expr {
kind:
hir::ExprKind::Path(hir::QPath::Resolved(
None,
hir::Path {
res: Res::Def(hir::def::DefKind::Ctor(_, _), _),
..
},
)),
..
},
..,
) => true,
hir::ExprKind::Path(hir::QPath::Resolved(
None,
hir::Path { res: Res::Def(hir::def::DefKind::Ctor(_, _), _), .. },
)) => true,
_ => false,
};
if !is_ctor && self.can_coerce(args.type_at(0), expected) {
err.span_suggestion_verbose(
expr.span.shrink_to_hi(),
"you may missing `unwrap` or `expect(...)` here",
".unwrap()",
Applicability::MaybeIncorrect,
);
return true;
};
}
}
return false;
}

pub(crate) fn suggest_coercing_result_via_try_operator(
&self,
err: &mut Diagnostic,
Expand Down
4 changes: 4 additions & 0 deletions tests/ui/lifetimes/issue-26638.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ LL | fn parse_type(iter: Box<dyn Iterator<Item=&str>+'static>) -> &str { iter.ne
|
= note: expected reference `&str`
found enum `Option<&str>`
help: you may missing `unwrap` or `expect(...)` here
|
LL | fn parse_type(iter: Box<dyn Iterator<Item=&str>+'static>) -> &str { iter.next().unwrap() }
| +++++++++

error[E0061]: this function takes 1 argument but 0 arguments were supplied
--> $DIR/issue-26638.rs:5:47
Expand Down
19 changes: 19 additions & 0 deletions tests/ui/mismatched_types/mismatch-ty-unwrap-expect.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
fn func() -> Option<i32> {
Some(1)
}

fn main() {
let v: i32 = Some(1); //~ ERROR mismatched types
let v: i32 = None; //~ ERROR mismatched types

let a = Some(1);
let v: i32 = a; //~ ERROR mismatched types

let b = Ok(1);
let v: i32 = b; //~ ERROR mismatched types

let c = Ok(false);
let v: i32 = c; //~ ERROR mismatched types

let v: i32 = func(); //~ ERROR mismatched types
}
81 changes: 81 additions & 0 deletions tests/ui/mismatched_types/mismatch-ty-unwrap-expect.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
error[E0308]: mismatched types
--> $DIR/mismatch-ty-unwrap-expect.rs:6:18
|
LL | let v: i32 = Some(1);
| --- ^^^^^^^ expected `i32`, found `Option<{integer}>`
| |
| expected due to this
|
= note: expected type `i32`
found enum `Option<{integer}>`

error[E0308]: mismatched types
--> $DIR/mismatch-ty-unwrap-expect.rs:7:18
|
LL | let v: i32 = None;
| --- ^^^^ expected `i32`, found `Option<_>`
| |
| expected due to this
|
= note: expected type `i32`
found enum `Option<_>`

error[E0308]: mismatched types
--> $DIR/mismatch-ty-unwrap-expect.rs:10:18
|
LL | let v: i32 = a;
| --- ^ expected `i32`, found `Option<{integer}>`
| |
| expected due to this
|
= note: expected type `i32`
found enum `Option<{integer}>`
help: you may missing `unwrap` or `expect(...)` here
|
LL | let v: i32 = a.unwrap();
| +++++++++

error[E0308]: mismatched types
--> $DIR/mismatch-ty-unwrap-expect.rs:13:18
|
LL | let v: i32 = b;
| --- ^ expected `i32`, found `Result<{integer}, _>`
| |
| expected due to this
|
= note: expected type `i32`
found enum `Result<{integer}, _>`
help: you may missing `unwrap` or `expect(...)` here
|
LL | let v: i32 = b.unwrap();
| +++++++++

error[E0308]: mismatched types
--> $DIR/mismatch-ty-unwrap-expect.rs:16:18
|
LL | let v: i32 = c;
| --- ^ expected `i32`, found `Result<bool, _>`
| |
| expected due to this
|
= note: expected type `i32`
found enum `Result<bool, _>`

error[E0308]: mismatched types
--> $DIR/mismatch-ty-unwrap-expect.rs:18:18
|
LL | let v: i32 = func();
| --- ^^^^^^ expected `i32`, found `Option<i32>`
| |
| expected due to this
|
= note: expected type `i32`
found enum `Option<i32>`
help: you may missing `unwrap` or `expect(...)` here
|
LL | let v: i32 = func().unwrap();
| +++++++++

error: aborting due to 6 previous errors

For more information about this error, try `rustc --explain E0308`.
4 changes: 4 additions & 0 deletions tests/ui/noexporttypeexe.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ LL | let x: isize = noexporttypelib::foo();
|
= note: expected type `isize`
found enum `Option<isize>`
help: you may missing `unwrap` or `expect(...)` here
|
LL | let x: isize = noexporttypelib::foo().unwrap();
| +++++++++

error: aborting due to previous error

Expand Down
4 changes: 4 additions & 0 deletions tests/ui/typeck/tag-that-dare-not-speak-its-name.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ LL | let x : char = last(y);
|
= note: expected type `char`
found enum `Option<_>`
help: you may missing `unwrap` or `expect(...)` here
|
LL | let x : char = last(y).unwrap();
| +++++++++

error: aborting due to previous error

Expand Down

0 comments on commit da907ec

Please sign in to comment.