From ead6c4b9d44f43945db6e91c92f14cef31240c64 Mon Sep 17 00:00:00 2001 From: P1start Date: Mon, 6 Oct 2014 13:36:53 +1300 Subject: Add a lint for not using field pattern shorthands Closes #17792. --- src/libsyntax/ast.rs | 3 ++- src/libsyntax/ast_util.rs | 2 +- src/libsyntax/ext/build.rs | 4 ++-- src/libsyntax/ext/deriving/generic/mod.rs | 5 ++++- src/libsyntax/ext/tt/macro_parser.rs | 2 +- src/libsyntax/fold.rs | 10 +++++---- src/libsyntax/parse/lexer/comments.rs | 2 +- src/libsyntax/parse/parser.rs | 37 +++++++++++++++++++------------ src/libsyntax/print/pprust.rs | 6 ++--- src/libsyntax/visit.rs | 2 +- 10 files changed, 44 insertions(+), 29 deletions(-) (limited to 'src/libsyntax') diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index df63d161eec..8eaee7282d1 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -340,6 +340,7 @@ pub struct Pat { pub struct FieldPat { pub ident: Ident, pub pat: P, + pub is_shorthand: bool, } #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] @@ -374,7 +375,7 @@ pub enum Pat_ { /// "None" means a * pattern where we don't bind the fields to names. PatEnum(Path, Option>>), - PatStruct(Path, Vec, bool), + PatStruct(Path, Vec>, bool), PatTup(Vec>), PatBox(P), PatRegion(P), // reference pattern diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 5626f0a8ad9..d5a460dc9db 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -602,7 +602,7 @@ pub fn walk_pat(pat: &Pat, it: |&Pat| -> bool) -> bool { match pat.node { PatIdent(_, _, Some(ref p)) => walk_pat(&**p, it), PatStruct(_, ref fields, _) => { - fields.iter().all(|field| walk_pat(&*field.pat, |p| it(p))) + fields.iter().all(|field| walk_pat(&*field.node.pat, |p| it(p))) } PatEnum(_, Some(ref s)) | PatTup(ref s) => { s.iter().all(|p| walk_pat(&**p, |p| it(p))) diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 437efbf96f8..dc4eaf7d7ad 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -169,7 +169,7 @@ pub trait AstBuilder { bm: ast::BindingMode) -> P; fn pat_enum(&self, span: Span, path: ast::Path, subpats: Vec> ) -> P; fn pat_struct(&self, span: Span, - path: ast::Path, field_pats: Vec ) -> P; + path: ast::Path, field_pats: Vec> ) -> P; fn pat_tuple(&self, span: Span, pats: Vec>) -> P; fn pat_some(&self, span: Span, pat: P) -> P; @@ -796,7 +796,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { self.pat(span, pat) } fn pat_struct(&self, span: Span, - path: ast::Path, field_pats: Vec) -> P { + path: ast::Path, field_pats: Vec>) -> P { let pat = ast::PatStruct(path, field_pats, false); self.pat(span, pat) } diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs index 2310a4460e2..533a28998bd 100644 --- a/src/libsyntax/ext/deriving/generic/mod.rs +++ b/src/libsyntax/ext/deriving/generic/mod.rs @@ -1248,7 +1248,10 @@ impl<'a> TraitDef<'a> { let pattern = if struct_type == Record { let field_pats = subpats.into_iter().zip(ident_expr.iter()).map(|(pat, &(_, id, _))| { // id is guaranteed to be Some - ast::FieldPat { ident: id.unwrap(), pat: pat } + codemap::Spanned { + span: pat.span, + node: ast::FieldPat { ident: id.unwrap(), pat: pat, is_shorthand: true }, + } }).collect(); cx.pat_struct(self.span, matching_path, field_pats) } else { diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index 78fcd729aae..f2081674fb7 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -250,7 +250,7 @@ pub fn parse(sess: &ParseSess, let mut next_eis = Vec::new(); // or proceed normally let mut eof_eis = Vec::new(); - let TokenAndSpan {tok: tok, sp: sp} = rdr.peek(); + let TokenAndSpan { tok, sp } = rdr.peek(); /* we append new items to this while we go */ loop { diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 5e29167bf1a..ceef190f5d4 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -1139,10 +1139,12 @@ pub fn noop_fold_pat(p: P, folder: &mut T) -> P { PatStruct(pth, fields, etc) => { let pth = folder.fold_path(pth); let fs = fields.move_map(|f| { - ast::FieldPat { - ident: f.ident, - pat: folder.fold_pat(f.pat) - } + Spanned { span: folder.new_span(f.span), + node: ast::FieldPat { + ident: f.node.ident, + pat: folder.fold_pat(f.node.pat), + is_shorthand: f.node.is_shorthand, + }} }); PatStruct(pth, fs, etc) } diff --git a/src/libsyntax/parse/lexer/comments.rs b/src/libsyntax/parse/lexer/comments.rs index 551d15048f1..3298eae125a 100644 --- a/src/libsyntax/parse/lexer/comments.rs +++ b/src/libsyntax/parse/lexer/comments.rs @@ -366,7 +366,7 @@ pub fn gather_comments_and_literals(span_diagnostic: &diagnostic::SpanHandler, let bstart = rdr.last_pos; rdr.next_token(); //discard, and look ahead; we're working with internal state - let TokenAndSpan {tok: tok, sp: sp} = rdr.peek(); + let TokenAndSpan { tok, sp } = rdr.peek(); if token::is_lit(&tok) { rdr.with_str_from(bstart, |s| { debug!("tok lit: {}", s); diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index ed806ad803a..5abf79836f5 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -3100,7 +3100,7 @@ impl<'a> Parser<'a> { } /// Parse the fields of a struct-like pattern - fn parse_pat_fields(&mut self) -> (Vec , bool) { + fn parse_pat_fields(&mut self) -> (Vec> , bool) { let mut fields = Vec::new(); let mut etc = false; let mut first = true; @@ -3113,6 +3113,9 @@ impl<'a> Parser<'a> { if self.token == token::RBRACE { break } } + let lo = self.span.lo; + let hi; + if self.token == token::DOTDOT { self.bump(); if self.token != token::RBRACE { @@ -3134,7 +3137,7 @@ impl<'a> Parser<'a> { let fieldname = self.parse_ident(); - let subpat = if self.token == token::COLON { + let (subpat, is_shorthand) = if self.token == token::COLON { match bind_type { BindByRef(..) | BindByValue(MutMutable) => { let token_str = self.this_token_to_string(); @@ -3145,16 +3148,22 @@ impl<'a> Parser<'a> { } self.bump(); - self.parse_pat() + let pat = self.parse_pat(); + hi = pat.span.hi; + (pat, false) } else { + hi = self.last_span.hi; let fieldpath = codemap::Spanned{span:self.last_span, node: fieldname}; - P(ast::Pat { + (P(ast::Pat { id: ast::DUMMY_NODE_ID, node: PatIdent(bind_type, fieldpath, None), span: self.last_span - }) + }), true) }; - fields.push(ast::FieldPat { ident: fieldname, pat: subpat }); + fields.push(codemap::Spanned { span: mk_sp(lo, hi), + node: ast::FieldPat { ident: fieldname, + pat: subpat, + is_shorthand: is_shorthand }}); } return (fields, etc); } @@ -3665,9 +3674,9 @@ impl<'a> Parser<'a> { // wouldn't it be more uniform to parse view items only, here? let ParsedItemsAndViewItems { - attrs_remaining: attrs_remaining, - view_items: view_items, - items: items, + attrs_remaining, + view_items, + items, .. } = self.parse_items_and_view_items(first_item_attrs, false, false); @@ -4705,8 +4714,8 @@ impl<'a> Parser<'a> { // parse all of the items up to closing or an attribute. // view items are legal here. let ParsedItemsAndViewItems { - attrs_remaining: attrs_remaining, - view_items: view_items, + attrs_remaining, + view_items, items: starting_items, .. } = self.parse_items_and_view_items(first_item_attrs, true, true); @@ -4978,10 +4987,10 @@ impl<'a> Parser<'a> { first_item_attrs: Vec ) -> ForeignMod { let ParsedItemsAndViewItems { - attrs_remaining: attrs_remaining, - view_items: view_items, + attrs_remaining, + view_items, items: _, - foreign_items: foreign_items + foreign_items, } = self.parse_foreign_items(first_item_attrs, true); if !attrs_remaining.is_empty() { let last_span = self.last_span; diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index cdcbeedddb2..b63f9b0120b 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1983,12 +1983,12 @@ impl<'a> State<'a> { Consistent, fields.as_slice(), |s, f| { try!(s.cbox(indent_unit)); - try!(s.print_ident(f.ident)); + try!(s.print_ident(f.node.ident)); try!(s.word_nbsp(":")); - try!(s.print_pat(&*f.pat)); + try!(s.print_pat(&*f.node.pat)); s.end() }, - |f| f.pat.span)); + |f| f.node.pat.span)); if etc { if fields.len() != 0u { try!(self.word_space(",")); } try!(word(&mut self.s, "..")); diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 00377a324a7..f2d56f53d22 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -429,7 +429,7 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) { PatStruct(ref path, ref fields, _) => { visitor.visit_path(path, pattern.id); for field in fields.iter() { - visitor.visit_pat(&*field.pat) + visitor.visit_pat(&*field.node.pat) } } PatTup(ref tuple_elements) => { -- cgit 1.4.1-3-g733a5