Rollup merge of #106363 - estebank:mutability-mismatch-arg, r=Nilstrieb
Structured suggestion for `&mut dyn Iterator` when possible Fix #37914.
This commit is contained in:
commit
334426b7a8
@ -57,7 +57,12 @@ pub enum MethodError<'tcx> {
|
|||||||
PrivateMatch(DefKind, DefId, Vec<DefId>),
|
PrivateMatch(DefKind, DefId, Vec<DefId>),
|
||||||
|
|
||||||
// Found a `Self: Sized` bound where `Self` is a trait object.
|
// Found a `Self: Sized` bound where `Self` is a trait object.
|
||||||
IllegalSizedBound(Vec<DefId>, bool, Span),
|
IllegalSizedBound {
|
||||||
|
candidates: Vec<DefId>,
|
||||||
|
needs_mut: bool,
|
||||||
|
bound_span: Span,
|
||||||
|
self_expr: &'tcx hir::Expr<'tcx>,
|
||||||
|
},
|
||||||
|
|
||||||
// Found a match, but the return type is wrong
|
// Found a match, but the return type is wrong
|
||||||
BadReturnType,
|
BadReturnType,
|
||||||
@ -112,7 +117,7 @@ pub fn method_exists(
|
|||||||
Err(NoMatch(..)) => false,
|
Err(NoMatch(..)) => false,
|
||||||
Err(Ambiguity(..)) => true,
|
Err(Ambiguity(..)) => true,
|
||||||
Err(PrivateMatch(..)) => allow_private,
|
Err(PrivateMatch(..)) => allow_private,
|
||||||
Err(IllegalSizedBound(..)) => true,
|
Err(IllegalSizedBound { .. }) => true,
|
||||||
Err(BadReturnType) => bug!("no return type expectations but got BadReturnType"),
|
Err(BadReturnType) => bug!("no return type expectations but got BadReturnType"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -236,7 +241,7 @@ pub fn lookup_method(
|
|||||||
_ => Vec::new(),
|
_ => Vec::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
return Err(IllegalSizedBound(candidates, needs_mut, span));
|
return Err(IllegalSizedBound { candidates, needs_mut, bound_span: span, self_expr });
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(result.callee)
|
Ok(result.callee)
|
||||||
|
@ -176,10 +176,18 @@ pub fn report_method_error(
|
|||||||
err.emit();
|
err.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
MethodError::IllegalSizedBound(candidates, needs_mut, bound_span) => {
|
MethodError::IllegalSizedBound { candidates, needs_mut, bound_span, self_expr } => {
|
||||||
let msg = format!("the `{}` method cannot be invoked on a trait object", item_name);
|
let msg = if needs_mut {
|
||||||
|
with_forced_trimmed_paths!(format!(
|
||||||
|
"the `{item_name}` method cannot be invoked on `{rcvr_ty}`"
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
format!("the `{item_name}` method cannot be invoked on a trait object")
|
||||||
|
};
|
||||||
let mut err = self.sess().struct_span_err(span, &msg);
|
let mut err = self.sess().struct_span_err(span, &msg);
|
||||||
err.span_label(bound_span, "this has a `Sized` requirement");
|
if !needs_mut {
|
||||||
|
err.span_label(bound_span, "this has a `Sized` requirement");
|
||||||
|
}
|
||||||
if !candidates.is_empty() {
|
if !candidates.is_empty() {
|
||||||
let help = format!(
|
let help = format!(
|
||||||
"{an}other candidate{s} {were} found in the following trait{s}, perhaps \
|
"{an}other candidate{s} {were} found in the following trait{s}, perhaps \
|
||||||
@ -197,7 +205,32 @@ pub fn report_method_error(
|
|||||||
*region,
|
*region,
|
||||||
ty::TypeAndMut { ty: *t_type, mutbl: mutability.invert() },
|
ty::TypeAndMut { ty: *t_type, mutbl: mutability.invert() },
|
||||||
);
|
);
|
||||||
err.note(&format!("you need `{}` instead of `{}`", trait_type, rcvr_ty));
|
let msg = format!("you need `{}` instead of `{}`", trait_type, rcvr_ty);
|
||||||
|
let mut kind = &self_expr.kind;
|
||||||
|
while let hir::ExprKind::AddrOf(_, _, expr)
|
||||||
|
| hir::ExprKind::Unary(hir::UnOp::Deref, expr) = kind
|
||||||
|
{
|
||||||
|
kind = &expr.kind;
|
||||||
|
}
|
||||||
|
if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = kind
|
||||||
|
&& let hir::def::Res::Local(hir_id) = path.res
|
||||||
|
&& let Some(hir::Node::Pat(b)) = self.tcx.hir().find(hir_id)
|
||||||
|
&& let Some(hir::Node::Param(p)) = self.tcx.hir().find_parent(b.hir_id)
|
||||||
|
&& let Some(node) = self.tcx.hir().find_parent(p.hir_id)
|
||||||
|
&& let Some(decl) = node.fn_decl()
|
||||||
|
&& let Some(ty) = decl.inputs.iter().find(|ty| ty.span == p.ty_span)
|
||||||
|
&& let hir::TyKind::Ref(_, mut_ty) = &ty.kind
|
||||||
|
&& let hir::Mutability::Not = mut_ty.mutbl
|
||||||
|
{
|
||||||
|
err.span_suggestion_verbose(
|
||||||
|
mut_ty.ty.span.shrink_to_lo(),
|
||||||
|
&msg,
|
||||||
|
"mut ",
|
||||||
|
Applicability::MachineApplicable,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
err.help(&msg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err.emit();
|
err.emit();
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
// run-rustfix
|
||||||
|
fn test(t: &mut dyn Iterator<Item=&u64>) -> u64 {
|
||||||
|
*t.min().unwrap() //~ ERROR the `min` method cannot be invoked on
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let array = [0u64];
|
||||||
|
test(&mut array.iter());
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
// run-rustfix
|
||||||
|
fn test(t: &dyn Iterator<Item=&u64>) -> u64 {
|
||||||
|
*t.min().unwrap() //~ ERROR the `min` method cannot be invoked on
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let array = [0u64];
|
||||||
|
test(&mut array.iter());
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
error: the `min` method cannot be invoked on `&dyn Iterator<Item = &u64>`
|
||||||
|
--> $DIR/mutability-mismatch-arg.rs:3:9
|
||||||
|
|
|
||||||
|
LL | *t.min().unwrap()
|
||||||
|
| ^^^
|
||||||
|
|
|
||||||
|
help: you need `&mut dyn Iterator<Item = &u64>` instead of `&dyn Iterator<Item = &u64>`
|
||||||
|
|
|
||||||
|
LL | fn test(t: &mut dyn Iterator<Item=&u64>) -> u64 {
|
||||||
|
| +++
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
@ -4,7 +4,6 @@ pub trait MutTrait {
|
|||||||
fn function(&mut self)
|
fn function(&mut self)
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
//~^ this has a `Sized` requirement
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MutTrait for MutType {
|
impl MutTrait for MutType {
|
||||||
@ -17,7 +16,6 @@ pub trait Trait {
|
|||||||
fn function(&self)
|
fn function(&self)
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
//~^ this has a `Sized` requirement
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Trait for Type {
|
impl Trait for Type {
|
||||||
@ -26,9 +24,9 @@ fn function(&self) {}
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
(&MutType as &dyn MutTrait).function();
|
(&MutType as &dyn MutTrait).function();
|
||||||
//~^ ERROR the `function` method cannot be invoked on a trait object
|
//~^ ERROR the `function` method cannot be invoked on `&dyn MutTrait`
|
||||||
//~| NOTE you need `&mut dyn MutTrait` instead of `&dyn MutTrait`
|
//~| HELP you need `&mut dyn MutTrait` instead of `&dyn MutTrait`
|
||||||
(&mut Type as &mut dyn Trait).function();
|
(&mut Type as &mut dyn Trait).function();
|
||||||
//~^ ERROR the `function` method cannot be invoked on a trait object
|
//~^ ERROR the `function` method cannot be invoked on `&mut dyn Trait`
|
||||||
//~| NOTE you need `&dyn Trait` instead of `&mut dyn Trait`
|
//~| HELP you need `&dyn Trait` instead of `&mut dyn Trait`
|
||||||
}
|
}
|
||||||
|
@ -1,24 +1,18 @@
|
|||||||
error: the `function` method cannot be invoked on a trait object
|
error: the `function` method cannot be invoked on `&dyn MutTrait`
|
||||||
--> $DIR/mutability-mismatch.rs:28:33
|
--> $DIR/mutability-mismatch.rs:26:33
|
||||||
|
|
|
|
||||||
LL | Self: Sized;
|
|
||||||
| ----- this has a `Sized` requirement
|
|
||||||
...
|
|
||||||
LL | (&MutType as &dyn MutTrait).function();
|
LL | (&MutType as &dyn MutTrait).function();
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: you need `&mut dyn MutTrait` instead of `&dyn MutTrait`
|
= help: you need `&mut dyn MutTrait` instead of `&dyn MutTrait`
|
||||||
|
|
||||||
error: the `function` method cannot be invoked on a trait object
|
error: the `function` method cannot be invoked on `&mut dyn Trait`
|
||||||
--> $DIR/mutability-mismatch.rs:31:35
|
--> $DIR/mutability-mismatch.rs:29:35
|
||||||
|
|
|
|
||||||
LL | Self: Sized;
|
|
||||||
| ----- this has a `Sized` requirement
|
|
||||||
...
|
|
||||||
LL | (&mut Type as &mut dyn Trait).function();
|
LL | (&mut Type as &mut dyn Trait).function();
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: you need `&dyn Trait` instead of `&mut dyn Trait`
|
= help: you need `&dyn Trait` instead of `&mut dyn Trait`
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
fn test(t: &dyn Iterator<Item=&u64>) -> u64 {
|
fn test(t: &dyn Iterator<Item=&u64>) -> u64 {
|
||||||
t.min().unwrap() //~ ERROR the `min` method cannot be invoked on a trait object
|
t.min().unwrap() //~ ERROR the `min` method cannot be invoked on `&dyn Iterator<Item = &u64>`
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
error: the `min` method cannot be invoked on a trait object
|
error: the `min` method cannot be invoked on `&dyn Iterator<Item = &u64>`
|
||||||
--> $DIR/imm-ref-trait-object.rs:2:8
|
--> $DIR/imm-ref-trait-object.rs:2:8
|
||||||
|
|
|
|
||||||
LL | t.min().unwrap()
|
LL | t.min().unwrap()
|
||||||
| ^^^
|
| ^^^
|
||||||
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
|
|
||||||
|
|
|
|
||||||
= note: this has a `Sized` requirement
|
help: you need `&mut dyn Iterator<Item = &u64>` instead of `&dyn Iterator<Item = &u64>`
|
||||||
|
|
|
|
||||||
= note: you need `&mut dyn Iterator<Item = &u64>` instead of `&dyn Iterator<Item = &u64>`
|
LL | fn test(t: &mut dyn Iterator<Item=&u64>) -> u64 {
|
||||||
|
| +++
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user