Skip to content

Commit

Permalink
Rollup merge of rust-lang#102951 - SparrowLii:type_annotation, r=este…
Browse files Browse the repository at this point in the history
…bank

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 rust-lang#102892
  • Loading branch information
Dylan-DPC authored Oct 25, 2022
2 parents 8c5d4e6 + 0fca075 commit ba39aab
Show file tree
Hide file tree
Showing 5 changed files with 160 additions and 4 deletions.
19 changes: 18 additions & 1 deletion compiler/rustc_hir_typeck/src/demand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -714,7 +714,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expr: &hir::Expr<'tcx>,
checked_ty: 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 sp = expr.span;

Expand Down Expand Up @@ -746,6 +753,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
String::new(),
Applicability::MachineApplicable,
true,
false,
));
}
}
Expand All @@ -760,6 +768,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
"b".to_string(),
Applicability::MachineApplicable,
true,
false,
));
}
}
Expand Down Expand Up @@ -817,6 +826,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
sugg.2,
Applicability::MachineApplicable,
false,
false,
));
}

Expand Down Expand Up @@ -844,13 +854,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
format!("{prefix}&mut {sugg_expr}"),
Applicability::MachineApplicable,
false,
false,
),
hir::Mutability::Not => (
sp,
"consider borrowing here".to_string(),
format!("{prefix}&{sugg_expr}"),
Applicability::MachineApplicable,
false,
false,
),
});
}
Expand Down Expand Up @@ -880,6 +892,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
String::new(),
Applicability::MachineApplicable,
true,
true
));
}
return None;
Expand All @@ -893,6 +906,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
String::new(),
Applicability::MachineApplicable,
true,
true,
));
}
}
Expand Down Expand Up @@ -959,6 +973,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
src,
applicability,
true,
false,
));
}
}
Expand Down Expand Up @@ -999,6 +1014,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Applicability::MachineApplicable
},
true,
false,
));
}

Expand Down Expand Up @@ -1050,6 +1066,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
suggestion,
Applicability::MachineApplicable,
true,
false,
));
}
}
Expand Down
47 changes: 44 additions & 3 deletions compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -327,17 +327,58 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
) -> bool {
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)
{
if verbose {
err.span_suggestion_verbose(sp, &msg, suggestion, applicability);
} else {
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;
} 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;
} else if self.suggest_fn_call(err, expr, found, |output| self.can_coerce(output, expected))
&& let ty::FnDef(def_id, ..) = &found.kind()
Expand Down
16 changes: 16 additions & 0 deletions src/test/ui/suggestions/format-borrow.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ help: consider removing the borrow
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
--> $DIR/format-borrow.rs:4:21
Expand All @@ -25,6 +29,10 @@ help: consider removing the borrow
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
--> $DIR/format-borrow.rs:6:21
Expand All @@ -39,6 +47,10 @@ help: consider removing the borrow
LL - let c: String = &mut 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
--> $DIR/format-borrow.rs:8:21
Expand All @@ -53,6 +65,10 @@ help: consider removing the borrow
LL - let d: String = &mut (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

Expand Down
25 changes: 25 additions & 0 deletions src/test/ui/suggestions/issue-102892.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 57 additions & 0 deletions src/test/ui/suggestions/issue-102892.stderr
Original file line number Diff line number Diff line change
@@ -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`.

0 comments on commit ba39aab

Please sign in to comment.