@@ -109,8 +109,10 @@ enum ResolutionError<'a> {
109109 TypeNotMemberOfTrait ( Name , & ' a str ) ,
110110 /// error E0438: const is not a member of trait
111111 ConstNotMemberOfTrait ( Name , & ' a str ) ,
112- /// error E0408: variable `{}` from pattern #{} is not bound in pattern #{}
113- VariableNotBoundInPattern ( Name , usize , usize ) ,
112+ /// error E0408: variable `{}` from pattern #{} is not bound in pattern #1
113+ VariableNotBoundInPattern ( Name , Span , Vec < ( Span , usize ) > ) ,
114+ /// error E0408: variable `{}` from pattern #1 is not bound in pattern #{}
115+ VariableNotBoundInFirstPattern ( Span , Vec < ( Name , usize , Span ) > ) ,
114116 /// error E0409: variable is bound with different mode in pattern #{} than in pattern #1
115117 VariableBoundWithDifferentMode ( Name , usize , Span ) ,
116118 /// error E0415: identifier is bound more than once in this parameter list
@@ -204,15 +206,53 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
204206 err. span_label ( span, & format ! ( "not a member of trait `{}`" , trait_) ) ;
205207 err
206208 }
207- ResolutionError :: VariableNotBoundInPattern ( variable_name, from, to) => {
208- let mut err = struct_span_err ! ( resolver. session,
209- span,
210- E0408 ,
211- "variable `{}` from pattern #{} is not bound in pattern #{}" ,
212- variable_name,
213- from,
214- to) ;
215- err. span_label ( span, & format ! ( "pattern doesn't bind `{}`" , variable_name) ) ;
209+ ResolutionError :: VariableNotBoundInPattern ( variable_name, sp, missing_vars) => {
210+ let spans: Vec < _ > = missing_vars. iter ( ) . map ( |x| x. 0 ) . collect ( ) ;
211+ let msp = MultiSpan :: from_spans ( spans. clone ( ) ) ;
212+ // "variable `a` from pattern #1 is not bound in patterns #2, #3"
213+ let msg = format ! ( "variable `{}` from pattern #1 isn't bound in pattern{} {}" ,
214+ variable_name,
215+ if spans. len( ) > 1 {
216+ "s"
217+ } else {
218+ ""
219+ } ,
220+ missing_vars. iter( )
221+ . map( |x| format!( "#{}" , x. 1 ) )
222+ . collect:: <Vec <_>>( )
223+ . join( ", " ) ) ;
224+ let mut err = resolver. session . struct_span_err_with_code ( msp, & msg, "E0408" ) ;
225+ for sp in spans {
226+ err. span_label ( sp, & format ! ( "pattern doesn't bind `{}`" , variable_name) ) ;
227+ }
228+ err. span_label ( sp, & "variable not in all patterns" ) ;
229+ err
230+ }
231+ ResolutionError :: VariableNotBoundInFirstPattern ( sp, extra_vars) => {
232+ let spans: Vec < _ > = extra_vars. iter ( ) . map ( |x| x. 2 ) . collect ( ) ;
233+ let msp = MultiSpan :: from_spans ( spans. clone ( ) ) ;
234+ // "variable `b` from pattern #2, variable `c` from pattern #3 aren't bound in pattern
235+ // #1"
236+ let msg = format ! ( "{} {}n't bound in pattern #1" ,
237+ extra_vars. iter( )
238+ . map( |x| format!( "variable `{}` from pattern #{}" , x. 0 , x. 1 ) )
239+ . collect:: <Vec <_>>( )
240+ . join( ", " ) ,
241+ if spans. len( ) > 1 {
242+ "are"
243+ } else {
244+ "is"
245+ } ) ;
246+ let mut err = resolver. session . struct_span_err_with_code ( msp, & msg, "E0408" ) ;
247+ for sp in spans {
248+ err. span_label ( sp, & "variable not in all patterns" ) ;
249+ }
250+ err. span_label ( sp,
251+ & format ! ( "pattern doesn't bind {}" ,
252+ extra_vars. iter( )
253+ . map( |x| format!( "`{}`" , x. 0 ) )
254+ . collect:: <Vec <_>>( )
255+ . join( ", " ) ) ) ;
216256 err
217257 }
218258 ResolutionError :: VariableBoundWithDifferentMode ( variable_name,
@@ -324,7 +364,7 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
324364 }
325365}
326366
327- #[ derive( Copy , Clone ) ]
367+ #[ derive( Copy , Clone , Debug ) ]
328368struct BindingInfo {
329369 span : Span ,
330370 binding_mode : BindingMode ,
@@ -1867,14 +1907,20 @@ impl<'a> Resolver<'a> {
18671907 return ;
18681908 }
18691909 let map_0 = self . binding_mode_map ( & arm. pats [ 0 ] ) ;
1910+
1911+ let mut missing_vars = FxHashMap ( ) ;
1912+ let mut extra_vars = vec ! [ ] ;
1913+
18701914 for ( i, p) in arm. pats . iter ( ) . enumerate ( ) {
18711915 let map_i = self . binding_mode_map ( & p) ;
18721916
18731917 for ( & key, & binding_0) in & map_0 {
18741918 match map_i. get ( & key) {
18751919 None => {
1876- let error = ResolutionError :: VariableNotBoundInPattern ( key. name , 1 , i + 1 ) ;
1877- resolve_error ( self , p. span , error) ;
1920+ let spans = missing_vars
1921+ . entry ( ( key. name , binding_0. span ) )
1922+ . or_insert ( vec ! [ ] ) ;
1923+ spans. push ( ( p. span , i + 1 ) ) ;
18781924 }
18791925 Some ( binding_i) => {
18801926 if binding_0. binding_mode != binding_i. binding_mode {
@@ -1891,12 +1937,20 @@ impl<'a> Resolver<'a> {
18911937
18921938 for ( & key, & binding) in & map_i {
18931939 if !map_0. contains_key ( & key) {
1894- resolve_error ( self ,
1895- binding. span ,
1896- ResolutionError :: VariableNotBoundInPattern ( key. name , i + 1 , 1 ) ) ;
1940+ extra_vars. push ( ( key. name , i + 1 , binding. span ) ) ;
18971941 }
18981942 }
18991943 }
1944+ for ( k, v) in missing_vars {
1945+ let ( name, sp) = k;
1946+ resolve_error ( self , sp, ResolutionError :: VariableNotBoundInPattern ( name, sp, v) ) ;
1947+ }
1948+ if extra_vars. len ( ) > 0 {
1949+ resolve_error ( self ,
1950+ arm. pats [ 0 ] . span ,
1951+ ResolutionError :: VariableNotBoundInFirstPattern ( arm. pats [ 0 ] . span ,
1952+ extra_vars) ) ;
1953+ }
19001954 }
19011955
19021956 fn resolve_arm ( & mut self , arm : & Arm ) {
0 commit comments