Auto merge of #45775 - petrochenkov:patnopat, r=nikomatsakis
Accept interpolated patterns in trait method parameters Permit this, basically ```rust macro_rules! m { ($pat: pat) => { trait Tr { fn f($pat: u8) {} } } } ``` it previously caused a parsing error during expansion because trait methods accept only very restricted set of patterns during parsing due to ambiguities caused by [anonymous parameters](https://github.com/rust-lang/rust/issues/41686), and this set didn't include interpolated patterns. Some outdated messages from "no patterns allowed" errors are also removed. Addresses https://github.com/rust-lang/rust/issues/35203#issuecomment-341937159
This commit is contained in:
commit
b22679366a
|
@ -72,7 +72,8 @@ impl<'a> AstValidator<'a> {
|
||||||
match arg.pat.node {
|
match arg.pat.node {
|
||||||
PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), _, None) |
|
PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), _, None) |
|
||||||
PatKind::Wild => {}
|
PatKind::Wild => {}
|
||||||
PatKind::Ident(..) => report_err(arg.pat.span, true),
|
PatKind::Ident(BindingMode::ByValue(Mutability::Mutable), _, None) =>
|
||||||
|
report_err(arg.pat.span, true),
|
||||||
_ => report_err(arg.pat.span, false),
|
_ => report_err(arg.pat.span, false),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -151,14 +152,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||||
match ty.node {
|
match ty.node {
|
||||||
TyKind::BareFn(ref bfty) => {
|
TyKind::BareFn(ref bfty) => {
|
||||||
self.check_decl_no_pat(&bfty.decl, |span, _| {
|
self.check_decl_no_pat(&bfty.decl, |span, _| {
|
||||||
let mut err = struct_span_err!(self.session,
|
struct_span_err!(self.session, span, E0561,
|
||||||
span,
|
"patterns aren't allowed in function pointer types").emit();
|
||||||
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();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
TyKind::TraitObject(ref bounds, ..) => {
|
TyKind::TraitObject(ref bounds, ..) => {
|
||||||
|
@ -260,12 +255,16 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||||
if let TraitItemKind::Method(ref sig, ref block) = trait_item.node {
|
if let TraitItemKind::Method(ref sig, ref block) = trait_item.node {
|
||||||
self.check_trait_fn_not_const(sig.constness);
|
self.check_trait_fn_not_const(sig.constness);
|
||||||
if block.is_none() {
|
if block.is_none() {
|
||||||
self.check_decl_no_pat(&sig.decl, |span, _| {
|
self.check_decl_no_pat(&sig.decl, |span, mut_ident| {
|
||||||
self.session.buffer_lint(
|
if mut_ident {
|
||||||
lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY,
|
self.session.buffer_lint(
|
||||||
trait_item.id, span,
|
lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY,
|
||||||
"patterns aren't allowed in methods \
|
trait_item.id, span,
|
||||||
without bodies");
|
"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();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -299,18 +298,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||||
fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
|
fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
|
||||||
match fi.node {
|
match fi.node {
|
||||||
ForeignItemKind::Fn(ref decl, _) => {
|
ForeignItemKind::Fn(ref decl, _) => {
|
||||||
self.check_decl_no_pat(decl, |span, is_recent| {
|
self.check_decl_no_pat(decl, |span, _| {
|
||||||
let mut err = struct_span_err!(self.session,
|
struct_span_err!(self.session, span, E0130,
|
||||||
span,
|
"patterns aren't allowed in foreign function declarations")
|
||||||
E0130,
|
.span_label(span, "pattern not allowed in foreign function").emit();
|
||||||
"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();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
ForeignItemKind::Static(..) | ForeignItemKind::Ty => {}
|
ForeignItemKind::Static(..) | ForeignItemKind::Ty => {}
|
||||||
|
|
|
@ -264,4 +264,5 @@ register_diagnostics! {
|
||||||
E0226, // only a single explicit lifetime bound is permitted
|
E0226, // only a single explicit lifetime bound is permitted
|
||||||
E0472, // asm! is unsupported on this target
|
E0472, // asm! is unsupported on this target
|
||||||
E0561, // patterns aren't allowed in function pointer types
|
E0561, // patterns aren't allowed in function pointer types
|
||||||
|
E0642, // patterns aren't allowed in methods without bodies
|
||||||
}
|
}
|
||||||
|
|
|
@ -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<u8, u8>`,
|
// Returns true if `IDENT t` can start a type - `IDENT::a::b`, `IDENT<u8, u8>`,
|
||||||
// `IDENT<<u8 as Trait>::AssocTy>`, `IDENT(u8, u8) -> u8`.
|
// `IDENT<<u8 as Trait>::AssocTy>`, `IDENT(u8, u8) -> u8`.
|
||||||
fn can_continue_type_after_ident(t: &token::Token) -> bool {
|
fn can_continue_type_after_ident(t: &token::Token) -> bool {
|
||||||
|
@ -1625,23 +1621,19 @@ impl<'a> Parser<'a> {
|
||||||
Ok(MutTy { ty: t, mutbl: mutbl })
|
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 {
|
let offset = match self.token {
|
||||||
token::BinOp(token::And) |
|
token::Interpolated(ref nt) => match nt.0 {
|
||||||
token::AndAnd => 1,
|
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,
|
_ if self.token.is_keyword(keywords::Mut) => 1,
|
||||||
_ => 0
|
_ => 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
debug!("parser is_named_argument offset:{}", offset);
|
self.look_ahead(offset, |t| t.is_ident() || t == &token::Underscore) &&
|
||||||
|
self.look_ahead(offset + 1, |t| t == &token::Colon)
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This version of parse arg doesn't necessarily require
|
/// This version of parse arg doesn't necessarily require
|
||||||
|
|
|
@ -14,7 +14,6 @@ trait Tr {
|
||||||
fn f1(mut arg: u8); //~ ERROR patterns aren't allowed in methods without bodies
|
fn f1(mut arg: u8); //~ ERROR patterns aren't allowed in methods without bodies
|
||||||
//~^ WARN was previously accepted
|
//~^ WARN was previously accepted
|
||||||
fn f2(&arg: u8); //~ ERROR patterns aren't allowed in methods without bodies
|
fn f2(&arg: u8); //~ ERROR patterns aren't allowed in methods without bodies
|
||||||
//~^ WARN was previously accepted
|
|
||||||
fn g1(arg: u8); // OK
|
fn g1(arg: u8); // OK
|
||||||
fn g2(_: u8); // OK
|
fn g2(_: u8); // OK
|
||||||
#[allow(anonymous_parameters)]
|
#[allow(anonymous_parameters)]
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
// 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 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
|
||||||
|
//~| ERROR patterns aren't allowed in methods without bodies
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -11,21 +11,17 @@
|
||||||
extern {
|
extern {
|
||||||
fn f1(mut arg: u8); //~ ERROR patterns aren't allowed in foreign function declarations
|
fn f1(mut arg: u8); //~ ERROR patterns aren't allowed in foreign function declarations
|
||||||
//~^ NOTE pattern not allowed in foreign function
|
//~^ 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
|
fn f2(&arg: u8); //~ ERROR patterns aren't allowed in foreign function declarations
|
||||||
//~^ NOTE pattern not allowed in foreign function
|
//~^ NOTE pattern not allowed in foreign function
|
||||||
fn f3(arg @ _: u8); //~ ERROR patterns aren't allowed in foreign function declarations
|
fn f3(arg @ _: u8); //~ ERROR patterns aren't allowed in foreign function declarations
|
||||||
//~^ NOTE pattern not allowed in foreign function
|
//~^ NOTE pattern not allowed in foreign function
|
||||||
//~| NOTE this is a recent error
|
|
||||||
fn g1(arg: u8); // OK
|
fn g1(arg: u8); // OK
|
||||||
fn g2(_: u8); // OK
|
fn g2(_: u8); // OK
|
||||||
// fn g3(u8); // Not yet
|
// fn g3(u8); // Not yet
|
||||||
}
|
}
|
||||||
|
|
||||||
type A1 = fn(mut arg: u8); //~ ERROR patterns aren't allowed in function pointer types
|
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
|
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 B1 = fn(arg: u8); // OK
|
||||||
type B2 = fn(_: u8); // OK
|
type B2 = fn(_: u8); // OK
|
||||||
type B3 = fn(u8); // OK
|
type B3 = fn(u8); // OK
|
||||||
|
|
Loading…
Reference in New Issue