Rollup merge of #124599 - estebank:issue-41708, r=wesleywiser · rust-lang/rust@8de487f (original) (raw)

`@@ -445,31 +445,81 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {

`

445

445

`} else {

`

446

446

`(None, &[][..], 0)

`

447

447

`};

`

``

448

`+

let mut can_suggest_clone = true;

`

448

449

`if let Some(def_id) = def_id

`

449

450

` && let node = self.infcx.tcx.hir_node_by_def_id(def_id)

`

450

451

` && let Some(fn_sig) = node.fn_sig()

`

451

452

` && let Some(ident) = node.ident()

`

452

453

` && let Some(pos) = args.iter().position(|arg| arg.hir_id == expr.hir_id)

`

453

454

` && let Some(arg) = fn_sig.decl.inputs.get(pos + offset)

`

454

455

`{

`

455

``

`-

let mut span: MultiSpan = arg.span.into();

`

456

``

`-

span.push_span_label(

`

457

``

`-

arg.span,

`

458

``

`-

"this parameter takes ownership of the value".to_string(),

`

459

``

`-

);

`

460

``

`-

let descr = match node.fn_kind() {

`

461

``

`-

Some(hir::intravisit::FnKind::ItemFn(..)) | None => "function",

`

462

``

`-

Some(hir::intravisit::FnKind::Method(..)) => "method",

`

463

``

`-

Some(hir::intravisit::FnKind::Closure) => "closure",

`

464

``

`-

};

`

465

``

`-

span.push_span_label(ident.span, format!("in this {descr}"));

`

466

``

`-

err.span_note(

`

467

``

`-

span,

`

468

``

`-

format!(

`

469

``

`` -

"consider changing this parameter type in {descr} {ident} to borrow \

``

470

``

`-

instead if owning the value isn't necessary",

`

471

``

`-

),

`

472

``

`-

);

`

``

456

`+

let mut is_mut = false;

`

``

457

`+

if let hir::TyKind::Path(hir::QPath::Resolved(None, path)) = arg.kind

`

``

458

`+

&& let Res::Def(DefKind::TyParam, param_def_id) = path.res

`

``

459

`+

&& self

`

``

460

`+

.infcx

`

``

461

`+

.tcx

`

``

462

`+

.predicates_of(def_id)

`

``

463

`+

.instantiate_identity(self.infcx.tcx)

`

``

464

`+

.predicates

`

``

465

`+

.into_iter()

`

``

466

`+

.any(|pred| {

`

``

467

`+

if let ty::ClauseKind::Trait(predicate) = pred.kind().skip_binder()

`

``

468

`+

&& [

`

``

469

`+

self.infcx.tcx.get_diagnostic_item(sym::AsRef),

`

``

470

`+

self.infcx.tcx.get_diagnostic_item(sym::AsMut),

`

``

471

`+

self.infcx.tcx.get_diagnostic_item(sym::Borrow),

`

``

472

`+

self.infcx.tcx.get_diagnostic_item(sym::BorrowMut),

`

``

473

`+

]

`

``

474

`+

.contains(&Some(predicate.def_id()))

`

``

475

`+

&& let ty::Param(param) = predicate.self_ty().kind()

`

``

476

`+

&& let generics = self.infcx.tcx.generics_of(def_id)

`

``

477

`+

&& let param = generics.type_param(*param, self.infcx.tcx)

`

``

478

`+

&& param.def_id == param_def_id

`

``

479

`+

{

`

``

480

`+

if [

`

``

481

`+

self.infcx.tcx.get_diagnostic_item(sym::AsMut),

`

``

482

`+

self.infcx.tcx.get_diagnostic_item(sym::BorrowMut),

`

``

483

`+

]

`

``

484

`+

.contains(&Some(predicate.def_id()))

`

``

485

`+

{

`

``

486

`+

is_mut = true;

`

``

487

`+

}

`

``

488

`+

true

`

``

489

`+

} else {

`

``

490

`+

false

`

``

491

`+

}

`

``

492

`+

})

`

``

493

`+

{

`

``

494

`+

// The type of the argument corresponding to the expression that got moved

`

``

495

`` +

// is a type parameter T, which is has a T: AsRef obligation.

``

``

496

`+

err.span_suggestion_verbose(

`

``

497

`+

expr.span.shrink_to_lo(),

`

``

498

`+

"borrow the value to avoid moving it",

`

``

499

`+

format!("&{}", if is_mut { "mut " } else { "" }),

`

``

500

`+

Applicability::MachineApplicable,

`

``

501

`+

);

`

``

502

`+

can_suggest_clone = is_mut;

`

``

503

`+

} else {

`

``

504

`+

let mut span: MultiSpan = arg.span.into();

`

``

505

`+

span.push_span_label(

`

``

506

`+

arg.span,

`

``

507

`+

"this parameter takes ownership of the value".to_string(),

`

``

508

`+

);

`

``

509

`+

let descr = match node.fn_kind() {

`

``

510

`+

Some(hir::intravisit::FnKind::ItemFn(..)) | None => "function",

`

``

511

`+

Some(hir::intravisit::FnKind::Method(..)) => "method",

`

``

512

`+

Some(hir::intravisit::FnKind::Closure) => "closure",

`

``

513

`+

};

`

``

514

`+

span.push_span_label(ident.span, format!("in this {descr}"));

`

``

515

`+

err.span_note(

`

``

516

`+

span,

`

``

517

`+

format!(

`

``

518

`` +

"consider changing this parameter type in {descr} {ident} to \

``

``

519

`+

borrow instead if owning the value isn't necessary",

`

``

520

`+

),

`

``

521

`+

);

`

``

522

`+

}

`

473

523

`}

`

474

524

`let place = &self.move_data.move_paths[mpi].place;

`

475

525

`let ty = place.ty(self.body, self.infcx.tcx).ty;

`

`@@ -487,9 +537,10 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {

`

487

537

`ClosureKind::Coroutine(CoroutineKind::Desugared(_, CoroutineSource::Block)),

`

488

538

` ..

`

489

539

`} = move_spans

`

``

540

`+

&& can_suggest_clone

`

490

541

`{

`

491

542

`self.suggest_cloning(err, ty, expr, None, Some(move_spans));

`

492

``

`-

} else if self.suggest_hoisting_call_outside_loop(err, expr) {

`

``

543

`+

} else if self.suggest_hoisting_call_outside_loop(err, expr) && can_suggest_clone {

`

493

544

`// The place where the type moves would be misleading to suggest clone.

`

494

545

`// #121466

`

495

546

`self.suggest_cloning(err, ty, expr, None, Some(move_spans));

`