ast: Keep string literals in ABIs precisely
This commit is contained in:
parent
266f547127
commit
00bc449602
6 changed files with 49 additions and 30 deletions
|
@ -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
|
||||
})
|
||||
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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")
|
||||
|
|
|
@ -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)]
|
||||
|
@ -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>,
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
|
|
@ -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" |
|
||||
|
|
|
@ -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);
|
||||
|
@ -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 => {},
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue