about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/Cargo.lock20
-rwxr-xr-xsrc/ci/docker/run.sh2
-rw-r--r--src/liballoc/collections/btree/node.rs2
-rw-r--r--src/libcore/lib.rs3
-rw-r--r--src/libcore/slice/rotate.rs2
-rw-r--r--src/libproc_macro/diagnostic.rs44
-rw-r--r--src/libproc_macro/lib.rs348
-rw-r--r--src/libproc_macro/quote.rs344
-rw-r--r--src/libproc_macro/rustc.rs284
-rw-r--r--src/librustc/hir/map/blocks.rs8
-rw-r--r--src/librustc/infer/mod.rs37
-rw-r--r--src/librustc/lint/builtin.rs6
-rw-r--r--src/librustc/lint/mod.rs18
-rw-r--r--src/librustc/middle/dead.rs16
-rw-r--r--src/librustc/ty/mod.rs9
-rw-r--r--src/librustc/ty/query/job.rs4
-rw-r--r--src/librustc_codegen_llvm/abi.rs8
-rw-r--r--src/librustc_codegen_llvm/back/lto.rs14
-rw-r--r--src/librustc_codegen_llvm/builder.rs19
-rw-r--r--src/librustc_data_structures/lib.rs21
-rw-r--r--src/librustc_data_structures/ptr_key.rs45
-rw-r--r--src/librustc_errors/diagnostic.rs2
-rw-r--r--src/librustc_llvm/ffi.rs1
-rw-r--r--src/librustc_metadata/cstore_impl.rs6
-rw-r--r--src/librustc_metadata/lib.rs1
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs5
-rw-r--r--src/librustc_resolve/lib.rs17
-rw-r--r--src/librustc_resolve/macros.rs17
-rw-r--r--src/librustc_resolve/resolve_imports.rs193
-rw-r--r--src/librustc_typeck/astconv.rs47
-rw-r--r--src/librustdoc/lib.rs10
-rw-r--r--src/libstd/lib.rs4
-rw-r--r--src/libsyntax/ext/expand.rs17
-rw-r--r--src/libsyntax/parse/lexer/mod.rs6
-rw-r--r--src/libsyntax/parse/token.rs49
-rw-r--r--src/rustllvm/PassWrapper.cpp14
m---------src/stdsimd0
-rw-r--r--src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-two-attrs.rs22
-rw-r--r--src/test/run-pass-fulldeps/proc-macro/derive-two-attrs.rs24
-rw-r--r--src/test/run-pass/const-block.rs10
-rw-r--r--src/test/run-pass/sepcomp-lib-lto.rs1
-rw-r--r--src/test/rustdoc-js/multi-query.js1
-rw-r--r--src/test/ui-fulldeps/proc-macro/attribute-spans-preserved.rs22
-rw-r--r--src/test/ui-fulldeps/proc-macro/attribute-spans-preserved.stderr21
-rw-r--r--src/test/ui-fulldeps/proc-macro/attribute-spans-preserved.stdout1
-rw-r--r--src/test/ui-fulldeps/proc-macro/auxiliary/attribute-spans-preserved.rs44
-rw-r--r--src/test/ui/imports/glob-shadowing.rs44
-rw-r--r--src/test/ui/imports/glob-shadowing.stderr49
m---------src/tools/clippy10
49 files changed, 1001 insertions, 891 deletions
diff --git a/src/Cargo.lock b/src/Cargo.lock
index 8299dea1c4b..09baaeadaee 100644
--- a/src/Cargo.lock
+++ b/src/Cargo.lock
@@ -44,7 +44,7 @@ dependencies = [
  "html5ever 0.22.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "matches 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -342,10 +342,10 @@ name = "clippy_lints"
 version = "0.0.212"
 dependencies = [
  "cargo_metadata 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "if_chain 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "if_chain 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "matches 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex-syntax 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -887,14 +887,14 @@ name = "idna"
 version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "matches 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "if_chain"
-version = "0.1.2"
+version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -1153,7 +1153,7 @@ dependencies = [
 
 [[package]]
 name = "matches"
-version = "0.1.6"
+version = "0.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -2868,7 +2868,7 @@ name = "unicode-bidi"
 version = "0.3.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "matches 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2932,7 +2932,7 @@ version = "1.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "matches 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -3123,7 +3123,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum html5ever 0.22.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b04478cf718862650a0bf66acaf8f2f8c906fbc703f35c916c1f4211b069a364"
 "checksum humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0484fda3e7007f2a4a0d9c3a703ca38c71c54c55602ce4660c419fd32e188c9e"
 "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e"
-"checksum if_chain 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "61bb90bdd39e3af69b0172dfc6130f6cd6332bf040fbb9bdd4401d37adbd48b8"
+"checksum if_chain 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4bac95d9aa0624e7b78187d6fb8ab012b41d9f6f54b1bcb61e61c4845f8357ec"
 "checksum ignore 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "787a5940ab88e0f2f3b2cad3687060bddcf67520f3b761abc31065c9c495d088"
 "checksum is-match 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7e5b386aef33a1c677be65237cb9d32c3f3ef56bd035949710c4bb13083eb053"
 "checksum isatty 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6c324313540cd4d7ba008d43dc6606a32a5579f13cc17b2804c13096f0a5c522"
@@ -3148,7 +3148,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
 "checksum maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08cbb6b4fef96b6d77bfc40ec491b1690c779e77b05cd9f07f787ed376fd4c43"
 "checksum markup5ever 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfedc97d5a503e96816d10fedcd5b42f760b2e525ce2f7ec71f6a41780548475"
-"checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376"
+"checksum matches 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "835511bab37c34c47da5cb44844bea2cfde0236db0b506f90ea4224482c9774a"
 "checksum mdbook 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "90b5a8d7e341ceee5db3882a06078d42661ddcfa2b3687319cc5da76ec4e782f"
 "checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d"
 "checksum memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2ffa2c986de11a9df78620c01eeaaf27d94d3ff02bf81bfcca953102dd0c6ff"
diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh
index 931c28f1ca9..b1ee636644e 100755
--- a/src/ci/docker/run.sh
+++ b/src/ci/docker/run.sh
@@ -99,7 +99,7 @@ objdir=$root_dir/obj
 
 mkdir -p $HOME/.cargo
 mkdir -p $objdir/tmp
-mkdir $objdir/cores
+mkdir -p $objdir/cores
 
 args=
 if [ "$SCCACHE_BUCKET" != "" ]; then
diff --git a/src/liballoc/collections/btree/node.rs b/src/liballoc/collections/btree/node.rs
index 19bdcbc6ad6..0ae45b31232 100644
--- a/src/liballoc/collections/btree/node.rs
+++ b/src/liballoc/collections/btree/node.rs
@@ -103,7 +103,7 @@ impl<K, V> LeafNode<K, V> {
     }
 
     fn is_shared_root(&self) -> bool {
-        self as *const _ == &EMPTY_ROOT_NODE as *const _ as *const LeafNode<K, V>
+        ptr::eq(self, &EMPTY_ROOT_NODE as *const _ as *const _)
     }
 }
 
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index bbe6ae8619f..72074e1dbce 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -244,9 +244,6 @@ macro_rules! vector_impl { ($([$f:ident, $($args:tt)*]),*) => { $($f!($($args)*)
 #[cfg(not(stage0))] // allow changes to how stdsimd works in stage0
 mod coresimd;
 
-#[unstable(feature = "stdsimd", issue = "48556")]
-#[cfg(not(stage0))]
-pub use coresimd::simd;
 #[stable(feature = "simd_arch", since = "1.27.0")]
 #[cfg(not(stage0))]
 pub use coresimd::arch;
diff --git a/src/libcore/slice/rotate.rs b/src/libcore/slice/rotate.rs
index e4a4e33c172..28ef53ccb5c 100644
--- a/src/libcore/slice/rotate.rs
+++ b/src/libcore/slice/rotate.rs
@@ -48,7 +48,6 @@ impl<T> RawArray<T> {
 /// # Safety
 ///
 /// The specified range must be valid for reading and writing.
-/// The type `T` must have non-zero size.
 ///
 /// # Algorithm
 ///
@@ -73,6 +72,7 @@ pub unsafe fn ptr_rotate<T>(mut left: usize, mid: *mut T, mut right: usize) {
     loop {
         let delta = cmp::min(left, right);
         if delta <= RawArray::<T>::cap() {
+            // We will always hit this immediately for ZST.
             break;
         }
 
diff --git a/src/libproc_macro/diagnostic.rs b/src/libproc_macro/diagnostic.rs
index 06939a9d1e1..51e7647f36c 100644
--- a/src/libproc_macro/diagnostic.rs
+++ b/src/libproc_macro/diagnostic.rs
@@ -10,7 +10,8 @@
 
 use Span;
 
-use rustc_errors as rustc;
+use rustc_errors as errors;
+use syntax_pos::MultiSpan;
 
 /// An enum representing a diagnostic level.
 #[unstable(feature = "proc_macro_diagnostic", issue = "38356")]
@@ -97,38 +98,21 @@ impl Diagnostic {
     /// Emit the diagnostic.
     #[unstable(feature = "proc_macro_diagnostic", issue = "38356")]
     pub fn emit(self) {
-        ::__internal::with_sess(move |sess, _| {
-            let handler = &sess.span_diagnostic;
-            let level = __internal::level_to_internal_level(self.level);
-            let mut diag = rustc::DiagnosticBuilder::new(handler, level, &*self.message);
+        let level = self.level.to_internal();
+        let mut diag = errors::Diagnostic::new(level, &*self.message);
 
-            if let Some(span) = self.span {
-                diag.set_span(span.0);
-            }
+        if let Some(span) = self.span {
+            diag.set_span(span.0);
+        }
 
-            for child in self.children {
-                let span = child.span.map(|s| s.0);
-                let level = __internal::level_to_internal_level(child.level);
-                diag.sub(level, &*child.message, span);
-            }
+        for child in self.children {
+            let span = child.span.map_or(MultiSpan::new(), |s| s.0.into());
+            let level = child.level.to_internal();
+            diag.sub(level, &*child.message, span, None);
+        }
 
-            diag.emit();
+        ::__internal::with_sess(move |sess, _| {
+            errors::DiagnosticBuilder::new_diagnostic(&sess.span_diagnostic, diag).emit();
         });
     }
 }
-
-#[unstable(feature = "proc_macro_internals", issue = "27812")]
-#[doc(hidden)]
-pub mod __internal {
-    use super::{Level, rustc};
-
-    pub fn level_to_internal_level(level: Level) -> rustc::Level {
-        match level {
-            Level::Error => rustc::Level::Error,
-            Level::Warning => rustc::Level::Warning,
-            Level::Note => rustc::Level::Note,
-            Level::Help => rustc::Level::Help,
-            Level::__Nonexhaustive => unreachable!("Level::__Nonexhaustive")
-        }
-    }
-}
diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs
index f5a7c88a1b7..61da9db76f6 100644
--- a/src/libproc_macro/lib.rs
+++ b/src/libproc_macro/lib.rs
@@ -44,21 +44,24 @@ extern crate syntax_pos;
 extern crate rustc_errors;
 extern crate rustc_data_structures;
 
+#[unstable(feature = "proc_macro_internals", issue = "27812")]
+#[doc(hidden)]
+pub mod rustc;
+
 mod diagnostic;
 
 #[unstable(feature = "proc_macro_diagnostic", issue = "38356")]
 pub use diagnostic::{Diagnostic, Level};
 
 use std::{ascii, fmt, iter};
+use std::path::PathBuf;
 use rustc_data_structures::sync::Lrc;
 use std::str::FromStr;
 
-use syntax::ast;
 use syntax::errors::DiagnosticBuilder;
 use syntax::parse::{self, token};
-use syntax::symbol::{keywords, Symbol};
+use syntax::symbol::Symbol;
 use syntax::tokenstream;
-use syntax::parse::lexer::{self, comments};
 use syntax_pos::{FileMap, Pos, FileName};
 
 /// The main type provided by this crate, representing an abstract stream of
@@ -145,6 +148,9 @@ impl fmt::Debug for TokenStream {
     }
 }
 
+#[unstable(feature = "proc_macro_quote", issue = "38356")]
+pub use quote::{quote, quote_span};
+
 /// Creates a token stream containing a single token tree.
     #[stable(feature = "proc_macro_lib2", since = "1.29.0")]
 impl From<TokenTree> for TokenStream {
@@ -237,7 +243,7 @@ pub mod token_stream {
 /// Unquoting is done with `$`, and works by taking the single next ident as the unquoted term.
 /// To quote `$` itself, use `$$`.
 ///
-/// This is a dummy macro, the actual implementation is in quote::Quoter
+/// This is a dummy macro, the actual implementation is in `quote::quote`.`
 #[unstable(feature = "proc_macro_quote", issue = "38356")]
 #[macro_export]
 macro_rules! quote { () => {} }
@@ -246,13 +252,6 @@ macro_rules! quote { () => {} }
 #[doc(hidden)]
 mod quote;
 
-/// Quote a `Span` into a `TokenStream`.
-/// This is needed to implement a custom quoter.
-#[unstable(feature = "proc_macro_quote", issue = "38356")]
-pub fn quote_span(span: Span) -> TokenStream {
-    quote::Quote::quote(span)
-}
-
 /// A region of source code, along with macro expansion information.
 #[stable(feature = "proc_macro_lib2", since = "1.29.0")]
 #[derive(Copy, Clone)]
@@ -425,8 +424,11 @@ impl SourceFile {
     ///
     /// [`is_real`]: #method.is_real
     #[unstable(feature = "proc_macro_span", issue = "38356")]
-    pub fn path(&self) -> &FileName {
-        &self.filemap.name
+    pub fn path(&self) -> PathBuf {
+        match self.filemap.name {
+            FileName::Real(ref path) => path.clone(),
+            _ => PathBuf::from(self.filemap.name.to_string())
+        }
     }
 
     /// Returns `true` if this source file is a real source file, and not generated by an external
@@ -440,18 +442,12 @@ impl SourceFile {
     }
 }
 
-#[unstable(feature = "proc_macro_span", issue = "38356")]
-impl AsRef<FileName> for SourceFile {
-    fn as_ref(&self) -> &FileName {
-        self.path()
-    }
-}
 
 #[unstable(feature = "proc_macro_span", issue = "38356")]
 impl fmt::Debug for SourceFile {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_struct("SourceFile")
-            .field("path", self.path())
+            .field("path", &self.path())
             .field("is_real", &self.is_real())
             .finish()
     }
@@ -467,13 +463,6 @@ impl PartialEq for SourceFile {
 #[unstable(feature = "proc_macro_span", issue = "38356")]
 impl Eq for SourceFile {}
 
-#[unstable(feature = "proc_macro_span", issue = "38356")]
-impl PartialEq<FileName> for SourceFile {
-    fn eq(&self, other: &FileName) -> bool {
-        self.as_ref() == other
-    }
-}
-
 /// A single token or a delimited sequence of token trees (e.g. `[1, (), ..]`).
 #[stable(feature = "proc_macro_lib2", since = "1.29.0")]
 #[derive(Clone)]
@@ -599,7 +588,7 @@ impl fmt::Display for TokenTree {
 /// A delimited token stream.
 ///
 /// A `Group` internally contains a `TokenStream` which is surrounded by `Delimiter`s.
-#[derive(Clone, Debug)]
+#[derive(Clone)]
 #[stable(feature = "proc_macro_lib2", since = "1.29.0")]
 pub struct Group {
     delimiter: Delimiter,
@@ -693,12 +682,23 @@ impl fmt::Display for Group {
     }
 }
 
+#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
+impl fmt::Debug for Group {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_struct("Group")
+            .field("delimiter", &self.delimiter())
+            .field("stream", &self.stream())
+            .field("span", &self.span())
+            .finish()
+    }
+}
+
 /// An `Punct` is an single punctuation character like `+`, `-` or `#`.
 ///
 /// Multicharacter operators like `+=` are represented as two instances of `Punct` with different
 /// forms of `Spacing` returned.
 #[stable(feature = "proc_macro_lib2", since = "1.29.0")]
-#[derive(Clone, Debug)]
+#[derive(Clone)]
 pub struct Punct {
     ch: char,
     spacing: Spacing,
@@ -782,8 +782,19 @@ impl fmt::Display for Punct {
     }
 }
 
+#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
+impl fmt::Debug for Punct {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_struct("Punct")
+            .field("ch", &self.as_char())
+            .field("spacing", &self.spacing())
+            .field("span", &self.span())
+            .finish()
+    }
+}
+
 /// An identifier (`ident`).
-#[derive(Clone, Debug)]
+#[derive(Clone)]
 #[stable(feature = "proc_macro_lib2", since = "1.29.0")]
 pub struct Ident {
     sym: Symbol,
@@ -797,6 +808,16 @@ impl !Send for Ident {}
 impl !Sync for Ident {}
 
 impl Ident {
+    fn is_valid(string: &str) -> bool {
+        let mut chars = string.chars();
+        if let Some(start) = chars.next() {
+            (start == '_' || start.is_xid_start())
+                && chars.all(|cont| cont == '_' || cont.is_xid_continue())
+        } else {
+            false
+        }
+    }
+
     /// Creates a new `Ident` with the given `string` as well as the specified
     /// `span`.
     /// The `string` argument must be a valid identifier permitted by the
@@ -818,26 +839,19 @@ impl Ident {
     /// tokens, requires a `Span` to be specified at construction.
     #[stable(feature = "proc_macro_lib2", since = "1.29.0")]
     pub fn new(string: &str, span: Span) -> Ident {
-        if !lexer::is_valid_ident(string) {
+        if !Ident::is_valid(string) {
             panic!("`{:?}` is not a valid identifier", string)
         }
-        Ident {
-            sym: Symbol::intern(string),
-            span,
-            is_raw: false,
-        }
+        Ident::new_maybe_raw(string, span, false)
     }
 
     /// Same as `Ident::new`, but creates a raw identifier (`r#ident`).
     #[unstable(feature = "proc_macro_raw_ident", issue = "38356")]
     pub fn new_raw(string: &str, span: Span) -> Ident {
-        let mut ident = Ident::new(string, span);
-        if ident.sym == keywords::Underscore.name() ||
-           ast::Ident::with_empty_ctxt(ident.sym).is_path_segment_keyword() {
-            panic!("`{:?}` is not a valid raw identifier", string)
+        if !Ident::is_valid(string) {
+            panic!("`{:?}` is not a valid identifier", string)
         }
-        ident.is_raw = true;
-        ident
+        Ident::new_maybe_raw(string, span, true)
     }
 
     /// Returns the span of this `Ident`, encompassing the entire string returned
@@ -859,10 +873,17 @@ impl Ident {
 #[stable(feature = "proc_macro_lib2", since = "1.29.0")]
 impl fmt::Display for Ident {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        if self.is_raw {
-            f.write_str("r#")?;
-        }
-        self.sym.as_str().fmt(f)
+        TokenStream::from(TokenTree::from(self.clone())).fmt(f)
+    }
+}
+
+#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
+impl fmt::Debug for Ident {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_struct("Ident")
+            .field("ident", &self.to_string())
+            .field("span", &self.span())
+            .finish()
     }
 }
 
@@ -870,11 +891,12 @@ impl fmt::Display for Ident {
 /// character (`'a'`), byte character (`b'a'`), an integer or floating point number
 /// with or without a suffix (`1`, `1u8`, `2.3`, `2.3f32`).
 /// Boolean literals like `true` and `false` do not belong here, they are `Ident`s.
+// FIXME(eddyb) `Literal` should not expose internal `Debug` impls.
 #[derive(Clone, Debug)]
 #[stable(feature = "proc_macro_lib2", since = "1.29.0")]
 pub struct Literal {
     lit: token::Lit,
-    suffix: Option<ast::Name>,
+    suffix: Option<Symbol>,
     span: Span,
 }
 
@@ -1122,236 +1144,6 @@ impl fmt::Display for Literal {
     }
 }
 
-impl Delimiter {
-    fn from_internal(delim: token::DelimToken) -> Delimiter {
-        match delim {
-            token::Paren => Delimiter::Parenthesis,
-            token::Brace => Delimiter::Brace,
-            token::Bracket => Delimiter::Bracket,
-            token::NoDelim => Delimiter::None,
-        }
-    }
-
-    fn to_internal(self) -> token::DelimToken {
-        match self {
-            Delimiter::Parenthesis => token::Paren,
-            Delimiter::Brace => token::Brace,
-            Delimiter::Bracket => token::Bracket,
-            Delimiter::None => token::NoDelim,
-        }
-    }
-}
-
-impl TokenTree {
-    fn from_internal(stream: tokenstream::TokenStream, stack: &mut Vec<TokenTree>)
-                -> TokenTree {
-        use syntax::parse::token::*;
-
-        let (tree, is_joint) = stream.as_tree();
-        let (span, token) = match tree {
-            tokenstream::TokenTree::Token(span, token) => (span, token),
-            tokenstream::TokenTree::Delimited(span, delimed) => {
-                let delimiter = Delimiter::from_internal(delimed.delim);
-                let mut g = Group::new(delimiter, TokenStream(delimed.tts.into()));
-                g.set_span(Span(span));
-                return g.into()
-            }
-        };
-
-        let op_kind = if is_joint { Spacing::Joint } else { Spacing::Alone };
-        macro_rules! tt {
-            ($e:expr) => ({
-                let mut x = TokenTree::from($e);
-                x.set_span(Span(span));
-                x
-            })
-        }
-        macro_rules! op {
-            ($a:expr) => (tt!(Punct::new($a, op_kind)));
-            ($a:expr, $b:expr) => ({
-                stack.push(tt!(Punct::new($b, op_kind)));
-                tt!(Punct::new($a, Spacing::Joint))
-            });
-            ($a:expr, $b:expr, $c:expr) => ({
-                stack.push(tt!(Punct::new($c, op_kind)));
-                stack.push(tt!(Punct::new($b, Spacing::Joint)));
-                tt!(Punct::new($a, Spacing::Joint))
-            })
-        }
-
-        match token {
-            Eq => op!('='),
-            Lt => op!('<'),
-            Le => op!('<', '='),
-            EqEq => op!('=', '='),
-            Ne => op!('!', '='),
-            Ge => op!('>', '='),
-            Gt => op!('>'),
-            AndAnd => op!('&', '&'),
-            OrOr => op!('|', '|'),
-            Not => op!('!'),
-            Tilde => op!('~'),
-            BinOp(Plus) => op!('+'),
-            BinOp(Minus) => op!('-'),
-            BinOp(Star) => op!('*'),
-            BinOp(Slash) => op!('/'),
-            BinOp(Percent) => op!('%'),
-            BinOp(Caret) => op!('^'),
-            BinOp(And) => op!('&'),
-            BinOp(Or) => op!('|'),
-            BinOp(Shl) => op!('<', '<'),
-            BinOp(Shr) => op!('>', '>'),
-            BinOpEq(Plus) => op!('+', '='),
-            BinOpEq(Minus) => op!('-', '='),
-            BinOpEq(Star) => op!('*', '='),
-            BinOpEq(Slash) => op!('/', '='),
-            BinOpEq(Percent) => op!('%', '='),
-            BinOpEq(Caret) => op!('^', '='),
-            BinOpEq(And) => op!('&', '='),
-            BinOpEq(Or) => op!('|', '='),
-            BinOpEq(Shl) => op!('<', '<', '='),
-            BinOpEq(Shr) => op!('>', '>', '='),
-            At => op!('@'),
-            Dot => op!('.'),
-            DotDot => op!('.', '.'),
-            DotDotDot => op!('.', '.', '.'),
-            DotDotEq => op!('.', '.', '='),
-            Comma => op!(','),
-            Semi => op!(';'),
-            Colon => op!(':'),
-            ModSep => op!(':', ':'),
-            RArrow => op!('-', '>'),
-            LArrow => op!('<', '-'),
-            FatArrow => op!('=', '>'),
-            Pound => op!('#'),
-            Dollar => op!('$'),
-            Question => op!('?'),
-            SingleQuote => op!('\''),
-
-            Ident(ident, false) => {
-                tt!(self::Ident::new(&ident.as_str(), Span(span)))
-            }
-            Ident(ident, true) => {
-                tt!(self::Ident::new_raw(&ident.as_str(), Span(span)))
-            }
-            Lifetime(ident) => {
-                let ident = ident.without_first_quote();
-                stack.push(tt!(self::Ident::new(&ident.as_str(), Span(span))));
-                tt!(Punct::new('\'', Spacing::Joint))
-            }
-            Literal(lit, suffix) => tt!(self::Literal { lit, suffix, span: Span(span) }),
-            DocComment(c) => {
-                let style = comments::doc_comment_style(&c.as_str());
-                let stripped = comments::strip_doc_comment_decoration(&c.as_str());
-                let stream = vec![
-                    tt!(self::Ident::new("doc", Span(span))),
-                    tt!(Punct::new('=', Spacing::Alone)),
-                    tt!(self::Literal::string(&stripped)),
-                ].into_iter().collect();
-                stack.push(tt!(Group::new(Delimiter::Bracket, stream)));
-                if style == ast::AttrStyle::Inner {
-                    stack.push(tt!(Punct::new('!', Spacing::Alone)));
-                }
-                tt!(Punct::new('#', Spacing::Alone))
-            }
-
-            Interpolated(_) => {
-                __internal::with_sess(|sess, _| {
-                    let tts = token.interpolated_to_tokenstream(sess, span);
-                    tt!(Group::new(Delimiter::None, TokenStream(tts)))
-                })
-            }
-
-            DotEq => op!('.', '='),
-            OpenDelim(..) | CloseDelim(..) => unreachable!(),
-            Whitespace | Comment | Shebang(..) | Eof => unreachable!(),
-        }
-    }
-
-    fn to_internal(self) -> tokenstream::TokenStream {
-        use syntax::parse::token::*;
-        use syntax::tokenstream::{TokenTree, Delimited};
-
-        let (ch, kind, span) = match self {
-            self::TokenTree::Punct(tt) => (tt.as_char(), tt.spacing(), tt.span()),
-            self::TokenTree::Group(tt) => {
-                return TokenTree::Delimited(tt.span.0, Delimited {
-                    delim: tt.delimiter.to_internal(),
-                    tts: tt.stream.0.into(),
-                }).into();
-            },
-            self::TokenTree::Ident(tt) => {
-                let token = Ident(ast::Ident::new(tt.sym, tt.span.0), tt.is_raw);
-                return TokenTree::Token(tt.span.0, token).into();
-            }
-            self::TokenTree::Literal(self::Literal {
-                lit: Lit::Integer(ref a),
-                suffix,
-                span,
-            })
-                if a.as_str().starts_with("-") =>
-            {
-                let minus = BinOp(BinOpToken::Minus);
-                let integer = Symbol::intern(&a.as_str()[1..]);
-                let integer = Literal(Lit::Integer(integer), suffix);
-                let a = TokenTree::Token(span.0, minus);
-                let b = TokenTree::Token(span.0, integer);
-                return vec![a, b].into_iter().collect()
-            }
-            self::TokenTree::Literal(self::Literal {
-                lit: Lit::Float(ref a),
-                suffix,
-                span,
-            })
-                if a.as_str().starts_with("-") =>
-            {
-                let minus = BinOp(BinOpToken::Minus);
-                let float = Symbol::intern(&a.as_str()[1..]);
-                let float = Literal(Lit::Float(float), suffix);
-                let a = TokenTree::Token(span.0, minus);
-                let b = TokenTree::Token(span.0, float);
-                return vec![a, b].into_iter().collect()
-            }
-            self::TokenTree::Literal(tt) => {
-                let token = Literal(tt.lit, tt.suffix);
-                return TokenTree::Token(tt.span.0, token).into()
-            }
-        };
-
-        let token = match ch {
-            '=' => Eq,
-            '<' => Lt,
-            '>' => Gt,
-            '!' => Not,
-            '~' => Tilde,
-            '+' => BinOp(Plus),
-            '-' => BinOp(Minus),
-            '*' => BinOp(Star),
-            '/' => BinOp(Slash),
-            '%' => BinOp(Percent),
-            '^' => BinOp(Caret),
-            '&' => BinOp(And),
-            '|' => BinOp(Or),
-            '@' => At,
-            '.' => Dot,
-            ',' => Comma,
-            ';' => Semi,
-            ':' => Colon,
-            '#' => Pound,
-            '$' => Dollar,
-            '?' => Question,
-            '\'' => SingleQuote,
-            _ => unreachable!(),
-        };
-
-        let tree = TokenTree::Token(span.0, token);
-        match kind {
-            Spacing::Alone => tree.into(),
-            Spacing::Joint => tree.joint(),
-        }
-    }
-}
-
 /// Permanently unstable internal implementation details of this crate. This
 /// should not be used.
 ///
@@ -1364,8 +1156,6 @@ impl TokenTree {
 #[unstable(feature = "proc_macro_internals", issue = "27812")]
 #[doc(hidden)]
 pub mod __internal {
-    pub use quote::{LiteralKind, SpannedSymbol, Quoter, unquote};
-
     use std::cell::Cell;
     use std::ptr;
 
diff --git a/src/libproc_macro/quote.rs b/src/libproc_macro/quote.rs
index 73a66640c59..7ae7b13a152 100644
--- a/src/libproc_macro/quote.rs
+++ b/src/libproc_macro/quote.rs
@@ -14,35 +14,26 @@
 //! This quasiquoter uses macros 2.0 hygiene to reliably access
 //! items from `proc_macro`, to build a `proc_macro::TokenStream`.
 
-use {Delimiter, Literal, Spacing, Span, Ident, Punct, Group, TokenStream, TokenTree};
-
-use syntax::ext::base::{ExtCtxt, ProcMacro};
-use syntax::parse::token;
-use syntax::symbol::Symbol;
-use syntax::tokenstream;
-
-/// This is the actual quote!() proc macro
-///
-/// It is manually loaded in CStore::load_macro_untracked
-pub struct Quoter;
-
-pub fn unquote<T: Into<TokenStream> + Clone>(tokens: &T) -> TokenStream {
-    tokens.clone().into()
-}
-
-pub trait Quote {
-    fn quote(self) -> TokenStream;
-}
-
-macro_rules! tt2ts {
-    ($e:expr) => (TokenStream::from(TokenTree::from($e)))
-}
-
-macro_rules! quote_tok {
-    (,) => { tt2ts!(Punct::new(',', Spacing::Alone)) };
-    (.) => { tt2ts!(Punct::new('.', Spacing::Alone)) };
-    (:) => { tt2ts!(Punct::new(':', Spacing::Alone)) };
-    (|) => { tt2ts!(Punct::new('|', Spacing::Alone)) };
+use {Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree};
+
+macro_rules! quote_tt {
+    (($($t:tt)*)) => { Group::new(Delimiter::Parenthesis, quote!($($t)*)) };
+    ([$($t:tt)*]) => { Group::new(Delimiter::Bracket, quote!($($t)*)) };
+    ({$($t:tt)*}) => { Group::new(Delimiter::Brace, quote!($($t)*)) };
+    (,) => { Punct::new(',', Spacing::Alone) };
+    (.) => { Punct::new('.', Spacing::Alone) };
+    (:) => { Punct::new(':', Spacing::Alone) };
+    (;) => { Punct::new(';', Spacing::Alone) };
+    (!) => { Punct::new('!', Spacing::Alone) };
+    (<) => { Punct::new('<', Spacing::Alone) };
+    (>) => { Punct::new('>', Spacing::Alone) };
+    (&) => { Punct::new('&', Spacing::Alone) };
+    (=) => { Punct::new('=', Spacing::Alone) };
+    ($i:ident) => { Ident::new(stringify!($i), Span::def_site()) };
+}
+
+macro_rules! quote_ts {
+    ((@ $($t:tt)*)) => { $($t)* };
     (::) => {
         [
             TokenTree::from(Punct::new(':', Spacing::Joint)),
@@ -55,65 +46,45 @@ macro_rules! quote_tok {
             })
             .collect::<TokenStream>()
     };
-    (!) => { tt2ts!(Punct::new('!', Spacing::Alone)) };
-    (<) => { tt2ts!(Punct::new('<', Spacing::Alone)) };
-    (>) => { tt2ts!(Punct::new('>', Spacing::Alone)) };
-    (_) => { tt2ts!(Punct::new('_', Spacing::Alone)) };
-    (0) => { tt2ts!(Literal::i8_unsuffixed(0)) };
-    (&) => { tt2ts!(Punct::new('&', Spacing::Alone)) };
-    ($i:ident) => { tt2ts!(Ident::new(stringify!($i), Span::def_site())) };
-}
-
-macro_rules! quote_tree {
-    ((unquote $($t:tt)*)) => { $($t)* };
-    ((quote $($t:tt)*)) => { ($($t)*).quote() };
-    (($($t:tt)*)) => { tt2ts!(Group::new(Delimiter::Parenthesis, quote!($($t)*))) };
-    ([$($t:tt)*]) => { tt2ts!(Group::new(Delimiter::Bracket, quote!($($t)*))) };
-    ({$($t:tt)*}) => { tt2ts!(Group::new(Delimiter::Brace, quote!($($t)*))) };
-    ($t:tt) => { quote_tok!($t) };
+    ($t:tt) => { TokenTree::from(quote_tt!($t)) };
 }
 
+/// Simpler version of the real `quote!` macro, implemented solely
+/// through `macro_rules`, for bootstrapping the real implementation
+/// (see the `quote` function), which does not have access to the
+/// real `quote!` macro due to the `proc_macro` crate not being
+/// able to depend on itself.
+///
+/// Note: supported tokens are a subset of the real `quote!`, but
+/// unquoting is different: instead of `$x`, this uses `(@ expr)`.
 macro_rules! quote {
     () => { TokenStream::new() };
     ($($t:tt)*) => {
-        [$(quote_tree!($t),)*].iter()
-            .cloned()
-            .flat_map(|x| x.into_iter())
-            .collect::<TokenStream>()
+        [
+            $(TokenStream::from(quote_ts!($t)),)*
+        ].iter().cloned().collect::<TokenStream>()
     };
 }
 
-impl ProcMacro for Quoter {
-    fn expand<'cx>(&self, cx: &'cx mut ExtCtxt,
-                   _: ::syntax_pos::Span,
-                   stream: tokenstream::TokenStream)
-                   -> tokenstream::TokenStream {
-        ::__internal::set_sess(cx, || TokenStream(stream).quote().0)
-    }
-}
-
-impl<T: Quote> Quote for Option<T> {
-    fn quote(self) -> TokenStream {
-        match self {
-            Some(t) => quote!(Some((quote t))),
-            None => quote!(None),
-        }
+/// Quote a `TokenStream` into a `TokenStream`.
+/// This is the actual `quote!()` proc macro.
+///
+/// It is manually loaded in `CStore::load_macro_untracked`.
+#[unstable(feature = "proc_macro_quote", issue = "38356")]
+pub fn quote(stream: TokenStream) -> TokenStream {
+    if stream.is_empty() {
+        return quote!(::TokenStream::new());
     }
-}
-
-impl Quote for TokenStream {
-    fn quote(self) -> TokenStream {
-        if self.is_empty() {
-            return quote!(::TokenStream::new());
-        }
-        let mut after_dollar = false;
-        let tokens = self.into_iter().filter_map(|tree| {
+    let mut after_dollar = false;
+    let tokens = stream
+        .into_iter()
+        .filter_map(|tree| {
             if after_dollar {
                 after_dollar = false;
                 match tree {
                     TokenTree::Ident(_) => {
-                        let tree = TokenStream::from(tree);
-                        return Some(quote!(::__internal::unquote(&(unquote tree)),));
+                        return Some(quote!(Into::<::TokenStream>::into(
+                        Clone::clone(&(@ tree))),));
                     }
                     TokenTree::Punct(ref tt) if tt.as_char() == '$' => {}
                     _ => panic!("`$` must be followed by an ident or `$` in `quote!`"),
@@ -125,186 +96,55 @@ impl Quote for TokenStream {
                 }
             }
 
-            Some(quote!(::TokenStream::from((quote tree)),))
-        }).flat_map(|t| t.into_iter()).collect::<TokenStream>();
-
-        if after_dollar {
-            panic!("unexpected trailing `$` in `quote!`");
-        }
-
-        quote!(
-            [(unquote tokens)].iter()
-                .cloned()
-                .flat_map(|x| x.into_iter())
-                .collect::<::TokenStream>()
-        )
-    }
-}
-
-impl Quote for TokenTree {
-    fn quote(self) -> TokenStream {
-        match self {
-            TokenTree::Punct(tt) => quote!(::TokenTree::Punct( (quote tt) )),
-            TokenTree::Group(tt) => quote!(::TokenTree::Group( (quote tt) )),
-            TokenTree::Ident(tt) => quote!(::TokenTree::Ident( (quote tt) )),
-            TokenTree::Literal(tt) => quote!(::TokenTree::Literal( (quote tt) )),
-        }
-    }
-}
-
-impl Quote for char {
-    fn quote(self) -> TokenStream {
-        TokenTree::from(Literal::character(self)).into()
-    }
-}
-
-impl<'a> Quote for &'a str {
-    fn quote(self) -> TokenStream {
-        TokenTree::from(Literal::string(self)).into()
-    }
-}
-
-impl Quote for u16 {
-    fn quote(self) -> TokenStream {
-        TokenTree::from(Literal::u16_unsuffixed(self)).into()
-    }
-}
-
-impl Quote for Group {
-    fn quote(self) -> TokenStream {
-        quote!(::Group::new((quote self.delimiter()), (quote self.stream())))
-    }
-}
-
-impl Quote for Punct {
-    fn quote(self) -> TokenStream {
-        quote!(::Punct::new((quote self.as_char()), (quote self.spacing())))
-    }
-}
-
-impl Quote for Ident {
-    fn quote(self) -> TokenStream {
-        quote!(::Ident::new((quote self.sym.as_str()), (quote self.span())))
-    }
-}
-
-impl Quote for Span {
-    fn quote(self) -> TokenStream {
-        quote!(::Span::def_site())
-    }
-}
-
-macro_rules! literals {
-    ($($i:ident),*; $($raw:ident),*) => {
-        pub struct SpannedSymbol {
-            sym: Symbol,
-            span: Span,
-        }
-
-        impl SpannedSymbol {
-            pub fn new(string: &str, span: Span) -> SpannedSymbol {
-                SpannedSymbol { sym: Symbol::intern(string), span }
-            }
-        }
-
-        impl Quote for SpannedSymbol {
-            fn quote(self) -> TokenStream {
-                quote!(::__internal::SpannedSymbol::new((quote self.sym.as_str()),
-                                                        (quote self.span)))
-            }
-        }
-
-        pub enum LiteralKind {
-            $($i,)*
-            $($raw(u16),)*
-        }
-
-        impl LiteralKind {
-            pub fn with_contents_and_suffix(self, contents: SpannedSymbol,
-                                            suffix: Option<SpannedSymbol>) -> Literal {
-                let sym = contents.sym;
-                let suffix = suffix.map(|t| t.sym);
-                match self {
-                    $(LiteralKind::$i => {
-                        Literal {
-                            lit: token::Lit::$i(sym),
-                            suffix,
-                            span: contents.span,
-                        }
-                    })*
-                    $(LiteralKind::$raw(n) => {
-                        Literal {
-                            lit: token::Lit::$raw(sym, n),
-                            suffix,
-                            span: contents.span,
-                        }
-                    })*
-                }
-            }
-        }
-
-        impl Literal {
-            fn kind_contents_and_suffix(self) -> (LiteralKind, SpannedSymbol, Option<SpannedSymbol>)
-            {
-                let (kind, contents) = match self.lit {
-                    $(token::Lit::$i(contents) => (LiteralKind::$i, contents),)*
-                    $(token::Lit::$raw(contents, n) => (LiteralKind::$raw(n), contents),)*
-                };
-                let suffix = self.suffix.map(|sym| SpannedSymbol::new(&sym.as_str(), self.span()));
-                (kind, SpannedSymbol::new(&contents.as_str(), self.span()), suffix)
-            }
-        }
-
-        impl Quote for LiteralKind {
-            fn quote(self) -> TokenStream {
-                match self {
-                    $(LiteralKind::$i => quote! {
-                        ::__internal::LiteralKind::$i
-                    },)*
-                    $(LiteralKind::$raw(n) => quote! {
-                        ::__internal::LiteralKind::$raw((quote n))
-                    },)*
-                }
-            }
-        }
+            Some(quote!(::TokenStream::from((@ match tree {
+                TokenTree::Punct(tt) => quote!(::TokenTree::Punct(::Punct::new(
+                    (@ TokenTree::from(Literal::character(tt.as_char()))),
+                    (@ match tt.spacing() {
+                        Spacing::Alone => quote!(::Spacing::Alone),
+                        Spacing::Joint => quote!(::Spacing::Joint),
+                    }),
+                ))),
+                TokenTree::Group(tt) => quote!(::TokenTree::Group(::Group::new(
+                    (@ match tt.delimiter() {
+                        Delimiter::Parenthesis => quote!(::Delimiter::Parenthesis),
+                        Delimiter::Brace => quote!(::Delimiter::Brace),
+                        Delimiter::Bracket => quote!(::Delimiter::Bracket),
+                        Delimiter::None => quote!(::Delimiter::None),
+                    }),
+                    (@ quote(tt.stream())),
+                ))),
+                TokenTree::Ident(tt) => quote!(::TokenTree::Ident(::Ident::new(
+                    (@ TokenTree::from(Literal::string(&tt.to_string()))),
+                    (@ quote_span(tt.span())),
+                ))),
+                TokenTree::Literal(tt) => quote!(::TokenTree::Literal({
+                    let mut iter = (@ TokenTree::from(Literal::string(&tt.to_string())))
+                        .parse::<::TokenStream>()
+                        .unwrap()
+                        .into_iter();
+                    if let (Some(::TokenTree::Literal(mut lit)), None) =
+                        (iter.next(), iter.next())
+                    {
+                        lit.set_span((@ quote_span(tt.span())));
+                        lit
+                    } else {
+                        unreachable!()
+                    }
+                }))
+            })),))
+        })
+        .collect::<TokenStream>();
 
-        impl Quote for Literal {
-            fn quote(self) -> TokenStream {
-                let (kind, contents, suffix) = self.kind_contents_and_suffix();
-                quote! {
-                    (quote kind).with_contents_and_suffix((quote contents), (quote suffix))
-                }
-            }
-        }
+    if after_dollar {
+        panic!("unexpected trailing `$` in `quote!`");
     }
-}
 
-literals!(Byte, Char, Float, Str_, Integer, ByteStr; StrRaw, ByteStrRaw);
-
-impl Quote for Delimiter {
-    fn quote(self) -> TokenStream {
-        macro_rules! gen_match {
-            ($($i:ident),*) => {
-                match self {
-                    $(Delimiter::$i => { quote!(::Delimiter::$i) })*
-                }
-            }
-        }
-
-        gen_match!(Parenthesis, Brace, Bracket, None)
-    }
+    quote!([(@ tokens)].iter().cloned().collect::<::TokenStream>())
 }
 
-impl Quote for Spacing {
-    fn quote(self) -> TokenStream {
-        macro_rules! gen_match {
-            ($($i:ident),*) => {
-                match self {
-                    $(Spacing::$i => { quote!(::Spacing::$i) })*
-                }
-            }
-        }
-
-        gen_match!(Alone, Joint)
-    }
+/// Quote a `Span` into a `TokenStream`.
+/// This is needed to implement a custom quoter.
+#[unstable(feature = "proc_macro_quote", issue = "38356")]
+pub fn quote_span(_: Span) -> TokenStream {
+    quote!(::Span::def_site())
 }
diff --git a/src/libproc_macro/rustc.rs b/src/libproc_macro/rustc.rs
new file mode 100644
index 00000000000..a54c695f637
--- /dev/null
+++ b/src/libproc_macro/rustc.rs
@@ -0,0 +1,284 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use {Delimiter, Level, Spacing, Span, __internal};
+use {Group, Ident, Literal, Punct, TokenTree};
+
+use rustc_errors as errors;
+use syntax::ast;
+use syntax::parse::lexer::comments;
+use syntax::parse::token;
+use syntax::tokenstream;
+use syntax_pos::symbol::{keywords, Symbol};
+
+impl Ident {
+    pub(crate) fn new_maybe_raw(string: &str, span: Span, is_raw: bool) -> Ident {
+        let sym = Symbol::intern(string);
+        if is_raw
+            && (sym == keywords::Underscore.name()
+                || ast::Ident::with_empty_ctxt(sym).is_path_segment_keyword())
+        {
+            panic!("`{:?}` is not a valid raw identifier", string)
+        }
+        Ident { sym, span, is_raw }
+    }
+}
+
+impl Delimiter {
+    pub(crate) fn from_internal(delim: token::DelimToken) -> Delimiter {
+        match delim {
+            token::Paren => Delimiter::Parenthesis,
+            token::Brace => Delimiter::Brace,
+            token::Bracket => Delimiter::Bracket,
+            token::NoDelim => Delimiter::None,
+        }
+    }
+
+    pub(crate) fn to_internal(self) -> token::DelimToken {
+        match self {
+            Delimiter::Parenthesis => token::Paren,
+            Delimiter::Brace => token::Brace,
+            Delimiter::Bracket => token::Bracket,
+            Delimiter::None => token::NoDelim,
+        }
+    }
+}
+
+impl TokenTree {
+    pub(crate) fn from_internal(
+        stream: tokenstream::TokenStream,
+        stack: &mut Vec<TokenTree>,
+    ) -> TokenTree {
+        use syntax::parse::token::*;
+
+        let (tree, is_joint) = stream.as_tree();
+        let (span, token) = match tree {
+            tokenstream::TokenTree::Token(span, token) => (span, token),
+            tokenstream::TokenTree::Delimited(span, delimed) => {
+                let delimiter = Delimiter::from_internal(delimed.delim);
+                let mut g = Group::new(delimiter, ::TokenStream(delimed.tts.into()));
+                g.set_span(Span(span));
+                return g.into();
+            }
+        };
+
+        let op_kind = if is_joint {
+            Spacing::Joint
+        } else {
+            Spacing::Alone
+        };
+        macro_rules! tt {
+            ($e:expr) => {{
+                let mut x = TokenTree::from($e);
+                x.set_span(Span(span));
+                x
+            }};
+        }
+        macro_rules! op {
+            ($a:expr) => {
+                tt!(Punct::new($a, op_kind))
+            };
+            ($a:expr, $b:expr) => {{
+                stack.push(tt!(Punct::new($b, op_kind)));
+                tt!(Punct::new($a, Spacing::Joint))
+            }};
+            ($a:expr, $b:expr, $c:expr) => {{
+                stack.push(tt!(Punct::new($c, op_kind)));
+                stack.push(tt!(Punct::new($b, Spacing::Joint)));
+                tt!(Punct::new($a, Spacing::Joint))
+            }};
+        }
+
+        match token {
+            Eq => op!('='),
+            Lt => op!('<'),
+            Le => op!('<', '='),
+            EqEq => op!('=', '='),
+            Ne => op!('!', '='),
+            Ge => op!('>', '='),
+            Gt => op!('>'),
+            AndAnd => op!('&', '&'),
+            OrOr => op!('|', '|'),
+            Not => op!('!'),
+            Tilde => op!('~'),
+            BinOp(Plus) => op!('+'),
+            BinOp(Minus) => op!('-'),
+            BinOp(Star) => op!('*'),
+            BinOp(Slash) => op!('/'),
+            BinOp(Percent) => op!('%'),
+            BinOp(Caret) => op!('^'),
+            BinOp(And) => op!('&'),
+            BinOp(Or) => op!('|'),
+            BinOp(Shl) => op!('<', '<'),
+            BinOp(Shr) => op!('>', '>'),
+            BinOpEq(Plus) => op!('+', '='),
+            BinOpEq(Minus) => op!('-', '='),
+            BinOpEq(Star) => op!('*', '='),
+            BinOpEq(Slash) => op!('/', '='),
+            BinOpEq(Percent) => op!('%', '='),
+            BinOpEq(Caret) => op!('^', '='),
+            BinOpEq(And) => op!('&', '='),
+            BinOpEq(Or) => op!('|', '='),
+            BinOpEq(Shl) => op!('<', '<', '='),
+            BinOpEq(Shr) => op!('>', '>', '='),
+            At => op!('@'),
+            Dot => op!('.'),
+            DotDot => op!('.', '.'),
+            DotDotDot => op!('.', '.', '.'),
+            DotDotEq => op!('.', '.', '='),
+            Comma => op!(','),
+            Semi => op!(';'),
+            Colon => op!(':'),
+            ModSep => op!(':', ':'),
+            RArrow => op!('-', '>'),
+            LArrow => op!('<', '-'),
+            FatArrow => op!('=', '>'),
+            Pound => op!('#'),
+            Dollar => op!('$'),
+            Question => op!('?'),
+            SingleQuote => op!('\''),
+
+            Ident(ident, false) => tt!(self::Ident::new(&ident.as_str(), Span(span))),
+            Ident(ident, true) => tt!(self::Ident::new_raw(&ident.as_str(), Span(span))),
+            Lifetime(ident) => {
+                let ident = ident.without_first_quote();
+                stack.push(tt!(self::Ident::new(&ident.as_str(), Span(span))));
+                tt!(Punct::new('\'', Spacing::Joint))
+            }
+            Literal(lit, suffix) => tt!(self::Literal {
+                lit,
+                suffix,
+                span: Span(span)
+            }),
+            DocComment(c) => {
+                let style = comments::doc_comment_style(&c.as_str());
+                let stripped = comments::strip_doc_comment_decoration(&c.as_str());
+                let stream = vec![
+                    tt!(self::Ident::new("doc", Span(span))),
+                    tt!(Punct::new('=', Spacing::Alone)),
+                    tt!(self::Literal::string(&stripped)),
+                ].into_iter()
+                    .collect();
+                stack.push(tt!(Group::new(Delimiter::Bracket, stream)));
+                if style == ast::AttrStyle::Inner {
+                    stack.push(tt!(Punct::new('!', Spacing::Alone)));
+                }
+                tt!(Punct::new('#', Spacing::Alone))
+            }
+
+            Interpolated(_) => __internal::with_sess(|sess, _| {
+                let tts = token.interpolated_to_tokenstream(sess, span);
+                tt!(Group::new(Delimiter::None, ::TokenStream(tts)))
+            }),
+
+            DotEq => op!('.', '='),
+            OpenDelim(..) | CloseDelim(..) => unreachable!(),
+            Whitespace | Comment | Shebang(..) | Eof => unreachable!(),
+        }
+    }
+
+    pub(crate) fn to_internal(self) -> tokenstream::TokenStream {
+        use syntax::parse::token::*;
+        use syntax::tokenstream::{Delimited, TokenTree};
+
+        let (ch, kind, span) = match self {
+            self::TokenTree::Punct(tt) => (tt.as_char(), tt.spacing(), tt.span()),
+            self::TokenTree::Group(tt) => {
+                return TokenTree::Delimited(
+                    tt.span.0,
+                    Delimited {
+                        delim: tt.delimiter.to_internal(),
+                        tts: tt.stream.0.into(),
+                    },
+                ).into();
+            }
+            self::TokenTree::Ident(tt) => {
+                let token = Ident(ast::Ident::new(tt.sym, tt.span.0), tt.is_raw);
+                return TokenTree::Token(tt.span.0, token).into();
+            }
+            self::TokenTree::Literal(self::Literal {
+                lit: Lit::Integer(ref a),
+                suffix,
+                span,
+            })
+                if a.as_str().starts_with("-") =>
+            {
+                let minus = BinOp(BinOpToken::Minus);
+                let integer = Symbol::intern(&a.as_str()[1..]);
+                let integer = Literal(Lit::Integer(integer), suffix);
+                let a = TokenTree::Token(span.0, minus);
+                let b = TokenTree::Token(span.0, integer);
+                return vec![a, b].into_iter().collect();
+            }
+            self::TokenTree::Literal(self::Literal {
+                lit: Lit::Float(ref a),
+                suffix,
+                span,
+            })
+                if a.as_str().starts_with("-") =>
+            {
+                let minus = BinOp(BinOpToken::Minus);
+                let float = Symbol::intern(&a.as_str()[1..]);
+                let float = Literal(Lit::Float(float), suffix);
+                let a = TokenTree::Token(span.0, minus);
+                let b = TokenTree::Token(span.0, float);
+                return vec![a, b].into_iter().collect();
+            }
+            self::TokenTree::Literal(tt) => {
+                let token = Literal(tt.lit, tt.suffix);
+                return TokenTree::Token(tt.span.0, token).into();
+            }
+        };
+
+        let token = match ch {
+            '=' => Eq,
+            '<' => Lt,
+            '>' => Gt,
+            '!' => Not,
+            '~' => Tilde,
+            '+' => BinOp(Plus),
+            '-' => BinOp(Minus),
+            '*' => BinOp(Star),
+            '/' => BinOp(Slash),
+            '%' => BinOp(Percent),
+            '^' => BinOp(Caret),
+            '&' => BinOp(And),
+            '|' => BinOp(Or),
+            '@' => At,
+            '.' => Dot,
+            ',' => Comma,
+            ';' => Semi,
+            ':' => Colon,
+            '#' => Pound,
+            '$' => Dollar,
+            '?' => Question,
+            '\'' => SingleQuote,
+            _ => unreachable!(),
+        };
+
+        let tree = TokenTree::Token(span.0, token);
+        match kind {
+            Spacing::Alone => tree.into(),
+            Spacing::Joint => tree.joint(),
+        }
+    }
+}
+
+impl Level {
+    pub(crate) fn to_internal(self) -> errors::Level {
+        match self {
+            Level::Error => errors::Level::Error,
+            Level::Warning => errors::Level::Warning,
+            Level::Note => errors::Level::Note,
+            Level::Help => errors::Level::Help,
+            Level::__Nonexhaustive => unreachable!("Level::__Nonexhaustive"),
+        }
+    }
+}
diff --git a/src/librustc/hir/map/blocks.rs b/src/librustc/hir/map/blocks.rs
index 5a595d14db7..f2f7f95426a 100644
--- a/src/librustc/hir/map/blocks.rs
+++ b/src/librustc/hir/map/blocks.rs
@@ -51,6 +51,12 @@ impl MaybeFnLike for ast::Item {
     }
 }
 
+impl MaybeFnLike for ast::ImplItem {
+    fn is_fn_like(&self) -> bool {
+        match self.node { ast::ImplItemKind::Method(..) => true, _ => false, }
+    }
+}
+
 impl MaybeFnLike for ast::TraitItem {
     fn is_fn_like(&self) -> bool {
         match self.node {
@@ -141,7 +147,7 @@ impl<'a> FnLikeNode<'a> {
         let fn_like = match node {
             map::NodeItem(item) => item.is_fn_like(),
             map::NodeTraitItem(tm) => tm.is_fn_like(),
-            map::NodeImplItem(_) => true,
+            map::NodeImplItem(it) => it.is_fn_like(),
             map::NodeExpr(e) => e.is_fn_like(),
             _ => false
         };
diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs
index 5b5ae6473f8..9283705b7b7 100644
--- a/src/librustc/infer/mod.rs
+++ b/src/librustc/infer/mod.rs
@@ -562,36 +562,25 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     }
 
     pub fn unsolved_variables(&self) -> Vec<Ty<'tcx>> {
-        let mut variables = Vec::new();
-
-        {
-            let mut type_variables = self.type_variables.borrow_mut();
-            variables.extend(
-                type_variables
-                    .unsolved_variables()
-                    .into_iter()
-                    .map(|t| self.tcx.mk_var(t)));
-        }
-
-        {
-            let mut int_unification_table = self.int_unification_table.borrow_mut();
-            variables.extend(
+        let mut type_variables = self.type_variables.borrow_mut();
+        let mut int_unification_table = self.int_unification_table.borrow_mut();
+        let mut float_unification_table = self.float_unification_table.borrow_mut();
+
+        type_variables
+            .unsolved_variables()
+            .into_iter()
+            .map(|t| self.tcx.mk_var(t))
+            .chain(
                 (0..int_unification_table.len())
                     .map(|i| ty::IntVid { index: i as u32 })
                     .filter(|&vid| int_unification_table.probe_value(vid).is_none())
-                    .map(|v| self.tcx.mk_int_var(v)));
-        }
-
-        {
-            let mut float_unification_table = self.float_unification_table.borrow_mut();
-            variables.extend(
+                    .map(|v| self.tcx.mk_int_var(v))
+            ).chain(
                 (0..float_unification_table.len())
                     .map(|i| ty::FloatVid { index: i as u32 })
                     .filter(|&vid| float_unification_table.probe_value(vid).is_none())
-                    .map(|v| self.tcx.mk_float_var(v)));
-        }
-
-        return variables;
+                    .map(|v| self.tcx.mk_float_var(v))
+            ).collect()
     }
 
     fn combine_fields(&'a self, trace: TypeTrace<'tcx>, param_env: ty::ParamEnv<'tcx>)
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index a46b3120622..0ab10bf223f 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -77,7 +77,8 @@ declare_lint! {
 declare_lint! {
     pub UNREACHABLE_CODE,
     Warn,
-    "detects unreachable code paths"
+    "detects unreachable code paths",
+    report_in_external_macro: true
 }
 
 declare_lint! {
@@ -216,7 +217,8 @@ declare_lint! {
 declare_lint! {
     pub DEPRECATED,
     Warn,
-    "detects use of deprecated items"
+    "detects use of deprecated items",
+    report_in_external_macro: true
 }
 
 declare_lint! {
diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs
index 8efce297a91..c0f3c351d26 100644
--- a/src/librustc/lint/mod.rs
+++ b/src/librustc/lint/mod.rs
@@ -39,7 +39,7 @@ use hir::intravisit;
 use hir;
 use lint::builtin::BuiltinLintDiagnostics;
 use session::{Session, DiagnosticMessageId};
-use std::hash;
+use std::{hash, ptr};
 use syntax::ast;
 use syntax::codemap::{MultiSpan, ExpnFormat};
 use syntax::edition::Edition;
@@ -80,6 +80,9 @@ pub struct Lint {
     /// Starting at the given edition, default to the given lint level. If this is `None`, then use
     /// `default_level`.
     pub edition_lint_opts: Option<(Edition, Level)>,
+
+    /// Whether this lint is reported even inside expansions of external macros
+    pub report_in_external_macro: bool,
 }
 
 impl Lint {
@@ -100,11 +103,18 @@ impl Lint {
 #[macro_export]
 macro_rules! declare_lint {
     ($vis: vis $NAME: ident, $Level: ident, $desc: expr) => (
+        declare_lint!{$vis $NAME, $Level, $desc, false}
+    );
+    ($vis: vis $NAME: ident, $Level: ident, $desc: expr, report_in_external_macro: $rep: expr) => (
+        declare_lint!{$vis $NAME, $Level, $desc, $rep}
+    );
+    ($vis: vis $NAME: ident, $Level: ident, $desc: expr, $external: expr) => (
         $vis static $NAME: &$crate::lint::Lint = &$crate::lint::Lint {
             name: stringify!($NAME),
             default_level: $crate::lint::$Level,
             desc: $desc,
             edition_lint_opts: None,
+            report_in_external_macro: $external,
         };
     );
     ($vis: vis $NAME: ident, $Level: ident, $desc: expr,
@@ -115,6 +125,7 @@ macro_rules! declare_lint {
             default_level: $crate::lint::$Level,
             desc: $desc,
             edition_lint_opts: Some(($lint_edition, $crate::lint::Level::$edition_level)),
+            report_in_external_macro: false,
         };
     );
 }
@@ -354,7 +365,7 @@ pub struct LintId {
 
 impl PartialEq for LintId {
     fn eq(&self, other: &LintId) -> bool {
-        (self.lint as *const Lint) == (other.lint as *const Lint)
+        ptr::eq(self.lint, other.lint)
     }
 }
 
@@ -583,8 +594,7 @@ pub fn struct_lint_level<'a>(sess: &'a Session,
     // items to take care of (delete the macro invocation). As a result we have
     // a few lints we whitelist here for allowing a lint even though it's in a
     // foreign macro invocation.
-    } else if lint_id != LintId::of(builtin::UNREACHABLE_CODE) &&
-        lint_id != LintId::of(builtin::DEPRECATED) {
+    } else if !lint.report_in_external_macro {
         if err.span.primary_spans().iter().any(|s| in_external_macro(sess, *s)) {
             err.cancel();
         }
diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index 60b47dbbd19..e4fc1b09fce 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -391,16 +391,12 @@ impl<'v, 'k, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'k, 'tcx> {
 fn create_and_seed_worklist<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                       access_levels: &privacy::AccessLevels,
                                       krate: &hir::Crate)
-                                      -> Vec<ast::NodeId> {
-    let mut worklist = Vec::new();
-    for (id, _) in &access_levels.map {
-        worklist.push(*id);
-    }
-
-    // Seed entry point
-    if let Some((id, _, _)) = *tcx.sess.entry_fn.borrow() {
-        worklist.push(id);
-    }
+                                      -> Vec<ast::NodeId>
+{
+    let worklist = access_levels.map.iter().map(|(&id, _)| id).chain(
+        // Seed entry point
+        tcx.sess.entry_fn.borrow().map(|(id, _, _)| id)
+    ).collect::<Vec<_>>();
 
     // Seed implemented trait items
     let mut life_seeder = LifeSeeder {
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 178f0d3cdcb..bd24b93f029 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -47,7 +47,7 @@ use std::ops::Deref;
 use rustc_data_structures::sync::{self, Lrc, ParallelIterator, par_iter};
 use std::slice;
 use std::vec::IntoIter;
-use std::mem;
+use std::{mem, ptr};
 use syntax::ast::{self, DUMMY_NODE_ID, Name, Ident, NodeId};
 use syntax::attr;
 use syntax::ext::hygiene::Mark;
@@ -527,8 +527,7 @@ impl<'tcx> PartialOrd for TyS<'tcx> {
 impl<'tcx> PartialEq for TyS<'tcx> {
     #[inline]
     fn eq(&self, other: &TyS<'tcx>) -> bool {
-        // (self as *const _) == (other as *const _)
-        (self as *const TyS<'tcx>) == (other as *const TyS<'tcx>)
+        ptr::eq(self, other)
     }
 }
 impl<'tcx> Eq for TyS<'tcx> {}
@@ -678,7 +677,7 @@ impl<T> PartialOrd for Slice<T> where T: PartialOrd {
 impl<T: PartialEq> PartialEq for Slice<T> {
     #[inline]
     fn eq(&self, other: &Slice<T>) -> bool {
-        (self as *const _) == (other as *const _)
+        ptr::eq(self, other)
     }
 }
 impl<T: Eq> Eq for Slice<T> {}
@@ -1730,7 +1729,7 @@ impl Ord for AdtDef {
 impl PartialEq for AdtDef {
     // AdtDef are always interned and this is part of TyS equality
     #[inline]
-    fn eq(&self, other: &Self) -> bool { self as *const _ == other as *const _ }
+    fn eq(&self, other: &Self) -> bool { ptr::eq(self, other) }
 }
 
 impl Eq for AdtDef {}
diff --git a/src/librustc/ty/query/job.rs b/src/librustc/ty/query/job.rs
index a54deeca293..56a8c13a8d3 100644
--- a/src/librustc/ty/query/job.rs
+++ b/src/librustc/ty/query/job.rs
@@ -20,7 +20,7 @@ use ty::query::plumbing::CycleError;
 use ty::context::TyCtxt;
 use errors::Diagnostic;
 use std::process;
-use std::fmt;
+use std::{fmt, ptr};
 use std::collections::HashSet;
 #[cfg(parallel_queries)]
 use {
@@ -124,7 +124,7 @@ impl<'tcx> QueryJob<'tcx> {
         while let Some(job) = current_job {
             cycle.insert(0, job.info.clone());
 
-            if &*job as *const _ == self as *const _ {
+            if ptr::eq(&*job, self) {
                 // This is the end of the cycle
                 // The span entry we included was for the usage
                 // of the cycle itself, and not part of the cycle
diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs
index b1502902079..f1a6e9913d6 100644
--- a/src/librustc_codegen_llvm/abi.rs
+++ b/src/librustc_codegen_llvm/abi.rs
@@ -565,7 +565,13 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> {
     }
 
     fn llvm_type(&self, cx: &CodegenCx<'a, 'tcx>) -> Type {
-        let mut llargument_tys = Vec::new();
+        let args_capacity: usize = self.args.iter().map(|arg|
+            if arg.pad.is_some() { 1 } else { 0 } +
+            if let PassMode::Pair(_, _) = arg.mode { 2 } else { 1 }
+        ).sum();
+        let mut llargument_tys = Vec::with_capacity(
+            if let PassMode::Indirect(_) = self.ret.mode { 1 } else { 0 } + args_capacity
+        );
 
         let llreturn_ty = match self.ret.mode {
             PassMode::Ignore => Type::void(cx),
diff --git a/src/librustc_codegen_llvm/back/lto.rs b/src/librustc_codegen_llvm/back/lto.rs
index a33f8b569d0..60b5cf2ec76 100644
--- a/src/librustc_codegen_llvm/back/lto.rs
+++ b/src/librustc_codegen_llvm/back/lto.rs
@@ -759,20 +759,6 @@ impl ThinModule {
         cgcx.save_temp_bitcode(&module, "thin-lto-after-pm");
         timeline.record("thin-done");
 
-        // FIXME: this is a hack around a bug in LLVM right now. Discovered in
-        // #46910 it was found out that on 32-bit MSVC LLVM will hit a codegen
-        // error if there's an available_externally function in the LLVM module.
-        // Typically we don't actually use these functions but ThinLTO makes
-        // heavy use of them when inlining across modules.
-        //
-        // Tracked upstream at https://bugs.llvm.org/show_bug.cgi?id=35736 this
-        // function call (and its definition on the C++ side of things)
-        // shouldn't be necessary eventually and we can safetly delete these few
-        // lines.
-        llvm::LLVMRustThinLTORemoveAvailableExternally(llmod);
-        cgcx.save_temp_bitcode(&module, "thin-lto-after-rm-ae");
-        timeline.record("no-ae");
-
         Ok(module)
     }
 }
diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs
index c71e49b0d88..e4acb2ad4b1 100644
--- a/src/librustc_codegen_llvm/builder.rs
+++ b/src/librustc_codegen_llvm/builder.rs
@@ -13,7 +13,7 @@
 use llvm;
 use llvm::{AtomicRmwBinOp, AtomicOrdering, SynchronizationScope, AsmDialect};
 use llvm::{Opcode, IntPredicate, RealPredicate, False, OperandBundleDef};
-use llvm::{ValueRef, BasicBlockRef, BuilderRef, ModuleRef};
+use llvm::{ValueRef, BasicBlockRef, BuilderRef};
 use common::*;
 use type_::Type;
 use value::Value;
@@ -1157,23 +1157,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
     }
 
-    pub fn trap(&self) {
-        unsafe {
-            let bb: BasicBlockRef = llvm::LLVMGetInsertBlock(self.llbuilder);
-            let fn_: ValueRef = llvm::LLVMGetBasicBlockParent(bb);
-            let m: ModuleRef = llvm::LLVMGetGlobalParent(fn_);
-            let p = "llvm.trap\0".as_ptr();
-            let t: ValueRef = llvm::LLVMGetNamedFunction(m, p as *const _);
-            assert!((t as isize != 0));
-            let args: &[ValueRef] = &[];
-            self.count_insn("trap");
-            llvm::LLVMRustBuildCall(self.llbuilder, t,
-                                    args.as_ptr(), args.len() as c_uint,
-                                    ptr::null_mut(),
-                                    noname());
-        }
-    }
-
     pub fn landing_pad(&self, ty: Type, pers_fn: ValueRef,
                        num_clauses: usize) -> ValueRef {
         self.count_insn("landingpad");
diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs
index b386f887d77..ef0d57c7b7c 100644
--- a/src/librustc_data_structures/lib.rs
+++ b/src/librustc_data_structures/lib.rs
@@ -56,29 +56,30 @@ extern crate rustc_cratesio_shim;
 
 pub use rustc_serialize::hex::ToHex;
 
-pub mod array_vec;
 pub mod accumulate_vec;
-pub mod small_vec;
+pub mod array_vec;
 pub mod base_n;
 pub mod bitslice;
 pub mod bitvec;
+pub mod flock;
+pub mod fx;
+pub mod graph;
 pub mod indexed_set;
 pub mod indexed_vec;
 pub mod obligation_forest;
+pub mod owning_ref;
+pub mod ptr_key;
 pub mod sip128;
+pub mod small_vec;
 pub mod snapshot_map;
 pub use ena::snapshot_vec;
+pub mod sorted_map;
 pub mod stable_hasher;
-pub mod transitive_relation;
-pub use ena::unify;
-pub mod fx;
-pub mod tuple_slice;
-pub mod graph;
-pub mod flock;
 pub mod sync;
-pub mod owning_ref;
 pub mod tiny_list;
-pub mod sorted_map;
+pub mod transitive_relation;
+pub mod tuple_slice;
+pub use ena::unify;
 pub mod work_queue;
 
 pub struct OnDrop<F: Fn()>(pub F);
diff --git a/src/librustc_data_structures/ptr_key.rs b/src/librustc_data_structures/ptr_key.rs
new file mode 100644
index 00000000000..6835dab38df
--- /dev/null
+++ b/src/librustc_data_structures/ptr_key.rs
@@ -0,0 +1,45 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::{hash, ptr};
+use std::ops::Deref;
+
+/// A wrapper around reference that compares and hashes like a pointer.
+/// Can be used as a key in sets/maps indexed by pointers to avoid `unsafe`.
+#[derive(Debug)]
+pub struct PtrKey<'a, T: 'a>(pub &'a T);
+
+impl<'a, T> Clone for PtrKey<'a, T> {
+    fn clone(&self) -> Self { *self }
+}
+
+impl<'a, T> Copy for PtrKey<'a, T> {}
+
+impl<'a, T> PartialEq for PtrKey<'a, T> {
+    fn eq(&self, rhs: &Self) -> bool {
+        ptr::eq(self.0, rhs.0)
+    }
+}
+
+impl<'a, T> Eq for PtrKey<'a, T> {}
+
+impl<'a, T> hash::Hash for PtrKey<'a, T> {
+    fn hash<H: hash::Hasher>(&self, hasher: &mut H) {
+        (self.0 as *const T).hash(hasher)
+    }
+}
+
+impl<'a, T> Deref for PtrKey<'a, T> {
+    type Target = T;
+
+    fn deref(&self) -> &Self::Target {
+        self.0
+    }
+}
diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs
index d079102a4ba..b1578b697bb 100644
--- a/src/librustc_errors/diagnostic.rs
+++ b/src/librustc_errors/diagnostic.rs
@@ -379,7 +379,7 @@ impl Diagnostic {
 
     /// Convenience function for internal use, clients should use one of the
     /// public methods above.
-    pub(crate) fn sub(&mut self,
+    pub fn sub(&mut self,
            level: Level,
            message: &str,
            span: MultiSpan,
diff --git a/src/librustc_llvm/ffi.rs b/src/librustc_llvm/ffi.rs
index b4483557dd3..8d04438eea2 100644
--- a/src/librustc_llvm/ffi.rs
+++ b/src/librustc_llvm/ffi.rs
@@ -1791,7 +1791,6 @@ extern "C" {
                                            CU1: *mut *mut c_void,
                                            CU2: *mut *mut c_void);
     pub fn LLVMRustThinLTOPatchDICompileUnit(M: ModuleRef, CU: *mut c_void);
-    pub fn LLVMRustThinLTORemoveAvailableExternally(M: ModuleRef);
 
     pub fn LLVMRustLinkerNew(M: ModuleRef) -> LinkerRef;
     pub fn LLVMRustLinkerAdd(linker: LinkerRef,
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index d5078642147..e3a7918f8c5 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -39,7 +39,6 @@ use syntax::ast;
 use syntax::attr;
 use syntax::codemap;
 use syntax::edition::Edition;
-use syntax::ext::base::SyntaxExtension;
 use syntax::parse::filemap_to_stream;
 use syntax::symbol::Symbol;
 use syntax_pos::{Span, NO_EXPANSION, FileName};
@@ -517,8 +516,11 @@ impl CrateStore for cstore::CStore {
             return LoadedMacro::ProcMacro(proc_macros[id.index.to_proc_macro_index()].1.clone());
         } else if data.name == "proc_macro" &&
                   self.get_crate_data(id.krate).item_name(id.index) == "quote" {
+            use syntax::ext::base::SyntaxExtension;
+            use syntax_ext::proc_macro_impl::BangProcMacro;
+
             let ext = SyntaxExtension::ProcMacro {
-                expander: Box::new(::proc_macro::__internal::Quoter),
+                expander: Box::new(BangProcMacro { inner: ::proc_macro::quote }),
                 allow_internal_unstable: true,
                 edition: data.root.edition,
             };
diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs
index 5c9915e94e5..d535c1ef903 100644
--- a/src/librustc_metadata/lib.rs
+++ b/src/librustc_metadata/lib.rs
@@ -19,6 +19,7 @@
 #![feature(libc)]
 #![feature(macro_at_most_once_rep)]
 #![feature(proc_macro_internals)]
+#![feature(proc_macro_quote)]
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(slice_sort_by_cached_key)]
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index e00919547fc..da2847dc557 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -651,7 +651,7 @@ impl<'a> Resolver<'a> {
                            binding: &'a NameBinding<'a>,
                            span: Span,
                            allow_shadowing: bool) {
-        if self.global_macros.insert(name, binding).is_some() && !allow_shadowing {
+        if self.macro_prelude.insert(name, binding).is_some() && !allow_shadowing {
             let msg = format!("`{}` is already in scope", name);
             let note =
                 "macro-expanded `#[macro_use]`s may not shadow existing macros (see RFC 1560)";
@@ -704,8 +704,7 @@ impl<'a> Resolver<'a> {
         } else {
             for (name, span) in legacy_imports.imports {
                 let ident = Ident::with_empty_ctxt(name);
-                let result = self.resolve_ident_in_module(module, ident, MacroNS,
-                                                          false, false, span);
+                let result = self.resolve_ident_in_module(module, ident, MacroNS, false, span);
                 if let Ok(binding) = result {
                     let directive = macro_use_directive(span);
                     self.potentially_unused_imports.push(directive);
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index d98434796d5..9fe25aaa6c0 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -1393,7 +1393,7 @@ pub struct Resolver<'a> {
 
     crate_loader: &'a mut dyn CrateLoader,
     macro_names: FxHashSet<Ident>,
-    global_macros: FxHashMap<Name, &'a NameBinding<'a>>,
+    macro_prelude: FxHashMap<Name, &'a NameBinding<'a>>,
     pub all_macros: FxHashMap<Name, Def>,
     lexical_macro_resolutions: Vec<(Ident, &'a Cell<LegacyScope<'a>>)>,
     macro_map: FxHashMap<DefId, Lrc<SyntaxExtension>>,
@@ -1715,7 +1715,7 @@ impl<'a> Resolver<'a> {
 
             crate_loader,
             macro_names: FxHashSet(),
-            global_macros: FxHashMap(),
+            macro_prelude: FxHashMap(),
             all_macros: FxHashMap(),
             lexical_macro_resolutions: Vec::new(),
             macro_map: FxHashMap(),
@@ -2002,7 +2002,6 @@ impl<'a> Resolver<'a> {
                                module: Module<'a>,
                                mut ident: Ident,
                                ns: Namespace,
-                               ignore_unresolved_invocations: bool,
                                record_used: bool,
                                span: Span)
                                -> Result<&'a NameBinding<'a>, Determinacy> {
@@ -2012,7 +2011,7 @@ impl<'a> Resolver<'a> {
             self.current_module = self.macro_def_scope(def);
         }
         let result = self.resolve_ident_in_module_unadjusted(
-            module, ident, ns, ignore_unresolved_invocations, record_used, span,
+            module, ident, ns, false, record_used, span,
         );
         self.current_module = orig_current_module;
         result
@@ -2518,7 +2517,7 @@ impl<'a> Resolver<'a> {
         // If there is a TraitRef in scope for an impl, then the method must be in the
         // trait.
         if let Some((module, _)) = self.current_trait_ref {
-            if self.resolve_ident_in_module(module, ident, ns, false, false, span).is_err() {
+            if self.resolve_ident_in_module(module, ident, ns, false, span).is_err() {
                 let path = &self.current_trait_ref.as_ref().unwrap().1.path;
                 resolve_error(self, span, err(ident.name, &path_names_to_string(path)));
             }
@@ -3225,7 +3224,7 @@ impl<'a> Resolver<'a> {
                 };
             }
         }
-        let is_global = self.global_macros.get(&path[0].name).cloned()
+        let is_global = self.macro_prelude.get(&path[0].name).cloned()
             .map(|binding| binding.get_macro(self).kind() == MacroKind::Bang).unwrap_or(false);
         if primary_ns != MacroNS && (is_global ||
                                      self.macro_names.contains(&path[0].modern())) {
@@ -3468,7 +3467,7 @@ impl<'a> Resolver<'a> {
             }
 
             let binding = if let Some(module) = module {
-                self.resolve_ident_in_module(module, ident, ns, false, record_used, path_span)
+                self.resolve_ident_in_module(module, ident, ns, record_used, path_span)
             } else if opt_ns == Some(MacroNS) {
                 self.resolve_lexical_macro_path_segment(ident, ns, record_used, path_span)
                     .map(MacroBinding::binding)
@@ -3762,7 +3761,7 @@ impl<'a> Resolver<'a> {
         // Look for associated items in the current trait.
         if let Some((module, _)) = self.current_trait_ref {
             if let Ok(binding) =
-                    self.resolve_ident_in_module(module, ident, ns, false, false, module.span) {
+                    self.resolve_ident_in_module(module, ident, ns, false, module.span) {
                 let def = binding.def();
                 if filter_fn(def) {
                     return Some(if self.has_self.contains(&def.def_id()) {
@@ -4075,7 +4074,7 @@ impl<'a> Resolver<'a> {
         let mut found_traits = Vec::new();
         // Look for the current trait.
         if let Some((module, _)) = self.current_trait_ref {
-            if self.resolve_ident_in_module(module, ident, ns, false, false, module.span).is_ok() {
+            if self.resolve_ident_in_module(module, ident, ns, false, module.span).is_ok() {
                 let def_id = module.def_id().unwrap();
                 found_traits.push(TraitCandidate { def_id: def_id, import_id: None });
             }
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index f076d884f60..0ad652b4710 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -220,7 +220,7 @@ impl<'a> base::Resolver for Resolver<'a> {
             vis: ty::Visibility::Invisible,
             expansion: Mark::root(),
         });
-        self.global_macros.insert(ident.name, binding);
+        self.macro_prelude.insert(ident.name, binding);
     }
 
     fn resolve_imports(&mut self) {
@@ -238,7 +238,7 @@ impl<'a> base::Resolver for Resolver<'a> {
                 attr::mark_known(&attrs[i]);
             }
 
-            match self.global_macros.get(&name).cloned() {
+            match self.macro_prelude.get(&name).cloned() {
                 Some(binding) => match *binding.get_macro(self) {
                     MultiModifier(..) | MultiDecorator(..) | SyntaxExtension::AttrProcMacro(..) => {
                         return Some(attrs.remove(i))
@@ -274,7 +274,7 @@ impl<'a> base::Resolver for Resolver<'a> {
                     }
                     let trait_name = traits[j].segments[0].ident.name;
                     let legacy_name = Symbol::intern(&format!("derive_{}", trait_name));
-                    if !self.global_macros.contains_key(&legacy_name) {
+                    if !self.macro_prelude.contains_key(&legacy_name) {
                         continue
                     }
                     let span = traits.remove(j).span;
@@ -565,7 +565,7 @@ impl<'a> Resolver<'a> {
                     module, ident, ns, true, record_used, path_span,
                 ).map(MacroBinding::Modern)
             } else {
-                self.global_macros.get(&ident.name).cloned().ok_or(determinacy)
+                self.macro_prelude.get(&ident.name).cloned().ok_or(determinacy)
                     .map(MacroBinding::Global)
             };
             self.current_module = orig_current_module;
@@ -588,8 +588,7 @@ impl<'a> Resolver<'a> {
                             return potential_illegal_shadower;
                         }
                     }
-                    if binding.expansion != Mark::root() ||
-                       (binding.is_glob_import() && module.unwrap().def().is_some()) {
+                    if binding.is_glob_import() || binding.expansion != Mark::root() {
                         potential_illegal_shadower = result;
                     } else {
                         return result;
@@ -652,7 +651,7 @@ impl<'a> Resolver<'a> {
 
         let binding = if let Some(binding) = binding {
             MacroBinding::Legacy(binding)
-        } else if let Some(binding) = self.global_macros.get(&ident.name).cloned() {
+        } else if let Some(binding) = self.macro_prelude.get(&ident.name).cloned() {
             if !self.use_extern_macros {
                 self.record_use(ident, MacroNS, binding, DUMMY_SP);
             }
@@ -762,8 +761,8 @@ impl<'a> Resolver<'a> {
         // Then check global macros.
         }.or_else(|| {
             // FIXME: get_macro needs an &mut Resolver, can we do it without cloning?
-            let global_macros = self.global_macros.clone();
-            let names = global_macros.iter().filter_map(|(name, binding)| {
+            let macro_prelude = self.macro_prelude.clone();
+            let names = macro_prelude.iter().filter_map(|(name, binding)| {
                 if binding.get_macro(self).kind() == kind {
                     Some(name)
                 } else {
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index 0ee17ebc487..50eb89be690 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -17,6 +17,7 @@ use Resolver;
 use {names_to_string, module_to_string};
 use {resolve_error, ResolutionError};
 
+use rustc_data_structures::ptr_key::PtrKey;
 use rustc::ty;
 use rustc::lint::builtin::BuiltinLintDiagnostics;
 use rustc::lint::builtin::{DUPLICATE_MACRO_EXPORTS, PUB_USE_OF_PRIVATE_EXTERN_CRATE};
@@ -104,67 +105,20 @@ impl<'a> ImportDirective<'a> {
 #[derive(Clone, Default, Debug)]
 /// Records information about the resolution of a name in a namespace of a module.
 pub struct NameResolution<'a> {
-    /// The single imports that define the name in the namespace.
-    single_imports: SingleImports<'a>,
+    /// Single imports that may define the name in the namespace.
+    /// Import directives are arena-allocated, so it's ok to use pointers as keys.
+    single_imports: FxHashSet<PtrKey<'a, ImportDirective<'a>>>,
     /// The least shadowable known binding for this name, or None if there are no known bindings.
     pub binding: Option<&'a NameBinding<'a>>,
-    shadows_glob: Option<&'a NameBinding<'a>>,
-}
-
-#[derive(Clone, Debug)]
-enum SingleImports<'a> {
-    /// No single imports can define the name in the namespace.
-    None,
-    /// Only the given single import can define the name in the namespace.
-    MaybeOne(&'a ImportDirective<'a>),
-    /// Only one of these two single imports can define the name in the namespace.
-    MaybeTwo(&'a ImportDirective<'a>, &'a ImportDirective<'a>),
-    /// At least one single import will define the name in the namespace.
-    AtLeastOne,
-}
-
-impl<'a> Default for SingleImports<'a> {
-    /// Creates a `SingleImports<'a>` of None type.
-    fn default() -> Self {
-        SingleImports::None
-    }
-}
-
-impl<'a> SingleImports<'a> {
-    fn add_directive(&mut self, directive: &'a ImportDirective<'a>, use_extern_macros: bool) {
-        match *self {
-            SingleImports::None => *self = SingleImports::MaybeOne(directive),
-            SingleImports::MaybeOne(directive_one) => *self = if use_extern_macros {
-                SingleImports::MaybeTwo(directive_one, directive)
-            } else {
-                SingleImports::AtLeastOne
-            },
-            // If three single imports can define the name in the namespace, we can assume that at
-            // least one of them will define it since otherwise we'd get duplicate errors in one of
-            // other namespaces.
-            SingleImports::MaybeTwo(..) => *self = SingleImports::AtLeastOne,
-            SingleImports::AtLeastOne => {}
-        };
-    }
-
-    fn directive_failed(&mut self, dir: &'a ImportDirective<'a>) {
-        match *self {
-            SingleImports::None => unreachable!(),
-            SingleImports::MaybeOne(_) => *self = SingleImports::None,
-            SingleImports::MaybeTwo(dir1, dir2) =>
-                *self = SingleImports::MaybeOne(if ptr::eq(dir1, dir) { dir1 } else { dir2 }),
-            SingleImports::AtLeastOne => {}
-        }
-    }
+    shadowed_glob: Option<&'a NameBinding<'a>>,
 }
 
 impl<'a> NameResolution<'a> {
     // Returns the binding for the name if it is known or None if it not known.
     fn binding(&self) -> Option<&'a NameBinding<'a>> {
-        self.binding.and_then(|binding| match self.single_imports {
-            SingleImports::None => Some(binding),
-            _ if !binding.is_glob_import() => Some(binding),
-            _ => None, // The binding could be shadowed by a single import, so it is not known.
+        self.binding.and_then(|binding| {
+            if !binding.is_glob_import() ||
+               self.single_imports.is_empty() { Some(binding) } else { None }
         })
     }
 }
@@ -177,7 +131,7 @@ impl<'a> Resolver<'a> {
     }
 
     /// Attempts to resolve `ident` in namespaces `ns` of `module`.
-    /// Invariant: if `record_used` is `Some`, import resolution must be complete.
+    /// Invariant: if `record_used` is `Some`, expansion and import resolution must be complete.
     pub fn resolve_ident_in_module_unadjusted(&mut self,
                                               module: Module<'a>,
                                               ident: Ident,
@@ -194,7 +148,7 @@ impl<'a> Resolver<'a> {
 
         if record_used {
             if let Some(binding) = resolution.binding {
-                if let Some(shadowed_glob) = resolution.shadows_glob {
+                if let Some(shadowed_glob) = resolution.shadowed_glob {
                     let name = ident.name;
                     // Forbid expanded shadowing to avoid time travel.
                     if restricted_shadowing &&
@@ -227,81 +181,72 @@ impl<'a> Resolver<'a> {
             if usable { Ok(binding) } else { Err(Determined) }
         };
 
-        // Items and single imports are not shadowable.
+        // Items and single imports are not shadowable, if we have one, then it's determined.
         if let Some(binding) = resolution.binding {
             if !binding.is_glob_import() {
                 return check_usable(self, binding);
             }
         }
 
-        // Check if a single import can still define the name.
-        let resolve_single_import = |this: &mut Self, directive: &'a ImportDirective<'a>| {
-            let module = match directive.imported_module.get() {
-                Some(module) => module,
-                None => return false,
-            };
-            let ident = match directive.subclass {
+        // --- From now on we either have a glob resolution or no resolution. ---
+
+        // Check if one of single imports can still define the name,
+        // if it can then our result is not determined and can be invalidated.
+        for single_import in &resolution.single_imports {
+            if !self.is_accessible(single_import.vis.get()) {
+                continue;
+            }
+            let module = unwrap_or!(single_import.imported_module.get(), return Err(Undetermined));
+            let ident = match single_import.subclass {
                 SingleImport { source, .. } => source,
                 _ => unreachable!(),
             };
-            match this.resolve_ident_in_module(module, ident, ns, false, false, path_span) {
-                Err(Determined) => {}
-                _ => return false,
-            }
-            true
-        };
-        match resolution.single_imports {
-            SingleImports::AtLeastOne => return Err(Undetermined),
-            SingleImports::MaybeOne(directive) => {
-                let accessible = self.is_accessible(directive.vis.get());
-                if accessible {
-                    if !resolve_single_import(self, directive) {
-                        return Err(Undetermined)
-                    }
-                }
-            }
-            SingleImports::MaybeTwo(directive1, directive2) => {
-                let accessible1 = self.is_accessible(directive1.vis.get());
-                let accessible2 = self.is_accessible(directive2.vis.get());
-                if accessible1 && accessible2 {
-                    if !resolve_single_import(self, directive1) &&
-                       !resolve_single_import(self, directive2) {
-                        return Err(Undetermined)
-                    }
-                } else if accessible1 {
-                    if !resolve_single_import(self, directive1) {
-                        return Err(Undetermined)
-                    }
-                } else {
-                    if !resolve_single_import(self, directive2) {
-                        return Err(Undetermined)
-                    }
-                }
+            match self.resolve_ident_in_module(module, ident, ns, false, path_span) {
+                Err(Determined) => continue,
+                Ok(_) | Err(Undetermined) => return Err(Undetermined),
             }
-            SingleImports::None => {},
         }
 
-        let no_unresolved_invocations =
-            restricted_shadowing || module.unresolved_invocations.borrow().is_empty();
-        match resolution.binding {
-            // In `MacroNS`, expanded bindings do not shadow (enforced in `try_define`).
-            Some(binding) if no_unresolved_invocations || ns == MacroNS =>
-                return check_usable(self, binding),
-            None if no_unresolved_invocations => {}
-            _ => return Err(Undetermined),
+        // So we have a resolution that's from a glob import. This resolution is determined
+        // if it cannot be shadowed by some new item/import expanded from a macro.
+        // This happens either if there are no unexpanded macros, or expanded names cannot
+        // shadow globs (that happens in macro namespace or with restricted shadowing).
+        let unexpanded_macros = !module.unresolved_invocations.borrow().is_empty();
+        if let Some(binding) = resolution.binding {
+            if !unexpanded_macros || ns == MacroNS || restricted_shadowing {
+                return check_usable(self, binding);
+            } else {
+                return Err(Undetermined);
+            }
         }
 
-        // Check if the globs are determined
-        if restricted_shadowing && module.def().is_some() {
+        // --- From now on we have no resolution. ---
+
+        // Now we are in situation when new item/import can appear only from a glob or a macro
+        // expansion. With restricted shadowing names from globs and macro expansions cannot
+        // shadow names from outer scopes, so we can freely fallback from module search to search
+        // in outer scopes. To continue search in outer scopes we have to lie a bit and return
+        // `Determined` to `resolve_lexical_macro_path_segment` even if the correct answer
+        // for in-module resolution could be `Undetermined`.
+        if restricted_shadowing {
             return Err(Determined);
         }
-        for directive in module.globs.borrow().iter() {
-            if !self.is_accessible(directive.vis.get()) {
+
+        // Check if one of unexpanded macros can still define the name,
+        // if it can then our "no resolution" result is not determined and can be invalidated.
+        if unexpanded_macros {
+            return Err(Undetermined);
+        }
+
+        // Check if one of glob imports can still define the name,
+        // if it can then our "no resolution" result is not determined and can be invalidated.
+        for glob_import in module.globs.borrow().iter() {
+            if !self.is_accessible(glob_import.vis.get()) {
                 continue
             }
-            let module = unwrap_or!(directive.imported_module.get(), return Err(Undetermined));
+            let module = unwrap_or!(glob_import.imported_module.get(), return Err(Undetermined));
             let (orig_current_module, mut ident) = (self.current_module, ident.modern());
-            match ident.span.glob_adjust(module.expansion, directive.span.ctxt().modern()) {
+            match ident.span.glob_adjust(module.expansion, glob_import.span.ctxt().modern()) {
                 Some(Some(def)) => self.current_module = self.macro_def_scope(def),
                 Some(None) => {}
                 None => continue,
@@ -310,11 +255,13 @@ impl<'a> Resolver<'a> {
                 module, ident, ns, false, false, path_span,
             );
             self.current_module = orig_current_module;
-            if let Err(Undetermined) = result {
-                return Err(Undetermined);
+            match result {
+                Err(Determined) => continue,
+                Ok(_) | Err(Undetermined) => return Err(Undetermined),
             }
         }
 
+        // No resolution and no one else can define the name - determinate error.
         Err(Determined)
     }
 
@@ -348,7 +295,7 @@ impl<'a> Resolver<'a> {
             SingleImport { target, type_ns_only, .. } => {
                 self.per_ns(|this, ns| if !type_ns_only || ns == TypeNS {
                     let mut resolution = this.resolution(current_module, target, ns).borrow_mut();
-                    resolution.single_imports.add_directive(directive, this.use_extern_macros);
+                    resolution.single_imports.insert(PtrKey(directive));
                 });
             }
             // We don't add prelude imports to the globs since they only affect lexical scopes,
@@ -401,7 +348,7 @@ impl<'a> Resolver<'a> {
                 if binding.is_glob_import() {
                     if !old_binding.is_glob_import() &&
                        !(ns == MacroNS && old_binding.expansion != Mark::root()) {
-                        resolution.shadows_glob = Some(binding);
+                        resolution.shadowed_glob = Some(binding);
                     } else if binding.def() != old_binding.def() {
                         resolution.binding = Some(this.ambiguity(old_binding, binding));
                     } else if !old_binding.vis.is_at_least(binding.vis, &*this) {
@@ -414,7 +361,7 @@ impl<'a> Resolver<'a> {
                         resolution.binding = Some(this.ambiguity(binding, old_binding));
                     } else {
                         resolution.binding = Some(binding);
-                        resolution.shadows_glob = Some(old_binding);
+                        resolution.shadowed_glob = Some(old_binding);
                     }
                 } else {
                     return Err(old_binding);
@@ -455,7 +402,7 @@ impl<'a> Resolver<'a> {
                 _ if old_binding.is_some() => return t,
                 None => return t,
                 Some(binding) => match old_binding {
-                    Some(old_binding) if old_binding as *const _ == binding as *const _ => return t,
+                    Some(old_binding) if ptr::eq(old_binding, binding) => return t,
                     _ => (binding, t),
                 }
             }
@@ -630,7 +577,6 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
                                                             source,
                                                             ns,
                                                             false,
-                                                            false,
                                                             directive.span));
             } else {
                 return
@@ -641,7 +587,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
                 Err(Undetermined) => indeterminate = true,
                 Err(Determined) => {
                     this.update_resolution(parent, target, ns, |_, resolution| {
-                        resolution.single_imports.directive_failed(directive)
+                        resolution.single_imports.remove(&PtrKey(directive));
                     });
                 }
                 Ok(binding) if !binding.is_importable() => {
@@ -803,7 +749,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
         if all_ns_err {
             let mut all_ns_failed = true;
             self.per_ns(|this, ns| if !type_ns_only || ns == TypeNS {
-                match this.resolve_ident_in_module(module, ident, ns, false, true, span) {
+                match this.resolve_ident_in_module(module, ident, ns, true, span) {
                     Ok(_) => all_ns_failed = false,
                     _ => {}
                 }
@@ -827,7 +773,8 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
                                 _ => Some(&i.name),
                             }
                         },
-                        NameResolution { single_imports: SingleImports::None, .. } => None,
+                        NameResolution { ref single_imports, .. }
+                            if single_imports.is_empty() => None,
                         _ => Some(&i.name),
                     }
                 });
@@ -973,7 +920,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
 
         let mut reexports = Vec::new();
         let mut exported_macro_names = FxHashMap();
-        if module as *const _ == self.graph_root as *const _ {
+        if ptr::eq(module, self.graph_root) {
             let macro_exports = mem::replace(&mut self.macro_exports, Vec::new());
             for export in macro_exports.into_iter().rev() {
                 if let Some(later_span) = exported_macro_names.insert(export.ident.modern(),
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 465faa1d477..a2dbf2aaca3 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -1473,35 +1473,34 @@ impl<'a, 'gcx, 'tcx> Bounds<'tcx> {
     pub fn predicates(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, param_ty: Ty<'tcx>)
                       -> Vec<ty::Predicate<'tcx>>
     {
-        let mut vec = Vec::new();
-
         // If it could be sized, and is, add the sized predicate
-        if self.implicitly_sized {
-            if let Some(sized) = tcx.lang_items().sized_trait() {
+        let sized_predicate = if self.implicitly_sized {
+            tcx.lang_items().sized_trait().map(|sized| {
                 let trait_ref = ty::TraitRef {
                     def_id: sized,
                     substs: tcx.mk_substs_trait(param_ty, &[])
                 };
-                vec.push(trait_ref.to_predicate());
-            }
-        }
-
-        for &region_bound in &self.region_bounds {
-            // account for the binder being introduced below; no need to shift `param_ty`
-            // because, at present at least, it can only refer to early-bound regions
-            let region_bound = tcx.mk_region(ty::fold::shift_region(*region_bound, 1));
-            vec.push(
-                ty::Binder::dummy(ty::OutlivesPredicate(param_ty, region_bound)).to_predicate());
-        }
-
-        for bound_trait_ref in &self.trait_bounds {
-            vec.push(bound_trait_ref.to_predicate());
-        }
-
-        for projection in &self.projection_bounds {
-            vec.push(projection.to_predicate());
-        }
+                trait_ref.to_predicate()
+            })
+        } else {
+            None
+        };
 
-        vec
+        sized_predicate.into_iter().chain(
+            self.region_bounds.iter().map(|&region_bound| {
+                // account for the binder being introduced below; no need to shift `param_ty`
+                // because, at present at least, it can only refer to early-bound regions
+                let region_bound = tcx.mk_region(ty::fold::shift_region(*region_bound, 1));
+                ty::Binder::dummy(ty::OutlivesPredicate(param_ty, region_bound)).to_predicate()
+            }).chain(
+                self.trait_bounds.iter().map(|bound_trait_ref| {
+                    bound_trait_ref.to_predicate()
+                })
+            ).chain(
+                self.projection_bounds.iter().map(|projection| {
+                    projection.to_predicate()
+                })
+            )
+        ).collect()
     }
 }
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 089ecebbc9c..ae64c6f1bfd 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -310,19 +310,19 @@ pub fn opts() -> Vec<RustcOptGroup> {
                        "disable-minification",
                        "Disable minification applied on JS files")
         }),
-        unstable("warn", |o| {
+        stable("warn", |o| {
             o.optmulti("W", "warn", "Set lint warnings", "OPT")
         }),
-        unstable("allow", |o| {
+        stable("allow", |o| {
             o.optmulti("A", "allow", "Set lint allowed", "OPT")
         }),
-        unstable("deny", |o| {
+        stable("deny", |o| {
             o.optmulti("D", "deny", "Set lint denied", "OPT")
         }),
-        unstable("forbid", |o| {
+        stable("forbid", |o| {
             o.optmulti("F", "forbid", "Set lint forbidden", "OPT")
         }),
-        unstable("cap-lints", |o| {
+        stable("cap-lints", |o| {
             o.optmulti(
                 "",
                 "cap-lints",
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index fec14b8d67d..3c01de2e997 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -532,12 +532,8 @@ mod stdsimd;
 #[cfg(not(stage0))]
 mod coresimd {
     pub use core::arch;
-    pub use core::simd;
 }
 
-#[unstable(feature = "stdsimd", issue = "48556")]
-#[cfg(all(not(stage0), not(test)))]
-pub use stdsimd::simd;
 #[stable(feature = "simd_arch", since = "1.27.0")]
 #[cfg(all(not(stage0), not(test)))]
 pub use stdsimd::arch;
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 1241e230b26..d64f3de8daa 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -240,6 +240,13 @@ impl Invocation {
             InvocationKind::Derive { ref path, .. } => path.span,
         }
     }
+
+    pub fn attr_id(&self) -> Option<ast::AttrId> {
+        match self.kind {
+            InvocationKind::Attr { attr: Some(ref attr), .. } => Some(attr.id),
+            _ => None,
+        }
+    }
 }
 
 pub struct MacroExpander<'a, 'b:'a> {
@@ -331,10 +338,20 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
 
             let scope =
                 if self.monotonic { invoc.expansion_data.mark } else { orig_expansion_data.mark };
+            let attr_id_before = invoc.attr_id();
             let ext = match self.cx.resolver.resolve_invoc(&mut invoc, scope, force) {
                 Ok(ext) => Some(ext),
                 Err(Determinacy::Determined) => None,
                 Err(Determinacy::Undetermined) => {
+                    // Sometimes attributes which we thought were invocations
+                    // end up being custom attributes for custom derives. If
+                    // that's the case our `invoc` will have changed out from
+                    // under us. If this is the case we're making progress so we
+                    // want to flag it as such, and we test this by looking if
+                    // the `attr_id()` method has been changing over time.
+                    if invoc.attr_id() != attr_id_before {
+                        progress = true;
+                    }
                     undetermined_invocations.push(invoc);
                     continue
                 }
diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs
index bf790e6143a..9748e2947ee 100644
--- a/src/libsyntax/parse/lexer/mod.rs
+++ b/src/libsyntax/parse/lexer/mod.rs
@@ -1775,12 +1775,6 @@ fn ident_continue(c: Option<char>) -> bool {
     (c > '\x7f' && c.is_xid_continue())
 }
 
-// The string is a valid identifier or a lifetime identifier.
-pub fn is_valid_ident(s: &str) -> bool {
-    let mut chars = s.chars();
-    ident_start(chars.next()) && chars.all(|ch| ident_continue(Some(ch)))
-}
-
 #[cfg(test)]
 mod tests {
     use super::*;
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index aef3beeccdf..fd8f394a600 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -777,11 +777,50 @@ fn prepend_attrs(sess: &ParseSess,
     for attr in attrs {
         assert_eq!(attr.style, ast::AttrStyle::Outer,
                    "inner attributes should prevent cached tokens from existing");
-        // FIXME: Avoid this pretty-print + reparse hack as bove
-        let name = FileName::MacroExpansion;
-        let source = pprust::attr_to_string(attr);
-        let stream = parse_stream_from_source_str(name, source, sess, Some(span));
-        builder.push(stream);
+
+        if attr.is_sugared_doc {
+            let stream = parse_stream_from_source_str(
+                FileName::MacroExpansion,
+                pprust::attr_to_string(attr),
+                sess,
+                Some(span),
+            );
+            builder.push(stream);
+            continue
+        }
+
+        // synthesize # [ $path $tokens ] manually here
+        let mut brackets = tokenstream::TokenStreamBuilder::new();
+
+        // For simple paths, push the identifier directly
+        if attr.path.segments.len() == 1 && attr.path.segments[0].args.is_none() {
+            let ident = attr.path.segments[0].ident;
+            let token = Ident(ident, ident.as_str().starts_with("r#"));
+            brackets.push(tokenstream::TokenTree::Token(ident.span, token));
+
+        // ... and for more complicated paths, fall back to a reparse hack that
+        // should eventually be removed.
+        } else {
+            let stream = parse_stream_from_source_str(
+                FileName::MacroExpansion,
+                pprust::path_to_string(&attr.path),
+                sess,
+                Some(span),
+            );
+            brackets.push(stream);
+        }
+
+        brackets.push(attr.tokens.clone());
+
+        let tokens = tokenstream::Delimited {
+            delim: DelimToken::Bracket,
+            tts: brackets.build().into(),
+        };
+        // The span we list here for `#` and for `[ ... ]` are both wrong in
+        // that it encompasses more than each token, but it hopefully is "good
+        // enough" for now at least.
+        builder.push(tokenstream::TokenTree::Token(attr.span, Pound));
+        builder.push(tokenstream::TokenTree::Delimited(attr.span, tokens));
     }
     builder.push(tokens.clone());
     Some(builder.build())
diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp
index a00ff3b345d..2f28c5b32fb 100644
--- a/src/rustllvm/PassWrapper.cpp
+++ b/src/rustllvm/PassWrapper.cpp
@@ -1228,15 +1228,6 @@ LLVMRustThinLTOPatchDICompileUnit(LLVMModuleRef Mod, DICompileUnit *Unit) {
   MD->addOperand(Unit);
 }
 
-extern "C" void
-LLVMRustThinLTORemoveAvailableExternally(LLVMModuleRef Mod) {
-  Module *M = unwrap(Mod);
-  for (Function &F : M->functions()) {
-    if (F.hasAvailableExternallyLinkage())
-      F.deleteBody();
-  }
-}
-
 #else
 
 extern "C" bool
@@ -1328,9 +1319,4 @@ LLVMRustThinLTOPatchDICompileUnit(LLVMModuleRef Mod) {
   report_fatal_error("ThinLTO not available");
 }
 
-extern "C" void
-LLVMRustThinLTORemoveAvailableExternally(LLVMModuleRef Mod) {
-  report_fatal_error("ThinLTO not available");
-}
-
 #endif // LLVM_VERSION_GE(4, 0)
diff --git a/src/stdsimd b/src/stdsimd
-Subproject 886ff388fbbe8798e292431d824a5ff3c3458f4
+Subproject b9de11ab43090c71ff7ab159a479394df1f968a
diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-two-attrs.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-two-attrs.rs
new file mode 100644
index 00000000000..d02edb50fb2
--- /dev/null
+++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-two-attrs.rs
@@ -0,0 +1,22 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::*;
+
+#[proc_macro_derive(A, attributes(b))]
+pub fn foo(_x: TokenStream) -> TokenStream {
+    TokenStream::new()
+}
diff --git a/src/test/run-pass-fulldeps/proc-macro/derive-two-attrs.rs b/src/test/run-pass-fulldeps/proc-macro/derive-two-attrs.rs
new file mode 100644
index 00000000000..6a0a3b3a941
--- /dev/null
+++ b/src/test/run-pass-fulldeps/proc-macro/derive-two-attrs.rs
@@ -0,0 +1,24 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:derive-two-attrs.rs
+
+#![feature(use_extern_macros)]
+
+extern crate derive_two_attrs as foo;
+
+use foo::A;
+
+#[derive(A)]
+#[b]
+#[b]
+struct B;
+
+fn main() {}
diff --git a/src/test/run-pass/const-block.rs b/src/test/run-pass/const-block.rs
index e56d01d7ba8..e6f191ea952 100644
--- a/src/test/run-pass/const-block.rs
+++ b/src/test/run-pass/const-block.rs
@@ -39,13 +39,6 @@ static BLOCK_FN: fn(usize) -> usize = { foo::<usize> };
 
 static BLOCK_ENUM_CONSTRUCTOR: fn(usize) -> Option<usize> = { Some };
 
-// FIXME #13972
-// static BLOCK_UNSAFE_SAFE_PTR: &'static isize = unsafe { &*(0xdeadbeef as *const isize) };
-// static BLOCK_UNSAFE_SAFE_PTR_2: &'static isize = unsafe {
-//     const X: *const isize = 0xdeadbeef as *const isize;
-//     &*X
-// };
-
 pub fn main() {
     assert_eq!(BLOCK_INTEGRAL, 1);
     assert_eq!(BLOCK_EXPLICIT_UNIT, ());
@@ -58,7 +51,4 @@ pub fn main() {
     assert_eq!(BLOCK_FN_INFERRED(300), 300);
     assert_eq!(BLOCK_FN(300), 300);
     assert_eq!(BLOCK_ENUM_CONSTRUCTOR(200), Some(200));
-    // FIXME #13972
-    // assert_eq!(BLOCK_UNSAFE_SAFE_PTR as *const isize as usize, 0xdeadbeef);
-    // assert_eq!(BLOCK_UNSAFE_SAFE_PTR_2 as *const isize as usize, 0xdeadbeef);
 }
diff --git a/src/test/run-pass/sepcomp-lib-lto.rs b/src/test/run-pass/sepcomp-lib-lto.rs
index f3e52fbd32f..8d73f4db7d2 100644
--- a/src/test/run-pass/sepcomp-lib-lto.rs
+++ b/src/test/run-pass/sepcomp-lib-lto.rs
@@ -14,7 +14,6 @@
 // aux-build:sepcomp_lib.rs
 // compile-flags: -C lto -g
 // no-prefer-dynamic
-// ignore-android FIXME #18800
 
 extern crate sepcomp_lib;
 use sepcomp_lib::a::one;
diff --git a/src/test/rustdoc-js/multi-query.js b/src/test/rustdoc-js/multi-query.js
index 3793ca6599c..3f583a3600a 100644
--- a/src/test/rustdoc-js/multi-query.js
+++ b/src/test/rustdoc-js/multi-query.js
@@ -15,6 +15,5 @@ const EXPECTED = {
         { 'path': 'std', 'name': 'str' },
         { 'path': 'std', 'name': 'u8' },
         { 'path': 'std::ffi', 'name': 'CStr' },
-        { 'path': 'std::simd', 'name': 'u8x2' },
     ],
 };
diff --git a/src/test/ui-fulldeps/proc-macro/attribute-spans-preserved.rs b/src/test/ui-fulldeps/proc-macro/attribute-spans-preserved.rs
new file mode 100644
index 00000000000..e1401653ba3
--- /dev/null
+++ b/src/test/ui-fulldeps/proc-macro/attribute-spans-preserved.rs
@@ -0,0 +1,22 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:attribute-spans-preserved.rs
+
+#![feature(use_extern_macros)]
+
+extern crate attribute_spans_preserved as foo;
+
+use foo::foo;
+
+#[ foo ( let y: u32 = "z"; ) ] //~ ERROR: mismatched types
+#[ bar let x: u32 = "y"; ] //~ ERROR: mismatched types
+fn main() {
+}
diff --git a/src/test/ui-fulldeps/proc-macro/attribute-spans-preserved.stderr b/src/test/ui-fulldeps/proc-macro/attribute-spans-preserved.stderr
new file mode 100644
index 00000000000..fe62bd23b87
--- /dev/null
+++ b/src/test/ui-fulldeps/proc-macro/attribute-spans-preserved.stderr
@@ -0,0 +1,21 @@
+error[E0308]: mismatched types
+  --> $DIR/attribute-spans-preserved.rs:19:23
+   |
+LL | #[ foo ( let y: u32 = "z"; ) ] //~ ERROR: mismatched types
+   |                       ^^^ expected u32, found reference
+   |
+   = note: expected type `u32`
+              found type `&'static str`
+
+error[E0308]: mismatched types
+  --> $DIR/attribute-spans-preserved.rs:20:21
+   |
+LL | #[ bar let x: u32 = "y"; ] //~ ERROR: mismatched types
+   |                     ^^^ expected u32, found reference
+   |
+   = note: expected type `u32`
+              found type `&'static str`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui-fulldeps/proc-macro/attribute-spans-preserved.stdout b/src/test/ui-fulldeps/proc-macro/attribute-spans-preserved.stdout
new file mode 100644
index 00000000000..33dc064ef68
--- /dev/null
+++ b/src/test/ui-fulldeps/proc-macro/attribute-spans-preserved.stdout
@@ -0,0 +1 @@
+fn main (  ) { let y : u32 = "z" ; let x : u32 = "y" ; }
diff --git a/src/test/ui-fulldeps/proc-macro/auxiliary/attribute-spans-preserved.rs b/src/test/ui-fulldeps/proc-macro/auxiliary/attribute-spans-preserved.rs
new file mode 100644
index 00000000000..e725cc7afb8
--- /dev/null
+++ b/src/test/ui-fulldeps/proc-macro/auxiliary/attribute-spans-preserved.rs
@@ -0,0 +1,44 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::*;
+
+#[proc_macro_attribute]
+pub fn foo(attr: TokenStream, f: TokenStream) -> TokenStream {
+    let mut tokens = f.into_iter();
+    assert_eq!(tokens.next().unwrap().to_string(), "#");
+    let next_attr = match tokens.next().unwrap() {
+        TokenTree::Group(g) => g,
+        _ => panic!(),
+    };
+
+    let fn_tok = tokens.next().unwrap();
+    let ident_tok = tokens.next().unwrap();
+    let args_tok = tokens.next().unwrap();
+    let body = tokens.next().unwrap();
+
+    let new_body = attr.into_iter()
+        .chain(next_attr.stream().into_iter().skip(1));
+
+    let tokens = vec![
+        fn_tok,
+        ident_tok,
+        args_tok,
+        Group::new(Delimiter::Brace, new_body.collect()).into(),
+    ].into_iter().collect::<TokenStream>();
+    println!("{}", tokens);
+    return tokens
+}
diff --git a/src/test/ui/imports/glob-shadowing.rs b/src/test/ui/imports/glob-shadowing.rs
new file mode 100644
index 00000000000..e4f55137e66
--- /dev/null
+++ b/src/test/ui/imports/glob-shadowing.rs
@@ -0,0 +1,44 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(decl_macro)]
+
+mod m {
+    pub macro env($e: expr) { $e }
+    pub macro fenv() { 0 }
+}
+
+mod glob_in_normal_module {
+    use m::*;
+    fn check() {
+        let x = env!("PATH"); //~ ERROR `env` is ambiguous
+    }
+}
+
+mod glob_in_block_module {
+    fn block() {
+        use m::*;
+        fn check() {
+            let x = env!("PATH"); //~ ERROR `env` is ambiguous
+        }
+    }
+}
+
+mod glob_shadows_item {
+    pub macro fenv($e: expr) { $e }
+    fn block() {
+        use m::*;
+        fn check() {
+            let x = fenv!(); //~ ERROR `fenv` is ambiguous
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/imports/glob-shadowing.stderr b/src/test/ui/imports/glob-shadowing.stderr
new file mode 100644
index 00000000000..7f61cd6c76d
--- /dev/null
+++ b/src/test/ui/imports/glob-shadowing.stderr
@@ -0,0 +1,49 @@
+error[E0659]: `env` is ambiguous
+  --> $DIR/glob-shadowing.rs:21:17
+   |
+LL |         let x = env!("PATH"); //~ ERROR `env` is ambiguous
+   |                 ^^^
+   |
+note: `env` could refer to the name imported here
+  --> $DIR/glob-shadowing.rs:19:9
+   |
+LL |     use m::*;
+   |         ^^^^
+   = note: `env` is also a builtin macro
+   = note: consider adding an explicit import of `env` to disambiguate
+
+error[E0659]: `env` is ambiguous
+  --> $DIR/glob-shadowing.rs:29:21
+   |
+LL |             let x = env!("PATH"); //~ ERROR `env` is ambiguous
+   |                     ^^^
+   |
+note: `env` could refer to the name imported here
+  --> $DIR/glob-shadowing.rs:27:13
+   |
+LL |         use m::*;
+   |             ^^^^
+   = note: `env` is also a builtin macro
+   = note: consider adding an explicit import of `env` to disambiguate
+
+error[E0659]: `fenv` is ambiguous
+  --> $DIR/glob-shadowing.rs:39:21
+   |
+LL |             let x = fenv!(); //~ ERROR `fenv` is ambiguous
+   |                     ^^^^
+   |
+note: `fenv` could refer to the name imported here
+  --> $DIR/glob-shadowing.rs:37:13
+   |
+LL |         use m::*;
+   |             ^^^^
+note: `fenv` could also refer to the name defined here
+  --> $DIR/glob-shadowing.rs:35:5
+   |
+LL |     pub macro fenv($e: expr) { $e }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: consider adding an explicit import of `fenv` to disambiguate
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0659`.
diff --git a/src/tools/clippy b/src/tools/clippy
-Subproject c05adc545cff45449d40b1c72070ada7db5fc95
+Subproject 8085ed733fefeaf37aca0a39da93344326de5d5