From 1055bdfb2a5ced99bb47c344c91af2f324ebbb6d Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 5 Nov 2017 04:22:18 +0300 Subject: [PATCH 1/2] Accept interpolated patterns in trait method parameters Remove some outdated messages from "no patterns allowed" errors --- src/librustc_passes/ast_validation.rs | 35 +++++------------- src/libsyntax/parse/parser.rs | 26 +++++-------- .../compile-fail/no-patterns-in-args-macro.rs | 37 +++++++++++++++++++ src/test/compile-fail/no-patterns-in-args.rs | 4 -- 4 files changed, 56 insertions(+), 46 deletions(-) create mode 100644 src/test/compile-fail/no-patterns-in-args-macro.rs diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 6d9c294884128..afa704025b9ad 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -67,13 +67,12 @@ impl<'a> AstValidator<'a> { } } - fn check_decl_no_pat(&self, decl: &FnDecl, report_err: ReportFn) { + fn check_decl_no_pat(&self, decl: &FnDecl, report_err: ReportFn) { for arg in &decl.inputs { match arg.pat.node { PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), _, None) | PatKind::Wild => {} - PatKind::Ident(..) => report_err(arg.pat.span, true), - _ => report_err(arg.pat.span, false), + _ => report_err(arg.pat.span), } } } @@ -150,15 +149,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> { fn visit_ty(&mut self, ty: &'a Ty) { match ty.node { TyKind::BareFn(ref bfty) => { - self.check_decl_no_pat(&bfty.decl, |span, _| { - let mut err = struct_span_err!(self.session, - span, - E0561, - "patterns aren't allowed in function pointer \ - types"); - err.span_note(span, - "this is a recent error, see issue #35203 for more details"); - err.emit(); + self.check_decl_no_pat(&bfty.decl, |span| { + struct_span_err!(self.session, span, E0561, + "patterns aren't allowed in function pointer types").emit(); }); } TyKind::TraitObject(ref bounds, ..) => { @@ -260,7 +253,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { if let TraitItemKind::Method(ref sig, ref block) = trait_item.node { self.check_trait_fn_not_const(sig.constness); if block.is_none() { - self.check_decl_no_pat(&sig.decl, |span, _| { + self.check_decl_no_pat(&sig.decl, |span| { self.session.buffer_lint( lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY, trait_item.id, span, @@ -299,18 +292,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> { fn visit_foreign_item(&mut self, fi: &'a ForeignItem) { match fi.node { ForeignItemKind::Fn(ref decl, _) => { - self.check_decl_no_pat(decl, |span, is_recent| { - let mut err = struct_span_err!(self.session, - span, - E0130, - "patterns aren't allowed in foreign function \ - declarations"); - err.span_label(span, "pattern not allowed in foreign function"); - if is_recent { - err.span_note(span, - "this is a recent error, see issue #35203 for more details"); - } - err.emit(); + self.check_decl_no_pat(decl, |span| { + struct_span_err!(self.session, span, E0130, + "patterns aren't allowed in foreign function declarations") + .span_label(span, "pattern not allowed in foreign function").emit(); }); } ForeignItemKind::Static(..) | ForeignItemKind::Ty => {} diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index e583981d9816b..c1819307928ba 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -360,10 +360,6 @@ impl TokenType { } } -fn is_ident_or_underscore(t: &token::Token) -> bool { - t.is_ident() || *t == token::Underscore -} - // Returns true if `IDENT t` can start a type - `IDENT::a::b`, `IDENT`, // `IDENT<::AssocTy>`, `IDENT(u8, u8) -> u8`. fn can_continue_type_after_ident(t: &token::Token) -> bool { @@ -1625,23 +1621,19 @@ impl<'a> Parser<'a> { Ok(MutTy { ty: t, mutbl: mutbl }) } - pub fn is_named_argument(&mut self) -> bool { + fn is_named_argument(&mut self) -> bool { let offset = match self.token { - token::BinOp(token::And) | - token::AndAnd => 1, + token::Interpolated(ref nt) => match nt.0 { + token::NtPat(..) => return self.look_ahead(1, |t| t == &token::Colon), + _ => 0, + } + token::BinOp(token::And) | token::AndAnd => 1, _ if self.token.is_keyword(keywords::Mut) => 1, - _ => 0 + _ => 0, }; - debug!("parser is_named_argument offset:{}", offset); - - if offset == 0 { - is_ident_or_underscore(&self.token) - && self.look_ahead(1, |t| *t == token::Colon) - } else { - self.look_ahead(offset, |t| is_ident_or_underscore(t)) - && self.look_ahead(offset + 1, |t| *t == token::Colon) - } + self.look_ahead(offset, |t| t.is_ident() || t == &token::Underscore) && + self.look_ahead(offset + 1, |t| t == &token::Colon) } /// This version of parse arg doesn't necessarily require diff --git a/src/test/compile-fail/no-patterns-in-args-macro.rs b/src/test/compile-fail/no-patterns-in-args-macro.rs new file mode 100644 index 0000000000000..3aabd19f6e649 --- /dev/null +++ b/src/test/compile-fail/no-patterns-in-args-macro.rs @@ -0,0 +1,37 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +macro_rules! m { + ($pat: pat) => { + trait Tr { + fn trait_method($pat: u8); + } + + type A = fn($pat: u8); + + extern { + fn foreign_fn($pat: u8); + } + } +} + +mod good_pat { + m!(good_pat); // OK +} + +mod bad_pat { + m!((bad, pat)); + //~^ ERROR patterns aren't allowed in function pointer types + //~| ERROR patterns aren't allowed in foreign function declarations + //~| WARN patterns aren't allowed in methods without bodies + //~| WARN this was previously accepted +} + +fn main() {} diff --git a/src/test/compile-fail/no-patterns-in-args.rs b/src/test/compile-fail/no-patterns-in-args.rs index b0278476998dd..081d6caaa13c9 100644 --- a/src/test/compile-fail/no-patterns-in-args.rs +++ b/src/test/compile-fail/no-patterns-in-args.rs @@ -11,21 +11,17 @@ extern { fn f1(mut arg: u8); //~ ERROR patterns aren't allowed in foreign function declarations //~^ NOTE pattern not allowed in foreign function - //~| NOTE this is a recent error fn f2(&arg: u8); //~ ERROR patterns aren't allowed in foreign function declarations //~^ NOTE pattern not allowed in foreign function fn f3(arg @ _: u8); //~ ERROR patterns aren't allowed in foreign function declarations //~^ NOTE pattern not allowed in foreign function - //~| NOTE this is a recent error fn g1(arg: u8); // OK fn g2(_: u8); // OK // fn g3(u8); // Not yet } type A1 = fn(mut arg: u8); //~ ERROR patterns aren't allowed in function pointer types - //~^ NOTE this is a recent error type A2 = fn(&arg: u8); //~ ERROR patterns aren't allowed in function pointer types - //~^ NOTE this is a recent error type B1 = fn(arg: u8); // OK type B2 = fn(_: u8); // OK type B3 = fn(u8); // OK From f7b4b88840d872909a67e5f9623281e3e2165fba Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 5 Nov 2017 05:08:41 +0300 Subject: [PATCH 2/2] Always report patterns more complex than `mut IDENT` as errors --- src/librustc_passes/ast_validation.rs | 26 ++++++++++++------- src/librustc_passes/diagnostics.rs | 1 + .../compile-fail/no-patterns-in-args-2.rs | 1 - .../compile-fail/no-patterns-in-args-macro.rs | 3 +-- 4 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index afa704025b9ad..40adc6bcb122f 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -67,12 +67,14 @@ impl<'a> AstValidator<'a> { } } - fn check_decl_no_pat(&self, decl: &FnDecl, report_err: ReportFn) { + fn check_decl_no_pat(&self, decl: &FnDecl, report_err: ReportFn) { for arg in &decl.inputs { match arg.pat.node { PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), _, None) | PatKind::Wild => {} - _ => report_err(arg.pat.span), + PatKind::Ident(BindingMode::ByValue(Mutability::Mutable), _, None) => + report_err(arg.pat.span, true), + _ => report_err(arg.pat.span, false), } } } @@ -149,7 +151,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { fn visit_ty(&mut self, ty: &'a Ty) { match ty.node { TyKind::BareFn(ref bfty) => { - self.check_decl_no_pat(&bfty.decl, |span| { + self.check_decl_no_pat(&bfty.decl, |span, _| { struct_span_err!(self.session, span, E0561, "patterns aren't allowed in function pointer types").emit(); }); @@ -253,12 +255,16 @@ impl<'a> Visitor<'a> for AstValidator<'a> { if let TraitItemKind::Method(ref sig, ref block) = trait_item.node { self.check_trait_fn_not_const(sig.constness); if block.is_none() { - self.check_decl_no_pat(&sig.decl, |span| { - self.session.buffer_lint( - lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY, - trait_item.id, span, - "patterns aren't allowed in methods \ - without bodies"); + self.check_decl_no_pat(&sig.decl, |span, mut_ident| { + if mut_ident { + self.session.buffer_lint( + lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY, + trait_item.id, span, + "patterns aren't allowed in methods without bodies"); + } else { + struct_span_err!(self.session, span, E0642, + "patterns aren't allowed in methods without bodies").emit(); + } }); } } @@ -292,7 +298,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { fn visit_foreign_item(&mut self, fi: &'a ForeignItem) { match fi.node { ForeignItemKind::Fn(ref decl, _) => { - self.check_decl_no_pat(decl, |span| { + self.check_decl_no_pat(decl, |span, _| { struct_span_err!(self.session, span, E0130, "patterns aren't allowed in foreign function declarations") .span_label(span, "pattern not allowed in foreign function").emit(); diff --git a/src/librustc_passes/diagnostics.rs b/src/librustc_passes/diagnostics.rs index 1bfa5943ee90a..3597a6f18287e 100644 --- a/src/librustc_passes/diagnostics.rs +++ b/src/librustc_passes/diagnostics.rs @@ -264,4 +264,5 @@ register_diagnostics! { E0226, // only a single explicit lifetime bound is permitted E0472, // asm! is unsupported on this target E0561, // patterns aren't allowed in function pointer types + E0642, // patterns aren't allowed in methods without bodies } diff --git a/src/test/compile-fail/no-patterns-in-args-2.rs b/src/test/compile-fail/no-patterns-in-args-2.rs index 967c292fa68d2..4d2412c34a5fa 100644 --- a/src/test/compile-fail/no-patterns-in-args-2.rs +++ b/src/test/compile-fail/no-patterns-in-args-2.rs @@ -14,7 +14,6 @@ trait Tr { fn f1(mut arg: u8); //~ ERROR patterns aren't allowed in methods without bodies //~^ WARN was previously accepted fn f2(&arg: u8); //~ ERROR patterns aren't allowed in methods without bodies - //~^ WARN was previously accepted fn g1(arg: u8); // OK fn g2(_: u8); // OK #[allow(anonymous_parameters)] diff --git a/src/test/compile-fail/no-patterns-in-args-macro.rs b/src/test/compile-fail/no-patterns-in-args-macro.rs index 3aabd19f6e649..f85ce8f57ea71 100644 --- a/src/test/compile-fail/no-patterns-in-args-macro.rs +++ b/src/test/compile-fail/no-patterns-in-args-macro.rs @@ -30,8 +30,7 @@ mod bad_pat { m!((bad, pat)); //~^ ERROR patterns aren't allowed in function pointer types //~| ERROR patterns aren't allowed in foreign function declarations - //~| WARN patterns aren't allowed in methods without bodies - //~| WARN this was previously accepted + //~| ERROR patterns aren't allowed in methods without bodies } fn main() {}