Skip to content

Commit

Permalink
ast: Keep string literals in ABIs precisely
Browse files Browse the repository at this point in the history
  • Loading branch information
petrochenkov committed Nov 16, 2019
1 parent 266f547 commit 00bc449
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 30 deletions.
6 changes: 3 additions & 3 deletions src/librustc/hir/lowering/item.rs
Expand Up @@ -1287,8 +1287,8 @@ impl LoweringContext<'_> {
}
}

pub(super) fn lower_abi(&mut self, abi: Abi) -> abi::Abi {
abi::lookup(&abi.symbol.as_str()).unwrap_or_else(|| {
pub(super) fn lower_abi(&mut self, abi: StrLit) -> abi::Abi {
abi::lookup(&abi.symbol_unescaped.as_str()).unwrap_or_else(|| {
self.error_on_invalid_abi(abi);
abi::Abi::Rust
})
Expand All @@ -1302,7 +1302,7 @@ impl LoweringContext<'_> {
}
}

fn error_on_invalid_abi(&self, abi: Abi) {
fn error_on_invalid_abi(&self, abi: StrLit) {
struct_span_err!(
self.sess,
abi.span,
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_parse/parser/item.rs
Expand Up @@ -1100,7 +1100,7 @@ impl<'a> Parser<'a> {
fn parse_item_foreign_mod(
&mut self,
lo: Span,
abi: Option<Abi>,
abi: Option<StrLit>,
visibility: Visibility,
mut attrs: Vec<Attribute>,
extern_sp: Span,
Expand Down Expand Up @@ -1778,7 +1778,7 @@ impl<'a> Parser<'a> {
let is_c_abi = match header.ext {
ast::Extern::None => false,
ast::Extern::Implicit => true,
ast::Extern::Explicit(abi) => abi.symbol == sym::C,
ast::Extern::Explicit(abi) => abi.symbol_unescaped == sym::C,
};
let (ident, decl, generics) = self.parse_fn_sig(ParamCfg {
is_self_allowed: false,
Expand Down
11 changes: 7 additions & 4 deletions src/librustc_parse/parser/mod.rs
Expand Up @@ -15,7 +15,7 @@ use crate::{Directory, DirectoryOwnership};
use crate::lexer::UnmatchedBrace;

use syntax::ast::{
self, Abi, DUMMY_NODE_ID, AttrStyle, Attribute, CrateSugar, Extern, Ident,
self, DUMMY_NODE_ID, AttrStyle, Attribute, CrateSugar, Extern, Ident,
IsAsync, MacDelimiter, Mutability, StrStyle, Visibility, VisibilityKind, Unsafety,
};

Expand Down Expand Up @@ -1221,11 +1221,14 @@ impl<'a> Parser<'a> {
}

/// Parses a string literal as an ABI spec.
fn parse_opt_abi(&mut self) -> PResult<'a, Option<Abi>> {
fn parse_opt_abi(&mut self) -> PResult<'a, Option<StrLit>> {
if self.token.can_begin_literal_or_bool() {
let ast::Lit { span, kind, .. } = self.parse_lit()?;
let ast::Lit { token: token::Lit { symbol, suffix, .. }, span, kind }
= self.parse_lit()?;
match kind {
ast::LitKind::Str(symbol, _) => return Ok(Some(Abi { symbol, span })),
ast::LitKind::Str(symbol_unescaped, style) => return Ok(Some(StrLit {
style, symbol, suffix, span, symbol_unescaped,
})),
ast::LitKind::Err(_) => {}
_ => {
self.struct_span_err(span, "non-string ABI literal")
Expand Down
42 changes: 30 additions & 12 deletions src/libsyntax/ast.rs
Expand Up @@ -1422,6 +1422,33 @@ pub struct Lit {
pub span: Span,
}

/// Same as `Lit`, but restricted to string literals.
#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
pub struct StrLit {
/// The original literal token as written in source code.
pub style: StrStyle,
pub symbol: Symbol,
pub suffix: Option<Symbol>,
pub span: Span,
/// The unescaped "semantic" representation of the literal lowered from the original token.
/// FIXME: Remove this and only create the semantic representation during lowering to HIR.
pub symbol_unescaped: Symbol,
}

impl StrLit {
crate fn as_lit(&self) -> Lit {
let token_kind = match self.style {
StrStyle::Cooked => token::Str,
StrStyle::Raw(n) => token::StrRaw(n),
};
Lit {
token: token::Lit::new(token_kind, self.symbol, self.suffix),
span: self.span,
kind: LitKind::Str(self.symbol_unescaped, self.style),
}
}
}

// Clippy uses Hash and PartialEq
/// Type of the integer literal based on provided suffix.
#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug, Hash, PartialEq)]
Expand Down Expand Up @@ -2128,7 +2155,7 @@ pub struct Mod {
/// E.g., `extern { .. }` or `extern C { .. }`.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct ForeignMod {
pub abi: Option<Abi>,
pub abi: Option<StrLit>,
pub items: Vec<ForeignItem>,
}

Expand Down Expand Up @@ -2411,25 +2438,16 @@ impl Item {
}
}

/// A reference to an ABI.
///
/// In AST our notion of an ABI is still syntactic unlike in `rustc_target::spec::abi::Abi`.
#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug, PartialEq)]
pub struct Abi {
pub symbol: Symbol,
pub span: Span,
}

/// `extern` qualifier on a function item or function type.
#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
pub enum Extern {
None,
Implicit,
Explicit(Abi),
Explicit(StrLit),
}

impl Extern {
pub fn from_abi(abi: Option<Abi>) -> Extern {
pub fn from_abi(abi: Option<StrLit>) -> Extern {
match abi {
Some(abi) => Extern::Explicit(abi),
None => Extern::Implicit,
Expand Down
6 changes: 3 additions & 3 deletions src/libsyntax/feature_gate/check.rs
Expand Up @@ -191,10 +191,10 @@ macro_rules! gate_feature_post {
}

impl<'a> PostExpansionVisitor<'a> {
fn check_abi(&self, abi: ast::Abi) {
let ast::Abi { symbol, span } = abi;
fn check_abi(&self, abi: ast::StrLit) {
let ast::StrLit { symbol_unescaped, span, .. } = abi;

match &*symbol.as_str() {
match &*symbol_unescaped.as_str() {
// Stable
"Rust" |
"C" |
Expand Down
10 changes: 4 additions & 6 deletions src/libsyntax/print/pprust.rs
Expand Up @@ -1233,7 +1233,8 @@ impl<'a> State<'a> {
ast::ItemKind::ForeignMod(ref nmod) => {
self.head("extern");
if let Some(abi) = nmod.abi {
self.print_abi(abi);
self.print_literal(&abi.as_lit());
self.nbsp();
}
self.bopen();
self.print_foreign_mod(nmod, &item.attrs);
Expand Down Expand Up @@ -2875,17 +2876,14 @@ impl<'a> State<'a> {
}
ast::Extern::Explicit(abi) => {
self.word_nbsp("extern");
self.print_abi(abi);
self.print_literal(&abi.as_lit());
self.nbsp();
}
}

self.s.word("fn")
}

fn print_abi(&mut self, abi: ast::Abi) {
self.word_nbsp(format!("\"{}\"", abi.symbol));
}

crate fn print_unsafety(&mut self, s: ast::Unsafety) {
match s {
ast::Unsafety::Normal => {},
Expand Down

0 comments on commit 00bc449

Please sign in to comment.