Fix the ordering of unsafe and extern in methods

This breaks code that looks like this:

    trait Foo {
        extern "C" unsafe fn foo();
    }

    impl Foo for Bar {
        extern "C" unsafe fn foo() { ... }
    }

Change such code to look like this:

    trait Foo {
        unsafe extern "C" fn foo();
    }

    impl Foo for Bar {
        unsafe extern "C" fn foo() { ... }
    }

Fixes #19398.

[breaking-change]
This commit is contained in:
P1start 2014-11-30 21:33:04 +13:00
parent 8d8f41b75f
commit 63553a10ad
4 changed files with 43 additions and 8 deletions

View file

@ -1296,13 +1296,14 @@ impl<'a> Parser<'a> {
let lo = p.span.lo;
let vis = p.parse_visibility();
let style = p.parse_fn_style();
let abi = if p.eat_keyword(keywords::Extern) {
p.parse_opt_abi().unwrap_or(abi::C)
} else {
abi::Rust
};
p.expect_keyword(keywords::Fn);
let style = p.parse_fn_style();
let ident = p.parse_ident();
let mut generics = p.parse_generics();
@ -4458,12 +4459,13 @@ impl<'a> Parser<'a> {
self.span.hi) };
(ast::MethMac(m), self.span.hi, attrs)
} else {
let fn_style = self.parse_fn_style();
let abi = if self.eat_keyword(keywords::Extern) {
self.parse_opt_abi().unwrap_or(abi::C)
} else {
abi::Rust
};
let fn_style = self.parse_fn_style();
self.expect_keyword(keywords::Fn);
let ident = self.parse_ident();
let mut generics = self.parse_generics();
let (explicit_self, decl) = self.parse_fn_decl_with_self(|p| {
@ -5009,14 +5011,13 @@ impl<'a> Parser<'a> {
})
}
/// Parse safe/unsafe and fn
/// Parse unsafe or not
fn parse_fn_style(&mut self) -> FnStyle {
if self.eat_keyword(keywords::Fn) { NormalFn }
else if self.eat_keyword(keywords::Unsafe) {
self.expect_keyword(keywords::Fn);
if self.eat_keyword(keywords::Unsafe) {
UnsafeFn
} else {
NormalFn
}
else { self.unexpected(); }
}

View file

@ -0,0 +1,15 @@
// Copyright 2014 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.
trait T {
extern "Rust" unsafe fn foo(); //~ ERROR expected `fn`, found `unsafe`
}
fn main() {}

View file

@ -11,5 +11,5 @@
struct S;
impl S {
static fn f() {} //~ ERROR unexpected token: `static`
static fn f() {} //~ ERROR expected `fn`, found `static`
}

View file

@ -0,0 +1,19 @@
// Copyright 2014 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.
trait T {
unsafe extern "Rust" fn foo();
}
impl T for () {
unsafe extern "Rust" fn foo() {}
}
fn main() {}