Skip to content

Commit 266f547

Browse files
committed
ast: Keep extern qualifiers in functions more precisely
1 parent 5f00849 commit 266f547

File tree

13 files changed

+118
-88
lines changed

13 files changed

+118
-88
lines changed

src/librustc/hir/lowering.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1219,7 +1219,7 @@ impl<'a> LoweringContext<'a> {
12191219
ImplTraitContext::disallowed(),
12201220
),
12211221
unsafety: f.unsafety,
1222-
abi: this.lower_abi(f.abi),
1222+
abi: this.lower_extern(f.ext),
12231223
decl: this.lower_fn_decl(&f.decl, None, false, None),
12241224
param_names: this.lower_fn_params_to_names(&f.decl),
12251225
}))

src/librustc/hir/lowering/item.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -735,7 +735,7 @@ impl LoweringContext<'_> {
735735

736736
fn lower_foreign_mod(&mut self, fm: &ForeignMod) -> hir::ForeignMod {
737737
hir::ForeignMod {
738-
abi: self.lower_abi(fm.abi),
738+
abi: fm.abi.map_or(abi::Abi::C, |abi| self.lower_abi(abi)),
739739
items: fm.items
740740
.iter()
741741
.map(|x| self.lower_foreign_item(x))
@@ -1283,7 +1283,7 @@ impl LoweringContext<'_> {
12831283
unsafety: h.unsafety,
12841284
asyncness: self.lower_asyncness(h.asyncness.node),
12851285
constness: h.constness.node,
1286-
abi: self.lower_abi(h.abi),
1286+
abi: self.lower_extern(h.ext),
12871287
}
12881288
}
12891289

@@ -1294,6 +1294,14 @@ impl LoweringContext<'_> {
12941294
})
12951295
}
12961296

1297+
pub(super) fn lower_extern(&mut self, ext: Extern) -> abi::Abi {
1298+
match ext {
1299+
Extern::None => abi::Abi::Rust,
1300+
Extern::Implicit => abi::Abi::C,
1301+
Extern::Explicit(abi) => self.lower_abi(abi),
1302+
}
1303+
}
1304+
12971305
fn error_on_invalid_abi(&self, abi: Abi) {
12981306
struct_span_err!(
12991307
self.sess,

src/librustc_parse/parser/item.rs

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ impl<'a> Parser<'a> {
114114
unsafety: Unsafety::Normal,
115115
asyncness: respan(fn_span, IsAsync::NotAsync),
116116
constness: respan(fn_span, Constness::NotConst),
117-
abi,
117+
ext: Extern::from_abi(abi),
118118
};
119119
return self.parse_item_fn(lo, vis, attrs, header);
120120
} else if self.check(&token::OpenDelim(token::Brace)) {
@@ -143,14 +143,14 @@ impl<'a> Parser<'a> {
143143
if self.check_keyword(kw::Extern) {
144144
self.sess.gated_spans.gate(sym::const_extern_fn, lo.to(self.token.span));
145145
}
146-
let abi = self.parse_extern_abi()?;
146+
let ext = self.parse_extern()?;
147147
self.bump(); // `fn`
148148

149149
let header = FnHeader {
150150
unsafety,
151151
asyncness: respan(const_span, IsAsync::NotAsync),
152152
constness: respan(const_span, Constness::Const),
153-
abi,
153+
ext,
154154
};
155155
return self.parse_item_fn(lo, vis, attrs, header);
156156
}
@@ -193,7 +193,7 @@ impl<'a> Parser<'a> {
193193
unsafety,
194194
asyncness,
195195
constness: respan(fn_span, Constness::NotConst),
196-
abi: Abi::new(sym::Rust, fn_span),
196+
ext: Extern::None,
197197
};
198198
return self.parse_item_fn(lo, vis, attrs, header);
199199
}
@@ -230,7 +230,7 @@ impl<'a> Parser<'a> {
230230
unsafety: Unsafety::Normal,
231231
asyncness: respan(fn_span, IsAsync::NotAsync),
232232
constness: respan(fn_span, Constness::NotConst),
233-
abi: Abi::new(sym::Rust, fn_span),
233+
ext: Extern::None,
234234
};
235235
return self.parse_item_fn(lo, vis, attrs, header);
236236
}
@@ -242,14 +242,14 @@ impl<'a> Parser<'a> {
242242
self.bump(); // `unsafe`
243243
// `{` is also expected after `unsafe`; in case of error, include it in the diagnostic.
244244
self.check(&token::OpenDelim(token::Brace));
245-
let abi = self.parse_extern_abi()?;
245+
let ext = self.parse_extern()?;
246246
self.expect_keyword(kw::Fn)?;
247247
let fn_span = self.prev_span;
248248
let header = FnHeader {
249249
unsafety: Unsafety::Unsafe,
250250
asyncness: respan(fn_span, IsAsync::NotAsync),
251251
constness: respan(fn_span, Constness::NotConst),
252-
abi,
252+
ext,
253253
};
254254
return self.parse_item_fn(lo, vis, attrs, header);
255255
}
@@ -1100,7 +1100,7 @@ impl<'a> Parser<'a> {
11001100
fn parse_item_foreign_mod(
11011101
&mut self,
11021102
lo: Span,
1103-
abi: Abi,
1103+
abi: Option<Abi>,
11041104
visibility: Visibility,
11051105
mut attrs: Vec<Attribute>,
11061106
extern_sp: Span,
@@ -1775,9 +1775,16 @@ impl<'a> Parser<'a> {
17751775
attrs: Vec<Attribute>,
17761776
header: FnHeader,
17771777
) -> PResult<'a, Option<P<Item>>> {
1778+
let is_c_abi = match header.ext {
1779+
ast::Extern::None => false,
1780+
ast::Extern::Implicit => true,
1781+
ast::Extern::Explicit(abi) => abi.symbol == sym::C,
1782+
};
17781783
let (ident, decl, generics) = self.parse_fn_sig(ParamCfg {
17791784
is_self_allowed: false,
1780-
allow_c_variadic: header.abi.symbol == sym::C && header.unsafety == Unsafety::Unsafe,
1785+
// FIXME: Parsing should not depend on ABI or unsafety and
1786+
// the variadic parameter should always be parsed.
1787+
allow_c_variadic: is_c_abi && header.unsafety == Unsafety::Unsafe,
17811788
is_name_required: |_| true,
17821789
})?;
17831790
let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
@@ -1905,19 +1912,19 @@ impl<'a> Parser<'a> {
19051912
}
19061913
let asyncness = respan(self.prev_span, asyncness);
19071914
let unsafety = self.parse_unsafety();
1908-
let (constness, unsafety, abi) = if is_const_fn {
1909-
(respan(const_span, Constness::Const), unsafety, Abi::default())
1915+
let (constness, unsafety, ext) = if is_const_fn {
1916+
(respan(const_span, Constness::Const), unsafety, Extern::None)
19101917
} else {
1911-
let abi = self.parse_extern_abi()?;
1912-
(respan(self.prev_span, Constness::NotConst), unsafety, abi)
1918+
let ext = self.parse_extern()?;
1919+
(respan(self.prev_span, Constness::NotConst), unsafety, ext)
19131920
};
19141921
if !self.eat_keyword(kw::Fn) {
19151922
// It is possible for `expect_one_of` to recover given the contents of
19161923
// `self.expected_tokens`, therefore, do not use `self.unexpected()` which doesn't
19171924
// account for this.
19181925
if !self.expect_one_of(&[], &[])? { unreachable!() }
19191926
}
1920-
Ok(FnHeader { constness, unsafety, asyncness, abi })
1927+
Ok(FnHeader { constness, unsafety, asyncness, ext })
19211928
}
19221929

19231930
/// Parse the "signature", including the identifier, parameters, and generics of a function.

src/librustc_parse/parser/mod.rs

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use crate::{Directory, DirectoryOwnership};
1515
use crate::lexer::UnmatchedBrace;
1616

1717
use syntax::ast::{
18-
self, Abi, DUMMY_NODE_ID, AttrStyle, Attribute, CrateSugar, Ident,
18+
self, Abi, DUMMY_NODE_ID, AttrStyle, Attribute, CrateSugar, Extern, Ident,
1919
IsAsync, MacDelimiter, Mutability, StrStyle, Visibility, VisibilityKind, Unsafety,
2020
};
2121

@@ -1212,23 +1212,20 @@ impl<'a> Parser<'a> {
12121212
}
12131213

12141214
/// Parses `extern string_literal?`.
1215-
/// If `extern` is not found, the Rust ABI is used.
1216-
/// If `extern` is found and a `string_literal` does not follow, the C ABI is used.
1217-
fn parse_extern_abi(&mut self) -> PResult<'a, Abi> {
1215+
fn parse_extern(&mut self) -> PResult<'a, Extern> {
12181216
Ok(if self.eat_keyword(kw::Extern) {
1219-
self.parse_opt_abi()?
1217+
Extern::from_abi(self.parse_opt_abi()?)
12201218
} else {
1221-
Abi::default()
1219+
Extern::None
12221220
})
12231221
}
12241222

12251223
/// Parses a string literal as an ABI spec.
1226-
/// If one is not found, the "C" ABI is used.
1227-
fn parse_opt_abi(&mut self) -> PResult<'a, Abi> {
1228-
let span = if self.token.can_begin_literal_or_bool() {
1224+
fn parse_opt_abi(&mut self) -> PResult<'a, Option<Abi>> {
1225+
if self.token.can_begin_literal_or_bool() {
12291226
let ast::Lit { span, kind, .. } = self.parse_lit()?;
12301227
match kind {
1231-
ast::LitKind::Str(symbol, _) => return Ok(Abi::new(symbol, span)),
1228+
ast::LitKind::Str(symbol, _) => return Ok(Some(Abi { symbol, span })),
12321229
ast::LitKind::Err(_) => {}
12331230
_ => {
12341231
self.struct_span_err(span, "non-string ABI literal")
@@ -1241,11 +1238,8 @@ impl<'a> Parser<'a> {
12411238
.emit();
12421239
}
12431240
}
1244-
span
1245-
} else {
1246-
self.prev_span
1247-
};
1248-
Ok(Abi::new(sym::C, span))
1241+
}
1242+
Ok(None)
12491243
}
12501244

12511245
/// We are parsing `async fn`. If we are on Rust 2015, emit an error.

src/librustc_parse/parser/ty.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ impl<'a> Parser<'a> {
287287
*/
288288

289289
let unsafety = self.parse_unsafety();
290-
let abi = self.parse_extern_abi()?;
290+
let ext = self.parse_extern()?;
291291
self.expect_keyword(kw::Fn)?;
292292
let cfg = ParamCfg {
293293
is_self_allowed: false,
@@ -296,7 +296,7 @@ impl<'a> Parser<'a> {
296296
};
297297
let decl = self.parse_fn_decl(cfg, false)?;
298298
Ok(TyKind::BareFn(P(BareFnTy {
299-
abi,
299+
ext,
300300
unsafety,
301301
generic_params,
302302
decl,

src/librustc_save_analysis/sig.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,8 @@ use crate::{id_from_def_id, id_from_node_id, SaveContext};
3030
use rls_data::{SigElement, Signature};
3131

3232
use rustc::hir::def::{Res, DefKind};
33-
use syntax::ast::{self, NodeId};
33+
use syntax::ast::{self, Extern, NodeId};
3434
use syntax::print::pprust;
35-
use syntax_pos::sym;
3635

3736
pub fn item_signature(item: &ast::Item, scx: &SaveContext<'_, '_>) -> Option<Signature> {
3837
if !scx.config.signatures {
@@ -157,9 +156,11 @@ fn text_sig(text: String) -> Signature {
157156
}
158157
}
159158

160-
fn push_abi(text: &mut String, abi: ast::Abi) {
161-
if abi.symbol != sym::Rust {
162-
text.push_str(&format!("extern \"{}\" ", abi.symbol));
159+
fn push_extern(text: &mut String, ext: Extern) {
160+
match ext {
161+
Extern::None => {}
162+
Extern::Implicit => text.push_str("extern "),
163+
Extern::Explicit(abi) => text.push_str(&format!("extern \"{}\" ", abi.symbol)),
163164
}
164165
}
165166

@@ -237,7 +238,7 @@ impl Sig for ast::Ty {
237238
if f.unsafety == ast::Unsafety::Unsafe {
238239
text.push_str("unsafe ");
239240
}
240-
push_abi(&mut text, f.abi);
241+
push_extern(&mut text, f.ext);
241242
text.push_str("fn(");
242243

243244
let mut defs = vec![];
@@ -387,7 +388,7 @@ impl Sig for ast::Item {
387388
if header.unsafety == ast::Unsafety::Unsafe {
388389
text.push_str("unsafe ");
389390
}
390-
push_abi(&mut text, header.abi);
391+
push_extern(&mut text, header.ext);
391392
text.push_str("fn ");
392393

393394
let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?;
@@ -936,7 +937,7 @@ fn make_method_signature(
936937
if m.header.unsafety == ast::Unsafety::Unsafe {
937938
text.push_str("unsafe ");
938939
}
939-
push_abi(&mut text, m.header.abi);
940+
push_extern(&mut text, m.header.ext);
940941
text.push_str("fn ");
941942

942943
let mut sig = name_and_generics(text, 0, generics, id, ident, scx)?;

src/libsyntax/ast.rs

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1745,7 +1745,7 @@ pub struct Ty {
17451745
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
17461746
pub struct BareFnTy {
17471747
pub unsafety: Unsafety,
1748-
pub abi: Abi,
1748+
pub ext: Extern,
17491749
pub generic_params: Vec<GenericParam>,
17501750
pub decl: P<FnDecl>,
17511751
}
@@ -2128,7 +2128,7 @@ pub struct Mod {
21282128
/// E.g., `extern { .. }` or `extern C { .. }`.
21292129
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
21302130
pub struct ForeignMod {
2131-
pub abi: Abi,
2131+
pub abi: Option<Abi>,
21322132
pub items: Vec<ForeignItem>,
21332133
}
21342134

@@ -2420,15 +2420,20 @@ pub struct Abi {
24202420
pub span: Span,
24212421
}
24222422

2423-
impl Abi {
2424-
pub fn new(symbol: Symbol, span: Span) -> Self {
2425-
Self { symbol, span }
2426-
}
2423+
/// `extern` qualifier on a function item or function type.
2424+
#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
2425+
pub enum Extern {
2426+
None,
2427+
Implicit,
2428+
Explicit(Abi),
24272429
}
24282430

2429-
impl Default for Abi {
2430-
fn default() -> Self {
2431-
Self::new(sym::Rust, DUMMY_SP)
2431+
impl Extern {
2432+
pub fn from_abi(abi: Option<Abi>) -> Extern {
2433+
match abi {
2434+
Some(abi) => Extern::Explicit(abi),
2435+
None => Extern::Implicit,
2436+
}
24322437
}
24332438
}
24342439

@@ -2441,7 +2446,7 @@ pub struct FnHeader {
24412446
pub unsafety: Unsafety,
24422447
pub asyncness: Spanned<IsAsync>,
24432448
pub constness: Spanned<Constness>,
2444-
pub abi: Abi,
2449+
pub ext: Extern,
24452450
}
24462451

24472452
impl Default for FnHeader {
@@ -2450,7 +2455,7 @@ impl Default for FnHeader {
24502455
unsafety: Unsafety::Normal,
24512456
asyncness: dummy_spanned(IsAsync::NotAsync),
24522457
constness: dummy_spanned(Constness::NotConst),
2453-
abi: Abi::default(),
2458+
ext: Extern::None,
24542459
}
24552460
}
24562461
}

src/libsyntax/feature_gate/check.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,12 @@ impl<'a> PostExpansionVisitor<'a> {
258258
}
259259
}
260260

261+
fn check_extern(&self, ext: ast::Extern) {
262+
if let ast::Extern::Explicit(abi) = ext {
263+
self.check_abi(abi);
264+
}
265+
}
266+
261267
fn maybe_report_invalid_custom_discriminants(&self, variants: &[ast::Variant]) {
262268
let has_fields = variants.iter().any(|variant| match variant.data {
263269
VariantData::Tuple(..) | VariantData::Struct(..) => true,
@@ -388,7 +394,9 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
388394
fn visit_item(&mut self, i: &'a ast::Item) {
389395
match i.kind {
390396
ast::ItemKind::ForeignMod(ref foreign_module) => {
391-
self.check_abi(foreign_module.abi);
397+
if let Some(abi) = foreign_module.abi {
398+
self.check_abi(abi);
399+
}
392400
}
393401

394402
ast::ItemKind::Fn(..) => {
@@ -511,7 +519,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
511519
fn visit_ty(&mut self, ty: &'a ast::Ty) {
512520
match ty.kind {
513521
ast::TyKind::BareFn(ref bare_fn_ty) => {
514-
self.check_abi(bare_fn_ty.abi);
522+
self.check_extern(bare_fn_ty.ext);
515523
}
516524
ast::TyKind::Never => {
517525
gate_feature_post!(&self, never_type, ty.span,
@@ -605,7 +613,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
605613
// Stability of const fn methods are covered in
606614
// `visit_trait_item` and `visit_impl_item` below; this is
607615
// because default methods don't pass through this point.
608-
self.check_abi(header.abi);
616+
self.check_extern(header.ext);
609617
}
610618

611619
if fn_decl.c_variadic() {
@@ -639,7 +647,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
639647
match ti.kind {
640648
ast::TraitItemKind::Method(ref sig, ref block) => {
641649
if block.is_none() {
642-
self.check_abi(sig.header.abi);
650+
self.check_extern(sig.header.ext);
643651
}
644652
if sig.decl.c_variadic() {
645653
gate_feature_post!(&self, c_variadic, ti.span,

0 commit comments

Comments
 (0)