Skip to content

Commit 62c082e

Browse files
committed
Fix binder handling in unnecessary_to_owned
1 parent 87aed03 commit 62c082e

File tree

3 files changed

+58
-16
lines changed

3 files changed

+58
-16
lines changed

clippy_lints/src/methods/unnecessary_to_owned.rs

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@ use rustc_lint::LateContext;
1515
use rustc_middle::mir::Mutability;
1616
use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref};
1717
use rustc_middle::ty::{
18-
self, ClauseKind, EarlyBinder, GenericArg, GenericArgKind, GenericArgsRef, ParamTy, ProjectionPredicate,
19-
TraitPredicate, Ty,
18+
self, ClauseKind, GenericArg, GenericArgKind, GenericArgsRef, ParamTy, ProjectionPredicate, TraitPredicate, Ty,
2019
};
2120
use rustc_span::{sym, Symbol};
2221
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
@@ -387,22 +386,21 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty<
387386
if let Some((callee_def_id, call_generic_args, recv, call_args)) =
388387
get_callee_generic_args_and_args(cx, parent_expr)
389388
{
390-
// FIXME: the `instantiate_identity()` below seems incorrect, since we eventually
391-
// call `tcx.try_instantiate_and_normalize_erasing_regions` further down
392-
// (i.e., we are explicitly not in the identity context).
393-
let fn_sig = cx.tcx.fn_sig(callee_def_id).instantiate_identity().skip_binder();
389+
let bound_fn_sig = cx.tcx.fn_sig(callee_def_id);
390+
let fn_sig = bound_fn_sig.skip_binder();
394391
if let Some(arg_index) = recv.into_iter().chain(call_args).position(|arg| arg.hir_id == expr.hir_id)
395-
&& let Some(param_ty) = fn_sig.inputs().get(arg_index)
396-
&& let ty::Param(ParamTy { index: param_index , ..}) = param_ty.kind()
392+
&& let param_ty = fn_sig.input(arg_index).skip_binder()
393+
&& let ty::Param(ParamTy { index: param_index , ..}) = *param_ty.kind()
397394
// https://github.com/rust-lang/rust-clippy/issues/9504 and https://github.com/rust-lang/rust-clippy/issues/10021
398-
&& (*param_index as usize) < call_generic_args.len()
395+
&& (param_index as usize) < call_generic_args.len()
399396
{
400397
if fn_sig
398+
.skip_binder()
401399
.inputs()
402400
.iter()
403401
.enumerate()
404402
.filter(|(i, _)| *i != arg_index)
405-
.any(|(_, ty)| ty.contains(*param_ty))
403+
.any(|(_, ty)| ty.contains(param_ty))
406404
{
407405
return false;
408406
}
@@ -414,7 +412,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty<
414412
.iter()
415413
.filter(|predicate| {
416414
if let ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder()
417-
&& trait_predicate.trait_ref.self_ty() == *param_ty
415+
&& trait_predicate.trait_ref.self_ty() == param_ty
418416
{
419417
true
420418
} else {
@@ -425,15 +423,15 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty<
425423
let new_subst = cx
426424
.tcx
427425
.mk_args_from_iter(call_generic_args.iter().enumerate().map(|(i, t)| {
428-
if i == (*param_index as usize) {
426+
if i == param_index as usize {
429427
GenericArg::from(ty)
430428
} else {
431429
t
432430
}
433431
}));
434432

435433
if trait_predicates.any(|predicate| {
436-
let predicate = EarlyBinder::bind(predicate).instantiate(cx.tcx, new_subst);
434+
let predicate = bound_fn_sig.rebind(predicate).instantiate(cx.tcx, new_subst);
437435
let obligation = Obligation::new(cx.tcx, ObligationCause::dummy(), cx.param_env, predicate);
438436
!cx.tcx
439437
.infer_ctxt()
@@ -443,12 +441,12 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty<
443441
return false;
444442
}
445443

446-
let output_ty = fn_sig.output();
447-
if output_ty.contains(*param_ty) {
444+
let output_ty = cx.tcx.instantiate_bound_regions_with_erased(fn_sig.output());
445+
if output_ty.contains(param_ty) {
448446
if let Ok(new_ty) = cx.tcx.try_instantiate_and_normalize_erasing_regions(
449447
new_subst,
450448
cx.param_env,
451-
EarlyBinder::bind(output_ty),
449+
bound_fn_sig.rebind(output_ty),
452450
) {
453451
expr = parent_expr;
454452
ty = new_ty;

tests/ui/unnecessary_to_owned.fixed

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,3 +506,25 @@ mod issue_10033 {
506506
}
507507
}
508508
}
509+
510+
mod issue_11952 {
511+
#[derive(Clone)]
512+
pub struct MyApi;
513+
514+
impl MyApi {
515+
pub async fn new() -> Result<Self, ()> {
516+
Ok(Self)
517+
}
518+
519+
pub async fn foo(&self, bytes: impl AsRef<[u8]>) -> Result<(), ()> {
520+
todo!()
521+
}
522+
}
523+
524+
async fn foo() -> Result<(), ()> {
525+
let api = MyApi::new().await.unwrap();
526+
let _ = api.foo([].to_vec()).await; //when using .to_vec() on [] clippy panics
527+
528+
Ok(())
529+
}
530+
}

tests/ui/unnecessary_to_owned.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,3 +506,25 @@ mod issue_10033 {
506506
}
507507
}
508508
}
509+
510+
mod issue_11952 {
511+
#[derive(Clone)]
512+
pub struct MyApi;
513+
514+
impl MyApi {
515+
pub async fn new() -> Result<Self, ()> {
516+
Ok(Self)
517+
}
518+
519+
pub async fn foo(&self, bytes: impl AsRef<[u8]>) -> Result<(), ()> {
520+
todo!()
521+
}
522+
}
523+
524+
async fn foo() -> Result<(), ()> {
525+
let api = MyApi::new().await.unwrap();
526+
let _ = api.foo([].to_vec()).await; //when using .to_vec() on [] clippy panics
527+
528+
Ok(())
529+
}
530+
}

0 commit comments

Comments
 (0)