Skip to content

Commit c217a84

Browse files
committed
auto merge of #14005 : alexcrichton/rust/extern-unsafe, r=pcwalton
Previously, the parser would not allow you to simultaneously implement a function with a different abi as well as being unsafe at the same time. This extends the parser to allow functions of the form: unsafe extern fn foo() { // ... } The closure type grammar was also changed to reflect this reversal, types previously written as "extern unsafe fn()" must now be written as "unsafe extern fn()". The parser currently has a hack which allows the old style, but this will go away once a snapshot has landed. Closes #10025 [breaking-change]
2 parents 828ffab + 08237ca commit c217a84

File tree

15 files changed

+59
-49
lines changed

15 files changed

+59
-49
lines changed

src/librustc/metadata/decoder.rs

-3
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,6 @@ enum Family {
110110
UnsafeFn, // u
111111
StaticMethod, // F
112112
UnsafeStaticMethod, // U
113-
ForeignFn, // e
114113
Type, // y
115114
ForeignType, // T
116115
Mod, // m
@@ -134,7 +133,6 @@ fn item_family(item: ebml::Doc) -> Family {
134133
'u' => UnsafeFn,
135134
'F' => StaticMethod,
136135
'U' => UnsafeStaticMethod,
137-
'e' => ForeignFn,
138136
'y' => Type,
139137
'T' => ForeignType,
140138
'm' => Mod,
@@ -339,7 +337,6 @@ fn item_to_def_like(item: ebml::Doc, did: ast::DefId, cnum: ast::CrateNum)
339337
Struct => DlDef(ast::DefStruct(did)),
340338
UnsafeFn => DlDef(ast::DefFn(did, ast::UnsafeFn)),
341339
Fn => DlDef(ast::DefFn(did, ast::NormalFn)),
342-
ForeignFn => DlDef(ast::DefFn(did, ast::ExternFn)),
343340
StaticMethod | UnsafeStaticMethod => {
344341
let fn_style = if fam == UnsafeStaticMethod { ast::UnsafeFn } else
345342
{ ast::NormalFn };

src/librustc/metadata/encoder.rs

-2
Original file line numberDiff line numberDiff line change
@@ -788,15 +788,13 @@ fn style_fn_family(s: FnStyle) -> char {
788788
match s {
789789
UnsafeFn => 'u',
790790
NormalFn => 'f',
791-
ExternFn => 'e'
792791
}
793792
}
794793

795794
fn fn_style_static_method_family(s: FnStyle) -> char {
796795
match s {
797796
UnsafeFn => 'U',
798797
NormalFn => 'F',
799-
_ => fail!("extern fn can't be static")
800798
}
801799
}
802800

src/librustc/metadata/tydecode.rs

-1
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,6 @@ fn parse_fn_style(c: char) -> FnStyle {
441441
match c {
442442
'u' => UnsafeFn,
443443
'n' => NormalFn,
444-
'c' => ExternFn,
445444
_ => fail!("parse_fn_style: bad fn_style {}", c)
446445
}
447446
}

src/librustc/metadata/tyencode.rs

-1
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,6 @@ fn enc_fn_style(w: &mut MemWriter, p: FnStyle) {
298298
match p {
299299
NormalFn => mywrite!(w, "n"),
300300
UnsafeFn => mywrite!(w, "u"),
301-
ExternFn => mywrite!(w, "c")
302301
}
303302
}
304303

src/librustc/middle/reachable.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use middle::privacy;
2222
use util::nodemap::NodeSet;
2323

2424
use collections::HashSet;
25+
use syntax::abi;
2526
use syntax::ast;
2627
use syntax::ast_map;
2728
use syntax::ast_util::{def_id_of_def, is_local};
@@ -250,8 +251,10 @@ impl<'a> ReachableContext<'a> {
250251
match *node {
251252
ast_map::NodeItem(item) => {
252253
match item.node {
253-
ast::ItemFn(_, ast::ExternFn, _, _, _) => {
254-
self.reachable_symbols.insert(search_item);
254+
ast::ItemFn(_, _, abi, _, _) => {
255+
if abi != abi::Rust {
256+
self.reachable_symbols.insert(search_item);
257+
}
255258
}
256259
_ => {}
257260
}

src/librustc/middle/trans/base.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -1594,8 +1594,8 @@ impl<'a> Visitor<()> for TransItemVisitor<'a> {
15941594
pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
15951595
let _icx = push_ctxt("trans_item");
15961596
match item.node {
1597-
ast::ItemFn(decl, fn_style, _abi, ref generics, body) => {
1598-
if fn_style == ast::ExternFn {
1597+
ast::ItemFn(decl, _fn_style, abi, ref generics, body) => {
1598+
if abi != Rust {
15991599
let llfndecl = get_item_val(ccx, item.id);
16001600
foreign::trans_rust_fn_with_foreign_abi(
16011601
ccx, decl, body, item.attrs.as_slice(), llfndecl, item.id);
@@ -1939,8 +1939,8 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
19391939
}
19401940
}
19411941

1942-
ast::ItemFn(_, fn_style, _, _, _) => {
1943-
let llfn = if fn_style != ast::ExternFn {
1942+
ast::ItemFn(_, _, abi, _, _) => {
1943+
let llfn = if abi == Rust {
19441944
register_fn(ccx, i.span, sym, i.id, ty)
19451945
} else {
19461946
foreign::register_rust_fn_with_foreign_abi(ccx,

src/librustc/middle/trans/reflect.rs

-1
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,5 @@ pub fn ast_fn_style_constant(fn_style: ast::FnStyle) -> uint {
403403
match fn_style {
404404
ast::UnsafeFn => 1u,
405405
ast::NormalFn => 2u,
406-
ast::ExternFn => 3u
407406
}
408407
}

src/librustc/middle/typeck/infer/glb.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use middle::typeck::infer::{cres, InferCtxt};
2222
use middle::typeck::infer::{TypeTrace, Subtype};
2323
use middle::typeck::infer::fold_regions_in_sig;
2424
use syntax::ast::{Many, Once, MutImmutable, MutMutable};
25-
use syntax::ast::{ExternFn, NormalFn, UnsafeFn, NodeId};
25+
use syntax::ast::{NormalFn, UnsafeFn, NodeId};
2626
use syntax::ast::{Onceness, FnStyle};
2727
use collections::HashMap;
2828
use util::common::{indenter};
@@ -83,7 +83,6 @@ impl<'f> Combine for Glb<'f> {
8383

8484
fn fn_styles(&self, a: FnStyle, b: FnStyle) -> cres<FnStyle> {
8585
match (a, b) {
86-
(ExternFn, _) | (_, ExternFn) => Ok(ExternFn),
8786
(NormalFn, _) | (_, NormalFn) => Ok(NormalFn),
8887
(UnsafeFn, UnsafeFn) => Ok(UnsafeFn)
8988
}

src/librustc/middle/typeck/infer/lub.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use middle::typeck::infer::fold_regions_in_sig;
2323
use middle::typeck::infer::{TypeTrace, Subtype};
2424
use collections::HashMap;
2525
use syntax::ast::{Many, Once, NodeId};
26-
use syntax::ast::{ExternFn, NormalFn, UnsafeFn};
26+
use syntax::ast::{NormalFn, UnsafeFn};
2727
use syntax::ast::{Onceness, FnStyle};
2828
use util::ppaux::mt_to_str;
2929

@@ -78,8 +78,7 @@ impl<'f> Combine for Lub<'f> {
7878
fn fn_styles(&self, a: FnStyle, b: FnStyle) -> cres<FnStyle> {
7979
match (a, b) {
8080
(UnsafeFn, _) | (_, UnsafeFn) => Ok(UnsafeFn),
81-
(NormalFn, _) | (_, NormalFn) => Ok(NormalFn),
82-
(ExternFn, ExternFn) => Ok(ExternFn),
81+
(NormalFn, NormalFn) => Ok(NormalFn),
8382
}
8483
}
8584

src/librustdoc/clean.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1206,7 +1206,7 @@ impl Clean<Item> for ast::ForeignItem {
12061206
ForeignFunctionItem(Function {
12071207
decl: decl.clean(),
12081208
generics: generics.clean(),
1209-
fn_style: ast::ExternFn,
1209+
fn_style: ast::NormalFn,
12101210
})
12111211
}
12121212
ast::ForeignItemStatic(ref ty, mutbl) => {

src/librustdoc/html/format.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -397,10 +397,10 @@ impl fmt::Show for clean::Type {
397397
clean::BareFunction(ref decl) => {
398398
write!(f.buf, "{}{}fn{}{}",
399399
FnStyleSpace(decl.fn_style),
400-
match decl.abi {
401-
ref x if "" == *x => "".to_owned(),
402-
ref x if "\"Rust\"" == *x => "".to_owned(),
403-
ref s => " " + *s + " ",
400+
match decl.abi.as_slice() {
401+
"" => " extern ".to_owned(),
402+
"\"Rust\"" => "".to_owned(),
403+
s => format!(" extern {} ", s)
404404
},
405405
decl.generics,
406406
decl.decl)
@@ -517,7 +517,6 @@ impl fmt::Show for FnStyleSpace {
517517
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
518518
match self.get() {
519519
ast::UnsafeFn => write!(f.buf, "unsafe "),
520-
ast::ExternFn => write!(f.buf, "extern "),
521520
ast::NormalFn => Ok(())
522521
}
523522
}

src/libsyntax/ast.rs

-2
Original file line numberDiff line numberDiff line change
@@ -876,15 +876,13 @@ pub struct FnDecl {
876876
pub enum FnStyle {
877877
UnsafeFn, // declared with "unsafe fn"
878878
NormalFn, // declared with "fn"
879-
ExternFn, // declared with "extern fn"
880879
}
881880

882881
impl fmt::Show for FnStyle {
883882
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
884883
match *self {
885884
NormalFn => "normal".fmt(f),
886885
UnsafeFn => "unsafe".fmt(f),
887-
ExternFn => "extern".fmt(f),
888886
}
889887
}
890888
}

src/libsyntax/parse/parser.rs

+24-14
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use ast::{ExprLit, ExprLoop, ExprMac};
2727
use ast::{ExprMethodCall, ExprParen, ExprPath, ExprProc};
2828
use ast::{ExprRepeat, ExprRet, ExprStruct, ExprTup, ExprUnary};
2929
use ast::{ExprVec, ExprVstore, ExprVstoreSlice};
30-
use ast::{ExprVstoreMutSlice, ExprWhile, ExprForLoop, ExternFn, Field, FnDecl};
30+
use ast::{ExprVstoreMutSlice, ExprWhile, ExprForLoop, Field, FnDecl};
3131
use ast::{ExprVstoreUniq, Once, Many};
3232
use ast::{ForeignItem, ForeignItemStatic, ForeignItemFn, ForeignMod};
3333
use ast::{Ident, NormalFn, Inherited, Item, Item_, ItemStatic};
@@ -884,25 +884,29 @@ impl<'a> Parser<'a> {
884884
pub fn parse_ty_bare_fn(&mut self) -> Ty_ {
885885
/*
886886
887-
[extern "ABI"] [unsafe] fn <'lt> (S) -> T
888-
^~~~^ ^~~~~~~^ ^~~~^ ^~^ ^
889-
| | | | |
890-
| | | | Return type
891-
| | | Argument types
892-
| | Lifetimes
893-
| |
894-
| Function Style
895-
ABI
896-
887+
[unsafe] [extern "ABI"] fn <'lt> (S) -> T
888+
^~~~^ ^~~~^ ^~~~^ ^~^ ^
889+
| | | | |
890+
| | | | Return type
891+
| | | Argument types
892+
| | Lifetimes
893+
| ABI
894+
Function Style
897895
*/
898896

897+
let fn_style = self.parse_unsafety();
899898
let abi = if self.eat_keyword(keywords::Extern) {
900899
self.parse_opt_abi().unwrap_or(abi::C)
901900
} else {
902901
abi::Rust
903902
};
904903

905-
let fn_style = self.parse_unsafety();
904+
// NOTE: remove after a stage0 snapshot
905+
let fn_style = match self.parse_unsafety() {
906+
UnsafeFn => UnsafeFn,
907+
NormalFn => fn_style,
908+
};
909+
906910
self.expect_keyword(keywords::Fn);
907911
let (decl, lifetimes) = self.parse_ty_fn_decl(true);
908912
return TyBareFn(@BareFnTy {
@@ -1256,6 +1260,7 @@ impl<'a> Parser<'a> {
12561260
self.expect_and();
12571261
self.parse_borrowed_pointee()
12581262
} else if self.is_keyword(keywords::Extern) ||
1263+
self.is_keyword(keywords::Unsafe) ||
12591264
self.token_is_bare_fn_keyword() {
12601265
// BARE FUNCTION
12611266
self.parse_ty_bare_fn()
@@ -4563,7 +4568,7 @@ impl<'a> Parser<'a> {
45634568
// EXTERN FUNCTION ITEM
45644569
let abi = opt_abi.unwrap_or(abi::C);
45654570
let (ident, item_, extra_attrs) =
4566-
self.parse_item_fn(ExternFn, abi);
4571+
self.parse_item_fn(NormalFn, abi);
45674572
let item = self.mk_item(lo,
45684573
self.last_span.hi,
45694574
ident,
@@ -4617,9 +4622,14 @@ impl<'a> Parser<'a> {
46174622
&& self.look_ahead(1u, |t| *t != token::LBRACE) {
46184623
// UNSAFE FUNCTION ITEM
46194624
self.bump();
4625+
let abi = if self.eat_keyword(keywords::Extern) {
4626+
self.parse_opt_abi().unwrap_or(abi::C)
4627+
} else {
4628+
abi::Rust
4629+
};
46204630
self.expect_keyword(keywords::Fn);
46214631
let (ident, item_, extra_attrs) =
4622-
self.parse_item_fn(UnsafeFn, abi::Rust);
4632+
self.parse_item_fn(UnsafeFn, abi);
46234633
let item = self.mk_item(lo,
46244634
self.last_span.hi,
46254635
ident,

src/libsyntax/print/pprust.rs

+1-8
Original file line numberDiff line numberDiff line change
@@ -2372,16 +2372,10 @@ impl<'a> State<'a> {
23722372
abi: abi::Abi,
23732373
vis: ast::Visibility) -> IoResult<()> {
23742374
try!(word(&mut self.s, visibility_qualified(vis, "")));
2375-
2375+
try!(self.print_opt_fn_style(opt_fn_style));
23762376
if abi != abi::Rust {
23772377
try!(self.word_nbsp("extern"));
23782378
try!(self.word_nbsp(abi.to_str()));
2379-
2380-
if opt_fn_style != Some(ast::ExternFn) {
2381-
try!(self.print_opt_fn_style(opt_fn_style));
2382-
}
2383-
} else {
2384-
try!(self.print_opt_fn_style(opt_fn_style));
23852379
}
23862380

23872381
word(&mut self.s, "fn")
@@ -2391,7 +2385,6 @@ impl<'a> State<'a> {
23912385
match s {
23922386
ast::NormalFn => Ok(()),
23932387
ast::UnsafeFn => self.word_nbsp("unsafe"),
2394-
ast::ExternFn => self.word_nbsp("extern")
23952388
}
23962389
}
23972390

src/test/run-pass/issue-10025.rs

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2014 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+
unsafe extern fn foo() {}
12+
unsafe extern "C" fn bar() {}
13+
14+
fn main() {
15+
let _a: unsafe extern fn() = foo;
16+
let _a: unsafe extern "C" fn() = foo;
17+
}

0 commit comments

Comments
 (0)