@@ -109,8 +109,10 @@ enum ResolutionError<'a> {
109
109
TypeNotMemberOfTrait ( Name , & ' a str ) ,
110
110
/// error E0438: const is not a member of trait
111
111
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 ) > ) ,
114
116
/// error E0409: variable is bound with different mode in pattern #{} than in pattern #1
115
117
VariableBoundWithDifferentMode ( Name , usize , Span ) ,
116
118
/// 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,
204
206
err. span_label ( span, & format ! ( "not a member of trait `{}`" , trait_) ) ;
205
207
err
206
208
}
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( ", " ) ) ) ;
216
256
err
217
257
}
218
258
ResolutionError :: VariableBoundWithDifferentMode ( variable_name,
@@ -324,7 +364,7 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
324
364
}
325
365
}
326
366
327
- #[ derive( Copy , Clone ) ]
367
+ #[ derive( Copy , Clone , Debug ) ]
328
368
struct BindingInfo {
329
369
span : Span ,
330
370
binding_mode : BindingMode ,
@@ -1867,14 +1907,20 @@ impl<'a> Resolver<'a> {
1867
1907
return ;
1868
1908
}
1869
1909
let map_0 = self . binding_mode_map ( & arm. pats [ 0 ] ) ;
1910
+
1911
+ let mut missing_vars = FxHashMap ( ) ;
1912
+ let mut extra_vars = vec ! [ ] ;
1913
+
1870
1914
for ( i, p) in arm. pats . iter ( ) . enumerate ( ) {
1871
1915
let map_i = self . binding_mode_map ( & p) ;
1872
1916
1873
1917
for ( & key, & binding_0) in & map_0 {
1874
1918
match map_i. get ( & key) {
1875
1919
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 ) ) ;
1878
1924
}
1879
1925
Some ( binding_i) => {
1880
1926
if binding_0. binding_mode != binding_i. binding_mode {
@@ -1891,12 +1937,20 @@ impl<'a> Resolver<'a> {
1891
1937
1892
1938
for ( & key, & binding) in & map_i {
1893
1939
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 ) ) ;
1897
1941
}
1898
1942
}
1899
1943
}
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
+ }
1900
1954
}
1901
1955
1902
1956
fn resolve_arm ( & mut self , arm : & Arm ) {
0 commit comments