@@ -3,6 +3,7 @@ use super::{ImplTraitContext, LoweringContext, ParamMode};
33use rustc_ast:: ast:: * ;
44use rustc_ast:: ptr:: P ;
55use rustc_data_structures:: stack:: ensure_sufficient_stack;
6+ use rustc_errors:: Applicability ;
67use rustc_hir as hir;
78use rustc_hir:: def:: Res ;
89use rustc_span:: symbol:: Ident ;
@@ -102,10 +103,36 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
102103 // Note that unlike for slice patterns,
103104 // where `xs @ ..` is a legal sub-slice pattern,
104105 // 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+ _ => { }
108134 }
135+
109136 // It was not a sub-tuple pattern so lower it normally.
110137 elems. push ( self . lower_pat ( pat) ) ;
111138 }
0 commit comments