ast: Keep string literals in ABIs precisely
This commit is contained in:
@@ -1287,8 +1287,8 @@ impl LoweringContext<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn lower_abi(&mut self, abi: Abi) -> abi::Abi {
|
pub(super) fn lower_abi(&mut self, abi: StrLit) -> abi::Abi {
|
||||||
abi::lookup(&abi.symbol.as_str()).unwrap_or_else(|| {
|
abi::lookup(&abi.symbol_unescaped.as_str()).unwrap_or_else(|| {
|
||||||
self.error_on_invalid_abi(abi);
|
self.error_on_invalid_abi(abi);
|
||||||
abi::Abi::Rust
|
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!(
|
struct_span_err!(
|
||||||
self.sess,
|
self.sess,
|
||||||
abi.span,
|
abi.span,
|
||||||
|
|||||||
@@ -1100,7 +1100,7 @@ impl<'a> Parser<'a> {
|
|||||||
fn parse_item_foreign_mod(
|
fn parse_item_foreign_mod(
|
||||||
&mut self,
|
&mut self,
|
||||||
lo: Span,
|
lo: Span,
|
||||||
abi: Option<Abi>,
|
abi: Option<StrLit>,
|
||||||
visibility: Visibility,
|
visibility: Visibility,
|
||||||
mut attrs: Vec<Attribute>,
|
mut attrs: Vec<Attribute>,
|
||||||
extern_sp: Span,
|
extern_sp: Span,
|
||||||
@@ -1778,7 +1778,7 @@ impl<'a> Parser<'a> {
|
|||||||
let is_c_abi = match header.ext {
|
let is_c_abi = match header.ext {
|
||||||
ast::Extern::None => false,
|
ast::Extern::None => false,
|
||||||
ast::Extern::Implicit => true,
|
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 {
|
let (ident, decl, generics) = self.parse_fn_sig(ParamCfg {
|
||||||
is_self_allowed: false,
|
is_self_allowed: false,
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ use crate::{Directory, DirectoryOwnership};
|
|||||||
use crate::lexer::UnmatchedBrace;
|
use crate::lexer::UnmatchedBrace;
|
||||||
|
|
||||||
use syntax::ast::{
|
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,
|
IsAsync, MacDelimiter, Mutability, StrStyle, Visibility, VisibilityKind, Unsafety,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1221,11 +1221,14 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Parses a string literal as an ABI spec.
|
/// 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() {
|
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 {
|
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(_) => {}
|
ast::LitKind::Err(_) => {}
|
||||||
_ => {
|
_ => {
|
||||||
self.struct_span_err(span, "non-string ABI literal")
|
self.struct_span_err(span, "non-string ABI literal")
|
||||||
|
|||||||
@@ -1422,6 +1422,33 @@ pub struct Lit {
|
|||||||
pub span: Span,
|
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
|
// Clippy uses Hash and PartialEq
|
||||||
/// Type of the integer literal based on provided suffix.
|
/// Type of the integer literal based on provided suffix.
|
||||||
#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug, Hash, PartialEq)]
|
#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug, Hash, PartialEq)]
|
||||||
@@ -2128,7 +2155,7 @@ pub struct Mod {
|
|||||||
/// E.g., `extern { .. }` or `extern C { .. }`.
|
/// E.g., `extern { .. }` or `extern C { .. }`.
|
||||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||||
pub struct ForeignMod {
|
pub struct ForeignMod {
|
||||||
pub abi: Option<Abi>,
|
pub abi: Option<StrLit>,
|
||||||
pub items: Vec<ForeignItem>,
|
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.
|
/// `extern` qualifier on a function item or function type.
|
||||||
#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
|
#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
|
||||||
pub enum Extern {
|
pub enum Extern {
|
||||||
None,
|
None,
|
||||||
Implicit,
|
Implicit,
|
||||||
Explicit(Abi),
|
Explicit(StrLit),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Extern {
|
impl Extern {
|
||||||
pub fn from_abi(abi: Option<Abi>) -> Extern {
|
pub fn from_abi(abi: Option<StrLit>) -> Extern {
|
||||||
match abi {
|
match abi {
|
||||||
Some(abi) => Extern::Explicit(abi),
|
Some(abi) => Extern::Explicit(abi),
|
||||||
None => Extern::Implicit,
|
None => Extern::Implicit,
|
||||||
|
|||||||
@@ -191,10 +191,10 @@ macro_rules! gate_feature_post {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> PostExpansionVisitor<'a> {
|
impl<'a> PostExpansionVisitor<'a> {
|
||||||
fn check_abi(&self, abi: ast::Abi) {
|
fn check_abi(&self, abi: ast::StrLit) {
|
||||||
let ast::Abi { symbol, span } = abi;
|
let ast::StrLit { symbol_unescaped, span, .. } = abi;
|
||||||
|
|
||||||
match &*symbol.as_str() {
|
match &*symbol_unescaped.as_str() {
|
||||||
// Stable
|
// Stable
|
||||||
"Rust" |
|
"Rust" |
|
||||||
"C" |
|
"C" |
|
||||||
|
|||||||
@@ -1233,7 +1233,8 @@ impl<'a> State<'a> {
|
|||||||
ast::ItemKind::ForeignMod(ref nmod) => {
|
ast::ItemKind::ForeignMod(ref nmod) => {
|
||||||
self.head("extern");
|
self.head("extern");
|
||||||
if let Some(abi) = nmod.abi {
|
if let Some(abi) = nmod.abi {
|
||||||
self.print_abi(abi);
|
self.print_literal(&abi.as_lit());
|
||||||
|
self.nbsp();
|
||||||
}
|
}
|
||||||
self.bopen();
|
self.bopen();
|
||||||
self.print_foreign_mod(nmod, &item.attrs);
|
self.print_foreign_mod(nmod, &item.attrs);
|
||||||
@@ -2875,17 +2876,14 @@ impl<'a> State<'a> {
|
|||||||
}
|
}
|
||||||
ast::Extern::Explicit(abi) => {
|
ast::Extern::Explicit(abi) => {
|
||||||
self.word_nbsp("extern");
|
self.word_nbsp("extern");
|
||||||
self.print_abi(abi);
|
self.print_literal(&abi.as_lit());
|
||||||
|
self.nbsp();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.s.word("fn")
|
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) {
|
crate fn print_unsafety(&mut self, s: ast::Unsafety) {
|
||||||
match s {
|
match s {
|
||||||
ast::Unsafety::Normal => {},
|
ast::Unsafety::Normal => {},
|
||||||
|
|||||||
Reference in New Issue
Block a user