@@ -3,6 +3,7 @@ use super::{ImplTraitContext, LoweringContext, ParamMode};
3
3
use rustc_ast:: ast:: * ;
4
4
use rustc_ast:: ptr:: P ;
5
5
use rustc_data_structures:: stack:: ensure_sufficient_stack;
6
+ use rustc_errors:: Applicability ;
6
7
use rustc_hir as hir;
7
8
use rustc_hir:: def:: Res ;
8
9
use rustc_span:: symbol:: Ident ;
@@ -102,10 +103,36 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
102
103
// Note that unlike for slice patterns,
103
104
// where `xs @ ..` is a legal sub-slice pattern,
104
105
// it is not a legal sub-tuple pattern.
105
- if pat. is_rest ( ) {
106
- rest = Some ( ( idx, pat. span ) ) ;
107
- break ;
106
+ match pat. kind {
107
+ // Found a sub-tuple rest pattern
108
+ PatKind :: Rest => {
109
+ rest = Some ( ( idx, pat. span ) ) ;
110
+ break ;
111
+ }
112
+ // Found a sub-tuple pattern `$binding_mode $ident @ ..`.
113
+ // This is not allowed as a sub-tuple pattern
114
+ PatKind :: Ident ( ref _bm, ident, Some ( ref sub) ) if sub. is_rest ( ) => {
115
+ rest = Some ( ( idx, pat. span ) ) ;
116
+ let sp = pat. span ;
117
+ self . diagnostic ( )
118
+ . struct_span_err (
119
+ sp,
120
+ & format ! ( "`{} @` is not allowed in a {}" , ident. name, ctx) ,
121
+ )
122
+ . span_label ( sp, "this is only allowed in slice patterns" )
123
+ . help ( "remove this and bind each tuple field independently" )
124
+ . span_suggestion_verbose (
125
+ sp,
126
+ & format ! ( "if you don't need to use the contents of {}, discard the tuple's remaining fields" , ident) ,
127
+ ".." . to_string ( ) ,
128
+ Applicability :: MaybeIncorrect ,
129
+ )
130
+ . emit ( ) ;
131
+ break ;
132
+ }
133
+ _ => { }
108
134
}
135
+
109
136
// It was not a sub-tuple pattern so lower it normally.
110
137
elems. push ( self . lower_pat ( pat) ) ;
111
138
}
0 commit comments