Skip to content

Commit a83c3e7

Browse files
committed
Auto merge of #43870 - GuillaumeGomez:deref-suggestion, r=nikomatsakis
Add deref suggestion Fixes #34562.
2 parents 7f8aef9 + 21d4ba2 commit a83c3e7

File tree

3 files changed

+126
-0
lines changed

3 files changed

+126
-0
lines changed

src/librustc_typeck/check/demand.rs

+33
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,39 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
261261
}
262262
None
263263
}
264+
(_, &ty::TyRef(_, checked)) => {
265+
// We have `&T`, check if what was expected was `T`. If so,
266+
// we may want to suggest adding a `*`, or removing
267+
// a `&`.
268+
//
269+
// (But, also check check the `expn_info()` to see if this is
270+
// a macro; if so, it's hard to extract the text and make a good
271+
// suggestion, so don't bother.)
272+
if self.infcx.can_sub(self.param_env, checked.ty, &expected).is_ok() &&
273+
expr.span.ctxt().outer().expn_info().is_none() {
274+
match expr.node {
275+
// Maybe remove `&`?
276+
hir::ExprAddrOf(_, ref expr) => {
277+
if let Ok(code) = self.tcx.sess.codemap().span_to_snippet(expr.span) {
278+
return Some(format!("try with `{}`", code));
279+
}
280+
}
281+
282+
// Maybe add `*`? Only if `T: Copy`.
283+
_ => {
284+
if !self.infcx.type_moves_by_default(self.param_env,
285+
checked.ty,
286+
expr.span) {
287+
let sp = self.sess().codemap().call_span_if_macro(expr.span);
288+
if let Ok(code) = self.tcx.sess.codemap().span_to_snippet(sp) {
289+
return Some(format!("try with `*{}`", code));
290+
}
291+
}
292+
},
293+
}
294+
}
295+
None
296+
}
264297
_ => None,
265298
}
266299
}

src/test/ui/deref-suggestion.rs

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
macro_rules! borrow {
12+
($x:expr) => { &$x }
13+
}
14+
15+
fn foo(_: String) {}
16+
17+
fn foo2(s: &String) {
18+
foo(s);
19+
}
20+
21+
fn foo3(_: u32) {}
22+
fn foo4(u: &u32) {
23+
foo3(u);
24+
}
25+
26+
fn main() {
27+
let s = String::new();
28+
let r_s = &s;
29+
foo2(r_s);
30+
foo(&"aaa".to_owned());
31+
foo(&mut "aaa".to_owned());
32+
foo3(borrow!(0));
33+
foo4(&0);
34+
}

src/test/ui/deref-suggestion.stderr

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/deref-suggestion.rs:18:9
3+
|
4+
18 | foo(s);
5+
| ^ expected struct `std::string::String`, found reference
6+
|
7+
= note: expected type `std::string::String`
8+
found type `&std::string::String`
9+
= help: here are some functions which might fulfill your needs:
10+
- .escape_debug()
11+
- .escape_default()
12+
- .escape_unicode()
13+
- .to_lowercase()
14+
- .to_uppercase()
15+
16+
error[E0308]: mismatched types
17+
--> $DIR/deref-suggestion.rs:23:10
18+
|
19+
23 | foo3(u);
20+
| ^ expected u32, found &u32
21+
|
22+
= note: expected type `u32`
23+
found type `&u32`
24+
= help: try with `*u`
25+
26+
error[E0308]: mismatched types
27+
--> $DIR/deref-suggestion.rs:30:9
28+
|
29+
30 | foo(&"aaa".to_owned());
30+
| ^^^^^^^^^^^^^^^^^ expected struct `std::string::String`, found reference
31+
|
32+
= note: expected type `std::string::String`
33+
found type `&std::string::String`
34+
= help: try with `"aaa".to_owned()`
35+
36+
error[E0308]: mismatched types
37+
--> $DIR/deref-suggestion.rs:31:9
38+
|
39+
31 | foo(&mut "aaa".to_owned());
40+
| ^^^^^^^^^^^^^^^^^^^^^ expected struct `std::string::String`, found mutable reference
41+
|
42+
= note: expected type `std::string::String`
43+
found type `&mut std::string::String`
44+
= help: try with `"aaa".to_owned()`
45+
46+
error[E0308]: mismatched types
47+
--> $DIR/deref-suggestion.rs:12:20
48+
|
49+
12 | ($x:expr) => { &$x }
50+
| ^^^ expected u32, found &{integer}
51+
...
52+
32 | foo3(borrow!(0));
53+
| ---------- in this macro invocation
54+
|
55+
= note: expected type `u32`
56+
found type `&{integer}`
57+
58+
error: aborting due to 5 previous errors
59+

0 commit comments

Comments
 (0)