diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 9009207bb0e..6d90d315f00 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)] diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index edcf41f758c..d24a20b079d 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 } }