diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index de7a213d7a42..6d90d315f005 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1,6 +1,7 @@ // error-pattern:cargo-clippy #![feature(box_syntax)] +#![feature(box_patterns)] #![feature(never_type)] #![feature(rustc_private)] #![feature(slice_patterns)] @@ -668,7 +669,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { utils::internal_lints::CLIPPY_LINTS_INTERNAL, utils::internal_lints::COMPILER_LINT_FUNCTIONS, utils::internal_lints::LINT_WITHOUT_LINT_PASS, - utils::internal_lints::OUTER_EXPN_INFO, + utils::internal_lints::OUTER_EXPN_EXPN_INFO, ]); reg.register_lint_group("clippy::all", Some("clippy"), vec![ diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index edcf41f758c0..d24a20b079d1 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -132,7 +132,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone { let pred_arg = if_chain! { if let Some((pred_fn_def_id, pred_arg, pred_arg_ty, Some(res))) = is_call_with_ref_arg(cx, mir, &pred_terminator.kind); - if *res == mir::Place::Base(mir::PlaceBase::Local(cloned)); + if res.base == mir::PlaceBase::Local(cloned); if match_def_path(cx, pred_fn_def_id, &paths::DEREF_TRAIT_METHOD); if match_type(cx, pred_arg_ty, &paths::PATH_BUF) || match_type(cx, pred_arg_ty, &paths::OS_STRING); @@ -218,7 +218,7 @@ fn is_call_with_ref_arg<'tcx>( if_chain! { if let TerminatorKind::Call { func, args, destination, .. } = kind; if args.len() == 1; - if let mir::Operand::Move(mir::Place::Base(mir::PlaceBase::Local(local))) = &args[0]; + if let mir::Operand::Move(mir::Place { base: mir::PlaceBase::Local(local), .. }) = &args[0]; if let ty::FnDef(def_id, _) = func.ty(&*mir, cx.tcx).sty; if let (inner_ty, 1) = walk_ptrs_ty_depth(args[0].ty(&*mir, cx.tcx)); if !is_copy(cx, inner_ty); @@ -244,7 +244,14 @@ fn find_stmt_assigns_to<'a, 'tcx: 'a>( stmts .rev() .find_map(|stmt| { - if let mir::StatementKind::Assign(mir::Place::Base(mir::PlaceBase::Local(local)), v) = &stmt.kind { + if let mir::StatementKind::Assign( + mir::Place { + base: mir::PlaceBase::Local(local), + .. + }, + v, + ) = &stmt.kind + { if *local == to { return Some(v); } @@ -271,28 +278,34 @@ fn find_stmt_assigns_to<'a, 'tcx: 'a>( fn base_local_and_movability<'tcx>( cx: &LateContext<'_, 'tcx>, mir: &mir::Body<'tcx>, - mut place: &mir::Place<'tcx>, + place: &mir::Place<'tcx>, ) -> Option<(mir::Local, CannotMoveOut)> { - use rustc::mir::Place::*; + use rustc::mir::Place; use rustc::mir::PlaceBase; + use rustc::mir::PlaceRef; + use rustc::mir::Projection; // Dereference. You cannot move things out from a borrowed value. let mut deref = false; // Accessing a field of an ADT that has `Drop`. Moving the field out will cause E0509. let mut field = false; - loop { - match place { - Base(PlaceBase::Local(local)) => return Some((*local, deref || field)), - Projection(proj) => { - place = &proj.base; - deref = deref || matches!(proj.elem, mir::ProjectionElem::Deref); - if !field && matches!(proj.elem, mir::ProjectionElem::Field(..)) { - field = has_drop(cx, place.ty(&mir.local_decls, cx.tcx).ty); - } - }, - _ => return None, + let PlaceRef { + base: place_base, + mut projection, + } = place.as_place_ref(); + if let PlaceBase::Local(local) = place_base { + while let Some(box Projection { base, elem }) = projection { + projection = base; + deref = matches!(elem, mir::ProjectionElem::Deref); + field = !field + && matches!(elem, mir::ProjectionElem::Field(..)) + && has_drop(cx, Place::ty_from(place_base, projection, &mir.local_decls, cx.tcx).ty); } + + Some((*local, deref || field)) + } else { + None } } diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index aba2543b13c8..6393bf2add47 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -93,9 +93,9 @@ declare_clippy_lint! { /// ```rust /// expr.span.ctxt().outer_expn_info() /// ``` - pub OUTER_EXPN_INFO, + pub OUTER_EXPN_EXPN_INFO, internal, - "using `cx.outer().expn_info()` instead of `cx.outer_expn_info()`" + "using `cx.outer_expn().expn_info()` instead of `cx.outer_expn_info()`" } declare_lint_pass!(ClippyLintsInternal => [CLIPPY_LINTS_INTERNAL]); @@ -280,7 +280,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CompilerLintFunctions { pub struct OuterExpnInfoPass; -impl_lint_pass!(OuterExpnInfoPass => [OUTER_EXPN_INFO]); +impl_lint_pass!(OuterExpnInfoPass => [OUTER_EXPN_EXPN_INFO]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OuterExpnInfoPass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) { @@ -288,7 +288,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OuterExpnInfoPass { let method_names: Vec = method_names.iter().map(|s| s.as_str()).collect(); let method_names: Vec<&str> = method_names.iter().map(std::convert::AsRef::as_ref).collect(); if_chain! { - if let ["expn_info", "outer"] = method_names.as_slice(); + if let ["expn_info", "outer_expn"] = method_names.as_slice(); let args = arg_lists[1]; if args.len() == 1; let self_arg = &args[0]; @@ -297,9 +297,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OuterExpnInfoPass { then { span_lint_and_sugg( cx, - OUTER_EXPN_INFO, + OUTER_EXPN_EXPN_INFO, expr.span.trim_start(self_arg.span).unwrap_or(expr.span), - "usage of `outer().expn_info()`", + "usage of `outer_expn().expn_info()`", "try", ".outer_expn_info()".to_string(), Applicability::MachineApplicable, diff --git a/tests/ui/outer_expn_info.rs b/tests/ui/outer_expn_info.rs index 1bc6f6888054..ed0542c9298b 100644 --- a/tests/ui/outer_expn_info.rs +++ b/tests/ui/outer_expn_info.rs @@ -16,7 +16,7 @@ declare_lint_pass!(Pass => [TEST_LINT]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, _cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - let _ = expr.span.ctxt().outer().expn_info(); + let _ = expr.span.ctxt().outer_expn().expn_info(); } } diff --git a/tests/ui/outer_expn_info.stderr b/tests/ui/outer_expn_info.stderr index d9efc91da8e4..4bbd1493dc4f 100644 --- a/tests/ui/outer_expn_info.stderr +++ b/tests/ui/outer_expn_info.stderr @@ -1,15 +1,15 @@ -error: usage of `outer().expn_info()` +error: usage of `outer_expn().expn_info()` --> $DIR/outer_expn_info.rs:19:33 | -LL | let _ = expr.span.ctxt().outer().expn_info(); - | ^^^^^^^^^^^^^^^^^^^^ help: try: `.outer_expn_info()` +LL | let _ = expr.span.ctxt().outer_expn().expn_info(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.outer_expn_info()` | note: lint level defined here --> $DIR/outer_expn_info.rs:1:9 | LL | #![deny(clippy::internal)] | ^^^^^^^^^^^^^^^^ - = note: `#[deny(clippy::outer_expn_info)]` implied by `#[deny(clippy::internal)]` + = note: `#[deny(clippy::outer_expn_expn_info)]` implied by `#[deny(clippy::internal)]` error: aborting due to previous error