Skip to content

Commit 22bd72a

Browse files
authored
Rollup merge of rust-lang#60393 - estebank:pat-sugg, r=oli-obk
Do not suggest incorrect syntax on pattern type error due to borrow Fix rust-lang#55174.
2 parents d38096a + ed08c6a commit 22bd72a

File tree

5 files changed

+151
-17
lines changed

5 files changed

+151
-17
lines changed

src/librustc_typeck/check/_match.rs

+46-11
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use crate::check::{FnCtxt, Expectation, Diverges, Needs};
22
use crate::check::coercion::CoerceMany;
33
use crate::util::nodemap::FxHashMap;
4-
use errors::Applicability;
5-
use rustc::hir::{self, PatKind};
4+
use errors::{Applicability, DiagnosticBuilder};
5+
use rustc::hir::{self, PatKind, Pat};
66
use rustc::hir::def::{Def, CtorKind};
77
use rustc::hir::pat_util::EnumerateAndAdjustIterator;
88
use rustc::infer;
@@ -377,15 +377,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
377377
// Look for a case like `fn foo(&foo: u32)` and suggest
378378
// `fn foo(foo: &u32)`
379379
if let Some(mut err) = err {
380-
if let PatKind::Binding(..) = inner.node {
381-
if let Ok(snippet) = tcx.sess.source_map()
382-
.span_to_snippet(pat.span)
383-
{
384-
err.help(&format!("did you mean `{}: &{}`?",
385-
&snippet[1..],
386-
expected));
387-
}
388-
}
380+
self.borrow_pat_suggestion(&mut err, &pat, &inner, &expected);
389381
err.emit();
390382
}
391383
(rptr_ty, inner_ty)
@@ -517,6 +509,49 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
517509
// subtyping.
518510
}
519511

512+
fn borrow_pat_suggestion(
513+
&self,
514+
err: &mut DiagnosticBuilder<'_>,
515+
pat: &Pat,
516+
inner: &Pat,
517+
expected: Ty<'tcx>,
518+
) {
519+
let tcx = self.tcx;
520+
if let PatKind::Binding(..) = inner.node {
521+
let parent_id = tcx.hir().get_parent_node_by_hir_id(pat.hir_id);
522+
let parent = tcx.hir().get_by_hir_id(parent_id);
523+
debug!("inner {:?} pat {:?} parent {:?}", inner, pat, parent);
524+
match parent {
525+
hir::Node::Item(hir::Item { node: hir::ItemKind::Fn(..), .. }) |
526+
hir::Node::ForeignItem(hir::ForeignItem {
527+
node: hir::ForeignItemKind::Fn(..), ..
528+
}) |
529+
hir::Node::TraitItem(hir::TraitItem { node: hir::TraitItemKind::Method(..), .. }) |
530+
hir::Node::ImplItem(hir::ImplItem { node: hir::ImplItemKind::Method(..), .. }) => {
531+
// this pat is likely an argument
532+
if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(inner.span) {
533+
// FIXME: turn into structured suggestion, will need a span that also
534+
// includes the the arg's type.
535+
err.help(&format!("did you mean `{}: &{}`?", snippet, expected));
536+
}
537+
}
538+
hir::Node::Expr(hir::Expr { node: hir::ExprKind::Match(..), .. }) |
539+
hir::Node::Pat(_) => {
540+
// rely on match ergonomics or it might be nested `&&pat`
541+
if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(inner.span) {
542+
err.span_suggestion(
543+
pat.span,
544+
"you can probably remove the explicit borrow",
545+
snippet,
546+
Applicability::MaybeIncorrect,
547+
);
548+
}
549+
}
550+
_ => {} // don't provide suggestions in other cases #55175
551+
}
552+
}
553+
}
554+
520555
pub fn check_dereferencable(&self, span: Span, expected: Ty<'tcx>, inner: &hir::Pat) -> bool {
521556
if let PatKind::Binding(..) = inner.node {
522557
if let Some(mt) = self.shallow_resolve(expected).builtin_deref(true) {

src/test/ui/destructure-trait-ref.stderr

+8-4
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,25 @@ error[E0308]: mismatched types
2020
--> $DIR/destructure-trait-ref.rs:31:10
2121
|
2222
LL | let &&x = &1isize as &T;
23-
| ^^ expected trait T, found reference
23+
| ^^
24+
| |
25+
| expected trait T, found reference
26+
| help: you can probably remove the explicit borrow: `x`
2427
|
2528
= note: expected type `dyn T`
2629
found type `&_`
27-
= help: did you mean `x: &dyn T`?
2830

2931
error[E0308]: mismatched types
3032
--> $DIR/destructure-trait-ref.rs:36:11
3133
|
3234
LL | let &&&x = &(&1isize as &T);
33-
| ^^ expected trait T, found reference
35+
| ^^
36+
| |
37+
| expected trait T, found reference
38+
| help: you can probably remove the explicit borrow: `x`
3439
|
3540
= note: expected type `dyn T`
3641
found type `&_`
37-
= help: did you mean `x: &dyn T`?
3842

3943
error[E0308]: mismatched types
4044
--> $DIR/destructure-trait-ref.rs:41:13

src/test/ui/mismatched_types/issue-38371.stderr

+4-2
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@ error[E0308]: mismatched types
1212
--> $DIR/issue-38371.rs:18:9
1313
|
1414
LL | fn agh(&&bar: &u32) {
15-
| ^^^^ expected u32, found reference
15+
| ^^^^
16+
| |
17+
| expected u32, found reference
18+
| help: you can probably remove the explicit borrow: `bar`
1619
|
1720
= note: expected type `u32`
1821
found type `&_`
19-
= help: did you mean `bar: &u32`?
2022

2123
error[E0308]: mismatched types
2224
--> $DIR/issue-38371.rs:21:8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
fn main() {
2+
let x = vec![1i32];
3+
match &x[..] {
4+
[&v] => {}, //~ ERROR mismatched types
5+
_ => {},
6+
}
7+
match x {
8+
[&v] => {}, //~ ERROR expected an array or slice
9+
_ => {},
10+
}
11+
match &x[..] {
12+
[v] => {},
13+
_ => {},
14+
}
15+
match &x[..] {
16+
&[v] => {},
17+
_ => {},
18+
}
19+
match x {
20+
[v] => {}, //~ ERROR expected an array or slice
21+
_ => {},
22+
}
23+
let y = 1i32;
24+
match &y {
25+
&v => {},
26+
_ => {},
27+
}
28+
match y {
29+
&v => {}, //~ ERROR mismatched types
30+
_ => {},
31+
}
32+
match &y {
33+
v => {},
34+
_ => {},
35+
}
36+
match y {
37+
v => {},
38+
_ => {},
39+
}
40+
if let [&v] = &x[..] {} //~ ERROR mismatched types
41+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/match-ergonomics.rs:4:10
3+
|
4+
LL | [&v] => {},
5+
| ^^
6+
| |
7+
| expected i32, found reference
8+
| help: you can probably remove the explicit borrow: `v`
9+
|
10+
= note: expected type `i32`
11+
found type `&_`
12+
13+
error[E0529]: expected an array or slice, found `std::vec::Vec<i32>`
14+
--> $DIR/match-ergonomics.rs:8:9
15+
|
16+
LL | [&v] => {},
17+
| ^^^^ pattern cannot match with input type `std::vec::Vec<i32>`
18+
19+
error[E0529]: expected an array or slice, found `std::vec::Vec<i32>`
20+
--> $DIR/match-ergonomics.rs:20:9
21+
|
22+
LL | [v] => {},
23+
| ^^^ pattern cannot match with input type `std::vec::Vec<i32>`
24+
25+
error[E0308]: mismatched types
26+
--> $DIR/match-ergonomics.rs:29:9
27+
|
28+
LL | &v => {},
29+
| ^^
30+
| |
31+
| expected i32, found reference
32+
| help: you can probably remove the explicit borrow: `v`
33+
|
34+
= note: expected type `i32`
35+
found type `&_`
36+
37+
error[E0308]: mismatched types
38+
--> $DIR/match-ergonomics.rs:40:13
39+
|
40+
LL | if let [&v] = &x[..] {}
41+
| ^^
42+
| |
43+
| expected i32, found reference
44+
| help: you can probably remove the explicit borrow: `v`
45+
|
46+
= note: expected type `i32`
47+
found type `&_`
48+
49+
error: aborting due to 5 previous errors
50+
51+
Some errors have detailed explanations: E0308, E0529.
52+
For more information about an error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)