@@ -23,9 +23,7 @@ use std::collections::hash_map::Entry::{Occupied, Vacant};
2323use std:: cmp;
2424use syntax:: ast;
2525use syntax:: codemap:: Spanned ;
26- use syntax:: errors:: DiagnosticBuilder ;
2726use syntax:: feature_gate;
28- use syntax:: parse:: ParseSess ;
2927use syntax:: ptr:: P ;
3028use syntax_pos:: Span ;
3129
@@ -122,32 +120,35 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
122120 . pat_adjustments_mut ( )
123121 . insert ( pat. hir_id , pat_adjustments) ;
124122 } 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 ;
142133 }
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) ) ;
150150 }
151+ err. emit ( ) ;
151152 }
152153 }
153154 }
0 commit comments