@@ -27,9 +27,17 @@ use syntax_pos::Span;
27
27
28
28
impl < ' a , ' gcx , ' tcx > FnCtxt < ' a , ' gcx , ' tcx > {
29
29
pub fn check_pat ( & self , pat : & ' gcx hir:: Pat , expected : Ty < ' tcx > ) {
30
+ self . check_pat_arg ( pat, expected, false ) ;
31
+ }
32
+
33
+ /// The `is_arg` argument indicates whether this pattern is the
34
+ /// *outermost* pattern in an argument (e.g., in `fn foo(&x:
35
+ /// &u32)`, it is true for the `&x` pattern but not `x`). This is
36
+ /// used to tailor error reporting.
37
+ pub fn check_pat_arg ( & self , pat : & ' gcx hir:: Pat , expected : Ty < ' tcx > , is_arg : bool ) {
30
38
let tcx = self . tcx ;
31
39
32
- debug ! ( "check_pat(pat={:?},expected={:?})" , pat, expected) ;
40
+ debug ! ( "check_pat(pat={:?},expected={:?},is_arg={} )" , pat, expected, is_arg ) ;
33
41
34
42
let ty = match pat. node {
35
43
PatKind :: Wild => {
@@ -202,6 +210,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
202
210
// can, to avoid creating needless variables. This
203
211
// also helps with the bad interactions of the given
204
212
// hack detailed in (*) below.
213
+ debug ! ( "check_pat_arg: expected={:?}" , expected) ;
205
214
let ( rptr_ty, inner_ty) = match expected. sty {
206
215
ty:: TyRef ( _, mt) if mt. mutbl == mutbl => {
207
216
( expected, mt. ty )
@@ -212,7 +221,25 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
212
221
let mt = ty:: TypeAndMut { ty : inner_ty, mutbl : mutbl } ;
213
222
let region = self . next_region_var ( infer:: PatternRegion ( pat. span ) ) ;
214
223
let rptr_ty = tcx. mk_ref ( region, mt) ;
215
- self . demand_eqtype ( pat. span , expected, rptr_ty) ;
224
+ debug ! ( "check_pat_arg: demanding {:?} = {:?}" , expected, rptr_ty) ;
225
+ let err = self . demand_eqtype_diag ( pat. span , expected, rptr_ty) ;
226
+
227
+ // Look for a case like `fn foo(&foo: u32)` and suggest
228
+ // `fn foo(foo: &u32)`
229
+ if let Some ( mut err) = err {
230
+ if is_arg {
231
+ if let PatKind :: Binding ( ..) = inner. node {
232
+ if let Ok ( snippet) = self . sess ( ) . codemap ( )
233
+ . span_to_snippet ( pat. span )
234
+ {
235
+ err. help ( & format ! ( "did you mean `{}: &{}`?" ,
236
+ & snippet[ 1 ..] ,
237
+ expected) ) ;
238
+ }
239
+ }
240
+ }
241
+ err. emit ( ) ;
242
+ }
216
243
( rptr_ty, inner_ty)
217
244
}
218
245
} ;
0 commit comments