Skip to content

Commit b226793

Browse files
committed
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](#41686), and this set didn't include interpolated patterns. Some outdated messages from "no patterns allowed" errors are also removed. Addresses #35203 (comment)
2 parents 965ace5 + f7b4b88 commit b226793

File tree

6 files changed

+64
-49
lines changed

6 files changed

+64
-49
lines changed

src/librustc_passes/ast_validation.rs

+18-27
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ impl<'a> AstValidator<'a> {
7272
match arg.pat.node {
7373
PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), _, None) |
7474
PatKind::Wild => {}
75-
PatKind::Ident(..) => report_err(arg.pat.span, true),
75+
PatKind::Ident(BindingMode::ByValue(Mutability::Mutable), _, None) =>
76+
report_err(arg.pat.span, true),
7677
_ => report_err(arg.pat.span, false),
7778
}
7879
}
@@ -151,14 +152,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
151152
match ty.node {
152153
TyKind::BareFn(ref bfty) => {
153154
self.check_decl_no_pat(&bfty.decl, |span, _| {
154-
let mut err = struct_span_err!(self.session,
155-
span,
156-
E0561,
157-
"patterns aren't allowed in function pointer \
158-
types");
159-
err.span_note(span,
160-
"this is a recent error, see issue #35203 for more details");
161-
err.emit();
155+
struct_span_err!(self.session, span, E0561,
156+
"patterns aren't allowed in function pointer types").emit();
162157
});
163158
}
164159
TyKind::TraitObject(ref bounds, ..) => {
@@ -260,12 +255,16 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
260255
if let TraitItemKind::Method(ref sig, ref block) = trait_item.node {
261256
self.check_trait_fn_not_const(sig.constness);
262257
if block.is_none() {
263-
self.check_decl_no_pat(&sig.decl, |span, _| {
264-
self.session.buffer_lint(
265-
lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY,
266-
trait_item.id, span,
267-
"patterns aren't allowed in methods \
268-
without bodies");
258+
self.check_decl_no_pat(&sig.decl, |span, mut_ident| {
259+
if mut_ident {
260+
self.session.buffer_lint(
261+
lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY,
262+
trait_item.id, span,
263+
"patterns aren't allowed in methods without bodies");
264+
} else {
265+
struct_span_err!(self.session, span, E0642,
266+
"patterns aren't allowed in methods without bodies").emit();
267+
}
269268
});
270269
}
271270
}
@@ -299,18 +298,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
299298
fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
300299
match fi.node {
301300
ForeignItemKind::Fn(ref decl, _) => {
302-
self.check_decl_no_pat(decl, |span, is_recent| {
303-
let mut err = struct_span_err!(self.session,
304-
span,
305-
E0130,
306-
"patterns aren't allowed in foreign function \
307-
declarations");
308-
err.span_label(span, "pattern not allowed in foreign function");
309-
if is_recent {
310-
err.span_note(span,
311-
"this is a recent error, see issue #35203 for more details");
312-
}
313-
err.emit();
301+
self.check_decl_no_pat(decl, |span, _| {
302+
struct_span_err!(self.session, span, E0130,
303+
"patterns aren't allowed in foreign function declarations")
304+
.span_label(span, "pattern not allowed in foreign function").emit();
314305
});
315306
}
316307
ForeignItemKind::Static(..) | ForeignItemKind::Ty => {}

src/librustc_passes/diagnostics.rs

+1
Original file line numberDiff line numberDiff line change
@@ -264,4 +264,5 @@ register_diagnostics! {
264264
E0226, // only a single explicit lifetime bound is permitted
265265
E0472, // asm! is unsupported on this target
266266
E0561, // patterns aren't allowed in function pointer types
267+
E0642, // patterns aren't allowed in methods without bodies
267268
}

src/libsyntax/parse/parser.rs

+9-17
Original file line numberDiff line numberDiff line change
@@ -360,10 +360,6 @@ impl TokenType {
360360
}
361361
}
362362

363-
fn is_ident_or_underscore(t: &token::Token) -> bool {
364-
t.is_ident() || *t == token::Underscore
365-
}
366-
367363
// Returns true if `IDENT t` can start a type - `IDENT::a::b`, `IDENT<u8, u8>`,
368364
// `IDENT<<u8 as Trait>::AssocTy>`, `IDENT(u8, u8) -> u8`.
369365
fn can_continue_type_after_ident(t: &token::Token) -> bool {
@@ -1625,23 +1621,19 @@ impl<'a> Parser<'a> {
16251621
Ok(MutTy { ty: t, mutbl: mutbl })
16261622
}
16271623

1628-
pub fn is_named_argument(&mut self) -> bool {
1624+
fn is_named_argument(&mut self) -> bool {
16291625
let offset = match self.token {
1630-
token::BinOp(token::And) |
1631-
token::AndAnd => 1,
1626+
token::Interpolated(ref nt) => match nt.0 {
1627+
token::NtPat(..) => return self.look_ahead(1, |t| t == &token::Colon),
1628+
_ => 0,
1629+
}
1630+
token::BinOp(token::And) | token::AndAnd => 1,
16321631
_ if self.token.is_keyword(keywords::Mut) => 1,
1633-
_ => 0
1632+
_ => 0,
16341633
};
16351634

1636-
debug!("parser is_named_argument offset:{}", offset);
1637-
1638-
if offset == 0 {
1639-
is_ident_or_underscore(&self.token)
1640-
&& self.look_ahead(1, |t| *t == token::Colon)
1641-
} else {
1642-
self.look_ahead(offset, |t| is_ident_or_underscore(t))
1643-
&& self.look_ahead(offset + 1, |t| *t == token::Colon)
1644-
}
1635+
self.look_ahead(offset, |t| t.is_ident() || t == &token::Underscore) &&
1636+
self.look_ahead(offset + 1, |t| t == &token::Colon)
16451637
}
16461638

16471639
/// This version of parse arg doesn't necessarily require

src/test/compile-fail/no-patterns-in-args-2.rs

-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ trait Tr {
1414
fn f1(mut arg: u8); //~ ERROR patterns aren't allowed in methods without bodies
1515
//~^ WARN was previously accepted
1616
fn f2(&arg: u8); //~ ERROR patterns aren't allowed in methods without bodies
17-
//~^ WARN was previously accepted
1817
fn g1(arg: u8); // OK
1918
fn g2(_: u8); // OK
2019
#[allow(anonymous_parameters)]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
macro_rules! m {
12+
($pat: pat) => {
13+
trait Tr {
14+
fn trait_method($pat: u8);
15+
}
16+
17+
type A = fn($pat: u8);
18+
19+
extern {
20+
fn foreign_fn($pat: u8);
21+
}
22+
}
23+
}
24+
25+
mod good_pat {
26+
m!(good_pat); // OK
27+
}
28+
29+
mod bad_pat {
30+
m!((bad, pat));
31+
//~^ ERROR patterns aren't allowed in function pointer types
32+
//~| ERROR patterns aren't allowed in foreign function declarations
33+
//~| ERROR patterns aren't allowed in methods without bodies
34+
}
35+
36+
fn main() {}

src/test/compile-fail/no-patterns-in-args.rs

-4
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,17 @@
1111
extern {
1212
fn f1(mut arg: u8); //~ ERROR patterns aren't allowed in foreign function declarations
1313
//~^ NOTE pattern not allowed in foreign function
14-
//~| NOTE this is a recent error
1514
fn f2(&arg: u8); //~ ERROR patterns aren't allowed in foreign function declarations
1615
//~^ NOTE pattern not allowed in foreign function
1716
fn f3(arg @ _: u8); //~ ERROR patterns aren't allowed in foreign function declarations
1817
//~^ NOTE pattern not allowed in foreign function
19-
//~| NOTE this is a recent error
2018
fn g1(arg: u8); // OK
2119
fn g2(_: u8); // OK
2220
// fn g3(u8); // Not yet
2321
}
2422

2523
type A1 = fn(mut arg: u8); //~ ERROR patterns aren't allowed in function pointer types
26-
//~^ NOTE this is a recent error
2724
type A2 = fn(&arg: u8); //~ ERROR patterns aren't allowed in function pointer types
28-
//~^ NOTE this is a recent error
2925
type B1 = fn(arg: u8); // OK
3026
type B2 = fn(_: u8); // OK
3127
type B3 = fn(u8); // OK

0 commit comments

Comments
 (0)