Skip to content

Commit 271d048

Browse files
authored
Auto merge of #35015 - petrochenkov:forearg, r=nikomatsakis
Properly enforce the "patterns aren't allowed in foreign functions" rule Cases like `arg @ PATTERN` or `mut arg` were missing. Apply the same rule to function pointer types. Closes #35203 [breaking-change], no breakage in sane code is expected though r? @nikomatsakis This is somewhat related to rust-lang/rfcs#1685 (cc @matklad). The goal is to eventually support full pattern syntax where it makes sense (function body may present) and to support *only* the following forms - `TYPE`, `ident: TYPE`, `_: TYPE` - where patterns don't make sense (function body doesn't present), i.e. in foreign functions and function pointer types.
2 parents 40f3ee2 + 5c88efc commit 271d048

File tree

5 files changed

+114
-47
lines changed

5 files changed

+114
-47
lines changed

src/librustc_passes/ast_validation.rs

+47
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,17 @@ impl<'a> AstValidator<'a> {
5555
err.emit();
5656
}
5757
}
58+
59+
fn check_decl_no_pat<ReportFn: Fn(Span, bool)>(&self, decl: &FnDecl, report_err: ReportFn) {
60+
for arg in &decl.inputs {
61+
match arg.pat.node {
62+
PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), _, None) |
63+
PatKind::Wild => {}
64+
PatKind::Ident(..) => report_err(arg.pat.span, true),
65+
_ => report_err(arg.pat.span, false),
66+
}
67+
}
68+
}
5869
}
5970

6071
impl<'a> Visitor for AstValidator<'a> {
@@ -82,6 +93,23 @@ impl<'a> Visitor for AstValidator<'a> {
8293
visit::walk_expr(self, expr)
8394
}
8495

96+
fn visit_ty(&mut self, ty: &Ty) {
97+
match ty.node {
98+
TyKind::BareFn(ref bfty) => {
99+
self.check_decl_no_pat(&bfty.decl, |span, _| {
100+
let mut err = struct_span_err!(self.session, span, E0561,
101+
"patterns aren't allowed in function pointer types");
102+
err.span_note(span, "this is a recent error, see \
103+
issue #35203 for more details");
104+
err.emit();
105+
});
106+
}
107+
_ => {}
108+
}
109+
110+
visit::walk_ty(self, ty)
111+
}
112+
85113
fn visit_path(&mut self, path: &Path, id: NodeId) {
86114
if path.global && path.segments.len() > 0 {
87115
let ident = path.segments[0].identifier;
@@ -135,6 +163,25 @@ impl<'a> Visitor for AstValidator<'a> {
135163
visit::walk_item(self, item)
136164
}
137165

166+
fn visit_foreign_item(&mut self, fi: &ForeignItem) {
167+
match fi.node {
168+
ForeignItemKind::Fn(ref decl, _) => {
169+
self.check_decl_no_pat(decl, |span, is_recent| {
170+
let mut err = struct_span_err!(self.session, span, E0130,
171+
"patterns aren't allowed in foreign function declarations");
172+
if is_recent {
173+
err.span_note(span, "this is a recent error, see \
174+
issue #35203 for more details");
175+
}
176+
err.emit();
177+
});
178+
}
179+
ForeignItemKind::Static(..) => {}
180+
}
181+
182+
visit::walk_foreign_item(self, fi)
183+
}
184+
138185
fn visit_variant_data(&mut self, vdata: &VariantData, _: Ident,
139186
_: &Generics, _: NodeId, span: Span) {
140187
if vdata.fields().is_empty() {

src/librustc_passes/diagnostics.rs

+34
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,39 @@ match 5u32 {
4949
```
5050
"##,
5151

52+
E0130: r##"
53+
You declared a pattern as an argument in a foreign function declaration.
54+
Erroneous code example:
55+
56+
```compile_fail
57+
extern {
58+
fn foo((a, b): (u32, u32)); // error: patterns aren't allowed in foreign
59+
// function declarations
60+
}
61+
```
62+
63+
Please replace the pattern argument with a regular one. Example:
64+
65+
```
66+
struct SomeStruct {
67+
a: u32,
68+
b: u32,
69+
}
70+
71+
extern {
72+
fn foo(s: SomeStruct); // ok!
73+
}
74+
```
75+
76+
Or:
77+
78+
```
79+
extern {
80+
fn foo(a: (u32, u32)); // ok!
81+
}
82+
```
83+
"##,
84+
5285
E0161: r##"
5386
A value was moved. However, its size was not known at compile time, and only
5487
values of a known size can be moved.
@@ -187,4 +220,5 @@ pub impl Foo for Bar {
187220

188221
register_diagnostics! {
189222
E0472, // asm! is unsupported on this target
223+
E0561, // patterns aren't allowed in function pointer types
190224
}

src/librustc_typeck/collect.rs

+3-14
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,6 @@ There are some shortcomings in this design:
6060

6161
use astconv::{AstConv, ast_region_to_region, Bounds, PartitionedBounds, partition_bounds};
6262
use lint;
63-
use hir::def::Def;
64-
use hir::def_id::DefId;
6563
use constrained_type_params as ctp;
6664
use middle::lang_items::SizedTraitLangItem;
6765
use middle::const_val::ConstVal;
@@ -74,7 +72,6 @@ use rustc::ty::{VariantKind};
7472
use rustc::ty::util::IntTypeExt;
7573
use rscope::*;
7674
use rustc::dep_graph::DepNode;
77-
use rustc::hir::map as hir_map;
7875
use util::common::{ErrorReported, MemoizationMap};
7976
use util::nodemap::{NodeMap, FnvHashMap};
8077
use {CrateCtxt, write_ty_to_tcx};
@@ -91,9 +88,9 @@ use syntax::parse::token::keywords;
9188
use syntax::ptr::P;
9289
use syntax_pos::Span;
9390

94-
use rustc::hir::{self, PatKind};
95-
use rustc::hir::intravisit;
96-
use rustc::hir::print as pprust;
91+
use rustc::hir::{self, intravisit, map as hir_map, print as pprust};
92+
use rustc::hir::def::Def;
93+
use rustc::hir::def_id::DefId;
9794

9895
///////////////////////////////////////////////////////////////////////////
9996
// Main entry point
@@ -2144,14 +2141,6 @@ fn compute_type_scheme_of_foreign_fn_decl<'a, 'tcx>(
21442141
abi: abi::Abi)
21452142
-> ty::TypeScheme<'tcx>
21462143
{
2147-
for i in &decl.inputs {
2148-
match i.pat.node {
2149-
PatKind::Binding(..) | PatKind::Wild => {}
2150-
_ => span_err!(ccx.tcx.sess, i.pat.span, E0130,
2151-
"patterns aren't allowed in foreign function declarations")
2152-
}
2153-
}
2154-
21552144
let ty_generics = ty_generics_for_fn(ccx, ast_generics, &ty::Generics::empty());
21562145

21572146
let rb = BindingRscope::new();

src/librustc_typeck/diagnostics.rs

-33
Original file line numberDiff line numberDiff line change
@@ -1800,39 +1800,6 @@ Please also verify that this wasn't because of a name-clash and rename the type
18001800
parameter if so.
18011801
"##,
18021802

1803-
E0130: r##"
1804-
You declared a pattern as an argument in a foreign function declaration.
1805-
Erroneous code example:
1806-
1807-
```compile_fail
1808-
extern {
1809-
fn foo((a, b): (u32, u32)); // error: patterns aren't allowed in foreign
1810-
// function declarations
1811-
}
1812-
```
1813-
1814-
Please replace the pattern argument with a regular one. Example:
1815-
1816-
```
1817-
struct SomeStruct {
1818-
a: u32,
1819-
b: u32,
1820-
}
1821-
1822-
extern {
1823-
fn foo(s: SomeStruct); // ok!
1824-
}
1825-
```
1826-
1827-
Or:
1828-
1829-
```
1830-
extern {
1831-
fn foo(a: (u32, u32)); // ok!
1832-
}
1833-
```
1834-
"##,
1835-
18361803
E0131: r##"
18371804
It is not possible to define `main` with type parameters, or even with function
18381805
parameters. When `main` is present, it must take no arguments and return `()`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright 2016 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+
extern {
12+
fn f1(mut arg: u8); //~ ERROR patterns aren't allowed in foreign function declarations
13+
//~^ NOTE this is a recent error
14+
fn f2(&arg: u8); //~ ERROR patterns aren't allowed in foreign function declarations
15+
fn f3(arg @ _: u8); //~ ERROR patterns aren't allowed in foreign function declarations
16+
//~^ NOTE this is a recent error
17+
fn g1(arg: u8); // OK
18+
fn g2(_: u8); // OK
19+
// fn g3(u8); // Not yet
20+
}
21+
22+
type A1 = fn(mut arg: u8); //~ ERROR patterns aren't allowed in function pointer types
23+
//~^ NOTE this is a recent error
24+
type A2 = fn(&arg: u8); //~ ERROR patterns aren't allowed in function pointer types
25+
//~^ NOTE this is a recent error
26+
type B1 = fn(arg: u8); // OK
27+
type B2 = fn(_: u8); // OK
28+
type B3 = fn(u8); // OK
29+
30+
fn main() {}

0 commit comments

Comments
 (0)