Skip to content

Commit bf6bfcd

Browse files
authored
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
2 parents a5406fe + 0fca075 commit bf6bfcd

File tree

5 files changed

+160
-4
lines changed

5 files changed

+160
-4
lines changed

compiler/rustc_hir_typeck/src/demand.rs

+18-1
Original file line numberDiff line numberDiff line change
@@ -714,7 +714,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
714714
expr: &hir::Expr<'tcx>,
715715
checked_ty: Ty<'tcx>,
716716
expected: Ty<'tcx>,
717-
) -> Option<(Span, String, String, Applicability, bool /* verbose */)> {
717+
) -> Option<(
718+
Span,
719+
String,
720+
String,
721+
Applicability,
722+
bool, /* verbose */
723+
bool, /* suggest `&` or `&mut` type annotation */
724+
)> {
718725
let sess = self.sess();
719726
let sp = expr.span;
720727

@@ -746,6 +753,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
746753
String::new(),
747754
Applicability::MachineApplicable,
748755
true,
756+
false,
749757
));
750758
}
751759
}
@@ -760,6 +768,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
760768
"b".to_string(),
761769
Applicability::MachineApplicable,
762770
true,
771+
false,
763772
));
764773
}
765774
}
@@ -817,6 +826,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
817826
sugg.2,
818827
Applicability::MachineApplicable,
819828
false,
829+
false,
820830
));
821831
}
822832

@@ -844,13 +854,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
844854
format!("{prefix}&mut {sugg_expr}"),
845855
Applicability::MachineApplicable,
846856
false,
857+
false,
847858
),
848859
hir::Mutability::Not => (
849860
sp,
850861
"consider borrowing here".to_string(),
851862
format!("{prefix}&{sugg_expr}"),
852863
Applicability::MachineApplicable,
853864
false,
865+
false,
854866
),
855867
});
856868
}
@@ -880,6 +892,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
880892
String::new(),
881893
Applicability::MachineApplicable,
882894
true,
895+
true
883896
));
884897
}
885898
return None;
@@ -893,6 +906,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
893906
String::new(),
894907
Applicability::MachineApplicable,
895908
true,
909+
true,
896910
));
897911
}
898912
}
@@ -959,6 +973,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
959973
src,
960974
applicability,
961975
true,
976+
false,
962977
));
963978
}
964979
}
@@ -999,6 +1014,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
9991014
Applicability::MachineApplicable
10001015
},
10011016
true,
1017+
false,
10021018
));
10031019
}
10041020

@@ -1050,6 +1066,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10501066
suggestion,
10511067
Applicability::MachineApplicable,
10521068
true,
1069+
false,
10531070
));
10541071
}
10551072
}

compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs

+44-3
Original file line numberDiff line numberDiff line change
@@ -327,17 +327,58 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
327327
expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
328328
) -> bool {
329329
let expr = expr.peel_blocks();
330-
if let Some((sp, msg, suggestion, applicability, verbose)) =
330+
if let Some((sp, msg, suggestion, applicability, verbose, annotation)) =
331331
self.check_ref(expr, found, expected)
332332
{
333333
if verbose {
334334
err.span_suggestion_verbose(sp, &msg, suggestion, applicability);
335335
} else {
336336
err.span_suggestion(sp, &msg, suggestion, applicability);
337337
}
338+
if annotation {
339+
let suggest_annotation = match expr.peel_drop_temps().kind {
340+
hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, _) => "&",
341+
hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mut, _) => "&mut ",
342+
_ => return true,
343+
};
344+
let mut tuple_indexes = Vec::new();
345+
let mut expr_id = expr.hir_id;
346+
for (parent_id, node) in self.tcx.hir().parent_iter(expr.hir_id) {
347+
match node {
348+
Node::Expr(&Expr { kind: ExprKind::Tup(subs), .. }) => {
349+
tuple_indexes.push(
350+
subs.iter()
351+
.enumerate()
352+
.find(|(_, sub_expr)| sub_expr.hir_id == expr_id)
353+
.unwrap()
354+
.0,
355+
);
356+
expr_id = parent_id;
357+
}
358+
Node::Local(local) => {
359+
if let Some(mut ty) = local.ty {
360+
while let Some(index) = tuple_indexes.pop() {
361+
match ty.kind {
362+
TyKind::Tup(tys) => ty = &tys[index],
363+
_ => return true,
364+
}
365+
}
366+
let annotation_span = ty.span;
367+
err.span_suggestion(
368+
annotation_span.with_hi(annotation_span.lo()),
369+
format!("alternatively, consider changing the type annotation"),
370+
suggest_annotation,
371+
Applicability::MaybeIncorrect,
372+
);
373+
}
374+
break;
375+
}
376+
_ => break,
377+
}
378+
}
379+
}
338380
return true;
339-
} else if self.suggest_else_fn_with_closure(err, expr, found, expected)
340-
{
381+
} else if self.suggest_else_fn_with_closure(err, expr, found, expected) {
341382
return true;
342383
} else if self.suggest_fn_call(err, expr, found, |output| self.can_coerce(output, expected))
343384
&& let ty::FnDef(def_id, ..) = &found.kind()

src/test/ui/suggestions/format-borrow.stderr

+16
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ help: consider removing the borrow
1111
LL - let a: String = &String::from("a");
1212
LL + let a: String = String::from("a");
1313
|
14+
help: alternatively, consider changing the type annotation
15+
|
16+
LL | let a: &String = &String::from("a");
17+
| +
1418

1519
error[E0308]: mismatched types
1620
--> $DIR/format-borrow.rs:4:21
@@ -25,6 +29,10 @@ help: consider removing the borrow
2529
LL - let b: String = &format!("b");
2630
LL + let b: String = format!("b");
2731
|
32+
help: alternatively, consider changing the type annotation
33+
|
34+
LL | let b: &String = &format!("b");
35+
| +
2836

2937
error[E0308]: mismatched types
3038
--> $DIR/format-borrow.rs:6:21
@@ -39,6 +47,10 @@ help: consider removing the borrow
3947
LL - let c: String = &mut format!("c");
4048
LL + let c: String = format!("c");
4149
|
50+
help: alternatively, consider changing the type annotation
51+
|
52+
LL | let c: &mut String = &mut format!("c");
53+
| ++++
4254

4355
error[E0308]: mismatched types
4456
--> $DIR/format-borrow.rs:8:21
@@ -53,6 +65,10 @@ help: consider removing the borrow
5365
LL - let d: String = &mut (format!("d"));
5466
LL + let d: String = format!("d"));
5567
|
68+
help: alternatively, consider changing the type annotation
69+
|
70+
LL | let d: &mut String = &mut (format!("d"));
71+
| ++++
5672

5773
error: aborting due to 4 previous errors
5874

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#![allow(dead_code, unused_variables)]
2+
3+
use std::sync::Arc;
4+
5+
#[derive(Debug)]
6+
struct A;
7+
#[derive(Debug)]
8+
struct B;
9+
10+
fn process_without_annot(arc: &Arc<(A, B)>) {
11+
let (a, b) = **arc; // suggests putting `&**arc` here; with that, fixed!
12+
}
13+
14+
fn process_with_annot(arc: &Arc<(A, B)>) {
15+
let (a, b): (A, B) = &**arc; // suggests putting `&**arc` here too
16+
//~^ ERROR mismatched types
17+
}
18+
19+
fn process_with_tuple_annot(mutation: &mut (A, B), arc: &Arc<(A, B)>) {
20+
let (a, b): ((A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too
21+
//~^ ERROR mismatched types
22+
//~| ERROR mismatched types
23+
}
24+
25+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/issue-102892.rs:15:26
3+
|
4+
LL | let (a, b): (A, B) = &**arc; // suggests putting `&**arc` here too
5+
| ------ ^^^^^^ expected tuple, found `&(A, B)`
6+
| |
7+
| expected due to this
8+
|
9+
= note: expected tuple `(A, B)`
10+
found reference `&(A, B)`
11+
help: consider removing the borrow
12+
|
13+
LL - let (a, b): (A, B) = &**arc; // suggests putting `&**arc` here too
14+
LL + let (a, b): (A, B) = **arc; // suggests putting `&**arc` here too
15+
|
16+
help: alternatively, consider changing the type annotation
17+
|
18+
LL | let (a, b): &(A, B) = &**arc; // suggests putting `&**arc` here too
19+
| +
20+
21+
error[E0308]: mismatched types
22+
--> $DIR/issue-102892.rs:20:32
23+
|
24+
LL | let (a, b): ((A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too
25+
| ^^^^^^^^^^^^^^ expected tuple, found `&mut (A, B)`
26+
|
27+
= note: expected tuple `(A, B)`
28+
found mutable reference `&mut (A, B)`
29+
help: consider removing the borrow
30+
|
31+
LL - let (a, b): ((A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too
32+
LL + let (a, b): ((A, B), A) = (*mutation, &(**arc).0); // suggests putting `&**arc` here too
33+
|
34+
help: alternatively, consider changing the type annotation
35+
|
36+
LL | let (a, b): (&mut (A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too
37+
| ++++
38+
39+
error[E0308]: mismatched types
40+
--> $DIR/issue-102892.rs:20:48
41+
|
42+
LL | let (a, b): ((A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too
43+
| ^^^^^^^^^^ expected struct `A`, found `&A`
44+
|
45+
help: consider removing the borrow
46+
|
47+
LL - let (a, b): ((A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too
48+
LL + let (a, b): ((A, B), A) = (&mut *mutation, (**arc).0); // suggests putting `&**arc` here too
49+
|
50+
help: alternatively, consider changing the type annotation
51+
|
52+
LL | let (a, b): ((A, B), &A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too
53+
| +
54+
55+
error: aborting due to 3 previous errors
56+
57+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)