Rollup merge of #102951 - SparrowLii:type_annotation, r=estebank
suggest type annotation for local statement initialed by ref expression In a local statement with a type declaration, if a ref expression is used on the right side and not used on the left side, in addition to removing the `&` and `&mut` on the right side, we can add them on the left side alternatively Fixes #102892
This commit is contained in:
commit
bf6bfcddf6
@ -714,7 +714,14 @@ pub fn check_ref(
|
|||||||
expr: &hir::Expr<'tcx>,
|
expr: &hir::Expr<'tcx>,
|
||||||
checked_ty: Ty<'tcx>,
|
checked_ty: Ty<'tcx>,
|
||||||
expected: Ty<'tcx>,
|
expected: Ty<'tcx>,
|
||||||
) -> Option<(Span, String, String, Applicability, bool /* verbose */)> {
|
) -> Option<(
|
||||||
|
Span,
|
||||||
|
String,
|
||||||
|
String,
|
||||||
|
Applicability,
|
||||||
|
bool, /* verbose */
|
||||||
|
bool, /* suggest `&` or `&mut` type annotation */
|
||||||
|
)> {
|
||||||
let sess = self.sess();
|
let sess = self.sess();
|
||||||
let sp = expr.span;
|
let sp = expr.span;
|
||||||
|
|
||||||
@ -746,6 +753,7 @@ pub fn check_ref(
|
|||||||
String::new(),
|
String::new(),
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
true,
|
true,
|
||||||
|
false,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -760,6 +768,7 @@ pub fn check_ref(
|
|||||||
"b".to_string(),
|
"b".to_string(),
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
true,
|
true,
|
||||||
|
false,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -817,6 +826,7 @@ pub fn check_ref(
|
|||||||
sugg.2,
|
sugg.2,
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -844,6 +854,7 @@ pub fn check_ref(
|
|||||||
format!("{prefix}&mut {sugg_expr}"),
|
format!("{prefix}&mut {sugg_expr}"),
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
hir::Mutability::Not => (
|
hir::Mutability::Not => (
|
||||||
sp,
|
sp,
|
||||||
@ -851,6 +862,7 @@ pub fn check_ref(
|
|||||||
format!("{prefix}&{sugg_expr}"),
|
format!("{prefix}&{sugg_expr}"),
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -880,6 +892,7 @@ pub fn check_ref(
|
|||||||
String::new(),
|
String::new(),
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
true,
|
true,
|
||||||
|
true
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
return None;
|
return None;
|
||||||
@ -893,6 +906,7 @@ pub fn check_ref(
|
|||||||
String::new(),
|
String::new(),
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
true,
|
true,
|
||||||
|
true,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -959,6 +973,7 @@ pub fn check_ref(
|
|||||||
src,
|
src,
|
||||||
applicability,
|
applicability,
|
||||||
true,
|
true,
|
||||||
|
false,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -999,6 +1014,7 @@ pub fn check_ref(
|
|||||||
Applicability::MachineApplicable
|
Applicability::MachineApplicable
|
||||||
},
|
},
|
||||||
true,
|
true,
|
||||||
|
false,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1050,6 +1066,7 @@ pub fn check_ref(
|
|||||||
suggestion,
|
suggestion,
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
true,
|
true,
|
||||||
|
false,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -327,7 +327,7 @@ pub fn suggest_deref_ref_or_into(
|
|||||||
expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
|
expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let expr = expr.peel_blocks();
|
let expr = expr.peel_blocks();
|
||||||
if let Some((sp, msg, suggestion, applicability, verbose)) =
|
if let Some((sp, msg, suggestion, applicability, verbose, annotation)) =
|
||||||
self.check_ref(expr, found, expected)
|
self.check_ref(expr, found, expected)
|
||||||
{
|
{
|
||||||
if verbose {
|
if verbose {
|
||||||
@ -335,9 +335,50 @@ pub fn suggest_deref_ref_or_into(
|
|||||||
} else {
|
} else {
|
||||||
err.span_suggestion(sp, &msg, suggestion, applicability);
|
err.span_suggestion(sp, &msg, suggestion, applicability);
|
||||||
}
|
}
|
||||||
|
if annotation {
|
||||||
|
let suggest_annotation = match expr.peel_drop_temps().kind {
|
||||||
|
hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, _) => "&",
|
||||||
|
hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mut, _) => "&mut ",
|
||||||
|
_ => return true,
|
||||||
|
};
|
||||||
|
let mut tuple_indexes = Vec::new();
|
||||||
|
let mut expr_id = expr.hir_id;
|
||||||
|
for (parent_id, node) in self.tcx.hir().parent_iter(expr.hir_id) {
|
||||||
|
match node {
|
||||||
|
Node::Expr(&Expr { kind: ExprKind::Tup(subs), .. }) => {
|
||||||
|
tuple_indexes.push(
|
||||||
|
subs.iter()
|
||||||
|
.enumerate()
|
||||||
|
.find(|(_, sub_expr)| sub_expr.hir_id == expr_id)
|
||||||
|
.unwrap()
|
||||||
|
.0,
|
||||||
|
);
|
||||||
|
expr_id = parent_id;
|
||||||
|
}
|
||||||
|
Node::Local(local) => {
|
||||||
|
if let Some(mut ty) = local.ty {
|
||||||
|
while let Some(index) = tuple_indexes.pop() {
|
||||||
|
match ty.kind {
|
||||||
|
TyKind::Tup(tys) => ty = &tys[index],
|
||||||
|
_ => return true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let annotation_span = ty.span;
|
||||||
|
err.span_suggestion(
|
||||||
|
annotation_span.with_hi(annotation_span.lo()),
|
||||||
|
format!("alternatively, consider changing the type annotation"),
|
||||||
|
suggest_annotation,
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_ => break,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
} else if self.suggest_else_fn_with_closure(err, expr, found, expected)
|
} else if self.suggest_else_fn_with_closure(err, expr, found, expected) {
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
} else if self.suggest_fn_call(err, expr, found, |output| self.can_coerce(output, expected))
|
} else if self.suggest_fn_call(err, expr, found, |output| self.can_coerce(output, expected))
|
||||||
&& let ty::FnDef(def_id, ..) = &found.kind()
|
&& let ty::FnDef(def_id, ..) = &found.kind()
|
||||||
|
@ -11,6 +11,10 @@ help: consider removing the borrow
|
|||||||
LL - let a: String = &String::from("a");
|
LL - let a: String = &String::from("a");
|
||||||
LL + let a: String = String::from("a");
|
LL + let a: String = String::from("a");
|
||||||
|
|
|
|
||||||
|
help: alternatively, consider changing the type annotation
|
||||||
|
|
|
||||||
|
LL | let a: &String = &String::from("a");
|
||||||
|
| +
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/format-borrow.rs:4:21
|
--> $DIR/format-borrow.rs:4:21
|
||||||
@ -25,6 +29,10 @@ help: consider removing the borrow
|
|||||||
LL - let b: String = &format!("b");
|
LL - let b: String = &format!("b");
|
||||||
LL + let b: String = format!("b");
|
LL + let b: String = format!("b");
|
||||||
|
|
|
|
||||||
|
help: alternatively, consider changing the type annotation
|
||||||
|
|
|
||||||
|
LL | let b: &String = &format!("b");
|
||||||
|
| +
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/format-borrow.rs:6:21
|
--> $DIR/format-borrow.rs:6:21
|
||||||
@ -39,6 +47,10 @@ help: consider removing the borrow
|
|||||||
LL - let c: String = &mut format!("c");
|
LL - let c: String = &mut format!("c");
|
||||||
LL + let c: String = format!("c");
|
LL + let c: String = format!("c");
|
||||||
|
|
|
|
||||||
|
help: alternatively, consider changing the type annotation
|
||||||
|
|
|
||||||
|
LL | let c: &mut String = &mut format!("c");
|
||||||
|
| ++++
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/format-borrow.rs:8:21
|
--> $DIR/format-borrow.rs:8:21
|
||||||
@ -53,6 +65,10 @@ help: consider removing the borrow
|
|||||||
LL - let d: String = &mut (format!("d"));
|
LL - let d: String = &mut (format!("d"));
|
||||||
LL + let d: String = format!("d"));
|
LL + let d: String = format!("d"));
|
||||||
|
|
|
|
||||||
|
help: alternatively, consider changing the type annotation
|
||||||
|
|
|
||||||
|
LL | let d: &mut String = &mut (format!("d"));
|
||||||
|
| ++++
|
||||||
|
|
||||||
error: aborting due to 4 previous errors
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
25
src/test/ui/suggestions/issue-102892.rs
Normal file
25
src/test/ui/suggestions/issue-102892.rs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#![allow(dead_code, unused_variables)]
|
||||||
|
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct A;
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct B;
|
||||||
|
|
||||||
|
fn process_without_annot(arc: &Arc<(A, B)>) {
|
||||||
|
let (a, b) = **arc; // suggests putting `&**arc` here; with that, fixed!
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_with_annot(arc: &Arc<(A, B)>) {
|
||||||
|
let (a, b): (A, B) = &**arc; // suggests putting `&**arc` here too
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_with_tuple_annot(mutation: &mut (A, B), arc: &Arc<(A, B)>) {
|
||||||
|
let (a, b): ((A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
//~| ERROR mismatched types
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
57
src/test/ui/suggestions/issue-102892.stderr
Normal file
57
src/test/ui/suggestions/issue-102892.stderr
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/issue-102892.rs:15:26
|
||||||
|
|
|
||||||
|
LL | let (a, b): (A, B) = &**arc; // suggests putting `&**arc` here too
|
||||||
|
| ------ ^^^^^^ expected tuple, found `&(A, B)`
|
||||||
|
| |
|
||||||
|
| expected due to this
|
||||||
|
|
|
||||||
|
= note: expected tuple `(A, B)`
|
||||||
|
found reference `&(A, B)`
|
||||||
|
help: consider removing the borrow
|
||||||
|
|
|
||||||
|
LL - let (a, b): (A, B) = &**arc; // suggests putting `&**arc` here too
|
||||||
|
LL + let (a, b): (A, B) = **arc; // suggests putting `&**arc` here too
|
||||||
|
|
|
||||||
|
help: alternatively, consider changing the type annotation
|
||||||
|
|
|
||||||
|
LL | let (a, b): &(A, B) = &**arc; // suggests putting `&**arc` here too
|
||||||
|
| +
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/issue-102892.rs:20:32
|
||||||
|
|
|
||||||
|
LL | let (a, b): ((A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too
|
||||||
|
| ^^^^^^^^^^^^^^ expected tuple, found `&mut (A, B)`
|
||||||
|
|
|
||||||
|
= note: expected tuple `(A, B)`
|
||||||
|
found mutable reference `&mut (A, B)`
|
||||||
|
help: consider removing the borrow
|
||||||
|
|
|
||||||
|
LL - let (a, b): ((A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too
|
||||||
|
LL + let (a, b): ((A, B), A) = (*mutation, &(**arc).0); // suggests putting `&**arc` here too
|
||||||
|
|
|
||||||
|
help: alternatively, consider changing the type annotation
|
||||||
|
|
|
||||||
|
LL | let (a, b): (&mut (A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too
|
||||||
|
| ++++
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/issue-102892.rs:20:48
|
||||||
|
|
|
||||||
|
LL | let (a, b): ((A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too
|
||||||
|
| ^^^^^^^^^^ expected struct `A`, found `&A`
|
||||||
|
|
|
||||||
|
help: consider removing the borrow
|
||||||
|
|
|
||||||
|
LL - let (a, b): ((A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too
|
||||||
|
LL + let (a, b): ((A, B), A) = (&mut *mutation, (**arc).0); // suggests putting `&**arc` here too
|
||||||
|
|
|
||||||
|
help: alternatively, consider changing the type annotation
|
||||||
|
|
|
||||||
|
LL | let (a, b): ((A, B), &A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too
|
||||||
|
| +
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
Loading…
Reference in New Issue
Block a user