@@ -23,9 +23,7 @@ use std::collections::hash_map::Entry::{Occupied, Vacant};
23
23
use std:: cmp;
24
24
use syntax:: ast;
25
25
use syntax:: codemap:: Spanned ;
26
- use syntax:: errors:: DiagnosticBuilder ;
27
26
use syntax:: feature_gate;
28
- use syntax:: parse:: ParseSess ;
29
27
use syntax:: ptr:: P ;
30
28
use syntax_pos:: Span ;
31
29
@@ -122,32 +120,35 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
122
120
. pat_adjustments_mut ( )
123
121
. insert ( pat. hir_id , pat_adjustments) ;
124
122
} else {
125
- fn feature_err < ' a > ( sp : Span , sess : & ' a ParseSess ) -> DiagnosticBuilder < ' a > {
126
- feature_gate:: feature_err (
127
- sess,
128
- "match_default_bindings" ,
129
- sp,
130
- feature_gate:: GateIssue :: Language ,
131
- "non-reference pattern used to match a reference" ,
132
- )
133
- }
134
- if let Ok ( snippet) = tcx. sess . codemap ( ) . span_to_snippet ( pat. span ) {
135
- // The following is a bit of a hack. We probably should check the AST for
136
- // this instead, but this should be good enough for the expected cases.
137
- let prev_span = pat. span . prev_point ( ) ;
138
- let ( sp, sugg) = match tcx. sess . codemap ( ) . span_to_snippet ( prev_span) {
139
- // Make the suggestion more obvious when having `&(_, _)`
140
- Ok ( ref prev) if & * prev == "&" => {
141
- ( prev_span. to ( pat. span ) , format ! ( "&&{}" , & snippet) ) ,
123
+ let mut ref_sp = pat. span ;
124
+ let mut id = pat. id ;
125
+ loop { // make span include all enclosing `&` to avoid confusing diag output
126
+ id = tcx. hir . get_parent_node ( id) ;
127
+ let node = tcx. hir . find ( id) ;
128
+ if let Some ( hir:: map:: NodePat ( pat) ) = node {
129
+ if let hir:: PatKind :: Ref ( ..) = pat. node {
130
+ ref_sp = pat. span ;
131
+ } else {
132
+ break ;
142
133
}
143
- _ => ( pat. span , format ! ( "&{}" , & snippet) ) ,
144
- } ;
145
- let mut err = feature_err ( sp, & tcx. sess . parse_sess ) ;
146
- err. span_suggestion ( sp, "consider using a reference" , sugg) ;
147
- err. emit ( ) ;
148
- } else {
149
- feature_err ( pat. span , & tcx. sess . parse_sess ) . emit ( ) ;
134
+ } else {
135
+ break ;
136
+ }
137
+ }
138
+ let sp = ref_sp. to ( pat. span ) ;
139
+ let mut err = feature_gate:: feature_err (
140
+ & tcx. sess . parse_sess ,
141
+ "match_default_bindings" ,
142
+ sp,
143
+ feature_gate:: GateIssue :: Language ,
144
+ "non-reference pattern used to match a reference" ,
145
+ ) ;
146
+ if let Ok ( snippet) = tcx. sess . codemap ( ) . span_to_snippet ( sp) {
147
+ err. span_suggestion ( sp,
148
+ "consider using a reference" ,
149
+ format ! ( "&{}" , & snippet) ) ;
150
150
}
151
+ err. emit ( ) ;
151
152
}
152
153
}
153
154
}
0 commit comments