diff options
| author | Eduardo Broto <ebroto@tutanota.com> | 2020-05-12 22:05:56 +0200 |
|---|---|---|
| committer | Eduardo Broto <ebroto@tutanota.com> | 2020-05-13 20:35:52 +0200 |
| commit | e4cd8e7961b553cac44671d63bc6dfc2223ea66b (patch) | |
| tree | 6afc0b883a63c34101cfc63a630814466945d2a5 | |
| parent | b20a9cd474776277a7ad7435fa0ff7b36f829ddf (diff) | |
| download | rust-e4cd8e7961b553cac44671d63bc6dfc2223ea66b.tar.gz rust-e4cd8e7961b553cac44671d63bc6dfc2223ea66b.zip | |
Fix ICE caused in unwrap module
| -rw-r--r-- | clippy_lints/src/unwrap.rs | 12 | ||||
| -rw-r--r-- | tests/ui/checked_unwrap/simple_conditionals.rs | 21 |
2 files changed, 31 insertions, 2 deletions
diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs index f3844c7d3b6..8b971e7064b 100644 --- a/clippy_lints/src/unwrap.rs +++ b/clippy_lints/src/unwrap.rs @@ -8,6 +8,7 @@ use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, HirId, Path, QPath, UnO use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::map::Map; use rustc_middle::lint::in_external_macro; +use rustc_middle::ty::Ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; @@ -90,6 +91,14 @@ fn collect_unwrap_info<'a, 'tcx>( branch: &'tcx Expr<'_>, invert: bool, ) -> Vec<UnwrapInfo<'tcx>> { + fn is_relevant_option_call(cx: &LateContext<'_, '_>, ty: Ty<'_>, method_name: &str) -> bool { + is_type_diagnostic_item(cx, ty, sym!(option_type)) && ["is_some", "is_none"].contains(&method_name) + } + + fn is_relevant_result_call(cx: &LateContext<'_, '_>, ty: Ty<'_>, method_name: &str) -> bool { + is_type_diagnostic_item(cx, ty, sym!(result_type)) && ["is_ok", "is_err"].contains(&method_name) + } + if let ExprKind::Binary(op, left, right) = &expr.kind { match (invert, op.node) { (false, BinOpKind::And) | (false, BinOpKind::BitAnd) | (true, BinOpKind::Or) | (true, BinOpKind::BitOr) => { @@ -106,9 +115,8 @@ fn collect_unwrap_info<'a, 'tcx>( if let ExprKind::MethodCall(method_name, _, args) = &expr.kind; if let ExprKind::Path(QPath::Resolved(None, path)) = &args[0].kind; let ty = cx.tables.expr_ty(&args[0]); - if is_type_diagnostic_item(cx, ty, sym!(option_type)) || is_type_diagnostic_item(cx, ty, sym!(result_type)); let name = method_name.ident.as_str(); - if ["is_some", "is_none", "is_ok", "is_err"].contains(&&*name); + if is_relevant_option_call(cx, ty, &name) || is_relevant_result_call(cx, ty, &name); then { assert!(args.len() == 1); let unwrappable = match name.as_ref() { diff --git a/tests/ui/checked_unwrap/simple_conditionals.rs b/tests/ui/checked_unwrap/simple_conditionals.rs index 3e7b4b390ba..49794e0c241 100644 --- a/tests/ui/checked_unwrap/simple_conditionals.rs +++ b/tests/ui/checked_unwrap/simple_conditionals.rs @@ -78,3 +78,24 @@ fn main() { assert!(x.is_ok(), "{:?}", x.unwrap_err()); // ok, it's a common test pattern } + +mod issue_5579 { + trait IsErr { + fn is_err(&self, err: &str) -> bool; + } + + impl<T> IsErr for Option<T> { + fn is_err(&self, _err: &str) -> bool { + true + } + } + + #[allow(unused)] + fn boom() { + let t = Some(1); + + if t.is_err("") { + t.unwrap(); + } + } +} |
