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 https://github.com/rust-lang/rust/issues/35203 [breaking-change], no breakage in sane code is expected though r? @nikomatsakis This is somewhat related to https://github.com/rust-lang/rfcs/pull/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.
This commit is contained in:
commit
271d048523
@ -55,6 +55,17 @@ impl<'a> AstValidator<'a> {
|
||||
err.emit();
|
||||
}
|
||||
}
|
||||
|
||||
fn check_decl_no_pat<ReportFn: Fn(Span, bool)>(&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),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Visitor for AstValidator<'a> {
|
||||
@ -82,6 +93,23 @@ impl<'a> Visitor for AstValidator<'a> {
|
||||
visit::walk_expr(self, expr)
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, ty: &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();
|
||||
});
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
visit::walk_ty(self, ty)
|
||||
}
|
||||
|
||||
fn visit_path(&mut self, path: &Path, id: NodeId) {
|
||||
if path.global && path.segments.len() > 0 {
|
||||
let ident = path.segments[0].identifier;
|
||||
@ -135,6 +163,25 @@ impl<'a> Visitor for AstValidator<'a> {
|
||||
visit::walk_item(self, item)
|
||||
}
|
||||
|
||||
fn visit_foreign_item(&mut self, fi: &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");
|
||||
if is_recent {
|
||||
err.span_note(span, "this is a recent error, see \
|
||||
issue #35203 for more details");
|
||||
}
|
||||
err.emit();
|
||||
});
|
||||
}
|
||||
ForeignItemKind::Static(..) => {}
|
||||
}
|
||||
|
||||
visit::walk_foreign_item(self, fi)
|
||||
}
|
||||
|
||||
fn visit_variant_data(&mut self, vdata: &VariantData, _: Ident,
|
||||
_: &Generics, _: NodeId, span: Span) {
|
||||
if vdata.fields().is_empty() {
|
||||
|
@ -49,6 +49,39 @@ match 5u32 {
|
||||
```
|
||||
"##,
|
||||
|
||||
E0130: r##"
|
||||
You declared a pattern as an argument in a foreign function declaration.
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail
|
||||
extern {
|
||||
fn foo((a, b): (u32, u32)); // error: patterns aren't allowed in foreign
|
||||
// function declarations
|
||||
}
|
||||
```
|
||||
|
||||
Please replace the pattern argument with a regular one. Example:
|
||||
|
||||
```
|
||||
struct SomeStruct {
|
||||
a: u32,
|
||||
b: u32,
|
||||
}
|
||||
|
||||
extern {
|
||||
fn foo(s: SomeStruct); // ok!
|
||||
}
|
||||
```
|
||||
|
||||
Or:
|
||||
|
||||
```
|
||||
extern {
|
||||
fn foo(a: (u32, u32)); // ok!
|
||||
}
|
||||
```
|
||||
"##,
|
||||
|
||||
E0161: r##"
|
||||
A value was moved. However, its size was not known at compile time, and only
|
||||
values of a known size can be moved.
|
||||
@ -187,4 +220,5 @@ pub impl Foo for Bar {
|
||||
|
||||
register_diagnostics! {
|
||||
E0472, // asm! is unsupported on this target
|
||||
E0561, // patterns aren't allowed in function pointer types
|
||||
}
|
||||
|
@ -60,8 +60,6 @@ There are some shortcomings in this design:
|
||||
|
||||
use astconv::{AstConv, ast_region_to_region, Bounds, PartitionedBounds, partition_bounds};
|
||||
use lint;
|
||||
use hir::def::Def;
|
||||
use hir::def_id::DefId;
|
||||
use constrained_type_params as ctp;
|
||||
use middle::lang_items::SizedTraitLangItem;
|
||||
use middle::const_val::ConstVal;
|
||||
@ -74,7 +72,6 @@ use rustc::ty::{VariantKind};
|
||||
use rustc::ty::util::IntTypeExt;
|
||||
use rscope::*;
|
||||
use rustc::dep_graph::DepNode;
|
||||
use rustc::hir::map as hir_map;
|
||||
use util::common::{ErrorReported, MemoizationMap};
|
||||
use util::nodemap::{NodeMap, FnvHashMap};
|
||||
use {CrateCtxt, write_ty_to_tcx};
|
||||
@ -91,9 +88,9 @@ use syntax::parse::token::keywords;
|
||||
use syntax::ptr::P;
|
||||
use syntax_pos::Span;
|
||||
|
||||
use rustc::hir::{self, PatKind};
|
||||
use rustc::hir::intravisit;
|
||||
use rustc::hir::print as pprust;
|
||||
use rustc::hir::{self, intravisit, map as hir_map, print as pprust};
|
||||
use rustc::hir::def::Def;
|
||||
use rustc::hir::def_id::DefId;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Main entry point
|
||||
@ -2144,14 +2141,6 @@ fn compute_type_scheme_of_foreign_fn_decl<'a, 'tcx>(
|
||||
abi: abi::Abi)
|
||||
-> ty::TypeScheme<'tcx>
|
||||
{
|
||||
for i in &decl.inputs {
|
||||
match i.pat.node {
|
||||
PatKind::Binding(..) | PatKind::Wild => {}
|
||||
_ => span_err!(ccx.tcx.sess, i.pat.span, E0130,
|
||||
"patterns aren't allowed in foreign function declarations")
|
||||
}
|
||||
}
|
||||
|
||||
let ty_generics = ty_generics_for_fn(ccx, ast_generics, &ty::Generics::empty());
|
||||
|
||||
let rb = BindingRscope::new();
|
||||
|
@ -1800,39 +1800,6 @@ Please also verify that this wasn't because of a name-clash and rename the type
|
||||
parameter if so.
|
||||
"##,
|
||||
|
||||
E0130: r##"
|
||||
You declared a pattern as an argument in a foreign function declaration.
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail
|
||||
extern {
|
||||
fn foo((a, b): (u32, u32)); // error: patterns aren't allowed in foreign
|
||||
// function declarations
|
||||
}
|
||||
```
|
||||
|
||||
Please replace the pattern argument with a regular one. Example:
|
||||
|
||||
```
|
||||
struct SomeStruct {
|
||||
a: u32,
|
||||
b: u32,
|
||||
}
|
||||
|
||||
extern {
|
||||
fn foo(s: SomeStruct); // ok!
|
||||
}
|
||||
```
|
||||
|
||||
Or:
|
||||
|
||||
```
|
||||
extern {
|
||||
fn foo(a: (u32, u32)); // ok!
|
||||
}
|
||||
```
|
||||
"##,
|
||||
|
||||
E0131: r##"
|
||||
It is not possible to define `main` with type parameters, or even with function
|
||||
parameters. When `main` is present, it must take no arguments and return `()`.
|
||||
|
30
src/test/compile-fail/no-patterns-in-args.rs
Normal file
30
src/test/compile-fail/no-patterns-in-args.rs
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
extern {
|
||||
fn f1(mut arg: u8); //~ ERROR patterns aren't allowed in foreign function declarations
|
||||
//~^ NOTE this is a recent error
|
||||
fn f2(&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 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
|
||||
|
||||
fn main() {}
|
Loading…
x
Reference in New Issue
Block a user