about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2019-11-07 08:51:55 +0100
committerGitHub <noreply@github.com>2019-11-07 08:51:55 +0100
commit883fe10da2f0651540fd5824898b7d7476969c41 (patch)
treec91a306e3e0e4d2f84a8c63245eac622d065eb8f /src/libsyntax
parenta3c8572b545124b62dcd16fb4b354f2efe842f35 (diff)
parent55f76cdb2f4d01cf87e47148c706c53a129fa45e (diff)
downloadrust-883fe10da2f0651540fd5824898b7d7476969c41.tar.gz
rust-883fe10da2f0651540fd5824898b7d7476969c41.zip
Rollup merge of #65884 - Centril:non-hardcoded-abis, r=petrochenkov
syntax: ABI-oblivious grammar

This PR has the following effects:

1. `extern $lit` is now legal where `$lit:literal` and `$lit` is substituted for a string literal.

2. `extern "abi_that_does_not_exist"` is now *syntactically* legal whereas before, the set of ABI strings was hard-coded into the grammar of the language. With this PR, the set of ABIs are instead validated and translated during lowering. That seems more appropriate.

3. `ast::FloatTy` is now distinct from `rustc_target::abi::FloatTy`. The former is used substantially more and the translation between them is only necessary in a single place.

4. As a result of 2-3, libsyntax no longer depends on librustc_target, which should improve pipe-lining somewhat.

cc @rust-lang/lang -- the points 1-2 slightly change the definition of the language but in a way which seems consistent with our general principles (in particular wrt. the discussions of turning things into semantic errors). I expect this to be uncontroversial but it's worth letting y'all know. :)

r? @varkor
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/Cargo.toml1
-rw-r--r--src/libsyntax/ast.rs115
-rw-r--r--src/libsyntax/error_codes.rs1
-rw-r--r--src/libsyntax/feature_gate/check.rs63
-rw-r--r--src/libsyntax/parse/literal.rs23
-rw-r--r--src/libsyntax/parse/parser.rs68
-rw-r--r--src/libsyntax/parse/parser/expr.rs6
-rw-r--r--src/libsyntax/parse/parser/item.rs21
-rw-r--r--src/libsyntax/parse/token.rs11
-rw-r--r--src/libsyntax/print/pprust.rs13
-rw-r--r--src/libsyntax/print/pprust/tests.rs7
11 files changed, 174 insertions, 155 deletions
diff --git a/src/libsyntax/Cargo.toml b/src/libsyntax/Cargo.toml
index b1839cc05cd..3e17e7949ea 100644
--- a/src/libsyntax/Cargo.toml
+++ b/src/libsyntax/Cargo.toml
@@ -20,5 +20,4 @@ errors = { path = "../librustc_errors", package = "rustc_errors" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_index = { path = "../librustc_index" }
 rustc_lexer = { path = "../librustc_lexer" }
-rustc_target = { path = "../librustc_target" }
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 2392b809150..67d1acbccfb 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -22,7 +22,6 @@ pub use GenericArgs::*;
 pub use UnsafeSource::*;
 pub use crate::util::parser::ExprPrecedence;
 
-pub use rustc_target::abi::FloatTy;
 pub use syntax_pos::symbol::{Ident, Symbol as Name};
 
 use crate::parse::token::{self, DelimToken};
@@ -38,7 +37,6 @@ use rustc_data_structures::sync::Lrc;
 use rustc_data_structures::thin_vec::ThinVec;
 use rustc_index::vec::Idx;
 use rustc_serialize::{self, Decoder, Encoder};
-use rustc_target::spec::abi::Abi;
 
 #[cfg(target_arch = "x86_64")]
 use rustc_data_structures::static_assert_size;
@@ -1401,7 +1399,7 @@ pub struct Lit {
 
 // Clippy uses Hash and PartialEq
 /// Type of the integer literal based on provided suffix.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy, Hash, PartialEq)]
+#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug, Hash, PartialEq)]
 pub enum LitIntType {
     /// e.g. `42_i32`.
     Signed(IntTy),
@@ -1411,6 +1409,15 @@ pub enum LitIntType {
     Unsuffixed,
 }
 
+/// Type of the float literal based on provided suffix.
+#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug, Hash, PartialEq)]
+pub enum LitFloatType {
+    /// A float literal with a suffix (`1f32` or `1E10f32`).
+    Suffixed(FloatTy),
+    /// A float literal without a suffix (`1.0 or 1.0E10`).
+    Unsuffixed,
+}
+
 /// Literal kind.
 ///
 /// E.g., `"foo"`, `42`, `12.34`, or `bool`.
@@ -1428,9 +1435,7 @@ pub enum LitKind {
     /// An integer literal (`1`).
     Int(u128, LitIntType),
     /// A float literal (`1f64` or `1E10f64`).
-    Float(Symbol, FloatTy),
-    /// A float literal without a suffix (`1.0 or 1.0E10`).
-    FloatUnsuffixed(Symbol),
+    Float(Symbol, LitFloatType),
     /// A boolean literal.
     Bool(bool),
     /// Placeholder for a literal that wasn't well-formed in some way.
@@ -1457,7 +1462,7 @@ impl LitKind {
     /// Returns `true` if this is a numeric literal.
     pub fn is_numeric(&self) -> bool {
         match *self {
-            LitKind::Int(..) | LitKind::Float(..) | LitKind::FloatUnsuffixed(..) => true,
+            LitKind::Int(..) | LitKind::Float(..) => true,
             _ => false,
         }
     }
@@ -1474,14 +1479,14 @@ impl LitKind {
             // suffixed variants
             LitKind::Int(_, LitIntType::Signed(..))
             | LitKind::Int(_, LitIntType::Unsigned(..))
-            | LitKind::Float(..) => true,
+            | LitKind::Float(_, LitFloatType::Suffixed(..)) => true,
             // unsuffixed variants
             LitKind::Str(..)
             | LitKind::ByteStr(..)
             | LitKind::Byte(..)
             | LitKind::Char(..)
             | LitKind::Int(_, LitIntType::Unsuffixed)
-            | LitKind::FloatUnsuffixed(..)
+            | LitKind::Float(_, LitFloatType::Unsuffixed)
             | LitKind::Bool(..)
             | LitKind::Err(..) => false,
         }
@@ -1553,7 +1558,36 @@ pub enum ImplItemKind {
     Macro(Mac),
 }
 
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Copy)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug)]
+pub enum FloatTy {
+    F32,
+    F64,
+}
+
+impl FloatTy {
+    pub fn name_str(self) -> &'static str {
+        match self {
+            FloatTy::F32 => "f32",
+            FloatTy::F64 => "f64",
+        }
+    }
+
+    pub fn name(self) -> Symbol {
+        match self {
+            FloatTy::F32 => sym::f32,
+            FloatTy::F64 => sym::f64,
+        }
+    }
+
+    pub fn bit_width(self) -> usize {
+        match self {
+            FloatTy::F32 => 32,
+            FloatTy::F64 => 64,
+        }
+    }
+}
+
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug)]
 pub enum IntTy {
     Isize,
     I8,
@@ -1563,20 +1597,8 @@ pub enum IntTy {
     I128,
 }
 
-impl fmt::Debug for IntTy {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Display::fmt(self, f)
-    }
-}
-
-impl fmt::Display for IntTy {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "{}", self.ty_to_string())
-    }
-}
-
 impl IntTy {
-    pub fn ty_to_string(&self) -> &'static str {
+    pub fn name_str(&self) -> &'static str {
         match *self {
             IntTy::Isize => "isize",
             IntTy::I8 => "i8",
@@ -1587,7 +1609,7 @@ impl IntTy {
         }
     }
 
-    pub fn to_symbol(&self) -> Symbol {
+    pub fn name(&self) -> Symbol {
         match *self {
             IntTy::Isize => sym::isize,
             IntTy::I8 => sym::i8,
@@ -1602,7 +1624,7 @@ impl IntTy {
         // Cast to a `u128` so we can correctly print `INT128_MIN`. All integral types
         // are parsed as `u128`, so we wouldn't want to print an extra negative
         // sign.
-        format!("{}{}", val as u128, self.ty_to_string())
+        format!("{}{}", val as u128, self.name_str())
     }
 
     pub fn bit_width(&self) -> Option<usize> {
@@ -1617,7 +1639,7 @@ impl IntTy {
     }
 }
 
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Copy)]
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Copy, Debug)]
 pub enum UintTy {
     Usize,
     U8,
@@ -1628,7 +1650,7 @@ pub enum UintTy {
 }
 
 impl UintTy {
-    pub fn ty_to_string(&self) -> &'static str {
+    pub fn name_str(&self) -> &'static str {
         match *self {
             UintTy::Usize => "usize",
             UintTy::U8 => "u8",
@@ -1639,7 +1661,7 @@ impl UintTy {
         }
     }
 
-    pub fn to_symbol(&self) -> Symbol {
+    pub fn name(&self) -> Symbol {
         match *self {
             UintTy::Usize => sym::usize,
             UintTy::U8 => sym::u8,
@@ -1651,7 +1673,7 @@ impl UintTy {
     }
 
     pub fn val_to_string(&self, val: u128) -> String {
-        format!("{}{}", val, self.ty_to_string())
+        format!("{}{}", val, self.name_str())
     }
 
     pub fn bit_width(&self) -> Option<usize> {
@@ -1666,18 +1688,6 @@ impl UintTy {
     }
 }
 
-impl fmt::Debug for UintTy {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Display::fmt(self, f)
-    }
-}
-
-impl fmt::Display for UintTy {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "{}", self.ty_to_string())
-    }
-}
-
 /// A constraint on an associated type (e.g., `A = Bar` in `Foo<A = Bar>` or
 /// `A: TraitA + TraitB` in `Foo<A: TraitA + TraitB>`).
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
@@ -2358,6 +2368,27 @@ 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,
+}
+
+impl Abi {
+    pub fn new(symbol: Symbol, span: Span) -> Self {
+        Self { symbol, span }
+    }
+}
+
+impl Default for Abi {
+    fn default() -> Self {
+        Self::new(sym::Rust, DUMMY_SP)
+    }
+}
+
 /// A function header.
 ///
 /// All the information between the visibility and the name of the function is
@@ -2376,7 +2407,7 @@ impl Default for FnHeader {
             unsafety: Unsafety::Normal,
             asyncness: dummy_spanned(IsAsync::NotAsync),
             constness: dummy_spanned(Constness::NotConst),
-            abi: Abi::Rust,
+            abi: Abi::default(),
         }
     }
 }
diff --git a/src/libsyntax/error_codes.rs b/src/libsyntax/error_codes.rs
index 941df5ea570..c23c8d65a7f 100644
--- a/src/libsyntax/error_codes.rs
+++ b/src/libsyntax/error_codes.rs
@@ -540,6 +540,5 @@ equivalent in Rust would be to use macros directly.
     E0630,
     E0693, // incorrect `repr(align)` attribute format
 //  E0694, // an unknown tool name found in scoped attributes
-    E0703, // invalid ABI
     E0717, // rustc_promotable without stability attribute
 }
diff --git a/src/libsyntax/feature_gate/check.rs b/src/libsyntax/feature_gate/check.rs
index b7e75ff3a7e..213e9680524 100644
--- a/src/libsyntax/feature_gate/check.rs
+++ b/src/libsyntax/feature_gate/check.rs
@@ -18,7 +18,6 @@ use crate::tokenstream::TokenTree;
 
 use errors::{Applicability, DiagnosticBuilder, Handler};
 use rustc_data_structures::fx::FxHashMap;
-use rustc_target::spec::abi::Abi;
 use syntax_pos::{Span, DUMMY_SP, MultiSpan};
 use log::debug;
 
@@ -192,62 +191,70 @@ macro_rules! gate_feature_post {
 }
 
 impl<'a> PostExpansionVisitor<'a> {
-    fn check_abi(&self, abi: Abi, span: Span) {
-        match abi {
-            Abi::RustIntrinsic => {
+    fn check_abi(&self, abi: ast::Abi) {
+        let ast::Abi { symbol, span } = abi;
+
+        match &*symbol.as_str() {
+            // Stable
+            "Rust" |
+            "C" |
+            "cdecl" |
+            "stdcall" |
+            "fastcall" |
+            "aapcs" |
+            "win64" |
+            "sysv64" |
+            "system" => {}
+            "rust-intrinsic" => {
                 gate_feature_post!(&self, intrinsics, span,
                                    "intrinsics are subject to change");
             },
-            Abi::PlatformIntrinsic => {
+            "platform-intrinsic" => {
                 gate_feature_post!(&self, platform_intrinsics, span,
                                    "platform intrinsics are experimental and possibly buggy");
             },
-            Abi::Vectorcall => {
+            "vectorcall" => {
                 gate_feature_post!(&self, abi_vectorcall, span,
                                    "vectorcall is experimental and subject to change");
             },
-            Abi::Thiscall => {
+            "thiscall" => {
                 gate_feature_post!(&self, abi_thiscall, span,
                                    "thiscall is experimental and subject to change");
             },
-            Abi::RustCall => {
+            "rust-call" => {
                 gate_feature_post!(&self, unboxed_closures, span,
                                    "rust-call ABI is subject to change");
             },
-            Abi::PtxKernel => {
+            "ptx-kernel" => {
                 gate_feature_post!(&self, abi_ptx, span,
                                    "PTX ABIs are experimental and subject to change");
             },
-            Abi::Unadjusted => {
+            "unadjusted" => {
                 gate_feature_post!(&self, abi_unadjusted, span,
                                    "unadjusted ABI is an implementation detail and perma-unstable");
             },
-            Abi::Msp430Interrupt => {
+            "msp430-interrupt" => {
                 gate_feature_post!(&self, abi_msp430_interrupt, span,
                                    "msp430-interrupt ABI is experimental and subject to change");
             },
-            Abi::X86Interrupt => {
+            "x86-interrupt" => {
                 gate_feature_post!(&self, abi_x86_interrupt, span,
                                    "x86-interrupt ABI is experimental and subject to change");
             },
-            Abi::AmdGpuKernel => {
+            "amdgpu-kernel" => {
                 gate_feature_post!(&self, abi_amdgpu_kernel, span,
                                    "amdgpu-kernel ABI is experimental and subject to change");
             },
-            Abi::EfiApi => {
+            "efiapi" => {
                 gate_feature_post!(&self, abi_efiapi, span,
                                    "efiapi ABI is experimental and subject to change");
             },
-            // Stable
-            Abi::Cdecl |
-            Abi::Stdcall |
-            Abi::Fastcall |
-            Abi::Aapcs |
-            Abi::Win64 |
-            Abi::SysV64 |
-            Abi::Rust |
-            Abi::C |
-            Abi::System => {}
+            abi => {
+                self.parse_sess.span_diagnostic.delay_span_bug(
+                    span,
+                    &format!("unrecognized ABI not caught in lowering: {}", abi),
+                )
+            }
         }
     }
 
@@ -373,7 +380,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
     fn visit_item(&mut self, i: &'a ast::Item) {
         match i.kind {
             ast::ItemKind::ForeignMod(ref foreign_module) => {
-                self.check_abi(foreign_module.abi, i.span);
+                self.check_abi(foreign_module.abi);
             }
 
             ast::ItemKind::Fn(..) => {
@@ -503,7 +510,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
     fn visit_ty(&mut self, ty: &'a ast::Ty) {
         match ty.kind {
             ast::TyKind::BareFn(ref bare_fn_ty) => {
-                self.check_abi(bare_fn_ty.abi, ty.span);
+                self.check_abi(bare_fn_ty.abi);
             }
             ast::TyKind::Never => {
                 gate_feature_post!(&self, never_type, ty.span,
@@ -597,7 +604,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
             // Stability of const fn methods are covered in
             // `visit_trait_item` and `visit_impl_item` below; this is
             // because default methods don't pass through this point.
-            self.check_abi(header.abi, span);
+            self.check_abi(header.abi);
         }
 
         if fn_decl.c_variadic() {
@@ -631,7 +638,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
         match ti.kind {
             ast::TraitItemKind::Method(ref sig, ref block) => {
                 if block.is_none() {
-                    self.check_abi(sig.header.abi, ti.span);
+                    self.check_abi(sig.header.abi);
                 }
                 if sig.decl.c_variadic() {
                     gate_feature_post!(&self, c_variadic, ti.span,
diff --git a/src/libsyntax/parse/literal.rs b/src/libsyntax/parse/literal.rs
index c42f4aa25cc..a8eeac59954 100644
--- a/src/libsyntax/parse/literal.rs
+++ b/src/libsyntax/parse/literal.rs
@@ -157,17 +157,18 @@ impl LitKind {
             }
             LitKind::Int(n, ty) => {
                 let suffix = match ty {
-                    ast::LitIntType::Unsigned(ty) => Some(ty.to_symbol()),
-                    ast::LitIntType::Signed(ty) => Some(ty.to_symbol()),
+                    ast::LitIntType::Unsigned(ty) => Some(ty.name()),
+                    ast::LitIntType::Signed(ty) => Some(ty.name()),
                     ast::LitIntType::Unsuffixed => None,
                 };
                 (token::Integer, sym::integer(n), suffix)
             }
             LitKind::Float(symbol, ty) => {
-                (token::Float, symbol, Some(ty.to_symbol()))
-            }
-            LitKind::FloatUnsuffixed(symbol) => {
-                (token::Float, symbol, None)
+                let suffix = match ty {
+                    ast::LitFloatType::Suffixed(ty) => Some(ty.name()),
+                    ast::LitFloatType::Unsuffixed => None,
+                };
+                (token::Float, symbol, suffix)
             }
             LitKind::Bool(value) => {
                 let symbol = if value { kw::True } else { kw::False };
@@ -244,12 +245,12 @@ fn filtered_float_lit(symbol: Symbol, suffix: Option<Symbol>, base: u32)
         return Err(LitError::NonDecimalFloat(base));
     }
     Ok(match suffix {
-        Some(suf) => match suf {
-            sym::f32 => LitKind::Float(symbol, ast::FloatTy::F32),
-            sym::f64 => LitKind::Float(symbol, ast::FloatTy::F64),
+        Some(suf) => LitKind::Float(symbol, ast::LitFloatType::Suffixed(match suf {
+            sym::f32 => ast::FloatTy::F32,
+            sym::f64 => ast::FloatTy::F64,
             _ => return Err(LitError::InvalidFloatSuffix),
-        }
-        None => LitKind::FloatUnsuffixed(symbol)
+        })),
+        None => LitKind::Float(symbol, ast::LitFloatType::Unsuffixed)
     })
 }
 
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 7652c730e51..0c358b1caaf 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -12,7 +12,7 @@ mod diagnostics;
 use diagnostics::Error;
 
 use crate::ast::{
-    self, DUMMY_NODE_ID, AttrStyle, Attribute, CrateSugar, Ident,
+    self, Abi, DUMMY_NODE_ID, AttrStyle, Attribute, CrateSugar, Ident,
     IsAsync, MacDelimiter, Mutability, StrStyle, Visibility, VisibilityKind, Unsafety,
 };
 use crate::parse::{PResult, Directory, DirectoryOwnership};
@@ -28,7 +28,6 @@ use crate::tokenstream::{self, DelimSpan, TokenTree, TokenStream, TreeAndJoint};
 use crate::ThinVec;
 
 use errors::{Applicability, DiagnosticBuilder, DiagnosticId, FatalError};
-use rustc_target::spec::abi::{self, Abi};
 use syntax_pos::{Span, BytePos, DUMMY_SP, FileName};
 use log::debug;
 
@@ -1206,48 +1205,41 @@ impl<'a> Parser<'a> {
         Ok(())
     }
 
-    /// Parses `extern` followed by an optional ABI string, or nothing.
+    /// Parses `extern string_literal?`.
+    /// If `extern` is not found, the Rust ABI is used.
+    /// If `extern` is found and a `string_literal` does not follow, the C ABI is used.
     fn parse_extern_abi(&mut self) -> PResult<'a, Abi> {
-        if self.eat_keyword(kw::Extern) {
-            Ok(self.parse_opt_abi()?.unwrap_or(Abi::C))
+        Ok(if self.eat_keyword(kw::Extern) {
+            self.parse_opt_abi()?
         } else {
-            Ok(Abi::Rust)
-        }
+            Abi::default()
+        })
     }
 
-    /// Parses a string as an ABI spec on an extern type or module. Consumes
-    /// the `extern` keyword, if one is found.
-    fn parse_opt_abi(&mut self) -> PResult<'a, Option<Abi>> {
-        match self.token.kind {
-            token::Literal(token::Lit { kind: token::Str, symbol, suffix }) |
-            token::Literal(token::Lit { kind: token::StrRaw(..), symbol, suffix }) => {
-                self.expect_no_suffix(self.token.span, "an ABI spec", suffix);
-                self.bump();
-                match abi::lookup(&symbol.as_str()) {
-                    Some(abi) => Ok(Some(abi)),
-                    None => {
-                        self.error_on_invalid_abi(symbol);
-                        Ok(None)
-                    }
+    /// Parses a string literal as an ABI spec.
+    /// If one is not found, the "C" ABI is used.
+    fn parse_opt_abi(&mut self) -> PResult<'a, Abi> {
+        let span = if self.token.can_begin_literal_or_bool() {
+            let ast::Lit { span, kind, .. } = self.parse_lit()?;
+            match kind {
+                ast::LitKind::Str(symbol, _) => return Ok(Abi::new(symbol, span)),
+                ast::LitKind::Err(_) => {}
+                _ => {
+                    self.struct_span_err(span, "non-string ABI literal")
+                        .span_suggestion(
+                            span,
+                            "specify the ABI with a string literal",
+                            "\"C\"".to_string(),
+                            Applicability::MaybeIncorrect,
+                        )
+                        .emit();
                 }
             }
-            _ => Ok(None),
-        }
-    }
-
-    /// Emit an error where `symbol` is an invalid ABI.
-    fn error_on_invalid_abi(&self, symbol: Symbol) {
-        let prev_span = self.prev_span;
-        struct_span_err!(
-            self.sess.span_diagnostic,
-            prev_span,
-            E0703,
-            "invalid ABI: found `{}`",
-            symbol
-        )
-        .span_label(prev_span, "invalid ABI")
-        .help(&format!("valid ABIs: {}", abi::all_names().join(", ")))
-        .emit();
+            span
+        } else {
+            self.prev_span
+        };
+        Ok(Abi::new(sym::C, span))
     }
 
     /// We are parsing `async fn`. If we are on Rust 2015, emit an error.
diff --git a/src/libsyntax/parse/parser/expr.rs b/src/libsyntax/parse/parser/expr.rs
index 97b1092452a..80ea8f380fb 100644
--- a/src/libsyntax/parse/parser/expr.rs
+++ b/src/libsyntax/parse/parser/expr.rs
@@ -1116,7 +1116,11 @@ impl<'a> Parser<'a> {
                 Err(self.span_fatal(token.span, &msg))
             }
             Err(err) => {
-                let (lit, span) = (token.expect_lit(), token.span);
+                let span = token.span;
+                let lit = match token.kind {
+                    token::Literal(lit) => lit,
+                    _ => unreachable!(),
+                };
                 self.bump();
                 self.error_literal_from_token(err, lit, span);
                 // Pack possible quotes and prefixes from the original literal into
diff --git a/src/libsyntax/parse/parser/item.rs b/src/libsyntax/parse/parser/item.rs
index cc6235c6fc7..ebb1cf12996 100644
--- a/src/libsyntax/parse/parser/item.rs
+++ b/src/libsyntax/parse/parser/item.rs
@@ -3,7 +3,7 @@ use super::diagnostics::{Error, dummy_arg, ConsumeClosingDelim};
 
 use crate::maybe_whole;
 use crate::ptr::P;
-use crate::ast::{self, DUMMY_NODE_ID, Ident, Attribute, AttrKind, AttrStyle, AnonConst, Item};
+use crate::ast::{self, Abi, DUMMY_NODE_ID, Ident, Attribute, AttrKind, AttrStyle, AnonConst, Item};
 use crate::ast::{ItemKind, ImplItem, ImplItemKind, TraitItem, TraitItemKind, UseTree, UseTreeKind};
 use crate::ast::{PathSegment, IsAuto, Constness, IsAsync, Unsafety, Defaultness};
 use crate::ast::{Visibility, VisibilityKind, Mutability, FnHeader, ForeignItem, ForeignItemKind};
@@ -17,7 +17,6 @@ use crate::ThinVec;
 
 use log::debug;
 use std::mem;
-use rustc_target::spec::abi::Abi;
 use errors::{Applicability, DiagnosticBuilder, DiagnosticId, StashKey};
 use syntax_pos::BytePos;
 
@@ -111,7 +110,7 @@ impl<'a> Parser<'a> {
                 return Ok(Some(self.parse_item_extern_crate(lo, vis, attrs)?));
             }
 
-            let opt_abi = self.parse_opt_abi()?;
+            let abi = self.parse_opt_abi()?;
 
             if self.eat_keyword(kw::Fn) {
                 // EXTERN FUNCTION ITEM
@@ -120,12 +119,12 @@ impl<'a> Parser<'a> {
                     unsafety: Unsafety::Normal,
                     asyncness: respan(fn_span, IsAsync::NotAsync),
                     constness: respan(fn_span, Constness::NotConst),
-                    abi: opt_abi.unwrap_or(Abi::C),
+                    abi,
                 };
                 return self.parse_item_fn(lo, vis, attrs, header);
             } else if self.check(&token::OpenDelim(token::Brace)) {
                 return Ok(Some(
-                    self.parse_item_foreign_mod(lo, opt_abi, vis, attrs, extern_sp)?,
+                    self.parse_item_foreign_mod(lo, abi, vis, attrs, extern_sp)?,
                 ));
             }
 
@@ -201,7 +200,7 @@ impl<'a> Parser<'a> {
                     unsafety,
                     asyncness,
                     constness: respan(fn_span, Constness::NotConst),
-                    abi: Abi::Rust,
+                    abi: Abi::new(sym::Rust, fn_span),
                 };
                 return self.parse_item_fn(lo, vis, attrs, header);
             }
@@ -238,7 +237,7 @@ impl<'a> Parser<'a> {
                 unsafety: Unsafety::Normal,
                 asyncness: respan(fn_span, IsAsync::NotAsync),
                 constness: respan(fn_span, Constness::NotConst),
-                abi: Abi::Rust,
+                abi: Abi::new(sym::Rust, fn_span),
             };
             return self.parse_item_fn(lo, vis, attrs, header);
         }
@@ -1115,15 +1114,13 @@ impl<'a> Parser<'a> {
     fn parse_item_foreign_mod(
         &mut self,
         lo: Span,
-        opt_abi: Option<Abi>,
+        abi: Abi,
         visibility: Visibility,
         mut attrs: Vec<Attribute>,
         extern_sp: Span,
     ) -> PResult<'a, P<Item>> {
         self.expect(&token::OpenDelim(token::Brace))?;
 
-        let abi = opt_abi.unwrap_or(Abi::C);
-
         attrs.extend(self.parse_inner_attributes()?);
 
         let mut foreign_items = vec![];
@@ -1801,7 +1798,7 @@ impl<'a> Parser<'a> {
     ) -> PResult<'a, Option<P<Item>>> {
         let (ident, decl, generics) = self.parse_fn_sig(ParamCfg {
             is_self_allowed: false,
-            allow_c_variadic: header.abi == Abi::C && header.unsafety == Unsafety::Unsafe,
+            allow_c_variadic: header.abi.symbol == sym::C && header.unsafety == Unsafety::Unsafe,
             is_name_required: |_| true,
         })?;
         let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
@@ -1930,7 +1927,7 @@ impl<'a> Parser<'a> {
         let asyncness = respan(self.prev_span, asyncness);
         let unsafety = self.parse_unsafety();
         let (constness, unsafety, abi) = if is_const_fn {
-            (respan(const_span, Constness::Const), unsafety, Abi::Rust)
+            (respan(const_span, Constness::Const), unsafety, Abi::default())
         } else {
             let abi = self.parse_extern_abi()?;
             (respan(self.prev_span, Constness::NotConst), unsafety, abi)
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index 03e77b199cc..6f3da344ccf 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -381,9 +381,7 @@ impl Token {
         match self.kind {
             OpenDelim(Brace) => true,
             Interpolated(ref nt) => match **nt {
-                NtExpr(..) => true,
-                NtBlock(..) => true,
-                NtLiteral(..) => true,
+                NtExpr(..) | NtBlock(..) | NtLiteral(..) => true,
                 _ => false,
             }
             _ => self.can_begin_literal_or_bool(),
@@ -404,13 +402,6 @@ impl Token {
         }
     }
 
-    crate fn expect_lit(&self) -> Lit {
-        match self.kind {
-            Literal(lit) => lit,
-            _ => panic!("`expect_lit` called on non-literal"),
-        }
-    }
-
     /// Returns `true` if the token is any literal, a minus (which can prefix a literal,
     /// for example a '-42', or one of the boolean idents).
     pub fn can_begin_literal_or_bool(&self) -> bool {
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index c8afe8a1ff4..1d59c13a9d0 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -14,7 +14,6 @@ use crate::sess::ParseSess;
 use crate::symbol::{kw, sym};
 use crate::tokenstream::{self, TokenStream, TokenTree};
 
-use rustc_target::spec::abi::{self, Abi};
 use syntax_pos::{self, BytePos};
 use syntax_pos::{FileName, Span};
 
@@ -1230,7 +1229,7 @@ impl<'a> State<'a> {
             }
             ast::ItemKind::ForeignMod(ref nmod) => {
                 self.head("extern");
-                self.word_nbsp(nmod.abi.to_string());
+                self.print_abi(nmod.abi);
                 self.bopen();
                 self.print_foreign_mod(nmod, &item.attrs);
                 self.bclose(item.span);
@@ -2823,7 +2822,7 @@ impl<'a> State<'a> {
     }
 
     crate fn print_ty_fn(&mut self,
-                       abi: abi::Abi,
+                       abi: ast::Abi,
                        unsafety: ast::Unsafety,
                        decl: &ast::FnDecl,
                        name: Option<ast::Ident>,
@@ -2884,14 +2883,18 @@ impl<'a> State<'a> {
         self.print_asyncness(header.asyncness.node);
         self.print_unsafety(header.unsafety);
 
-        if header.abi != Abi::Rust {
+        if header.abi.symbol != sym::Rust {
             self.word_nbsp("extern");
-            self.word_nbsp(header.abi.to_string());
+            self.print_abi(header.abi);
         }
 
         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 => {},
diff --git a/src/libsyntax/print/pprust/tests.rs b/src/libsyntax/print/pprust/tests.rs
index faa70edbfa2..2c6dd0fb1c6 100644
--- a/src/libsyntax/print/pprust/tests.rs
+++ b/src/libsyntax/print/pprust/tests.rs
@@ -34,12 +34,7 @@ fn test_fun_to_string() {
         assert_eq!(
             fun_to_string(
                 &decl,
-                ast::FnHeader {
-                    unsafety: ast::Unsafety::Normal,
-                    constness: source_map::dummy_spanned(ast::Constness::NotConst),
-                    asyncness: source_map::dummy_spanned(ast::IsAsync::NotAsync),
-                    abi: Abi::Rust,
-                },
+                ast::FnHeader::default(),
                 abba_ident,
                 &generics
             ),