From 32d07cc2fc23e7cfa8b23a495e6667bcc7cf643a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de>
Date: Fri, 26 Oct 2018 16:23:02 +0200
Subject: [PATCH 01/50] bootstrap: be more explicit on what we collect into.
 NFC

---
 src/bootstrap/lib.rs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index ba601249ea895..957ebd2540ad9 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -783,10 +783,10 @@ impl Build {
     fn cflags(&self, target: Interned<String>, which: GitRepo) -> Vec<String> {
         // Filter out -O and /O (the optimization flags) that we picked up from
         // cc-rs because the build scripts will determine that for themselves.
-        let mut base: Vec<String> = self.cc[&target].args().iter()
+        let mut base = self.cc[&target].args().iter()
                            .map(|s| s.to_string_lossy().into_owned())
                            .filter(|s| !s.starts_with("-O") && !s.starts_with("/O"))
-                           .collect::<Vec<_>>();
+                           .collect::<Vec<String>>();
 
         // If we're compiling on macOS then we add a few unconditional flags
         // indicating that we want libc++ (more filled out than libstdc++) and

From cc63bd47efe4387982b399e2397adab6ac4030ef Mon Sep 17 00:00:00 2001
From: Michal 'vorner' Vaner <vorner@vorner.cz>
Date: Sat, 17 Nov 2018 14:48:18 +0100
Subject: [PATCH 02/50] atomic::Ordering: Get rid of misleading parts of intro

Remove the parts of atomic::Ordering's intro that wrongly claimed that
SeqCst prevents all reorderings around it.

Closes #55196
---
 src/libcore/sync/atomic.rs | 16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs
index 56d3b429fdb44..27eeb045bb196 100644
--- a/src/libcore/sync/atomic.rs
+++ b/src/libcore/sync/atomic.rs
@@ -173,11 +173,11 @@ unsafe impl<T> Sync for AtomicPtr<T> {}
 
 /// Atomic memory orderings
 ///
-/// Memory orderings limit the ways that both the compiler and CPU may reorder
-/// instructions around atomic operations. At its most restrictive,
-/// "sequentially consistent" atomics allow neither reads nor writes
-/// to be moved either before or after the atomic operation; on the other end
-/// "relaxed" atomics allow all reorderings.
+/// Memory orderings specify the way atomic operations synchronize memory.
+/// In its weakest [`Relaxed`][Ordering::Relaxed], only the memory directly touched by the
+/// operation is synchronized. On the other hand, a store-load pair of [`SeqCst`][Ordering::SeqCst]
+/// operations synchronize other memory while additionally preserving a total order of such
+/// operations across all threads.
 ///
 /// Rust's memory orderings are [the same as
 /// LLVM's](https://llvm.org/docs/LangRef.html#memory-model-for-concurrent-operations).
@@ -185,6 +185,8 @@ unsafe impl<T> Sync for AtomicPtr<T> {}
 /// For more information see the [nomicon].
 ///
 /// [nomicon]: ../../../nomicon/atomics.html
+/// [Ordering::Relaxed]: #variant.Relaxed
+/// [Ordering::SeqCst]: #variant.SeqCst
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Copy, Clone, Debug)]
 #[non_exhaustive]
@@ -234,8 +236,8 @@ pub enum Ordering {
     /// For loads it uses [`Acquire`] ordering. For stores it uses the [`Release`] ordering.
     ///
     /// Notice that in the case of `compare_and_swap`, it is possible that the operation ends up
-    /// not performing any store and hence it has just `Acquire` ordering. However,
-    /// `AcqRel` will never perform [`Relaxed`] accesses.
+    /// not performing any store and hence it has just [`Acquire`] ordering. However,
+    /// [`AcqRel`][`AcquireRelease`] will never perform [`Relaxed`] accesses.
     ///
     /// This ordering is only applicable for operations that combine both loads and stores.
     ///

From 7dc0dd292ba31681f35c62af6cc0f641761f36b1 Mon Sep 17 00:00:00 2001
From: Matthew Jasper <mjjasper1@gmail.com>
Date: Sun, 18 Nov 2018 14:49:24 +0000
Subject: [PATCH 03/50] Drop function parameters in expected order

Given the function

fn foo((_x, _): (LogDrop, LogDrop), (_, _y): (LogDrop, LogDrop)) {}

Prior to 1.12 we dropped both `_x` and `_y` before the rest of their
respective parameters, since then we dropped `_x` and `_y` after. The
original order appears to be the correct order, as the value created
later is dropped first, so we revert to that order and add a test for
it.
---
 src/librustc_mir/build/mod.rs                 | 14 ++---
 .../fn-arg-incomplete-pattern-drop-order.rs   | 54 +++++++++++++++++++
 2 files changed, 61 insertions(+), 7 deletions(-)
 create mode 100644 src/test/run-pass/binding/fn-arg-incomplete-pattern-drop-order.rs

diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs
index a01f8940a948a..a123f97efa832 100644
--- a/src/librustc_mir/build/mod.rs
+++ b/src/librustc_mir/build/mod.rs
@@ -915,6 +915,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             let place = Place::Local(local);
             let &ArgInfo(ty, opt_ty_info, pattern, ref self_binding) = arg_info;
 
+            // Make sure we drop (parts of) the argument even when not matched on.
+            self.schedule_drop(
+                pattern.as_ref().map_or(ast_body.span, |pat| pat.span),
+                argument_scope, &place, ty,
+                DropKind::Value { cached_block: CachedBlock::default() },
+            );
+
             if let Some(pattern) = pattern {
                 let pattern = self.hir.pattern_from_hir(pattern);
                 let span = pattern.span;
@@ -946,13 +953,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                     }
                 }
             }
-
-            // Make sure we drop (parts of) the argument even when not matched on.
-            self.schedule_drop(
-                pattern.as_ref().map_or(ast_body.span, |pat| pat.span),
-                argument_scope, &place, ty,
-                DropKind::Value { cached_block: CachedBlock::default() },
-            );
         }
 
         // Enter the argument pattern bindings source scope, if it exists.
diff --git a/src/test/run-pass/binding/fn-arg-incomplete-pattern-drop-order.rs b/src/test/run-pass/binding/fn-arg-incomplete-pattern-drop-order.rs
new file mode 100644
index 0000000000000..41e0750000146
--- /dev/null
+++ b/src/test/run-pass/binding/fn-arg-incomplete-pattern-drop-order.rs
@@ -0,0 +1,54 @@
+// Check that partially moved from function parameters are dropped after the
+// named bindings that move from them.
+
+use std::{panic, cell::RefCell};
+
+struct LogDrop<'a>(i32, Context<'a>);
+
+#[derive(Copy, Clone)]
+struct Context<'a> {
+    panic_on: i32,
+    drops: &'a RefCell<Vec<i32>>,
+}
+
+impl<'a> Context<'a> {
+    fn record_drop(self, index: i32) {
+        self.drops.borrow_mut().push(index);
+        if index == self.panic_on {
+            panic!();
+        }
+    }
+}
+
+impl<'a> Drop for LogDrop<'a> {
+    fn drop(&mut self) {
+        self.1.record_drop(self.0);
+    }
+}
+
+fn foo((_x, _): (LogDrop, LogDrop), (_, _y): (LogDrop, LogDrop)) {}
+
+fn test_drop_order(panic_on: i32) {
+    let context = Context {
+        panic_on,
+        drops: &RefCell::new(Vec::new()),
+    };
+    let one = LogDrop(1, context);
+    let two = LogDrop(2, context);
+    let three = LogDrop(3, context);
+    let four = LogDrop(4, context);
+
+    let res = panic::catch_unwind(panic::AssertUnwindSafe(|| {
+        foo((three, four), (two, one));
+    }));
+    if panic_on == 0 {
+        assert!(res.is_ok(), "should not have panicked");
+    } else {
+        assert!(res.is_err(), "should have panicked");
+    }
+    assert_eq!(*context.drops.borrow(), [1, 2, 3, 4], "incorrect drop order");
+}
+
+fn main() {
+    (0..=4).for_each(test_drop_order);
+}

From 28cc944530420bb3b1fc2dc96e2a8f433a41c6e4 Mon Sep 17 00:00:00 2001
From: Who? Me?! <mark-i-m@users.noreply.github.com>
Date: Mon, 19 Nov 2018 15:50:24 -0600
Subject: [PATCH 04/50] Reduce the amount of bold text at doc.rust-lang.org

---
 src/doc/index.md | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/doc/index.md b/src/doc/index.md
index 33ee76739c5b2..b79a349a453b6 100644
--- a/src/doc/index.md
+++ b/src/doc/index.md
@@ -21,6 +21,9 @@ nav {
 #search-but:hover, #search-input:focus {
     border-color: #55a9ff;
 }
+h2 {
+    font-size: 18px;
+}
 </style>
 
 Welcome to an overview of the documentation provided by the Rust project.

From 6674db48872c1b84fe3ac3feb94b8d3e0ee82b24 Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote <nnethercote@mozilla.com>
Date: Tue, 20 Nov 2018 20:16:57 +1100
Subject: [PATCH 05/50] Reuse the `P` in
 `InvocationCollector::fold_{,opt_}expr`.

This requires adding a new method, `P::filter_map`.

This commit reduces instruction counts for various benchmarks by up to
0.7%.
---
 src/libsyntax/ext/expand.rs | 84 +++++++++++++++++++++----------------
 src/libsyntax/ptr.rs        | 28 +++++++++++--
 2 files changed, 73 insertions(+), 39 deletions(-)

diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index cc8af70a050c9..68a96293891a0 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -1201,50 +1201,62 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
 
 impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
     fn fold_expr(&mut self, expr: P<ast::Expr>) -> P<ast::Expr> {
-        let mut expr = self.cfg.configure_expr(expr).into_inner();
-        expr.node = self.cfg.configure_expr_kind(expr.node);
-
-        // ignore derives so they remain unused
-        let (attr, expr, after_derive) = self.classify_nonitem(expr);
-
-        if attr.is_some() {
-            // collect the invoc regardless of whether or not attributes are permitted here
-            // expansion will eat the attribute so it won't error later
-            attr.as_ref().map(|a| self.cfg.maybe_emit_expr_attr_err(a));
-
-            // AstFragmentKind::Expr requires the macro to emit an expression
-            return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)),
-                                     AstFragmentKind::Expr, after_derive).make_expr();
-        }
+        let expr = self.cfg.configure_expr(expr);
+        expr.map(|mut expr| {
+            expr.node = self.cfg.configure_expr_kind(expr.node);
+
+            // ignore derives so they remain unused
+            let (attr, expr, after_derive) = self.classify_nonitem(expr);
+
+            if attr.is_some() {
+                // Collect the invoc regardless of whether or not attributes are permitted here
+                // expansion will eat the attribute so it won't error later.
+                attr.as_ref().map(|a| self.cfg.maybe_emit_expr_attr_err(a));
+
+                // AstFragmentKind::Expr requires the macro to emit an expression.
+                return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)),
+                                         AstFragmentKind::Expr, after_derive)
+                    .make_expr()
+                    .into_inner()
+            }
 
-        if let ast::ExprKind::Mac(mac) = expr.node {
-            self.check_attributes(&expr.attrs);
-            self.collect_bang(mac, expr.span, AstFragmentKind::Expr).make_expr()
-        } else {
-            P(noop_fold_expr(expr, self))
-        }
+            if let ast::ExprKind::Mac(mac) = expr.node {
+                self.check_attributes(&expr.attrs);
+                self.collect_bang(mac, expr.span, AstFragmentKind::Expr)
+                    .make_expr()
+                    .into_inner()
+            } else {
+                noop_fold_expr(expr, self)
+            }
+        })
     }
 
     fn fold_opt_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
-        let mut expr = configure!(self, expr).into_inner();
-        expr.node = self.cfg.configure_expr_kind(expr.node);
+        let expr = configure!(self, expr);
+        expr.filter_map(|mut expr| {
+            expr.node = self.cfg.configure_expr_kind(expr.node);
 
-        // ignore derives so they remain unused
-        let (attr, expr, after_derive) = self.classify_nonitem(expr);
+            // Ignore derives so they remain unused.
+            let (attr, expr, after_derive) = self.classify_nonitem(expr);
 
-        if attr.is_some() {
-            attr.as_ref().map(|a| self.cfg.maybe_emit_expr_attr_err(a));
+            if attr.is_some() {
+                attr.as_ref().map(|a| self.cfg.maybe_emit_expr_attr_err(a));
 
-            return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)),
-                                     AstFragmentKind::OptExpr, after_derive).make_opt_expr();
-        }
+                return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)),
+                                         AstFragmentKind::OptExpr, after_derive)
+                    .make_opt_expr()
+                    .map(|expr| expr.into_inner())
+            }
 
-        if let ast::ExprKind::Mac(mac) = expr.node {
-            self.check_attributes(&expr.attrs);
-            self.collect_bang(mac, expr.span, AstFragmentKind::OptExpr).make_opt_expr()
-        } else {
-            Some(P(noop_fold_expr(expr, self)))
-        }
+            if let ast::ExprKind::Mac(mac) = expr.node {
+                self.check_attributes(&expr.attrs);
+                self.collect_bang(mac, expr.span, AstFragmentKind::OptExpr)
+                    .make_opt_expr()
+                    .map(|expr| expr.into_inner())
+            } else {
+                Some(noop_fold_expr(expr, self))
+            }
+        })
     }
 
     fn fold_pat(&mut self, pat: P<ast::Pat>) -> P<ast::Pat> {
diff --git a/src/libsyntax/ptr.rs b/src/libsyntax/ptr.rs
index bb47d9b535bef..9fbc64758da4d 100644
--- a/src/libsyntax/ptr.rs
+++ b/src/libsyntax/ptr.rs
@@ -72,7 +72,7 @@ impl<T: 'static> P<T> {
         *self.ptr
     }
 
-    /// Transform the inner value, consuming `self` and producing a new `P<T>`.
+    /// Produce a new `P<T>` from `self` without reallocating.
     pub fn map<F>(mut self, f: F) -> P<T> where
         F: FnOnce(T) -> T,
     {
@@ -88,8 +88,30 @@ impl<T: 'static> P<T> {
             ptr::write(p, f(ptr::read(p)));
 
             // Recreate self from the raw pointer.
-            P {
-                ptr: Box::from_raw(p)
+            P { ptr: Box::from_raw(p) }
+        }
+    }
+
+    /// Optionally produce a new `P<T>` from `self` without reallocating.
+    pub fn filter_map<F>(mut self, f: F) -> Option<P<T>> where
+        F: FnOnce(T) -> Option<T>,
+    {
+        let p: *mut T = &mut *self.ptr;
+
+        // Leak self in case of panic.
+        // FIXME(eddyb) Use some sort of "free guard" that
+        // only deallocates, without dropping the pointee,
+        // in case the call the `f` below ends in a panic.
+        mem::forget(self);
+
+        unsafe {
+            if let Some(v) = f(ptr::read(p)) {
+                ptr::write(p, v);
+
+                // Recreate self from the raw pointer.
+                Some(P { ptr: Box::from_raw(p) })
+            } else {
+                None
             }
         }
     }

From b99f9f775c59de7223e810b303e56b39f7bbaf03 Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Tue, 20 Nov 2018 21:48:13 +0000
Subject: [PATCH 06/50] Enclose type in backticks for "non-exhaustive patterns"
 error

This makes the error style consistent with the convention in error messages.
---
 src/librustc_mir/hair/pattern/check_match.rs                | 2 +-
 src/test/ui/error-codes/E0004-2.stderr                      | 2 +-
 src/test/ui/issues/issue-3096-1.stderr                      | 2 +-
 src/test/ui/issues/issue-3096-2.stderr                      | 2 +-
 .../ui/uninhabited/uninhabited-matches-feature-gated.stderr | 6 +++---
 5 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs
index bafabe4e9972c..a6bd36e582fcd 100644
--- a/src/librustc_mir/hair/pattern/check_match.rs
+++ b/src/librustc_mir/hair/pattern/check_match.rs
@@ -234,7 +234,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
                 if !scrutinee_is_uninhabited {
                     // We know the type is inhabited, so this must be wrong
                     let mut err = create_e0004(self.tcx.sess, scrut.span,
-                                               format!("non-exhaustive patterns: type {} \
+                                               format!("non-exhaustive patterns: type `{}` \
                                                         is non-empty",
                                                        pat_ty));
                     span_help!(&mut err, scrut.span,
diff --git a/src/test/ui/error-codes/E0004-2.stderr b/src/test/ui/error-codes/E0004-2.stderr
index 900812787bcf7..2d46196ddda55 100644
--- a/src/test/ui/error-codes/E0004-2.stderr
+++ b/src/test/ui/error-codes/E0004-2.stderr
@@ -1,4 +1,4 @@
-error[E0004]: non-exhaustive patterns: type std::option::Option<i32> is non-empty
+error[E0004]: non-exhaustive patterns: type `std::option::Option<i32>` is non-empty
   --> $DIR/E0004-2.rs:14:11
    |
 LL |     match x { } //~ ERROR E0004
diff --git a/src/test/ui/issues/issue-3096-1.stderr b/src/test/ui/issues/issue-3096-1.stderr
index b2bfe6b5e8c07..f0782bd973805 100644
--- a/src/test/ui/issues/issue-3096-1.stderr
+++ b/src/test/ui/issues/issue-3096-1.stderr
@@ -1,4 +1,4 @@
-error[E0004]: non-exhaustive patterns: type () is non-empty
+error[E0004]: non-exhaustive patterns: type `()` is non-empty
   --> $DIR/issue-3096-1.rs:12:11
    |
 LL |     match () { } //~ ERROR non-exhaustive
diff --git a/src/test/ui/issues/issue-3096-2.stderr b/src/test/ui/issues/issue-3096-2.stderr
index bb9dfabe7be03..e0fa641ff39e7 100644
--- a/src/test/ui/issues/issue-3096-2.stderr
+++ b/src/test/ui/issues/issue-3096-2.stderr
@@ -1,4 +1,4 @@
-error[E0004]: non-exhaustive patterns: type *const bottom is non-empty
+error[E0004]: non-exhaustive patterns: type `*const bottom` is non-empty
   --> $DIR/issue-3096-2.rs:15:11
    |
 LL |     match x { } //~ ERROR non-exhaustive patterns
diff --git a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr
index 83fd736a997a9..f4974b8fa3854 100644
--- a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr
+++ b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr
@@ -4,7 +4,7 @@ error[E0004]: non-exhaustive patterns: `Err(_)` not covered
 LL |     let _ = match x {   //~ ERROR non-exhaustive
    |                   ^ pattern `Err(_)` not covered
 
-error[E0004]: non-exhaustive patterns: type &Void is non-empty
+error[E0004]: non-exhaustive patterns: type `&Void` is non-empty
   --> $DIR/uninhabited-matches-feature-gated.rs:20:19
    |
 LL |     let _ = match x {}; //~ ERROR non-exhaustive
@@ -16,7 +16,7 @@ help: ensure that all possible cases are being handled, possibly by adding wildc
 LL |     let _ = match x {}; //~ ERROR non-exhaustive
    |                   ^
 
-error[E0004]: non-exhaustive patterns: type (Void,) is non-empty
+error[E0004]: non-exhaustive patterns: type `(Void,)` is non-empty
   --> $DIR/uninhabited-matches-feature-gated.rs:23:19
    |
 LL |     let _ = match x {}; //~ ERROR non-exhaustive
@@ -28,7 +28,7 @@ help: ensure that all possible cases are being handled, possibly by adding wildc
 LL |     let _ = match x {}; //~ ERROR non-exhaustive
    |                   ^
 
-error[E0004]: non-exhaustive patterns: type [Void; 1] is non-empty
+error[E0004]: non-exhaustive patterns: type `[Void; 1]` is non-empty
   --> $DIR/uninhabited-matches-feature-gated.rs:26:19
    |
 LL |     let _ = match x {}; //~ ERROR non-exhaustive

From 464c9da9c229111298d413882735ea707a30e077 Mon Sep 17 00:00:00 2001
From: ljedrz <ljedrz@gmail.com>
Date: Wed, 21 Nov 2018 10:07:33 +0100
Subject: [PATCH 07/50] serialize: preallocate VecDeque in Decodable::decode

---
 src/libserialize/collection_impls.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/libserialize/collection_impls.rs b/src/libserialize/collection_impls.rs
index 3e028d755c6d4..cbd642dd6ad91 100644
--- a/src/libserialize/collection_impls.rs
+++ b/src/libserialize/collection_impls.rs
@@ -86,7 +86,7 @@ impl<T: Encodable> Encodable for VecDeque<T> {
 impl<T:Decodable> Decodable for VecDeque<T> {
     fn decode<D: Decoder>(d: &mut D) -> Result<VecDeque<T>, D::Error> {
         d.read_seq(|d, len| {
-            let mut deque: VecDeque<T> = VecDeque::new();
+            let mut deque: VecDeque<T> = VecDeque::with_capacity(len);
             for i in 0..len {
                 deque.push_back(d.read_seq_elt(i, |d| Decodable::decode(d))?);
             }

From 591607d237665857880e16899788517b9b82d414 Mon Sep 17 00:00:00 2001
From: ljedrz <ljedrz@gmail.com>
Date: Wed, 21 Nov 2018 10:17:54 +0100
Subject: [PATCH 08/50] String: add a FIXME to from_utf16

---
 src/liballoc/string.rs | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs
index 8d009101ce7da..0b25d911a299c 100644
--- a/src/liballoc/string.rs
+++ b/src/liballoc/string.rs
@@ -618,6 +618,8 @@ impl String {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn from_utf16(v: &[u16]) -> Result<String, FromUtf16Error> {
+        // This isn't done via collect::<Result<_, _>>() for performance reasons.
+        // FIXME: the function can be simplified again when #48994 is closed.
         let mut ret = String::with_capacity(v.len());
         for c in decode_utf16(v.iter().cloned()) {
             if let Ok(c) = c {

From 1ed91951c3012e9aabb403d28b902c56cc143907 Mon Sep 17 00:00:00 2001
From: antoine-de <antoine.desbordes@gmail.com>
Date: Wed, 21 Nov 2018 11:17:48 +0100
Subject: [PATCH 09/50] fix small doc mistake

The std::io::read main documentation can lead to error because the
buffer is prefilled with 10 zeros that will pad the response.
Using an empty vector is better.

The `read_to_end` documentation is already correct though.

This is my first rust PR, don't hesitate to tell me if I did something
wrong.
---
 src/libstd/io/mod.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index e263db24fc2c8..076524e624a47 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -431,7 +431,7 @@ fn read_to_end_with_reservation<R: Read + ?Sized>(r: &mut R,
 ///     // read up to 10 bytes
 ///     f.read(&mut buffer)?;
 ///
-///     let mut buffer = vec![0; 10];
+///     let mut buffer = Vec::new();
 ///     // read the whole file
 ///     f.read_to_end(&mut buffer)?;
 ///

From 83388e84c25f86563d82514d7bf71cfd474e008a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Oliver=20S=CC=B6c=CC=B6h=CC=B6n=CC=B6e=CC=B6i=CC=B6d=CC=B6?=
 =?UTF-8?q?e=CC=B6r=20Scherer?= <github35764891676564198441@oli-obk.de>
Date: Wed, 21 Nov 2018 12:26:40 +0100
Subject: [PATCH 10/50] Update an outdated comment in mir building

---
 src/librustc_mir/build/expr/as_temp.rs | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/src/librustc_mir/build/expr/as_temp.rs b/src/librustc_mir/build/expr/as_temp.rs
index 8f50a1e9a21b9..19bfb35ed620d 100644
--- a/src/librustc_mir/build/expr/as_temp.rs
+++ b/src/librustc_mir/build/expr/as_temp.rs
@@ -85,9 +85,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
 
         unpack!(block = this.into(&Place::Local(temp), block, expr));
 
-        // In constants, temp_lifetime is None. We should not need to drop
-        // anything because no values with a destructor can be created in
-        // a constant at this time, even if the type may need dropping.
+        // In constants, temp_lifetime is None. We do not drop anything because
+        // values with a destructor will simply be leaked in constants.
         if let Some(temp_lifetime) = temp_lifetime {
             this.schedule_drop_storage_and_value(
                 expr_span,

From 5a2a251b9cb0358851bb9d8d8870163f43c081dc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Oliver=20S=CC=B6c=CC=B6h=CC=B6n=CC=B6e=CC=B6i=CC=B6d=CC=B6?=
 =?UTF-8?q?e=CC=B6r=20Scherer?= <github35764891676564198441@oli-obk.de>
Date: Wed, 21 Nov 2018 12:40:53 +0100
Subject: [PATCH 11/50] Update as_temp.rs

---
 src/librustc_mir/build/expr/as_temp.rs | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/src/librustc_mir/build/expr/as_temp.rs b/src/librustc_mir/build/expr/as_temp.rs
index 19bfb35ed620d..f060eefe520a6 100644
--- a/src/librustc_mir/build/expr/as_temp.rs
+++ b/src/librustc_mir/build/expr/as_temp.rs
@@ -85,8 +85,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
 
         unpack!(block = this.into(&Place::Local(temp), block, expr));
 
-        // In constants, temp_lifetime is None. We do not drop anything because
-        // values with a destructor will simply be leaked in constants.
+        // In constants, temp_lifetime is None for temporaries that live for the
+        // entire constant. Thus we do not drop these temporaries and simply leak them.
+        // Anything with a shorter lifetime (e.g the `&foo()` in `bar(&foo())` or anything
+        // within a block will keep the regular drops just like runtime code.
         if let Some(temp_lifetime) = temp_lifetime {
             this.schedule_drop_storage_and_value(
                 expr_span,

From 925274ab70c15ac5dcb3537e3473c29771ab7df5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Oliver=20S=CC=B6c=CC=B6h=CC=B6n=CC=B6e=CC=B6i=CC=B6d=CC=B6?=
 =?UTF-8?q?e=CC=B6r=20Scherer?= <github35764891676564198441@oli-obk.de>
Date: Wed, 21 Nov 2018 13:10:10 +0100
Subject: [PATCH 12/50] Update as_temp.rs

---
 src/librustc_mir/build/expr/as_temp.rs | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/src/librustc_mir/build/expr/as_temp.rs b/src/librustc_mir/build/expr/as_temp.rs
index f060eefe520a6..2db9fb9cb99f4 100644
--- a/src/librustc_mir/build/expr/as_temp.rs
+++ b/src/librustc_mir/build/expr/as_temp.rs
@@ -86,7 +86,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         unpack!(block = this.into(&Place::Local(temp), block, expr));
 
         // In constants, temp_lifetime is None for temporaries that live for the
-        // entire constant. Thus we do not drop these temporaries and simply leak them.
+        // 'static lifetime. Thus we do not drop these temporaries and simply leak them.
+        // This is equivalent to what `let x = &foo();` does in functions. The temporary
+        // is lifted to their surrounding scope. In a function that means the temporary lives
+        // until just before the function returns. In constants that means it outlives the
+        // constant's initialization value computation. Anything outliving a constant
+        // must have the `'static` lifetime and live forever.
         // Anything with a shorter lifetime (e.g the `&foo()` in `bar(&foo())` or anything
         // within a block will keep the regular drops just like runtime code.
         if let Some(temp_lifetime) = temp_lifetime {

From f03987276656134f25f92f7434d7d1c63c9e981c Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Wed, 21 Nov 2018 16:06:24 +0000
Subject: [PATCH 13/50] Enclose type in backticks for "reached the recursion
 limit while auto-dereferencing" error

---
 src/librustc_typeck/check/autoderef.rs                | 4 ++--
 src/librustc_typeck/diagnostics.rs                    | 2 +-
 src/test/ui/did_you_mean/recursion_limit_deref.stderr | 2 +-
 src/test/ui/error-codes/E0055.stderr                  | 2 +-
 src/test/ui/infinite/infinite-autoderef.stderr        | 6 +++---
 src/test/ui/issues/issue-38940.rs                     | 2 +-
 src/test/ui/issues/issue-38940.stderr                 | 2 +-
 7 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/src/librustc_typeck/check/autoderef.rs b/src/librustc_typeck/check/autoderef.rs
index 73489309d0742..2cd2bb5064877 100644
--- a/src/librustc_typeck/check/autoderef.rs
+++ b/src/librustc_typeck/check/autoderef.rs
@@ -59,7 +59,7 @@ impl<'a, 'gcx, 'tcx> Iterator for Autoderef<'a, 'gcx, 'tcx> {
         if self.steps.len() >= *tcx.sess.recursion_limit.get() {
             // We've reached the recursion limit, error gracefully.
             let suggested_limit = *tcx.sess.recursion_limit.get() * 2;
-            let msg = format!("reached the recursion limit while auto-dereferencing {:?}",
+            let msg = format!("reached the recursion limit while auto-dereferencing `{:?}`",
                               self.cur_ty);
             let error_id = (DiagnosticMessageId::ErrorId(55), Some(self.span), msg);
             let fresh = tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id);
@@ -67,7 +67,7 @@ impl<'a, 'gcx, 'tcx> Iterator for Autoderef<'a, 'gcx, 'tcx> {
                 struct_span_err!(tcx.sess,
                                  self.span,
                                  E0055,
-                                 "reached the recursion limit while auto-dereferencing {:?}",
+                                 "reached the recursion limit while auto-dereferencing `{:?}`",
                                  self.cur_ty)
                     .span_label(self.span, "deref recursion limit reached")
                     .help(&format!(
diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs
index a985c3e9fdf44..084951f4a2c16 100644
--- a/src/librustc_typeck/diagnostics.rs
+++ b/src/librustc_typeck/diagnostics.rs
@@ -538,7 +538,7 @@ fn main() {
     let foo = Foo;
     let ref_foo = &&Foo;
 
-    // error, reached the recursion limit while auto-dereferencing &&Foo
+    // error, reached the recursion limit while auto-dereferencing `&&Foo`
     ref_foo.foo();
 }
 ```
diff --git a/src/test/ui/did_you_mean/recursion_limit_deref.stderr b/src/test/ui/did_you_mean/recursion_limit_deref.stderr
index 20a94f7aac196..7e7f21dd69c92 100644
--- a/src/test/ui/did_you_mean/recursion_limit_deref.stderr
+++ b/src/test/ui/did_you_mean/recursion_limit_deref.stderr
@@ -1,4 +1,4 @@
-error[E0055]: reached the recursion limit while auto-dereferencing I
+error[E0055]: reached the recursion limit while auto-dereferencing `I`
   --> $DIR/recursion_limit_deref.rs:60:22
    |
 LL |     let x: &Bottom = &t; //~ ERROR mismatched types
diff --git a/src/test/ui/error-codes/E0055.stderr b/src/test/ui/error-codes/E0055.stderr
index 9653f4eaeefd0..dddbd92765a5d 100644
--- a/src/test/ui/error-codes/E0055.stderr
+++ b/src/test/ui/error-codes/E0055.stderr
@@ -1,4 +1,4 @@
-error[E0055]: reached the recursion limit while auto-dereferencing Foo
+error[E0055]: reached the recursion limit while auto-dereferencing `Foo`
   --> $DIR/E0055.rs:21:13
    |
 LL |     ref_foo.foo();
diff --git a/src/test/ui/infinite/infinite-autoderef.stderr b/src/test/ui/infinite/infinite-autoderef.stderr
index b5e20ea5cbf99..ef68adecd1a5f 100644
--- a/src/test/ui/infinite/infinite-autoderef.stderr
+++ b/src/test/ui/infinite/infinite-autoderef.stderr
@@ -7,7 +7,7 @@ LL |         x = box x;
    |             cyclic type of infinite size
    |             help: try using a conversion method: `box x.to_string()`
 
-error[E0055]: reached the recursion limit while auto-dereferencing Foo
+error[E0055]: reached the recursion limit while auto-dereferencing `Foo`
   --> $DIR/infinite-autoderef.rs:35:5
    |
 LL |     Foo.foo;
@@ -15,7 +15,7 @@ LL |     Foo.foo;
    |
    = help: consider adding a `#![recursion_limit="128"]` attribute to your crate
 
-error[E0055]: reached the recursion limit while auto-dereferencing Foo
+error[E0055]: reached the recursion limit while auto-dereferencing `Foo`
   --> $DIR/infinite-autoderef.rs:35:9
    |
 LL |     Foo.foo;
@@ -29,7 +29,7 @@ error[E0609]: no field `foo` on type `Foo`
 LL |     Foo.foo;
    |         ^^^ unknown field
 
-error[E0055]: reached the recursion limit while auto-dereferencing Foo
+error[E0055]: reached the recursion limit while auto-dereferencing `Foo`
   --> $DIR/infinite-autoderef.rs:36:9
    |
 LL |     Foo.bar();
diff --git a/src/test/ui/issues/issue-38940.rs b/src/test/ui/issues/issue-38940.rs
index 7f9b141e02e3c..1c785949547e5 100644
--- a/src/test/ui/issues/issue-38940.rs
+++ b/src/test/ui/issues/issue-38940.rs
@@ -42,5 +42,5 @@ fn main() {
     let t = Top::new();
     let x: &Bottom = &t;
     //~^ ERROR mismatched types
-    //~| ERROR reached the recursion limit while auto-dereferencing I
+    //~| ERROR reached the recursion limit while auto-dereferencing `I`
 }
diff --git a/src/test/ui/issues/issue-38940.stderr b/src/test/ui/issues/issue-38940.stderr
index 2d3cfda9a5f72..d94a7101c0a38 100644
--- a/src/test/ui/issues/issue-38940.stderr
+++ b/src/test/ui/issues/issue-38940.stderr
@@ -1,4 +1,4 @@
-error[E0055]: reached the recursion limit while auto-dereferencing I
+error[E0055]: reached the recursion limit while auto-dereferencing `I`
   --> $DIR/issue-38940.rs:43:22
    |
 LL |     let x: &Bottom = &t;

From ec3ac112e115c02a942c7a84c37a0cfd270dbad4 Mon Sep 17 00:00:00 2001
From: ariasuni <perso@hack-libre.org>
Date: Wed, 21 Nov 2018 23:39:33 +0100
Subject: [PATCH 14/50] Make std::os::unix/linux::fs::MetadataExt::a/m/ctime*
 documentation clearer

---
 src/libstd/os/linux/fs.rs     | 18 ++++++++++++------
 src/libstd/sys/unix/ext/fs.rs | 18 ++++++++++++------
 2 files changed, 24 insertions(+), 12 deletions(-)

diff --git a/src/libstd/os/linux/fs.rs b/src/libstd/os/linux/fs.rs
index 76fb10da850b1..b518f524e0b08 100644
--- a/src/libstd/os/linux/fs.rs
+++ b/src/libstd/os/linux/fs.rs
@@ -191,7 +191,7 @@ pub trait MetadataExt {
     /// ```
     #[stable(feature = "metadata_ext2", since = "1.8.0")]
     fn st_size(&self) -> u64;
-    /// Returns the last access time.
+    /// Returns the last access time of the file, in seconds since Unix Epoch.
     ///
     /// # Examples
     ///
@@ -208,7 +208,9 @@ pub trait MetadataExt {
     /// ```
     #[stable(feature = "metadata_ext2", since = "1.8.0")]
     fn st_atime(&self) -> i64;
-    /// Returns the last access time, nano seconds part.
+    /// Returns the last access time of the file, in nanoseconds since [`st_atime`].
+    ///
+    /// [`st_atime`]: #tymethod.st_atime
     ///
     /// # Examples
     ///
@@ -225,7 +227,7 @@ pub trait MetadataExt {
     /// ```
     #[stable(feature = "metadata_ext2", since = "1.8.0")]
     fn st_atime_nsec(&self) -> i64;
-    /// Returns the last modification time.
+    /// Returns the last modification time of the file, in seconds since Unix Epoch.
     ///
     /// # Examples
     ///
@@ -242,7 +244,9 @@ pub trait MetadataExt {
     /// ```
     #[stable(feature = "metadata_ext2", since = "1.8.0")]
     fn st_mtime(&self) -> i64;
-    /// Returns the last modification time, nano seconds part.
+    /// Returns the last modification time of the file, in nanoseconds since [`st_mtime`].
+    ///
+    /// [`st_mtime`]: #tymethod.st_mtime
     ///
     /// # Examples
     ///
@@ -259,7 +263,7 @@ pub trait MetadataExt {
     /// ```
     #[stable(feature = "metadata_ext2", since = "1.8.0")]
     fn st_mtime_nsec(&self) -> i64;
-    /// Returns the last status change time.
+    /// Returns the last status change time of the file, in seconds since Unix Epoch.
     ///
     /// # Examples
     ///
@@ -276,7 +280,9 @@ pub trait MetadataExt {
     /// ```
     #[stable(feature = "metadata_ext2", since = "1.8.0")]
     fn st_ctime(&self) -> i64;
-    /// Returns the last status change time, nano seconds part.
+    /// Returns the last status change time of the file, in nanoseconds since [`st_ctime`].
+    ///
+    /// [`st_ctime`]: #tymethod.st_ctime
     ///
     /// # Examples
     ///
diff --git a/src/libstd/sys/unix/ext/fs.rs b/src/libstd/sys/unix/ext/fs.rs
index 507e9d881717b..7e65bbdef2a96 100644
--- a/src/libstd/sys/unix/ext/fs.rs
+++ b/src/libstd/sys/unix/ext/fs.rs
@@ -522,7 +522,7 @@ pub trait MetadataExt {
     /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn size(&self) -> u64;
-    /// Returns the time of the last access to the file.
+    /// Returns the last access time of the file, in seconds since Unix Epoch.
     ///
     /// # Examples
     ///
@@ -539,7 +539,9 @@ pub trait MetadataExt {
     /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn atime(&self) -> i64;
-    /// Returns the time of the last access to the file in nanoseconds.
+    /// Returns the last access time of the file, in nanoseconds since [`atime`].
+    ///
+    /// [`atime`]: #tymethod.atime
     ///
     /// # Examples
     ///
@@ -556,7 +558,7 @@ pub trait MetadataExt {
     /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn atime_nsec(&self) -> i64;
-    /// Returns the time of the last modification of the file.
+    /// Returns the last modification time of the file, in seconds since Unix Epoch.
     ///
     /// # Examples
     ///
@@ -573,7 +575,9 @@ pub trait MetadataExt {
     /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn mtime(&self) -> i64;
-    /// Returns the time of the last modification of the file in nanoseconds.
+    /// Returns the last modification time of the file, in nanoseconds since [`mtime`].
+    ///
+    /// [`mtime`]: #tymethod.mtime
     ///
     /// # Examples
     ///
@@ -590,7 +594,7 @@ pub trait MetadataExt {
     /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn mtime_nsec(&self) -> i64;
-    /// Returns the time of the last status change of the file.
+    /// Returns the last status change time of the file, in seconds since Unix Epoch.
     ///
     /// # Examples
     ///
@@ -607,7 +611,9 @@ pub trait MetadataExt {
     /// ```
     #[stable(feature = "metadata_ext", since = "1.1.0")]
     fn ctime(&self) -> i64;
-    /// Returns the time of the last status change of the file in nanoseconds.
+    /// Returns the last status change time of the file, in nanoseconds since [`ctime`].
+    ///
+    /// [`ctime`]: #tymethod.ctime
     ///
     /// # Examples
     ///

From af9b057156f610df3528a502c668cfed99ce8a1a Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Thu, 22 Nov 2018 13:43:05 +0100
Subject: [PATCH 15/50] drop glue takes in mutable references, it should
 reflect that in its type

---
 src/libcore/ptr.rs                       | 14 ++++++++++++--
 src/librustc_mir/interpret/terminator.rs |  3 +++
 src/librustc_mir/shim.rs                 |  7 ++++++-
 3 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index e9cf11424cae1..ba1028f76c1c3 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -189,12 +189,22 @@ pub use intrinsics::write_bytes;
 /// i.e., you do not usually have to worry about such issues unless you call `drop_in_place`
 /// manually.
 #[stable(feature = "drop_in_place", since = "1.8.0")]
+#[inline(always)]
+pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
+    real_drop_in_place(&mut *to_drop)
+}
+
+// The real `drop_in_place` -- the one that gets called implicitly when variables go
+// out of scope -- should have a safe reference and not a raw pointer as argument
+// type.  When we drop a local variable, we access it with a pointer that behaves
+// like a safe reference; transmuting that to a raw pointer does not mean we can
+// actually access it with raw pointers.
 #[lang = "drop_in_place"]
 #[allow(unconditional_recursion)]
-pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
+unsafe fn real_drop_in_place<T: ?Sized>(to_drop: &mut T) {
     // Code here does not matter - this is replaced by the
     // real drop glue by the compiler.
-    drop_in_place(to_drop);
+    real_drop_in_place(to_drop)
 }
 
 /// Creates a null raw pointer.
diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs
index 6070b31d3e7a3..4489465679740 100644
--- a/src/librustc_mir/interpret/terminator.rs
+++ b/src/librustc_mir/interpret/terminator.rs
@@ -196,6 +196,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
                 // that will take care to make it UB to leave the range, just
                 // like for transmute).
                 caller.value == callee.value,
+            (layout::Abi::ScalarPair(ref caller1, ref caller2),
+             layout::Abi::ScalarPair(ref callee1, ref callee2)) =>
+                caller1.value == callee1.value && caller2.value == callee2.value,
             // Be conservative
             _ => false
         }
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
index 93bf1b3e36e38..04079319a7877 100644
--- a/src/librustc_mir/shim.rs
+++ b/src/librustc_mir/shim.rs
@@ -226,8 +226,13 @@ fn build_drop_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         // The first argument (index 0), but add 1 for the return value.
         let dropee_ptr = Place::Local(Local::new(1+0));
         if tcx.sess.opts.debugging_opts.mir_emit_retag {
-            // We use raw ptr operations, better prepare the alias tracking for that
+            // Function arguments should be retagged
             mir.basic_blocks_mut()[START_BLOCK].statements.insert(0, Statement {
+                source_info,
+                kind: StatementKind::Retag { fn_entry: true, place: dropee_ptr.clone() },
+            });
+            // We use raw ptr operations, better prepare the alias tracking for that
+            mir.basic_blocks_mut()[START_BLOCK].statements.insert(1, Statement {
                 source_info,
                 kind: StatementKind::EscapeToRaw(Operand::Copy(dropee_ptr.clone())),
             })

From e1ca4f63f4cee0c468325572b86f00badce70ad7 Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Thu, 22 Nov 2018 17:26:44 +0100
Subject: [PATCH 16/50] fix codegen-units tests

---
 .../item-collection/drop_in_place_intrinsic.rs |  5 +++--
 .../item-collection/generic-drop-glue.rs       | 12 ++++++------
 .../instantiation-through-vtable.rs            |  4 ++--
 .../item-collection/non-generic-drop-glue.rs   |  4 ++--
 .../item-collection/transitive-drop-glue.rs    | 18 +++++++++---------
 .../item-collection/tuple-drop-glue.rs         |  8 ++++----
 .../codegen-units/item-collection/unsizing.rs  |  8 ++++----
 .../partitioning/extern-drop-glue.rs           |  6 +++---
 .../partitioning/local-drop-glue.rs            |  8 ++++----
 .../partitioning/vtable-through-const.rs       |  2 +-
 10 files changed, 38 insertions(+), 37 deletions(-)

diff --git a/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs b/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs
index cec88f1c6a245..1793a311f968a 100644
--- a/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs
+++ b/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs
@@ -14,7 +14,7 @@
 
 #![feature(start)]
 
-//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<drop_in_place_intrinsic::StructWithDtor[0]> @@ drop_in_place_intrinsic-cgu.0[Internal]
+//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<drop_in_place_intrinsic::StructWithDtor[0]> @@ drop_in_place_intrinsic-cgu.0[Internal]
 struct StructWithDtor(u32);
 
 impl Drop for StructWithDtor {
@@ -26,7 +26,7 @@ impl Drop for StructWithDtor {
 #[start]
 fn start(_: isize, _: *const *const u8) -> isize {
 
-    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<[drop_in_place_intrinsic::StructWithDtor[0]; 2]> @@ drop_in_place_intrinsic-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<[drop_in_place_intrinsic::StructWithDtor[0]; 2]> @@ drop_in_place_intrinsic-cgu.0[Internal]
     let x = [StructWithDtor(0), StructWithDtor(1)];
 
     drop_slice_in_place(&x);
@@ -41,6 +41,7 @@ fn drop_slice_in_place(x: &[StructWithDtor]) {
         // not have drop-glue for the unsized [StructWithDtor]. This has to be
         // generated though when the drop_in_place() intrinsic is used.
         //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<[drop_in_place_intrinsic::StructWithDtor[0]]> @@ drop_in_place_intrinsic-cgu.0[Internal]
+        //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<[drop_in_place_intrinsic::StructWithDtor[0]]> @@ drop_in_place_intrinsic-cgu.0[Internal]
         ::std::ptr::drop_in_place(x as *const _ as *mut [StructWithDtor]);
     }
 }
diff --git a/src/test/codegen-units/item-collection/generic-drop-glue.rs b/src/test/codegen-units/item-collection/generic-drop-glue.rs
index 5afa519bc5902..4ae5832ec4ed4 100644
--- a/src/test/codegen-units/item-collection/generic-drop-glue.rs
+++ b/src/test/codegen-units/item-collection/generic-drop-glue.rs
@@ -47,7 +47,7 @@ enum EnumNoDrop<T1, T2> {
 struct NonGenericNoDrop(i32);
 
 struct NonGenericWithDrop(i32);
-//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<generic_drop_glue::NonGenericWithDrop[0]> @@ generic_drop_glue-cgu.0[Internal]
+//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<generic_drop_glue::NonGenericWithDrop[0]> @@ generic_drop_glue-cgu.0[Internal]
 
 impl Drop for NonGenericWithDrop {
     //~ MONO_ITEM fn generic_drop_glue::{{impl}}[2]::drop[0]
@@ -57,11 +57,11 @@ impl Drop for NonGenericWithDrop {
 //~ MONO_ITEM fn generic_drop_glue::start[0]
 #[start]
 fn start(_: isize, _: *const *const u8) -> isize {
-    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<generic_drop_glue::StructWithDrop[0]<i8, char>> @@ generic_drop_glue-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<generic_drop_glue::StructWithDrop[0]<i8, char>> @@ generic_drop_glue-cgu.0[Internal]
     //~ MONO_ITEM fn generic_drop_glue::{{impl}}[0]::drop[0]<i8, char>
     let _ = StructWithDrop { x: 0i8, y: 'a' }.x;
 
-    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<generic_drop_glue::StructWithDrop[0]<&str, generic_drop_glue::NonGenericNoDrop[0]>> @@ generic_drop_glue-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<generic_drop_glue::StructWithDrop[0]<&str, generic_drop_glue::NonGenericNoDrop[0]>> @@ generic_drop_glue-cgu.0[Internal]
     //~ MONO_ITEM fn generic_drop_glue::{{impl}}[0]::drop[0]<&str, generic_drop_glue::NonGenericNoDrop[0]>
     let _ = StructWithDrop { x: "&str", y: NonGenericNoDrop(0) }.y;
 
@@ -70,17 +70,17 @@ fn start(_: isize, _: *const *const u8) -> isize {
 
     // This is supposed to generate drop-glue because it contains a field that
     // needs to be dropped.
-    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<generic_drop_glue::StructNoDrop[0]<generic_drop_glue::NonGenericWithDrop[0], f64>> @@ generic_drop_glue-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<generic_drop_glue::StructNoDrop[0]<generic_drop_glue::NonGenericWithDrop[0], f64>> @@ generic_drop_glue-cgu.0[Internal]
     let _ = StructNoDrop { x: NonGenericWithDrop(0), y: 0f64 }.y;
 
-    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<generic_drop_glue::EnumWithDrop[0]<i32, i64>> @@ generic_drop_glue-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<generic_drop_glue::EnumWithDrop[0]<i32, i64>> @@ generic_drop_glue-cgu.0[Internal]
     //~ MONO_ITEM fn generic_drop_glue::{{impl}}[1]::drop[0]<i32, i64>
     let _ = match EnumWithDrop::A::<i32, i64>(0) {
         EnumWithDrop::A(x) => x,
         EnumWithDrop::B(x) => x as i32
     };
 
-    //~MONO_ITEM fn core::ptr[0]::drop_in_place[0]<generic_drop_glue::EnumWithDrop[0]<f64, f32>> @@ generic_drop_glue-cgu.0[Internal]
+    //~MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<generic_drop_glue::EnumWithDrop[0]<f64, f32>> @@ generic_drop_glue-cgu.0[Internal]
     //~ MONO_ITEM fn generic_drop_glue::{{impl}}[1]::drop[0]<f64, f32>
     let _ = match EnumWithDrop::B::<f64, f32>(1.0) {
         EnumWithDrop::A(x) => x,
diff --git a/src/test/codegen-units/item-collection/instantiation-through-vtable.rs b/src/test/codegen-units/item-collection/instantiation-through-vtable.rs
index d09d343a8458e..bfa67b16d0e63 100644
--- a/src/test/codegen-units/item-collection/instantiation-through-vtable.rs
+++ b/src/test/codegen-units/item-collection/instantiation-through-vtable.rs
@@ -34,13 +34,13 @@ impl<T> Trait for Struct<T> {
 fn start(_: isize, _: *const *const u8) -> isize {
     let s1 = Struct { _a: 0u32 };
 
-    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<instantiation_through_vtable::Struct[0]<u32>> @@ instantiation_through_vtable-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<instantiation_through_vtable::Struct[0]<u32>> @@ instantiation_through_vtable-cgu.0[Internal]
     //~ MONO_ITEM fn instantiation_through_vtable::{{impl}}[0]::foo[0]<u32>
     //~ MONO_ITEM fn instantiation_through_vtable::{{impl}}[0]::bar[0]<u32>
     let _ = &s1 as &Trait;
 
     let s1 = Struct { _a: 0u64 };
-    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<instantiation_through_vtable::Struct[0]<u64>> @@ instantiation_through_vtable-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<instantiation_through_vtable::Struct[0]<u64>> @@ instantiation_through_vtable-cgu.0[Internal]
     //~ MONO_ITEM fn instantiation_through_vtable::{{impl}}[0]::foo[0]<u64>
     //~ MONO_ITEM fn instantiation_through_vtable::{{impl}}[0]::bar[0]<u64>
     let _ = &s1 as &Trait;
diff --git a/src/test/codegen-units/item-collection/non-generic-drop-glue.rs b/src/test/codegen-units/item-collection/non-generic-drop-glue.rs
index a939dd56cda5b..2d72383391daa 100644
--- a/src/test/codegen-units/item-collection/non-generic-drop-glue.rs
+++ b/src/test/codegen-units/item-collection/non-generic-drop-glue.rs
@@ -15,7 +15,7 @@
 #![deny(dead_code)]
 #![feature(start)]
 
-//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<non_generic_drop_glue::StructWithDrop[0]> @@ non_generic_drop_glue-cgu.0[Internal]
+//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<non_generic_drop_glue::StructWithDrop[0]> @@ non_generic_drop_glue-cgu.0[Internal]
 struct StructWithDrop {
     x: i32
 }
@@ -29,7 +29,7 @@ struct StructNoDrop {
     x: i32
 }
 
-//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<non_generic_drop_glue::EnumWithDrop[0]> @@ non_generic_drop_glue-cgu.0[Internal]
+//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<non_generic_drop_glue::EnumWithDrop[0]> @@ non_generic_drop_glue-cgu.0[Internal]
 enum EnumWithDrop {
     A(i32)
 }
diff --git a/src/test/codegen-units/item-collection/transitive-drop-glue.rs b/src/test/codegen-units/item-collection/transitive-drop-glue.rs
index 7bbc9b6d0fbc9..d90171726b2c6 100644
--- a/src/test/codegen-units/item-collection/transitive-drop-glue.rs
+++ b/src/test/codegen-units/item-collection/transitive-drop-glue.rs
@@ -15,11 +15,11 @@
 #![deny(dead_code)]
 #![feature(start)]
 
-//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::Root[0]> @@ transitive_drop_glue-cgu.0[Internal]
+//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<transitive_drop_glue::Root[0]> @@ transitive_drop_glue-cgu.0[Internal]
 struct Root(Intermediate);
-//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::Intermediate[0]> @@ transitive_drop_glue-cgu.0[Internal]
+//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<transitive_drop_glue::Intermediate[0]> @@ transitive_drop_glue-cgu.0[Internal]
 struct Intermediate(Leaf);
-//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::Leaf[0]> @@ transitive_drop_glue-cgu.0[Internal]
+//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<transitive_drop_glue::Leaf[0]> @@ transitive_drop_glue-cgu.0[Internal]
 struct Leaf;
 
 impl Drop for Leaf {
@@ -40,15 +40,15 @@ impl<T> Drop for LeafGen<T> {
 fn start(_: isize, _: *const *const u8) -> isize {
     let _ = Root(Intermediate(Leaf));
 
-    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::RootGen[0]<u32>> @@ transitive_drop_glue-cgu.0[Internal]
-    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::IntermediateGen[0]<u32>> @@ transitive_drop_glue-cgu.0[Internal]
-    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::LeafGen[0]<u32>> @@ transitive_drop_glue-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<transitive_drop_glue::RootGen[0]<u32>> @@ transitive_drop_glue-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<transitive_drop_glue::IntermediateGen[0]<u32>> @@ transitive_drop_glue-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<transitive_drop_glue::LeafGen[0]<u32>> @@ transitive_drop_glue-cgu.0[Internal]
     //~ MONO_ITEM fn transitive_drop_glue::{{impl}}[1]::drop[0]<u32>
     let _ = RootGen(IntermediateGen(LeafGen(0u32)));
 
-    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::RootGen[0]<i16>> @@ transitive_drop_glue-cgu.0[Internal]
-    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::IntermediateGen[0]<i16>> @@ transitive_drop_glue-cgu.0[Internal]
-    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::LeafGen[0]<i16>> @@ transitive_drop_glue-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<transitive_drop_glue::RootGen[0]<i16>> @@ transitive_drop_glue-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<transitive_drop_glue::IntermediateGen[0]<i16>> @@ transitive_drop_glue-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<transitive_drop_glue::LeafGen[0]<i16>> @@ transitive_drop_glue-cgu.0[Internal]
     //~ MONO_ITEM fn transitive_drop_glue::{{impl}}[1]::drop[0]<i16>
     let _ = RootGen(IntermediateGen(LeafGen(0i16)));
 
diff --git a/src/test/codegen-units/item-collection/tuple-drop-glue.rs b/src/test/codegen-units/item-collection/tuple-drop-glue.rs
index 865570ccfa55a..e94af0c2989b2 100644
--- a/src/test/codegen-units/item-collection/tuple-drop-glue.rs
+++ b/src/test/codegen-units/item-collection/tuple-drop-glue.rs
@@ -15,7 +15,7 @@
 #![deny(dead_code)]
 #![feature(start)]
 
-//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<tuple_drop_glue::Dropped[0]> @@ tuple_drop_glue-cgu.0[Internal]
+//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<tuple_drop_glue::Dropped[0]> @@ tuple_drop_glue-cgu.0[Internal]
 struct Dropped;
 
 impl Drop for Dropped {
@@ -26,11 +26,11 @@ impl Drop for Dropped {
 //~ MONO_ITEM fn tuple_drop_glue::start[0]
 #[start]
 fn start(_: isize, _: *const *const u8) -> isize {
-    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<(u32, tuple_drop_glue::Dropped[0])> @@ tuple_drop_glue-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<(u32, tuple_drop_glue::Dropped[0])> @@ tuple_drop_glue-cgu.0[Internal]
     let x = (0u32, Dropped);
 
-    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<(i16, (tuple_drop_glue::Dropped[0], bool))> @@ tuple_drop_glue-cgu.0[Internal]
-    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<(tuple_drop_glue::Dropped[0], bool)> @@ tuple_drop_glue-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<(i16, (tuple_drop_glue::Dropped[0], bool))> @@ tuple_drop_glue-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<(tuple_drop_glue::Dropped[0], bool)> @@ tuple_drop_glue-cgu.0[Internal]
     let x = (0i16, (Dropped, true));
 
     0
diff --git a/src/test/codegen-units/item-collection/unsizing.rs b/src/test/codegen-units/item-collection/unsizing.rs
index 5e9a3258c7adf..c85f7fc1bdd8d 100644
--- a/src/test/codegen-units/item-collection/unsizing.rs
+++ b/src/test/codegen-units/item-collection/unsizing.rs
@@ -59,13 +59,13 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Wrapper<U>> for Wrapper<T>
 fn start(_: isize, _: *const *const u8) -> isize {
     // simple case
     let bool_sized = &true;
-    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<bool> @@ unsizing-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<bool> @@ unsizing-cgu.0[Internal]
     //~ MONO_ITEM fn unsizing::{{impl}}[0]::foo[0]
     let _bool_unsized = bool_sized as &Trait;
 
     let char_sized = &'a';
 
-    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<char> @@ unsizing-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<char> @@ unsizing-cgu.0[Internal]
     //~ MONO_ITEM fn unsizing::{{impl}}[1]::foo[0]
     let _char_unsized = char_sized as &Trait;
 
@@ -75,13 +75,13 @@ fn start(_: isize, _: *const *const u8) -> isize {
         _b: 2,
         _c: 3.0f64
     };
-    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<f64> @@ unsizing-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<f64> @@ unsizing-cgu.0[Internal]
     //~ MONO_ITEM fn unsizing::{{impl}}[2]::foo[0]
     let _struct_unsized = struct_sized as &Struct<Trait>;
 
     // custom coercion
     let wrapper_sized = Wrapper(&0u32);
-    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<u32> @@ unsizing-cgu.0[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<u32> @@ unsizing-cgu.0[Internal]
     //~ MONO_ITEM fn unsizing::{{impl}}[3]::foo[0]
     let _wrapper_sized = wrapper_sized as Wrapper<Trait>;
 
diff --git a/src/test/codegen-units/partitioning/extern-drop-glue.rs b/src/test/codegen-units/partitioning/extern-drop-glue.rs
index cbad3a638840c..87b4430b4cab6 100644
--- a/src/test/codegen-units/partitioning/extern-drop-glue.rs
+++ b/src/test/codegen-units/partitioning/extern-drop-glue.rs
@@ -21,14 +21,14 @@
 // aux-build:cgu_extern_drop_glue.rs
 extern crate cgu_extern_drop_glue;
 
-//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<cgu_extern_drop_glue::Struct[0]> @@ extern_drop_glue[Internal] extern_drop_glue-mod1[Internal]
+//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<cgu_extern_drop_glue::Struct[0]> @@ extern_drop_glue[Internal] extern_drop_glue-mod1[Internal]
 
 struct LocalStruct(cgu_extern_drop_glue::Struct);
 
 //~ MONO_ITEM fn extern_drop_glue::user[0] @@ extern_drop_glue[External]
 pub fn user()
 {
-    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<extern_drop_glue::LocalStruct[0]> @@ extern_drop_glue[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<extern_drop_glue::LocalStruct[0]> @@ extern_drop_glue[Internal]
     let _ = LocalStruct(cgu_extern_drop_glue::Struct(0));
 }
 
@@ -40,7 +40,7 @@ pub mod mod1 {
     //~ MONO_ITEM fn extern_drop_glue::mod1[0]::user[0] @@ extern_drop_glue-mod1[External]
     pub fn user()
     {
-        //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<extern_drop_glue::mod1[0]::LocalStruct[0]> @@ extern_drop_glue-mod1[Internal]
+        //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<extern_drop_glue::mod1[0]::LocalStruct[0]> @@ extern_drop_glue-mod1[Internal]
         let _ = LocalStruct(cgu_extern_drop_glue::Struct(0));
     }
 }
diff --git a/src/test/codegen-units/partitioning/local-drop-glue.rs b/src/test/codegen-units/partitioning/local-drop-glue.rs
index 98729d99ea950..e09eb318708e1 100644
--- a/src/test/codegen-units/partitioning/local-drop-glue.rs
+++ b/src/test/codegen-units/partitioning/local-drop-glue.rs
@@ -17,7 +17,7 @@
 #![allow(dead_code)]
 #![crate_type="rlib"]
 
-//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<local_drop_glue::Struct[0]> @@ local_drop_glue[Internal] local_drop_glue-mod1[Internal]
+//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<local_drop_glue::Struct[0]> @@ local_drop_glue[Internal] local_drop_glue-mod1[Internal]
 struct Struct {
     _a: u32
 }
@@ -27,7 +27,7 @@ impl Drop for Struct {
     fn drop(&mut self) {}
 }
 
-//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<local_drop_glue::Outer[0]> @@ local_drop_glue[Internal]
+//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<local_drop_glue::Outer[0]> @@ local_drop_glue[Internal]
 struct Outer {
     _a: Struct
 }
@@ -46,10 +46,10 @@ pub mod mod1
 {
     use super::Struct;
 
-    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<local_drop_glue::mod1[0]::Struct2[0]> @@ local_drop_glue-mod1[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<local_drop_glue::mod1[0]::Struct2[0]> @@ local_drop_glue-mod1[Internal]
     struct Struct2 {
         _a: Struct,
-        //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<(u32, local_drop_glue::Struct[0])> @@ local_drop_glue-mod1[Internal]
+        //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<(u32, local_drop_glue::Struct[0])> @@ local_drop_glue-mod1[Internal]
         _b: (u32, Struct),
     }
 
diff --git a/src/test/codegen-units/partitioning/vtable-through-const.rs b/src/test/codegen-units/partitioning/vtable-through-const.rs
index ebda08a29f66d..459c6b6f15410 100644
--- a/src/test/codegen-units/partitioning/vtable-through-const.rs
+++ b/src/test/codegen-units/partitioning/vtable-through-const.rs
@@ -76,7 +76,7 @@ mod mod1 {
 //~ MONO_ITEM fn vtable_through_const::start[0]
 #[start]
 fn start(_: isize, _: *const *const u8) -> isize {
-    //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<u32> @@ vtable_through_const[Internal]
+    //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<u32> @@ vtable_through_const[Internal]
 
     // Since Trait1::do_something() is instantiated via its default implementation,
     // it is considered a generic and is instantiated here only because it is

From d9de72fcac7cfd90742a8fa8e4f6c0efd664ecde Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Thu, 22 Nov 2018 17:38:59 +0100
Subject: [PATCH 17/50] miri: restrict fn argument punning to Rust ABI

---
 src/librustc_mir/interpret/terminator.rs | 33 +++++++++++++++---------
 1 file changed, 21 insertions(+), 12 deletions(-)

diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs
index 4489465679740..11c44fc943daa 100644
--- a/src/librustc_mir/interpret/terminator.rs
+++ b/src/librustc_mir/interpret/terminator.rs
@@ -182,6 +182,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
     }
 
     fn check_argument_compat(
+        rust_abi: bool,
         caller: TyLayout<'tcx>,
         callee: TyLayout<'tcx>,
     ) -> bool {
@@ -189,12 +190,16 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
             // No question
             return true;
         }
+        if !rust_abi {
+            // Don't risk anything
+            return false;
+        }
         // Compare layout
         match (&caller.abi, &callee.abi) {
+            // Different valid ranges are okay (once we enforce validity,
+            // that will take care to make it UB to leave the range, just
+            // like for transmute).
             (layout::Abi::Scalar(ref caller), layout::Abi::Scalar(ref callee)) =>
-                // Different valid ranges are okay (once we enforce validity,
-                // that will take care to make it UB to leave the range, just
-                // like for transmute).
                 caller.value == callee.value,
             (layout::Abi::ScalarPair(ref caller1, ref caller2),
              layout::Abi::ScalarPair(ref callee1, ref callee2)) =>
@@ -207,22 +212,22 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
     /// Pass a single argument, checking the types for compatibility.
     fn pass_argument(
         &mut self,
-        skip_zst: bool,
+        rust_abi: bool,
         caller_arg: &mut impl Iterator<Item=OpTy<'tcx, M::PointerTag>>,
         callee_arg: PlaceTy<'tcx, M::PointerTag>,
     ) -> EvalResult<'tcx> {
-        if skip_zst && callee_arg.layout.is_zst() {
+        if rust_abi && callee_arg.layout.is_zst() {
             // Nothing to do.
             trace!("Skipping callee ZST");
             return Ok(());
         }
         let caller_arg = caller_arg.next()
             .ok_or_else(|| EvalErrorKind::FunctionArgCountMismatch)?;
-        if skip_zst {
+        if rust_abi {
             debug_assert!(!caller_arg.layout.is_zst(), "ZSTs must have been already filtered out");
         }
         // Now, check
-        if !Self::check_argument_compat(caller_arg.layout, callee_arg.layout) {
+        if !Self::check_argument_compat(rust_abi, caller_arg.layout, callee_arg.layout) {
             return err!(FunctionArgMismatch(caller_arg.layout.ty, callee_arg.layout.ty));
         }
         // We allow some transmutes here
@@ -322,7 +327,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
                     // Figure out how to pass which arguments.
                     // We have two iterators: Where the arguments come from,
                     // and where they go to.
-                    let skip_zst = match caller_abi {
+                    let rust_abi = match caller_abi {
                         Abi::Rust | Abi::RustCall => true,
                         _ => false
                     };
@@ -347,7 +352,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
                         };
                     // Skip ZSTs
                     let mut caller_iter = caller_args.iter()
-                        .filter(|op| !skip_zst || !op.layout.is_zst())
+                        .filter(|op| !rust_abi || !op.layout.is_zst())
                         .map(|op| *op);
 
                     // Now we have to spread them out across the callee's locals,
@@ -362,11 +367,11 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
                             // Must be a tuple
                             for i in 0..dest.layout.fields.count() {
                                 let dest = self.place_field(dest, i as u64)?;
-                                self.pass_argument(skip_zst, &mut caller_iter, dest)?;
+                                self.pass_argument(rust_abi, &mut caller_iter, dest)?;
                             }
                         } else {
                             // Normal argument
-                            self.pass_argument(skip_zst, &mut caller_iter, dest)?;
+                            self.pass_argument(rust_abi, &mut caller_iter, dest)?;
                         }
                     }
                     // Now we should have no more caller args
@@ -377,7 +382,11 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
                     // Don't forget to check the return type!
                     if let Some(caller_ret) = dest {
                         let callee_ret = self.eval_place(&mir::Place::Local(mir::RETURN_PLACE))?;
-                        if !Self::check_argument_compat(caller_ret.layout, callee_ret.layout) {
+                        if !Self::check_argument_compat(
+                            rust_abi,
+                            caller_ret.layout,
+                            callee_ret.layout,
+                        ) {
                             return err!(FunctionRetMismatch(
                                 caller_ret.layout.ty, callee_ret.layout.ty
                             ));

From 5c99ae6661311e42abaa590dcf592106155b3c98 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar>
Date: Sat, 24 Nov 2018 17:12:28 -0800
Subject: [PATCH 18/50] Fix ICE with feature self_struct_ctor

---
 src/librustc/middle/reachable.rs      |  1 +
 src/test/ui/issues/issue-56202.rs     | 15 +++++++++++++++
 src/test/ui/issues/issue-56202.stderr |  7 +++++++
 3 files changed, 23 insertions(+)
 create mode 100644 src/test/ui/issues/issue-56202.rs
 create mode 100644 src/test/ui/issues/issue-56202.stderr

diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs
index 0009a517dd1db..cf81729bdaba8 100644
--- a/src/librustc/middle/reachable.rs
+++ b/src/librustc/middle/reachable.rs
@@ -116,6 +116,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ReachableContext<'a, 'tcx> {
             Some(Def::Local(node_id)) | Some(Def::Upvar(node_id, ..)) => {
                 self.reachable_symbols.insert(node_id);
             }
+            Some(Def::Err) => {}  // #56202: calling `def.def_id()` would be an error
             Some(def) => {
                 let def_id = def.def_id();
                 if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) {
diff --git a/src/test/ui/issues/issue-56202.rs b/src/test/ui/issues/issue-56202.rs
new file mode 100644
index 0000000000000..c80c372c9e2ea
--- /dev/null
+++ b/src/test/ui/issues/issue-56202.rs
@@ -0,0 +1,15 @@
+#![feature(self_struct_ctor)]
+
+trait FooTrait {}
+
+trait BarTrait {
+    fn foo<T: FooTrait>(_: T) -> Self;
+}
+
+struct FooStruct(u32);
+
+impl BarTrait for FooStruct {
+    fn foo<T: FooTrait>(_: T) -> Self {
+        Self(u32::default())
+    }
+}
diff --git a/src/test/ui/issues/issue-56202.stderr b/src/test/ui/issues/issue-56202.stderr
new file mode 100644
index 0000000000000..3007b08450298
--- /dev/null
+++ b/src/test/ui/issues/issue-56202.stderr
@@ -0,0 +1,7 @@
+error[E0601]: `main` function not found in crate `issue_56202`
+   |
+   = note: consider adding a `main` function to `$DIR/issue-56202.rs`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0601`.

From 8d76f54fd8f866c2ccefb736cb084dddedd9230d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar>
Date: Sun, 25 Nov 2018 07:40:26 -0800
Subject: [PATCH 19/50] Use opt_def_id instead of having special branch

---
 src/librustc/middle/reachable.rs | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs
index cf81729bdaba8..ab0094df0e219 100644
--- a/src/librustc/middle/reachable.rs
+++ b/src/librustc/middle/reachable.rs
@@ -116,10 +116,10 @@ impl<'a, 'tcx> Visitor<'tcx> for ReachableContext<'a, 'tcx> {
             Some(Def::Local(node_id)) | Some(Def::Upvar(node_id, ..)) => {
                 self.reachable_symbols.insert(node_id);
             }
-            Some(Def::Err) => {}  // #56202: calling `def.def_id()` would be an error
             Some(def) => {
-                let def_id = def.def_id();
-                if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) {
+                if let Some((node_id, def_id)) = def.opt_def_id().and_then(|def_id| {
+                    self.tcx.hir.as_local_node_id(def_id).map(|node_id| (node_id, def_id))
+                }) {
                     if self.def_id_represents_local_inlined_item(def_id) {
                         self.worklist.push(node_id);
                     } else {

From 79ee8f329d1d3105555fd40be5b0eac56c9a8e8f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar>
Date: Sun, 25 Nov 2018 12:41:38 -0800
Subject: [PATCH 20/50] Suggest appropriate place for lifetime when declared
 after type arguments

---
 src/libsyntax/parse/parser.rs                 | 43 +++++++++++++++----
 src/test/ui/parser/issue-14303-enum.stderr    |  4 ++
 src/test/ui/parser/issue-14303-fn-def.stderr  |  4 ++
 src/test/ui/parser/issue-14303-impl.stderr    |  4 ++
 src/test/ui/parser/issue-14303-struct.stderr  |  4 ++
 src/test/ui/parser/issue-14303-trait.stderr   |  4 ++
 .../ui/suggestions/suggest-move-lifetimes.rs  | 15 +++++++
 .../suggestions/suggest-move-lifetimes.stderr | 32 ++++++++++++++
 8 files changed, 102 insertions(+), 8 deletions(-)
 create mode 100644 src/test/ui/suggestions/suggest-move-lifetimes.rs
 create mode 100644 src/test/ui/suggestions/suggest-move-lifetimes.stderr

diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index e2f09affd4fea..07e13ffc3143b 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -5178,8 +5178,10 @@ impl<'a> Parser<'a> {
     /// Parses (possibly empty) list of lifetime and type parameters, possibly including
     /// trailing comma and erroneous trailing attributes.
     crate fn parse_generic_params(&mut self) -> PResult<'a, Vec<ast::GenericParam>> {
+        let mut lifetimes = Vec::new();
         let mut params = Vec::new();
-        let mut seen_ty_param = false;
+        let mut seen_ty_param: Option<Span> = None;
+        let mut last_comma_span = None;
         loop {
             let attrs = self.parse_outer_attributes()?;
             if self.check_lifetime() {
@@ -5190,25 +5192,48 @@ impl<'a> Parser<'a> {
                 } else {
                     Vec::new()
                 };
-                params.push(ast::GenericParam {
+                lifetimes.push(ast::GenericParam {
                     ident: lifetime.ident,
                     id: lifetime.id,
                     attrs: attrs.into(),
                     bounds,
                     kind: ast::GenericParamKind::Lifetime,
                 });
-                if seen_ty_param {
-                    self.span_err(self.prev_span,
-                        "lifetime parameters must be declared prior to type parameters");
+                if let Some(sp) = seen_ty_param {
+                    let param_span = self.prev_span;
+                    let ate_comma = self.eat(&token::Comma);
+                    let remove_sp = if ate_comma {
+                        param_span.until(self.span)
+                    } else {
+                        last_comma_span.unwrap_or(param_span).to(param_span)
+                    };
+                    let mut err = self.struct_span_err(
+                        self.prev_span,
+                        "lifetime parameters must be declared prior to type parameters",
+                    );
+                    if let Ok(snippet) = self.sess.source_map().span_to_snippet(param_span) {
+                        err.multipart_suggestion(
+                            "move the lifetime parameter prior to the first type parameter",
+                            vec![
+                                (remove_sp, String::new()),
+                                (sp.shrink_to_lo(), format!("{}, ", snippet)),
+                            ],
+                        );
+                    }
+                    err.emit();
+                    if ate_comma {
+                        last_comma_span = Some(self.prev_span);
+                        continue
+                    }
                 }
             } else if self.check_ident() {
                 // Parse type parameter.
                 params.push(self.parse_ty_param(attrs)?);
-                seen_ty_param = true;
+                seen_ty_param = Some(self.prev_span);
             } else {
                 // Check for trailing attributes and stop parsing.
                 if !attrs.is_empty() {
-                    let param_kind = if seen_ty_param { "type" } else { "lifetime" };
+                    let param_kind = if seen_ty_param.is_some() { "type" } else { "lifetime" };
                     self.span_err(attrs[0].span,
                         &format!("trailing attribute after {} parameters", param_kind));
                 }
@@ -5218,8 +5243,10 @@ impl<'a> Parser<'a> {
             if !self.eat(&token::Comma) {
                 break
             }
+            last_comma_span = Some(self.prev_span);
         }
-        Ok(params)
+        lifetimes.extend(params);  // ensure the correct order of lifetimes and type params
+        Ok(lifetimes)
     }
 
     /// Parse a set of optional generic type parameter declarations. Where
diff --git a/src/test/ui/parser/issue-14303-enum.stderr b/src/test/ui/parser/issue-14303-enum.stderr
index 7d546cb2180e3..622066a94f80a 100644
--- a/src/test/ui/parser/issue-14303-enum.stderr
+++ b/src/test/ui/parser/issue-14303-enum.stderr
@@ -3,6 +3,10 @@ error: lifetime parameters must be declared prior to type parameters
    |
 LL | enum X<'a, T, 'b> {
    |               ^^
+help: move the lifetime parameter prior to the first type parameter
+   |
+LL | enum X<'a, 'b, T> {
+   |            ^^^ --
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/issue-14303-fn-def.stderr b/src/test/ui/parser/issue-14303-fn-def.stderr
index c7b57f36376b5..630c9cb40de37 100644
--- a/src/test/ui/parser/issue-14303-fn-def.stderr
+++ b/src/test/ui/parser/issue-14303-fn-def.stderr
@@ -3,6 +3,10 @@ error: lifetime parameters must be declared prior to type parameters
    |
 LL | fn foo<'a, T, 'b>(x: &'a T) {}
    |               ^^
+help: move the lifetime parameter prior to the first type parameter
+   |
+LL | fn foo<'a, 'b, T>(x: &'a T) {}
+   |            ^^^ --
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/issue-14303-impl.stderr b/src/test/ui/parser/issue-14303-impl.stderr
index 0b7016eb7f71d..2e3181de90275 100644
--- a/src/test/ui/parser/issue-14303-impl.stderr
+++ b/src/test/ui/parser/issue-14303-impl.stderr
@@ -3,6 +3,10 @@ error: lifetime parameters must be declared prior to type parameters
    |
 LL | impl<'a, T, 'b> X {}
    |             ^^
+help: move the lifetime parameter prior to the first type parameter
+   |
+LL | impl<'a, 'b, T> X {}
+   |          ^^^ --
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/issue-14303-struct.stderr b/src/test/ui/parser/issue-14303-struct.stderr
index 4a4b678919495..c6b33120c18f0 100644
--- a/src/test/ui/parser/issue-14303-struct.stderr
+++ b/src/test/ui/parser/issue-14303-struct.stderr
@@ -3,6 +3,10 @@ error: lifetime parameters must be declared prior to type parameters
    |
 LL | struct X<'a, T, 'b> {
    |                 ^^
+help: move the lifetime parameter prior to the first type parameter
+   |
+LL | struct X<'a, 'b, T> {
+   |              ^^^ --
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/parser/issue-14303-trait.stderr b/src/test/ui/parser/issue-14303-trait.stderr
index ab5cc5655bbe1..6d00f284bbbe7 100644
--- a/src/test/ui/parser/issue-14303-trait.stderr
+++ b/src/test/ui/parser/issue-14303-trait.stderr
@@ -3,6 +3,10 @@ error: lifetime parameters must be declared prior to type parameters
    |
 LL | trait Foo<'a, T, 'b> {}
    |                  ^^
+help: move the lifetime parameter prior to the first type parameter
+   |
+LL | trait Foo<'a, 'b, T> {}
+   |               ^^^ --
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/suggestions/suggest-move-lifetimes.rs b/src/test/ui/suggestions/suggest-move-lifetimes.rs
new file mode 100644
index 0000000000000..be6d29d933763
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-move-lifetimes.rs
@@ -0,0 +1,15 @@
+struct A<T, 'a> {
+    t: &'a T,
+}
+
+struct B<T, 'a, U> {
+    t: &'a T,
+    u: U,
+}
+
+struct C<T, U, 'a> {
+    t: &'a T,
+    u: U,
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/suggest-move-lifetimes.stderr b/src/test/ui/suggestions/suggest-move-lifetimes.stderr
new file mode 100644
index 0000000000000..57e6780b35984
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-move-lifetimes.stderr
@@ -0,0 +1,32 @@
+error: lifetime parameters must be declared prior to type parameters
+  --> $DIR/suggest-move-lifetimes.rs:1:13
+   |
+LL | struct A<T, 'a> {
+   |             ^^
+help: move the lifetime parameter prior to the first type parameter
+   |
+LL | struct A<'a, T> {
+   |          ^^^ --
+
+error: lifetime parameters must be declared prior to type parameters
+  --> $DIR/suggest-move-lifetimes.rs:5:15
+   |
+LL | struct B<T, 'a, U> {
+   |               ^
+help: move the lifetime parameter prior to the first type parameter
+   |
+LL | struct B<'a, T, U> {
+   |          ^^^   --
+
+error: lifetime parameters must be declared prior to type parameters
+  --> $DIR/suggest-move-lifetimes.rs:10:16
+   |
+LL | struct C<T, U, 'a> {
+   |                ^^
+help: move the lifetime parameter prior to the first type parameter
+   |
+LL | struct C<T, 'a, U> {
+   |             ^^^ --
+
+error: aborting due to 3 previous errors
+

From 234d043d18175aff37200a91df2a1b7c3064fc80 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar>
Date: Sun, 25 Nov 2018 12:46:42 -0800
Subject: [PATCH 21/50] Move lifetimes before the *first* type argument

---
 src/libsyntax/parse/parser.rs                         | 4 +++-
 src/test/ui/suggestions/suggest-move-lifetimes.stderr | 4 ++--
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 07e13ffc3143b..1fdf86d48670b 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -5229,7 +5229,9 @@ impl<'a> Parser<'a> {
             } else if self.check_ident() {
                 // Parse type parameter.
                 params.push(self.parse_ty_param(attrs)?);
-                seen_ty_param = Some(self.prev_span);
+                if seen_ty_param.is_none() {
+                    seen_ty_param = Some(self.prev_span);
+                }
             } else {
                 // Check for trailing attributes and stop parsing.
                 if !attrs.is_empty() {
diff --git a/src/test/ui/suggestions/suggest-move-lifetimes.stderr b/src/test/ui/suggestions/suggest-move-lifetimes.stderr
index 57e6780b35984..fa1cfe66ab530 100644
--- a/src/test/ui/suggestions/suggest-move-lifetimes.stderr
+++ b/src/test/ui/suggestions/suggest-move-lifetimes.stderr
@@ -25,8 +25,8 @@ LL | struct C<T, U, 'a> {
    |                ^^
 help: move the lifetime parameter prior to the first type parameter
    |
-LL | struct C<T, 'a, U> {
-   |             ^^^ --
+LL | struct C<'a, T, U> {
+   |          ^^^    --
 
 error: aborting due to 3 previous errors
 

From db8540e746ef3d2532c820d02a77f0111fda09fb Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote <nnethercote@mozilla.com>
Date: Wed, 21 Nov 2018 22:03:59 +1100
Subject: [PATCH 22/50] Avoid a useless `FxHashSet::insert` in
 `FileSearch::for_each_lib_search_path`.

---
 src/librustc/session/filesearch.rs | 2 --
 1 file changed, 2 deletions(-)

diff --git a/src/librustc/session/filesearch.rs b/src/librustc/session/filesearch.rs
index f410c270bcef9..2b84317b3d6dd 100644
--- a/src/librustc/session/filesearch.rs
+++ b/src/librustc/session/filesearch.rs
@@ -53,8 +53,6 @@ impl<'a> FileSearch<'a> {
         if !visited_dirs.contains(&tlib_path) {
             f(&tlib_path, PathKind::All);
         }
-
-        visited_dirs.insert(tlib_path);
     }
 
     pub fn get_lib_path(&self) -> PathBuf {

From 145e2abc069b27c28ee6c32ddb8b6d2851fa5fd7 Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote <nnethercote@mozilla.com>
Date: Thu, 22 Nov 2018 15:49:48 +1100
Subject: [PATCH 23/50] Remove `Session::sysroot()`.

Instead of maybe storing its own sysroot and maybe deferring to the one
in `Session::opts`, just clone the latter when necessary so one is
always directly available. This removes the need for the getter.
---
 src/librustc/session/mod.rs             | 24 ++++++++----------------
 src/librustc_codegen_llvm/back/link.rs  |  3 +--
 src/librustc_codegen_ssa/back/linker.rs |  3 +--
 src/librustc_driver/lib.rs              |  2 +-
 src/librustc_metadata/locator.rs        |  2 +-
 5 files changed, 12 insertions(+), 22 deletions(-)

diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index 1187c53305d1c..79441eec3922f 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -48,7 +48,7 @@ use std::cell::{self, Cell, RefCell};
 use std::env;
 use std::fmt;
 use std::io::Write;
-use std::path::{Path, PathBuf};
+use std::path::PathBuf;
 use std::time::Duration;
 use std::sync::mpsc;
 use std::sync::atomic::{AtomicUsize, Ordering};
@@ -69,7 +69,7 @@ pub struct Session {
     pub entry_fn: Once<Option<(NodeId, Span, config::EntryFnType)>>,
     pub plugin_registrar_fn: Once<Option<ast::NodeId>>,
     pub derive_registrar_fn: Once<Option<ast::NodeId>>,
-    pub default_sysroot: Option<PathBuf>,
+    pub sysroot: PathBuf,
     /// The name of the root source file of the crate, in the local file system.
     /// `None` means that there is no source file.
     pub local_crate_source_file: Option<PathBuf>,
@@ -694,17 +694,9 @@ impl Session {
         )
     }
 
-    pub fn sysroot<'a>(&'a self) -> &'a Path {
-        match self.opts.maybe_sysroot {
-            Some(ref sysroot) => sysroot,
-            None => self.default_sysroot
-                        .as_ref()
-                        .expect("missing sysroot and default_sysroot in Session"),
-        }
-    }
     pub fn target_filesearch(&self, kind: PathKind) -> filesearch::FileSearch<'_> {
         filesearch::FileSearch::new(
-            self.sysroot(),
+            &self.sysroot,
             self.opts.target_triple.triple(),
             &self.opts.search_paths,
             kind,
@@ -712,7 +704,7 @@ impl Session {
     }
     pub fn host_filesearch(&self, kind: PathKind) -> filesearch::FileSearch<'_> {
         filesearch::FileSearch::new(
-            self.sysroot(),
+            &self.sysroot,
             config::host_triple(),
             &self.opts.search_paths,
             kind,
@@ -1109,9 +1101,9 @@ pub fn build_session_(
     let target_cfg = config::build_target_config(&sopts, &span_diagnostic);
 
     let p_s = parse::ParseSess::with_span_handler(span_diagnostic, source_map);
-    let default_sysroot = match sopts.maybe_sysroot {
-        Some(_) => None,
-        None => Some(filesearch::get_or_default_sysroot()),
+    let sysroot = match &sopts.maybe_sysroot {
+        Some(sysroot) => sysroot.clone(),
+        None => filesearch::get_or_default_sysroot(),
     };
 
     let file_path_mapping = sopts.file_path_mapping();
@@ -1147,7 +1139,7 @@ pub fn build_session_(
         entry_fn: Once::new(),
         plugin_registrar_fn: Once::new(),
         derive_registrar_fn: Once::new(),
-        default_sysroot,
+        sysroot,
         local_crate_source_file,
         working_dir,
         lint_store: RwLock::new(lint::LintStore::new()),
diff --git a/src/librustc_codegen_llvm/back/link.rs b/src/librustc_codegen_llvm/back/link.rs
index 89d84acdd8876..60dc1a72a3295 100644
--- a/src/librustc_codegen_llvm/back/link.rs
+++ b/src/librustc_codegen_llvm/back/link.rs
@@ -1024,11 +1024,10 @@ fn link_args(cmd: &mut dyn Linker,
     // where extern libraries might live, based on the
     // addl_lib_search_paths
     if sess.opts.cg.rpath {
-        let sysroot = sess.sysroot();
         let target_triple = sess.opts.target_triple.triple();
         let mut get_install_prefix_lib_path = || {
             let install_prefix = option_env!("CFG_PREFIX").expect("CFG_PREFIX");
-            let tlib = filesearch::relative_target_lib_path(sysroot, target_triple);
+            let tlib = filesearch::relative_target_lib_path(&sess.sysroot, target_triple);
             let mut path = PathBuf::from(install_prefix);
             path.push(&tlib);
 
diff --git a/src/librustc_codegen_ssa/back/linker.rs b/src/librustc_codegen_ssa/back/linker.rs
index ec5ca5801049e..c15ac12401582 100644
--- a/src/librustc_codegen_ssa/back/linker.rs
+++ b/src/librustc_codegen_ssa/back/linker.rs
@@ -606,8 +606,7 @@ impl<'a> Linker for MsvcLinker<'a> {
         self.cmd.arg("/DEBUG");
 
         // This will cause the Microsoft linker to embed .natvis info into the PDB file
-        let sysroot = self.sess.sysroot();
-        let natvis_dir_path = sysroot.join("lib\\rustlib\\etc");
+        let natvis_dir_path = self.sess.sysroot.join("lib\\rustlib\\etc");
         if let Ok(natvis_dir) = fs::read_dir(&natvis_dir_path) {
             // LLVM 5.0.0's lld-link frontend doesn't yet recognize, and chokes
             // on, the /NATVIS:... flags.  LLVM 6 (or earlier) should at worst ignore
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index ec3cb95db88f8..960cdcb1a95b1 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -1042,7 +1042,7 @@ impl RustcDefaultCalls {
                     targets.sort();
                     println!("{}", targets.join("\n"));
                 },
-                Sysroot => println!("{}", sess.sysroot().display()),
+                Sysroot => println!("{}", sess.sysroot.display()),
                 TargetSpec => println!("{}", sess.target.target.to_json().pretty()),
                 FileNames | CrateName => {
                     let input = input.unwrap_or_else(||
diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs
index 528c96f240dba..f58cc00477789 100644
--- a/src/librustc_metadata/locator.rs
+++ b/src/librustc_metadata/locator.rs
@@ -678,7 +678,7 @@ impl<'a> Context<'a> {
             // candidates are all canonicalized, so we canonicalize the sysroot
             // as well.
             if let Some((ref prev, _)) = ret {
-                let sysroot = self.sess.sysroot();
+                let sysroot = &self.sess.sysroot;
                 let sysroot = sysroot.canonicalize()
                                      .unwrap_or_else(|_| sysroot.to_path_buf());
                 if prev.starts_with(&sysroot) {

From 057e6d3a35a54e8b88c2cef1e6a1b9e590066276 Mon Sep 17 00:00:00 2001
From: Simon Sapin <simon.sapin@exyr.org>
Date: Sun, 25 Nov 2018 17:33:16 +0100
Subject: [PATCH 24/50] Add TryFrom<&[T]> for [T; $N] where T: Copy

`TryFrom<&[T]> for &[T; $N]` (note *reference* to an array) already exists,
but not needing to dereference makes type inference easier
for example when using `u32::from_be_bytes`.

Also add doc examples doing just that.
---
 src/libcore/array.rs   |  9 +++++
 src/libcore/num/mod.rs | 78 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 87 insertions(+)

diff --git a/src/libcore/array.rs b/src/libcore/array.rs
index 3d24f8902bd83..26e7a79d35df6 100644
--- a/src/libcore/array.rs
+++ b/src/libcore/array.rs
@@ -148,6 +148,15 @@ macro_rules! array_impls {
                 }
             }
 
+            #[unstable(feature = "try_from", issue = "33417")]
+            impl<'a, T> TryFrom<&'a [T]> for [T; $N] where T: Copy {
+                type Error = TryFromSliceError;
+
+                fn try_from(slice: &[T]) -> Result<[T; $N], TryFromSliceError> {
+                    <&Self>::try_from(slice).map(|r| *r)
+                }
+            }
+
             #[unstable(feature = "try_from", issue = "33417")]
             impl<'a, T> TryFrom<&'a [T]> for &'a [T; $N] {
                 type Error = TryFromSliceError;
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index 9deae12482976..f6f649bc06d01 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -1989,6 +1989,19 @@ big endian.
 ```
 let value = ", stringify!($SelfT), "::from_be_bytes(", $be_bytes, ");
 assert_eq!(value, ", $swap_op, ");
+```
+
+When starting from a slice rather than an array, fallible conversion APIs can be used:
+
+```
+#![feature(try_from)]
+use std::convert::TryInto;
+
+fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " {
+    let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">());
+    *input = rest;
+    ", stringify!($SelfT), "::from_be_bytes(int_bytes.try_into().unwrap())
+}
 ```"),
             #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
             #[rustc_const_unstable(feature = "const_int_conversion")]
@@ -2008,6 +2021,19 @@ little endian.
 ```
 let value = ", stringify!($SelfT), "::from_le_bytes(", $le_bytes, ");
 assert_eq!(value, ", $swap_op, ");
+```
+
+When starting from a slice rather than an array, fallible conversion APIs can be used:
+
+```
+#![feature(try_from)]
+use std::convert::TryInto;
+
+fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " {
+    let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">());
+    *input = rest;
+    ", stringify!($SelfT), "::from_be_bytes(int_bytes.try_into().unwrap())
+}
 ```"),
             #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
             #[rustc_const_unstable(feature = "const_int_conversion")]
@@ -2037,6 +2063,19 @@ let value = ", stringify!($SelfT), "::from_ne_bytes(if cfg!(target_endian = \"bi
         ", $le_bytes, "
     });
 assert_eq!(value, ", $swap_op, ");
+```
+
+When starting from a slice rather than an array, fallible conversion APIs can be used:
+
+```
+#![feature(try_from)]
+use std::convert::TryInto;
+
+fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " {
+    let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">());
+    *input = rest;
+    ", stringify!($SelfT), "::from_be_bytes(int_bytes.try_into().unwrap())
+}
 ```"),
             #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
             #[rustc_const_unstable(feature = "const_int_conversion")]
@@ -3719,6 +3758,19 @@ big endian.
 ```
 let value = ", stringify!($SelfT), "::from_be_bytes(", $be_bytes, ");
 assert_eq!(value, ", $swap_op, ");
+```
+
+When starting from a slice rather than an array, fallible conversion APIs can be used:
+
+```
+#![feature(try_from)]
+use std::convert::TryInto;
+
+fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " {
+    let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">());
+    *input = rest;
+    ", stringify!($SelfT), "::from_be_bytes(int_bytes.try_into().unwrap())
+}
 ```"),
             #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
             #[rustc_const_unstable(feature = "const_int_conversion")]
@@ -3738,6 +3790,19 @@ little endian.
 ```
 let value = ", stringify!($SelfT), "::from_le_bytes(", $le_bytes, ");
 assert_eq!(value, ", $swap_op, ");
+```
+
+When starting from a slice rather than an array, fallible conversion APIs can be used:
+
+```
+#![feature(try_from)]
+use std::convert::TryInto;
+
+fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " {
+    let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">());
+    *input = rest;
+    ", stringify!($SelfT), "::from_be_bytes(int_bytes.try_into().unwrap())
+}
 ```"),
             #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
             #[rustc_const_unstable(feature = "const_int_conversion")]
@@ -3767,6 +3832,19 @@ let value = ", stringify!($SelfT), "::from_ne_bytes(if cfg!(target_endian = \"bi
         ", $le_bytes, "
     });
 assert_eq!(value, ", $swap_op, ");
+```
+
+When starting from a slice rather than an array, fallible conversion APIs can be used:
+
+```
+#![feature(try_from)]
+use std::convert::TryInto;
+
+fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), " {
+    let (int_bytes, rest) = input.split_at(std::mem::size_of::<", stringify!($SelfT), ">());
+    *input = rest;
+    ", stringify!($SelfT), "::from_be_bytes(int_bytes.try_into().unwrap())
+}
 ```"),
             #[stable(feature = "int_to_from_bytes", since = "1.32.0")]
             #[rustc_const_unstable(feature = "const_int_conversion")]

From 8e75844d95284599d6ea3c43cb1bb82e9292ebe7 Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote <nnethercote@mozilla.com>
Date: Thu, 22 Nov 2018 16:33:07 +1100
Subject: [PATCH 25/50] Introduce `SearchPath` and replace `SearchPaths` with
 `Vec<SearchPath>`.

It's more idiomatic, makes the code shorter, and will help with the next
commit.
---
 src/librustc/session/config.rs         | 51 ++++++++++++-----------
 src/librustc/session/filesearch.rs     | 33 +++++++--------
 src/librustc/session/search_paths.rs   | 57 +++++++++-----------------
 src/librustc_codegen_llvm/back/link.rs | 12 +++---
 src/librustdoc/config.rs               | 11 +++--
 src/librustdoc/core.rs                 |  2 +-
 src/librustdoc/test.rs                 |  8 ++--
 7 files changed, 79 insertions(+), 95 deletions(-)

diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index 3fd22793a08a0..c5799d9130256 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -14,7 +14,7 @@
 use std::str::FromStr;
 
 use session::{early_error, early_warn, Session};
-use session::search_paths::SearchPaths;
+use session::search_paths::SearchPath;
 
 use rustc_target::spec::{LinkerFlavor, PanicStrategy, RelroLevel};
 use rustc_target::spec::{Target, TargetTriple};
@@ -374,7 +374,7 @@ top_level_options!(
         lint_cap: Option<lint::Level> [TRACKED],
         describe_lints: bool [UNTRACKED],
         output_types: OutputTypes [TRACKED],
-        search_paths: SearchPaths [UNTRACKED],
+        search_paths: Vec<SearchPath> [UNTRACKED],
         libs: Vec<(String, Option<String>, Option<cstore::NativeLibraryKind>)> [TRACKED],
         maybe_sysroot: Option<PathBuf> [TRACKED],
 
@@ -593,7 +593,7 @@ impl Default for Options {
             lint_cap: None,
             describe_lints: false,
             output_types: OutputTypes(BTreeMap::new()),
-            search_paths: SearchPaths::new(),
+            search_paths: vec![],
             maybe_sysroot: None,
             target_triple: TargetTriple::from_triple(host_triple()),
             test: false,
@@ -2112,9 +2112,9 @@ pub fn build_session_options_and_crate_config(
         }
     };
 
-    let mut search_paths = SearchPaths::new();
+    let mut search_paths = vec![];
     for s in &matches.opt_strs("L") {
-        search_paths.add_path(&s[..], error_format);
+        search_paths.push(SearchPath::from_cli_opt(&s[..], error_format));
     }
 
     let libs = matches
@@ -2532,6 +2532,7 @@ mod tests {
     use session::config::{build_configuration, build_session_options_and_crate_config};
     use session::config::{LtoCli, CrossLangLto};
     use session::build_session;
+    use session::search_paths::SearchPath;
     use std::collections::{BTreeMap, BTreeSet};
     use std::iter::FromIterator;
     use std::path::PathBuf;
@@ -2787,48 +2788,48 @@ mod tests {
 
         // Reference
         v1.search_paths
-            .add_path("native=abc", super::ErrorOutputType::Json(false));
+            .push(SearchPath::from_cli_opt("native=abc", super::ErrorOutputType::Json(false)));
         v1.search_paths
-            .add_path("crate=def", super::ErrorOutputType::Json(false));
+            .push(SearchPath::from_cli_opt("crate=def", super::ErrorOutputType::Json(false)));
         v1.search_paths
-            .add_path("dependency=ghi", super::ErrorOutputType::Json(false));
+            .push(SearchPath::from_cli_opt("dependency=ghi", super::ErrorOutputType::Json(false)));
         v1.search_paths
-            .add_path("framework=jkl", super::ErrorOutputType::Json(false));
+            .push(SearchPath::from_cli_opt("framework=jkl", super::ErrorOutputType::Json(false)));
         v1.search_paths
-            .add_path("all=mno", super::ErrorOutputType::Json(false));
+            .push(SearchPath::from_cli_opt("all=mno", super::ErrorOutputType::Json(false)));
 
         v2.search_paths
-            .add_path("native=abc", super::ErrorOutputType::Json(false));
+            .push(SearchPath::from_cli_opt("native=abc", super::ErrorOutputType::Json(false)));
         v2.search_paths
-            .add_path("dependency=ghi", super::ErrorOutputType::Json(false));
+            .push(SearchPath::from_cli_opt("dependency=ghi", super::ErrorOutputType::Json(false)));
         v2.search_paths
-            .add_path("crate=def", super::ErrorOutputType::Json(false));
+            .push(SearchPath::from_cli_opt("crate=def", super::ErrorOutputType::Json(false)));
         v2.search_paths
-            .add_path("framework=jkl", super::ErrorOutputType::Json(false));
+            .push(SearchPath::from_cli_opt("framework=jkl", super::ErrorOutputType::Json(false)));
         v2.search_paths
-            .add_path("all=mno", super::ErrorOutputType::Json(false));
+            .push(SearchPath::from_cli_opt("all=mno", super::ErrorOutputType::Json(false)));
 
         v3.search_paths
-            .add_path("crate=def", super::ErrorOutputType::Json(false));
+            .push(SearchPath::from_cli_opt("crate=def", super::ErrorOutputType::Json(false)));
         v3.search_paths
-            .add_path("framework=jkl", super::ErrorOutputType::Json(false));
+            .push(SearchPath::from_cli_opt("framework=jkl", super::ErrorOutputType::Json(false)));
         v3.search_paths
-            .add_path("native=abc", super::ErrorOutputType::Json(false));
+            .push(SearchPath::from_cli_opt("native=abc", super::ErrorOutputType::Json(false)));
         v3.search_paths
-            .add_path("dependency=ghi", super::ErrorOutputType::Json(false));
+            .push(SearchPath::from_cli_opt("dependency=ghi", super::ErrorOutputType::Json(false)));
         v3.search_paths
-            .add_path("all=mno", super::ErrorOutputType::Json(false));
+            .push(SearchPath::from_cli_opt("all=mno", super::ErrorOutputType::Json(false)));
 
         v4.search_paths
-            .add_path("all=mno", super::ErrorOutputType::Json(false));
+            .push(SearchPath::from_cli_opt("all=mno", super::ErrorOutputType::Json(false)));
         v4.search_paths
-            .add_path("native=abc", super::ErrorOutputType::Json(false));
+            .push(SearchPath::from_cli_opt("native=abc", super::ErrorOutputType::Json(false)));
         v4.search_paths
-            .add_path("crate=def", super::ErrorOutputType::Json(false));
+            .push(SearchPath::from_cli_opt("crate=def", super::ErrorOutputType::Json(false)));
         v4.search_paths
-            .add_path("dependency=ghi", super::ErrorOutputType::Json(false));
+            .push(SearchPath::from_cli_opt("dependency=ghi", super::ErrorOutputType::Json(false)));
         v4.search_paths
-            .add_path("framework=jkl", super::ErrorOutputType::Json(false));
+            .push(SearchPath::from_cli_opt("framework=jkl", super::ErrorOutputType::Json(false)));
 
         assert!(v1.dep_tracking_hash() == v2.dep_tracking_hash());
         assert!(v1.dep_tracking_hash() == v3.dep_tracking_hash());
diff --git a/src/librustc/session/filesearch.rs b/src/librustc/session/filesearch.rs
index 2b84317b3d6dd..d9abbe6cf6925 100644
--- a/src/librustc/session/filesearch.rs
+++ b/src/librustc/session/filesearch.rs
@@ -18,7 +18,7 @@ use std::env;
 use std::fs;
 use std::path::{Path, PathBuf};
 
-use session::search_paths::{SearchPaths, PathKind};
+use session::search_paths::{SearchPath, PathKind};
 use rustc_fs_util::fix_windows_verbatim_for_gcc;
 
 #[derive(Copy, Clone)]
@@ -31,27 +31,28 @@ pub enum FileMatch {
 
 pub struct FileSearch<'a> {
     pub sysroot: &'a Path,
-    pub search_paths: &'a SearchPaths,
+    pub search_paths: &'a [SearchPath],
     pub triple: &'a str,
     pub kind: PathKind,
 }
 
 impl<'a> FileSearch<'a> {
     pub fn for_each_lib_search_path<F>(&self, mut f: F) where
-        F: FnMut(&Path, PathKind)
+        F: FnMut(&SearchPath)
     {
         let mut visited_dirs = FxHashSet::default();
-        visited_dirs.reserve(self.search_paths.paths.len() + 1);
-        for (path, kind) in self.search_paths.iter(self.kind) {
-            f(path, kind);
-            visited_dirs.insert(path.to_path_buf());
+        visited_dirs.reserve(self.search_paths.len() + 1);
+        let iter = self.search_paths.iter().filter(|sp| sp.kind.matches(self.kind));
+        for search_path in iter {
+            f(search_path);
+            visited_dirs.insert(search_path.dir.to_path_buf());
         }
 
         debug!("filesearch: searching lib path");
         let tlib_path = make_target_lib_path(self.sysroot,
                                              self.triple);
         if !visited_dirs.contains(&tlib_path) {
-            f(&tlib_path, PathKind::All);
+            f(&SearchPath { kind: PathKind::All, dir: tlib_path });
         }
     }
 
@@ -62,9 +63,9 @@ impl<'a> FileSearch<'a> {
     pub fn search<F>(&self, mut pick: F)
         where F: FnMut(&Path, PathKind) -> FileMatch
     {
-        self.for_each_lib_search_path(|lib_search_path, kind| {
-            debug!("searching {}", lib_search_path.display());
-            let files = match fs::read_dir(lib_search_path) {
+        self.for_each_lib_search_path(|search_path| {
+            debug!("searching {}", search_path.dir.display());
+            let files = match fs::read_dir(&search_path.dir) {
                 Ok(files) => files,
                 Err(..) => return,
             };
@@ -81,7 +82,7 @@ impl<'a> FileSearch<'a> {
             let files2 = files.iter().filter(|p| !is_rlib(p));
             for path in files1.chain(files2) {
                 debug!("testing {}", path.display());
-                let maybe_picked = pick(path, kind);
+                let maybe_picked = pick(path, search_path.kind);
                 match maybe_picked {
                     FileMatches => {
                         debug!("picked {}", path.display());
@@ -96,7 +97,7 @@ impl<'a> FileSearch<'a> {
 
     pub fn new(sysroot: &'a Path,
                triple: &'a str,
-               search_paths: &'a SearchPaths,
+               search_paths: &'a Vec<SearchPath>,
                kind: PathKind) -> FileSearch<'a> {
         debug!("using sysroot = {}, triple = {}", sysroot.display(), triple);
         FileSearch {
@@ -110,8 +111,8 @@ impl<'a> FileSearch<'a> {
     // Returns a list of directories where target-specific dylibs might be located.
     pub fn get_dylib_search_paths(&self) -> Vec<PathBuf> {
         let mut paths = Vec::new();
-        self.for_each_lib_search_path(|lib_search_path, _| {
-            paths.push(lib_search_path.to_path_buf());
+        self.for_each_lib_search_path(|search_path| {
+            paths.push(search_path.dir.to_path_buf());
         });
         paths
     }
@@ -136,7 +137,7 @@ pub fn relative_target_lib_path(sysroot: &Path, target_triple: &str) -> PathBuf
     p
 }
 
-fn make_target_lib_path(sysroot: &Path,
+pub fn make_target_lib_path(sysroot: &Path,
                         target_triple: &str) -> PathBuf {
     sysroot.join(&relative_target_lib_path(sysroot, target_triple))
 }
diff --git a/src/librustc/session/search_paths.rs b/src/librustc/session/search_paths.rs
index 768d4f1e5fb65..7a0bd2ed439b2 100644
--- a/src/librustc/session/search_paths.rs
+++ b/src/librustc/session/search_paths.rs
@@ -8,18 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::slice;
 use std::path::{Path, PathBuf};
 use session::{early_error, config};
+use session::filesearch::make_target_lib_path;
 
 #[derive(Clone, Debug)]
-pub struct SearchPaths {
-    crate paths: Vec<(PathKind, PathBuf)>,
-}
-
-pub struct Iter<'a> {
-    kind: PathKind,
-    iter: slice::Iter<'a, (PathKind, PathBuf)>,
+pub struct SearchPath {
+    pub kind: PathKind,
+    pub dir: PathBuf,
 }
 
 #[derive(Eq, PartialEq, Clone, Copy, Debug, PartialOrd, Ord, Hash)]
@@ -32,12 +28,17 @@ pub enum PathKind {
     All,
 }
 
-impl SearchPaths {
-    pub fn new() -> SearchPaths {
-        SearchPaths { paths: Vec::new() }
+impl PathKind {
+    pub fn matches(&self, kind: PathKind) -> bool {
+        match (self, kind) {
+            (PathKind::All, _) | (_, PathKind::All) => true,
+            _ => *self == kind,
+        }
     }
+}
 
-    pub fn add_path(&mut self, path: &str, output: config::ErrorOutputType) {
+impl SearchPath {
+    pub fn from_cli_opt(path: &str, output: config::ErrorOutputType) -> Self {
         let (kind, path) = if path.starts_with("native=") {
             (PathKind::Native, &path["native=".len()..])
         } else if path.starts_with("crate=") {
@@ -54,35 +55,17 @@ impl SearchPaths {
         if path.is_empty() {
             early_error(output, "empty search path given via `-L`");
         }
-        self.paths.push((kind, PathBuf::from(path)));
-    }
 
-    pub fn iter(&self, kind: PathKind) -> Iter<'_> {
-        Iter { kind: kind, iter: self.paths.iter() }
+        let dir = PathBuf::from(path);
+        Self::new(kind, dir)
     }
-}
-
-impl<'a> Iterator for Iter<'a> {
-    type Item = (&'a Path, PathKind);
 
-    fn next(&mut self) -> Option<(&'a Path, PathKind)> {
-        loop {
-            match self.iter.next() {
-                Some(&(kind, ref p)) if self.kind == PathKind::All ||
-                                        kind == PathKind::All ||
-                                        kind == self.kind => {
-                    return Some((p, kind))
-                }
-                Some(..) => {}
-                None => return None,
-            }
-        }
+    pub fn from_sysroot_and_triple(sysroot: &Path, triple: &str) -> Self {
+        Self::new(PathKind::All, make_target_lib_path(sysroot, triple))
     }
 
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        // This iterator will never return more elements than the base iterator;
-        // but it can ignore all the remaining elements.
-        let (_, upper) = self.iter.size_hint();
-        (0, upper)
+    fn new(kind: PathKind, dir: PathBuf) -> Self {
+        SearchPath { kind, dir }
     }
 }
+
diff --git a/src/librustc_codegen_llvm/back/link.rs b/src/librustc_codegen_llvm/back/link.rs
index 60dc1a72a3295..392e3ff3a8812 100644
--- a/src/librustc_codegen_llvm/back/link.rs
+++ b/src/librustc_codegen_llvm/back/link.rs
@@ -213,8 +213,8 @@ fn link_binary_output(sess: &Session,
 
 fn archive_search_paths(sess: &Session) -> Vec<PathBuf> {
     let mut search = Vec::new();
-    sess.target_filesearch(PathKind::Native).for_each_lib_search_path(|path, _| {
-        search.push(path.to_path_buf());
+    sess.target_filesearch(PathKind::Native).for_each_lib_search_path(|search_path| {
+        search.push(search_path.dir.to_path_buf());
     });
 
     search
@@ -1067,10 +1067,10 @@ fn link_args(cmd: &mut dyn Linker,
 fn add_local_native_libraries(cmd: &mut dyn Linker,
                               sess: &Session,
                               codegen_results: &CodegenResults) {
-    sess.target_filesearch(PathKind::All).for_each_lib_search_path(|path, k| {
-        match k {
-            PathKind::Framework => { cmd.framework_path(path); }
-            _ => { cmd.include_path(&fix_windows_verbatim_for_gcc(path)); }
+    sess.target_filesearch(PathKind::All).for_each_lib_search_path(|search_path| {
+        match search_path.kind {
+            PathKind::Framework => { cmd.framework_path(&search_path.dir); }
+            _ => { cmd.include_path(&fix_windows_verbatim_for_gcc(&search_path.dir)); }
         }
     });
 
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index f4d05c6dbd65c..b421f07ddafa2 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -20,7 +20,7 @@ use rustc::session::early_error;
 use rustc::session::config::{CodegenOptions, DebuggingOptions, ErrorOutputType, Externs};
 use rustc::session::config::{nightly_options, build_codegen_options, build_debugging_options,
                              get_cmd_lint_options};
-use rustc::session::search_paths::SearchPaths;
+use rustc::session::search_paths::SearchPath;
 use rustc_driver;
 use rustc_target::spec::TargetTriple;
 use syntax::edition::Edition;
@@ -46,7 +46,7 @@ pub struct Options {
     /// How to format errors and warnings.
     pub error_format: ErrorOutputType,
     /// Library search paths to hand to the compiler.
-    pub libs: SearchPaths,
+    pub libs: Vec<SearchPath>,
     /// The list of external crates to link against.
     pub externs: Externs,
     /// List of `cfg` flags to hand to the compiler. Always includes `rustdoc`.
@@ -295,10 +295,9 @@ impl Options {
         }
         let input = PathBuf::from(&matches.free[0]);
 
-        let mut libs = SearchPaths::new();
-        for s in &matches.opt_strs("L") {
-            libs.add_path(s, error_format);
-        }
+        let libs = matches.opt_strs("L").iter()
+            .map(|s| SearchPath::from_cli_opt(s, error_format))
+            .collect();
         let externs = match parse_externs(&matches) {
             Ok(ex) => ex,
             Err(err) => {
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index aac0f9f94e329..9502993ed243c 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -51,7 +51,7 @@ use html::render::RenderInfo;
 use passes;
 
 pub use rustc::session::config::{Input, Options, CodegenOptions};
-pub use rustc::session::search_paths::SearchPaths;
+pub use rustc::session::search_paths::SearchPath;
 
 pub type ExternalPaths = FxHashMap<DefId, (Vec<String>, clean::TypeKind)>;
 
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index d9bab91fd0c78..918fdc1f38a48 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -25,7 +25,7 @@ use rustc::hir;
 use rustc::hir::intravisit;
 use rustc::session::{self, CompileIncomplete, config};
 use rustc::session::config::{OutputType, OutputTypes, Externs, CodegenOptions};
-use rustc::session::search_paths::{SearchPaths, PathKind};
+use rustc::session::search_paths::{SearchPath, PathKind};
 use rustc_metadata::dynamic_lib::DynamicLibrary;
 use tempfile::Builder as TempFileBuilder;
 use rustc_driver::{self, driver, target_features, Compilation};
@@ -187,7 +187,7 @@ fn scrape_test_config(krate: &::rustc::hir::Crate) -> TestOptions {
 }
 
 fn run_test(test: &str, cratename: &str, filename: &FileName, line: usize,
-            cfgs: Vec<String>, libs: SearchPaths,
+            cfgs: Vec<String>, libs: Vec<SearchPath>,
             cg: CodegenOptions, externs: Externs,
             should_panic: bool, no_run: bool, as_test_harness: bool,
             compile_fail: bool, mut error_codes: Vec<String>, opts: &TestOptions,
@@ -557,7 +557,7 @@ pub struct Collector {
     names: Vec<String>,
 
     cfgs: Vec<String>,
-    libs: SearchPaths,
+    libs: Vec<SearchPath>,
     cg: CodegenOptions,
     externs: Externs,
     use_headers: bool,
@@ -572,7 +572,7 @@ pub struct Collector {
 }
 
 impl Collector {
-    pub fn new(cratename: String, cfgs: Vec<String>, libs: SearchPaths, cg: CodegenOptions,
+    pub fn new(cratename: String, cfgs: Vec<String>, libs: Vec<SearchPath>, cg: CodegenOptions,
                externs: Externs, use_headers: bool, opts: TestOptions,
                maybe_sysroot: Option<PathBuf>, source_map: Option<Lrc<SourceMap>>,
                filename: Option<PathBuf>, linker: Option<PathBuf>, edition: Edition) -> Collector {

From ca82a8238520de6add93e9bd6d8a56935b88931d Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote <nnethercote@mozilla.com>
Date: Tue, 20 Nov 2018 11:06:45 +1100
Subject: [PATCH 26/50] Avoid regenerating the `Vec<PathBuf>` in
 `FileSearch::search()`.

`FileSearch::search()` traverses one or more directories. For each
directory it generates a `Vec<PathBuf>` containing one element per file
in that directory.

In some benchmarks this occurs enough that the allocations done for the
`PathBuf`s are significant, and in practice a small number of
directories are being traversed over and over again. For example, when
compiling the `tokio-webpush-simple` benchmark, two directories are
traversed 58 times each. Each of these directories have more than 100
files.

This commit changes things so that all the `Vec<PathBuf>`s that will be
needed by a `Session` are precomputed when that `Session` is created;
they are stored in `SearchPath`. `FileSearch` gets a reference to the
necessary `SearchPath`s. This reduces instruction counts on several
benchmarks by 1--5%.

The commit also removes the barely-used `visited_dirs` hash in
`for_each_lib_searchPath`. It only detects if `tlib_path` is the same as
one of the previously seen paths, which is unlikely.
---
 src/librustc/session/filesearch.rs   | 34 +++++++++-------------------
 src/librustc/session/mod.rs          | 19 +++++++++++++++-
 src/librustc/session/search_paths.rs | 14 +++++++++++-
 3 files changed, 42 insertions(+), 25 deletions(-)

diff --git a/src/librustc/session/filesearch.rs b/src/librustc/session/filesearch.rs
index d9abbe6cf6925..73fb95bd9744b 100644
--- a/src/librustc/session/filesearch.rs
+++ b/src/librustc/session/filesearch.rs
@@ -12,7 +12,6 @@
 
 pub use self::FileMatch::*;
 
-use rustc_data_structures::fx::FxHashSet;
 use std::borrow::Cow;
 use std::env;
 use std::fs;
@@ -31,8 +30,9 @@ pub enum FileMatch {
 
 pub struct FileSearch<'a> {
     pub sysroot: &'a Path,
-    pub search_paths: &'a [SearchPath],
     pub triple: &'a str,
+    pub search_paths: &'a [SearchPath],
+    pub tlib_path: &'a SearchPath,
     pub kind: PathKind,
 }
 
@@ -40,20 +40,12 @@ impl<'a> FileSearch<'a> {
     pub fn for_each_lib_search_path<F>(&self, mut f: F) where
         F: FnMut(&SearchPath)
     {
-        let mut visited_dirs = FxHashSet::default();
-        visited_dirs.reserve(self.search_paths.len() + 1);
         let iter = self.search_paths.iter().filter(|sp| sp.kind.matches(self.kind));
         for search_path in iter {
             f(search_path);
-            visited_dirs.insert(search_path.dir.to_path_buf());
         }
 
-        debug!("filesearch: searching lib path");
-        let tlib_path = make_target_lib_path(self.sysroot,
-                                             self.triple);
-        if !visited_dirs.contains(&tlib_path) {
-            f(&SearchPath { kind: PathKind::All, dir: tlib_path });
-        }
+        f(self.tlib_path);
     }
 
     pub fn get_lib_path(&self) -> PathBuf {
@@ -65,12 +57,6 @@ impl<'a> FileSearch<'a> {
     {
         self.for_each_lib_search_path(|search_path| {
             debug!("searching {}", search_path.dir.display());
-            let files = match fs::read_dir(&search_path.dir) {
-                Ok(files) => files,
-                Err(..) => return,
-            };
-            let files = files.filter_map(|p| p.ok().map(|s| s.path()))
-                             .collect::<Vec<_>>();
             fn is_rlib(p: &Path) -> bool {
                 p.extension() == Some("rlib".as_ref())
             }
@@ -78,8 +64,8 @@ impl<'a> FileSearch<'a> {
             // an rlib and a dylib we only read one of the files of
             // metadata, so in the name of speed, bring all rlib files to
             // the front of the search list.
-            let files1 = files.iter().filter(|p| is_rlib(p));
-            let files2 = files.iter().filter(|p| !is_rlib(p));
+            let files1 = search_path.files.iter().filter(|p| is_rlib(p));
+            let files2 = search_path.files.iter().filter(|p| !is_rlib(p));
             for path in files1.chain(files2) {
                 debug!("testing {}", path.display());
                 let maybe_picked = pick(path, search_path.kind);
@@ -98,12 +84,15 @@ impl<'a> FileSearch<'a> {
     pub fn new(sysroot: &'a Path,
                triple: &'a str,
                search_paths: &'a Vec<SearchPath>,
-               kind: PathKind) -> FileSearch<'a> {
+               tlib_path: &'a SearchPath,
+               kind: PathKind)
+               -> FileSearch<'a> {
         debug!("using sysroot = {}, triple = {}", sysroot.display(), triple);
         FileSearch {
             sysroot,
-            search_paths,
             triple,
+            search_paths,
+            tlib_path,
             kind,
         }
     }
@@ -137,8 +126,7 @@ pub fn relative_target_lib_path(sysroot: &Path, target_triple: &str) -> PathBuf
     p
 }
 
-pub fn make_target_lib_path(sysroot: &Path,
-                        target_triple: &str) -> PathBuf {
+pub fn make_target_lib_path(sysroot: &Path, target_triple: &str) -> PathBuf {
     sysroot.join(&relative_target_lib_path(sysroot, target_triple))
 }
 
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index 79441eec3922f..6b323d89ed0dd 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -19,8 +19,8 @@ use lint;
 use lint::builtin::BuiltinLintDiagnostics;
 use middle::allocator::AllocatorKind;
 use middle::dependency_format;
-use session::search_paths::PathKind;
 use session::config::{OutputType, Lto};
+use session::search_paths::{PathKind, SearchPath};
 use util::nodemap::{FxHashMap, FxHashSet};
 use util::common::{duration_to_secs_str, ErrorReported};
 use util::common::ProfileQueriesMsg;
@@ -64,6 +64,9 @@ pub struct Session {
     pub target: config::Config,
     pub host: Target,
     pub opts: config::Options,
+    pub host_tlib_path: SearchPath,
+    /// This is `None` if the host and target are the same.
+    pub target_tlib_path: Option<SearchPath>,
     pub parse_sess: ParseSess,
     /// For a library crate, this is always none
     pub entry_fn: Once<Option<(NodeId, Span, config::EntryFnType)>>,
@@ -699,6 +702,8 @@ impl Session {
             &self.sysroot,
             self.opts.target_triple.triple(),
             &self.opts.search_paths,
+            // target_tlib_path==None means it's the same as host_tlib_path.
+            self.target_tlib_path.as_ref().unwrap_or(&self.host_tlib_path),
             kind,
         )
     }
@@ -707,6 +712,7 @@ impl Session {
             &self.sysroot,
             config::host_triple(),
             &self.opts.search_paths,
+            &self.host_tlib_path,
             kind,
         )
     }
@@ -1106,6 +1112,15 @@ pub fn build_session_(
         None => filesearch::get_or_default_sysroot(),
     };
 
+    let host_triple = config::host_triple();
+    let target_triple = sopts.target_triple.triple();
+    let host_tlib_path = SearchPath::from_sysroot_and_triple(&sysroot, host_triple);
+    let target_tlib_path = if host_triple == target_triple {
+        None
+    } else {
+        Some(SearchPath::from_sysroot_and_triple(&sysroot, target_triple))
+    };
+
     let file_path_mapping = sopts.file_path_mapping();
 
     let local_crate_source_file =
@@ -1134,6 +1149,8 @@ pub fn build_session_(
         target: target_cfg,
         host,
         opts: sopts,
+        host_tlib_path,
+        target_tlib_path,
         parse_sess: p_s,
         // For a library crate, this is always none
         entry_fn: Once::new(),
diff --git a/src/librustc/session/search_paths.rs b/src/librustc/session/search_paths.rs
index 7a0bd2ed439b2..5c44a07f84341 100644
--- a/src/librustc/session/search_paths.rs
+++ b/src/librustc/session/search_paths.rs
@@ -16,6 +16,7 @@ use session::filesearch::make_target_lib_path;
 pub struct SearchPath {
     pub kind: PathKind,
     pub dir: PathBuf,
+    pub files: Vec<PathBuf>,
 }
 
 #[derive(Eq, PartialEq, Clone, Copy, Debug, PartialOrd, Ord, Hash)]
@@ -65,7 +66,18 @@ impl SearchPath {
     }
 
     fn new(kind: PathKind, dir: PathBuf) -> Self {
-        SearchPath { kind, dir }
+        // Get the files within the directory.
+        let files = match std::fs::read_dir(&dir) {
+            Ok(files) => {
+                files.filter_map(|p| {
+                    p.ok().map(|s| s.path())
+                })
+                .collect::<Vec<_>>()
+            }
+            Err(..) => vec![],
+        };
+
+        SearchPath { kind, dir, files }
     }
 }
 

From 2d2b7c01ebee3f2926af58b9461284e271955855 Mon Sep 17 00:00:00 2001
From: Mark Rousskov <mark.simulacrum@gmail.com>
Date: Sun, 25 Nov 2018 15:43:00 -0700
Subject: [PATCH 27/50] Make JSON output from -Zprofile-json valid

---
 src/librustc/util/profiling.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/librustc/util/profiling.rs b/src/librustc/util/profiling.rs
index 6540a09d87763..bea3453b31adf 100644
--- a/src/librustc/util/profiling.rs
+++ b/src/librustc/util/profiling.rs
@@ -102,7 +102,7 @@ macro_rules! define_categories {
                         };
 
                     json.push_str(&format!(
-                        "{{ \"category\": {}, \"time_ms\": {},
+                        "{{ \"category\": \"{}\", \"time_ms\": {},\
                             \"query_count\": {}, \"query_hits\": {} }},",
                         stringify!($name),
                         self.times.$name / 1_000_000,

From 4dd0f66f12564a9be2ebd1e1fb03f0b722a63a4d Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote <nnethercote@mozilla.com>
Date: Fri, 23 Nov 2018 13:36:41 +1100
Subject: [PATCH 28/50] Replace `FileSearch::for_each_lib_search_path` with
 `search_paths`.

Returning an iterator leads to nicer code all around.
---
 src/librustc/session/filesearch.rs     | 40 +++++++++++---------------
 src/librustc_codegen_llvm/back/link.rs | 12 +++-----
 src/librustc_driver/driver.rs          |  2 +-
 3 files changed, 22 insertions(+), 32 deletions(-)

diff --git a/src/librustc/session/filesearch.rs b/src/librustc/session/filesearch.rs
index 73fb95bd9744b..402f6216250d4 100644
--- a/src/librustc/session/filesearch.rs
+++ b/src/librustc/session/filesearch.rs
@@ -29,23 +29,19 @@ pub enum FileMatch {
 // A module for searching for libraries
 
 pub struct FileSearch<'a> {
-    pub sysroot: &'a Path,
-    pub triple: &'a str,
-    pub search_paths: &'a [SearchPath],
-    pub tlib_path: &'a SearchPath,
-    pub kind: PathKind,
+    sysroot: &'a Path,
+    triple: &'a str,
+    search_paths: &'a [SearchPath],
+    tlib_path: &'a SearchPath,
+    kind: PathKind,
 }
 
 impl<'a> FileSearch<'a> {
-    pub fn for_each_lib_search_path<F>(&self, mut f: F) where
-        F: FnMut(&SearchPath)
-    {
-        let iter = self.search_paths.iter().filter(|sp| sp.kind.matches(self.kind));
-        for search_path in iter {
-            f(search_path);
-        }
-
-        f(self.tlib_path);
+    pub fn search_paths(&self) -> impl Iterator<Item = &'a SearchPath> {
+        let kind = self.kind;
+        self.search_paths.iter()
+            .filter(move |sp| sp.kind.matches(kind))
+            .chain(std::iter::once(self.tlib_path))
     }
 
     pub fn get_lib_path(&self) -> PathBuf {
@@ -55,7 +51,7 @@ impl<'a> FileSearch<'a> {
     pub fn search<F>(&self, mut pick: F)
         where F: FnMut(&Path, PathKind) -> FileMatch
     {
-        self.for_each_lib_search_path(|search_path| {
+        for search_path in self.search_paths() {
             debug!("searching {}", search_path.dir.display());
             fn is_rlib(p: &Path) -> bool {
                 p.extension() == Some("rlib".as_ref())
@@ -78,7 +74,7 @@ impl<'a> FileSearch<'a> {
                     }
                 }
             }
-        });
+        }
     }
 
     pub fn new(sysroot: &'a Path,
@@ -97,13 +93,11 @@ impl<'a> FileSearch<'a> {
         }
     }
 
-    // Returns a list of directories where target-specific dylibs might be located.
-    pub fn get_dylib_search_paths(&self) -> Vec<PathBuf> {
-        let mut paths = Vec::new();
-        self.for_each_lib_search_path(|search_path| {
-            paths.push(search_path.dir.to_path_buf());
-        });
-        paths
+    // Returns just the directories within the search paths.
+    pub fn search_path_dirs(&self) -> Vec<PathBuf> {
+        self.search_paths()
+            .map(|sp| sp.dir.to_path_buf())
+            .collect()
     }
 
     // Returns a list of directories where target-specific tool binaries are located.
diff --git a/src/librustc_codegen_llvm/back/link.rs b/src/librustc_codegen_llvm/back/link.rs
index 392e3ff3a8812..6242ad80a8c90 100644
--- a/src/librustc_codegen_llvm/back/link.rs
+++ b/src/librustc_codegen_llvm/back/link.rs
@@ -212,12 +212,7 @@ fn link_binary_output(sess: &Session,
 }
 
 fn archive_search_paths(sess: &Session) -> Vec<PathBuf> {
-    let mut search = Vec::new();
-    sess.target_filesearch(PathKind::Native).for_each_lib_search_path(|search_path| {
-        search.push(search_path.dir.to_path_buf());
-    });
-
-    search
+    sess.target_filesearch(PathKind::Native).search_path_dirs()
 }
 
 fn archive_config<'a>(sess: &'a Session,
@@ -1067,12 +1062,13 @@ fn link_args(cmd: &mut dyn Linker,
 fn add_local_native_libraries(cmd: &mut dyn Linker,
                               sess: &Session,
                               codegen_results: &CodegenResults) {
-    sess.target_filesearch(PathKind::All).for_each_lib_search_path(|search_path| {
+    let filesearch = sess.target_filesearch(PathKind::All);
+    for search_path in filesearch.search_paths() {
         match search_path.kind {
             PathKind::Framework => { cmd.framework_path(&search_path.dir); }
             _ => { cmd.include_path(&fix_windows_verbatim_for_gcc(&search_path.dir)); }
         }
-    });
+    }
 
     let relevant_libs = codegen_results.crate_info.used_libraries.iter().filter(|l| {
         relevant_lib(sess, l)
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index 7ad012409b53a..1ac3a9ff9c870 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -977,7 +977,7 @@ where
         let mut old_path = OsString::new();
         if cfg!(windows) {
             old_path = env::var_os("PATH").unwrap_or(old_path);
-            let mut new_path = sess.host_filesearch(PathKind::All).get_dylib_search_paths();
+            let mut new_path = sess.host_filesearch(PathKind::All).search_path_dirs();
             for path in env::split_paths(&old_path) {
                 if !new_path.contains(&path) {
                     new_path.push(path);

From cc466851bc458219121142ae75f5cc47bb3a927f Mon Sep 17 00:00:00 2001
From: Corey Farwell <coreyf@rwell.org>
Date: Mon, 26 Nov 2018 08:40:34 -0500
Subject: [PATCH 29/50] Remove unsafe `unsafe` inner function.

Within this `Iterator` implementation, a function `unsafe_get` is
defined which unsafely allows _unchecked_ indexing of any element in a
slice. This should be marked as _unsafe_, but it is not.

To address this issue, I removed that inner function.
---
 src/libcore/str/lossy.rs | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/src/libcore/str/lossy.rs b/src/libcore/str/lossy.rs
index 186d6adbc91cf..52abd8f99529b 100644
--- a/src/libcore/str/lossy.rs
+++ b/src/libcore/str/lossy.rs
@@ -62,18 +62,15 @@ impl<'a> Iterator for Utf8LossyChunksIter<'a> {
         }
 
         const TAG_CONT_U8: u8 = 128;
-        fn unsafe_get(xs: &[u8], i: usize) -> u8 {
-            unsafe { *xs.get_unchecked(i) }
-        }
         fn safe_get(xs: &[u8], i: usize) -> u8 {
-            if i >= xs.len() { 0 } else { unsafe_get(xs, i) }
+            *xs.get(i).unwrap_or(&0)
         }
 
         let mut i = 0;
         while i < self.source.len() {
             let i_ = i;
 
-            let byte = unsafe_get(self.source, i);
+            let byte = unsafe { *self.source.get_unchecked(i) };
             i += 1;
 
             if byte < 128 {

From 45dfe43887fee6c2ce4cbc3e46b31626330be094 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar>
Date: Mon, 26 Nov 2018 08:32:47 -0800
Subject: [PATCH 30/50] Emit one diagnostic for multiple misplaced lifetimes

---
 src/libsyntax/parse/parser.rs                 | 31 ++++++++++++-------
 .../ui/suggestions/suggest-move-lifetimes.rs  |  6 ++++
 .../suggestions/suggest-move-lifetimes.stderr | 16 ++++++++--
 3 files changed, 38 insertions(+), 15 deletions(-)

diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 1fdf86d48670b..ab5afaf3d99fe 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -5182,6 +5182,8 @@ impl<'a> Parser<'a> {
         let mut params = Vec::new();
         let mut seen_ty_param: Option<Span> = None;
         let mut last_comma_span = None;
+        let mut bad_lifetime_pos = vec![];
+        let mut suggestions = vec![];
         loop {
             let attrs = self.parse_outer_attributes()?;
             if self.check_lifetime() {
@@ -5207,20 +5209,12 @@ impl<'a> Parser<'a> {
                     } else {
                         last_comma_span.unwrap_or(param_span).to(param_span)
                     };
-                    let mut err = self.struct_span_err(
-                        self.prev_span,
-                        "lifetime parameters must be declared prior to type parameters",
-                    );
+                    bad_lifetime_pos.push(param_span);
+
                     if let Ok(snippet) = self.sess.source_map().span_to_snippet(param_span) {
-                        err.multipart_suggestion(
-                            "move the lifetime parameter prior to the first type parameter",
-                            vec![
-                                (remove_sp, String::new()),
-                                (sp.shrink_to_lo(), format!("{}, ", snippet)),
-                            ],
-                        );
+                        suggestions.push((remove_sp, String::new()));
+                        suggestions.push((sp.shrink_to_lo(), format!("{}, ", snippet)));
                     }
-                    err.emit();
                     if ate_comma {
                         last_comma_span = Some(self.prev_span);
                         continue
@@ -5247,6 +5241,19 @@ impl<'a> Parser<'a> {
             }
             last_comma_span = Some(self.prev_span);
         }
+        if !bad_lifetime_pos.is_empty() {
+            let mut err = self.struct_span_err(
+                bad_lifetime_pos,
+                "lifetime parameters must be declared prior to type parameters",
+            );
+            if !suggestions.is_empty() {
+                err.multipart_suggestion(
+                    "move the lifetime parameter prior to the first type parameter",
+                    suggestions,
+                );
+            }
+            err.emit();
+        }
         lifetimes.extend(params);  // ensure the correct order of lifetimes and type params
         Ok(lifetimes)
     }
diff --git a/src/test/ui/suggestions/suggest-move-lifetimes.rs b/src/test/ui/suggestions/suggest-move-lifetimes.rs
index be6d29d933763..5051a406078aa 100644
--- a/src/test/ui/suggestions/suggest-move-lifetimes.rs
+++ b/src/test/ui/suggestions/suggest-move-lifetimes.rs
@@ -12,4 +12,10 @@ struct C<T, U, 'a> {
     u: U,
 }
 
+struct D<T, U, 'a, 'b, V, 'c> {
+    t: &'a T,
+    u: &'b U,
+    v: &'c V,
+}
+
 fn main() {}
diff --git a/src/test/ui/suggestions/suggest-move-lifetimes.stderr b/src/test/ui/suggestions/suggest-move-lifetimes.stderr
index fa1cfe66ab530..f3d6469b51255 100644
--- a/src/test/ui/suggestions/suggest-move-lifetimes.stderr
+++ b/src/test/ui/suggestions/suggest-move-lifetimes.stderr
@@ -9,10 +9,10 @@ LL | struct A<'a, T> {
    |          ^^^ --
 
 error: lifetime parameters must be declared prior to type parameters
-  --> $DIR/suggest-move-lifetimes.rs:5:15
+  --> $DIR/suggest-move-lifetimes.rs:5:13
    |
 LL | struct B<T, 'a, U> {
-   |               ^
+   |             ^^
 help: move the lifetime parameter prior to the first type parameter
    |
 LL | struct B<'a, T, U> {
@@ -28,5 +28,15 @@ help: move the lifetime parameter prior to the first type parameter
 LL | struct C<'a, T, U> {
    |          ^^^    --
 
-error: aborting due to 3 previous errors
+error: lifetime parameters must be declared prior to type parameters
+  --> $DIR/suggest-move-lifetimes.rs:15:16
+   |
+LL | struct D<T, U, 'a, 'b, V, 'c> {
+   |                ^^  ^^     ^^
+help: move the lifetime parameter prior to the first type parameter
+   |
+LL | struct D<'a, 'b, 'c, T, U, V> {
+   |          ^^^ ^^^ ^^^      ---
+
+error: aborting due to 4 previous errors
 

From 769d7115fed078c93f66d8db24de2046a6ab6334 Mon Sep 17 00:00:00 2001
From: Andy Russell <arussell123@gmail.com>
Date: Wed, 14 Nov 2018 14:51:28 -0500
Subject: [PATCH 31/50] add test for issue #21335

Fixes #21335.
---
 src/test/run-make/llvm-outputs/Makefile | 5 +++++
 1 file changed, 5 insertions(+)
 create mode 100644 src/test/run-make/llvm-outputs/Makefile

diff --git a/src/test/run-make/llvm-outputs/Makefile b/src/test/run-make/llvm-outputs/Makefile
new file mode 100644
index 0000000000000..d7f67577b04ce
--- /dev/null
+++ b/src/test/run-make/llvm-outputs/Makefile
@@ -0,0 +1,5 @@
+-include ../../run-make-fulldeps/tools.mk
+
+all:
+	echo 'fn main() {}' | $(BARE_RUSTC) - --out-dir=$(TMPDIR)/random_directory_that_does_not_exist_ir/ --emit=llvm-ir
+	echo 'fn main() {}' | $(BARE_RUSTC) - --out-dir=$(TMPDIR)/random_directory_that_does_not_exist_bc/ --emit=llvm-bc

From cd20be50912170842689e4f936c31c5a28184432 Mon Sep 17 00:00:00 2001
From: Jason Langenauer <jason@jasonlangenauer.com>
Date: Mon, 26 Nov 2018 21:21:17 +0100
Subject: [PATCH 32/50] Update outdated code comments in StringReader

---
 src/libsyntax/parse/lexer/mod.rs | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs
index 0584cd5a3df47..c90c62c13f969 100644
--- a/src/libsyntax/parse/lexer/mod.rs
+++ b/src/libsyntax/parse/lexer/mod.rs
@@ -60,11 +60,11 @@ pub struct StringReader<'a> {
     // cache a direct reference to the source text, so that we don't have to
     // retrieve it via `self.source_file.src.as_ref().unwrap()` all the time.
     src: Lrc<String>,
-    /// Stack of open delimiters and their spans. Used for error message.
     token: token::Token,
     span: Span,
     /// The raw source span which *does not* take `override_span` into account
     span_src_raw: Span,
+    /// Stack of open delimiters and their spans. Used for error message.
     open_braces: Vec<(token::DelimToken, Span)>,
     /// The type and spans for all braces
     ///
@@ -506,8 +506,7 @@ impl<'a> StringReader<'a> {
         }
     }
 
-    /// Advance the StringReader by one character. If a newline is
-    /// discovered, add it to the SourceFile's list of line start offsets.
+    /// Advance the StringReader by one character.
     crate fn bump(&mut self) {
         let next_src_index = self.src_index(self.next_pos);
         if next_src_index < self.end_src_index {

From a1865edb75288b88cba7f26f754daee0b4a37f3f Mon Sep 17 00:00:00 2001
From: Mark Mansi <markm@cs.wisc.edu>
Date: Wed, 21 Nov 2018 18:57:14 -0600
Subject: [PATCH 33/50] Add rustc-guide as a submodule

---
 .gitmodules         | 3 +++
 src/doc/rustc-guide | 1 +
 2 files changed, 4 insertions(+)
 create mode 160000 src/doc/rustc-guide

diff --git a/.gitmodules b/.gitmodules
index bf9bdd9a5b4b0..5cc4cab62d173 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -62,3 +62,6 @@
 	url = https://github.com/rust-lang-nursery/clang.git
 	branch = rust-release-80-v1
 
+[submodule "src/doc/rustc-guide"]
+	path = src/doc/rustc-guide
+	url = https://github.com/rust-lang/rustc-guide.git
diff --git a/src/doc/rustc-guide b/src/doc/rustc-guide
new file mode 160000
index 0000000000000..3a804956e3c28
--- /dev/null
+++ b/src/doc/rustc-guide
@@ -0,0 +1 @@
+Subproject commit 3a804956e3c28d7e44e38804207a00013594e1d3

From 6494f1e60e1931ac62eaef0a203bcb013fd77acf Mon Sep 17 00:00:00 2001
From: Mark Mansi <markm@cs.wisc.edu>
Date: Mon, 26 Nov 2018 15:03:13 -0600
Subject: [PATCH 34/50] rustc-guide has moved

---
 CONTRIBUTING.md                                     | 4 ++--
 README.md                                           | 2 +-
 src/README.md                                       | 2 +-
 src/doc/rustc/src/contributing.md                   | 4 ++--
 src/librustc/README.md                              | 2 +-
 src/librustc/dep_graph/README.md                    | 2 +-
 src/librustc/dep_graph/graph.rs                     | 2 +-
 src/librustc/hir/mod.rs                             | 2 +-
 src/librustc/infer/canonical/canonicalizer.rs       | 6 +++---
 src/librustc/infer/canonical/mod.rs                 | 2 +-
 src/librustc/infer/canonical/query_response.rs      | 4 ++--
 src/librustc/infer/canonical/substitute.rs          | 2 +-
 src/librustc/infer/higher_ranked/mod.rs             | 2 +-
 src/librustc/infer/lexical_region_resolve/README.md | 2 +-
 src/librustc/infer/region_constraints/README.md     | 4 ++--
 src/librustc/lib.rs                                 | 2 +-
 src/librustc/middle/region.rs                       | 2 +-
 src/librustc/mir/mod.rs                             | 2 +-
 src/librustc/traits/coherence.rs                    | 4 ++--
 src/librustc/traits/mod.rs                          | 2 +-
 src/librustc/traits/query/type_op/mod.rs            | 2 +-
 src/librustc/traits/select.rs                       | 6 +++---
 src/librustc/traits/specialize/mod.rs               | 2 +-
 src/librustc/ty/context.rs                          | 2 +-
 src/librustc/ty/sty.rs                              | 2 +-
 src/librustc_borrowck/borrowck/README.md            | 2 +-
 src/librustc_codegen_llvm/README.md                 | 2 +-
 src/librustc_driver/README.md                       | 2 +-
 src/librustc_target/README.md                       | 2 +-
 src/librustc_typeck/README.md                       | 4 ++--
 src/librustc_typeck/check/method/mod.rs             | 2 +-
 src/librustc_typeck/variance/mod.rs                 | 2 +-
 src/librustc_typeck/variance/terms.rs               | 4 ++--
 src/librustdoc/README.md                            | 2 +-
 src/libsyntax/README.md                             | 4 ++--
 src/test/COMPILER_TESTS.md                          | 2 +-
 36 files changed, 48 insertions(+), 48 deletions(-)

diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index e04b1bdfefdd8..137fe61320796 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -640,7 +640,7 @@ are:
 * **Google!** ([search only in Rust Documentation][gsearchdocs] to find types, traits, etc. quickly)
 * Don't be afraid to ask! The Rust community is friendly and helpful.
 
-[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/about-this-guide.html
+[rustc guide]: https://rust-lang.github.io/rustc-guide/about-this-guide.html
 [gdfrustc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/
 [gsearchdocs]: https://www.google.com/search?q=site:doc.rust-lang.org+your+query+here
 [rif]: http://internals.rust-lang.org
@@ -648,5 +648,5 @@ are:
 [rustforge]: https://forge.rust-lang.org/
 [tlgba]: http://tomlee.co/2014/04/a-more-detailed-tour-of-the-rust-compiler/
 [ro]: http://www.rustaceans.org/
-[rctd]: https://rust-lang-nursery.github.io/rustc-guide/tests/intro.html
+[rctd]: https://rust-lang.github.io/rustc-guide/tests/intro.html
 [cheatsheet]: https://buildbot2.rust-lang.org/homu/
diff --git a/README.md b/README.md
index 0e5b7170bc6b4..37442661bcbc1 100644
--- a/README.md
+++ b/README.md
@@ -233,7 +233,7 @@ Also, you may find the [rustdocs for the compiler itself][rustdocs] useful.
 [IRC]: https://en.wikipedia.org/wiki/Internet_Relay_Chat
 [#rust]: irc://irc.mozilla.org/rust
 [#rust-beginners]: irc://irc.mozilla.org/rust-beginners
-[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/about-this-guide.html
+[rustc guide]: https://rust-lang.github.io/rustc-guide/about-this-guide.html
 [rustdocs]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/
 
 ## License
diff --git a/src/README.md b/src/README.md
index a4f89960a0bfd..65228915866ea 100644
--- a/src/README.md
+++ b/src/README.md
@@ -12,4 +12,4 @@ There is also useful content in the following READMEs, which are gradually being
 - https://github.com/rust-lang/rust/tree/master/src/librustc/infer/higher_ranked
 - https://github.com/rust-lang/rust/tree/master/src/librustc/infer/lexical_region_resolve
 
-[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/about-this-guide.html
+[rustc guide]: https://rust-lang.github.io/rustc-guide/about-this-guide.html
diff --git a/src/doc/rustc/src/contributing.md b/src/doc/rustc/src/contributing.md
index fcb8e6b27dbf0..3a1cafe8a6153 100644
--- a/src/doc/rustc/src/contributing.md
+++ b/src/doc/rustc/src/contributing.md
@@ -1,6 +1,6 @@
 # Contributing to rustc
 
 We'd love to have your help improving `rustc`! To that end, we've written [a
-whole book](https://rust-lang-nursery.github.io/rustc-guide/) on its
+whole book](https://rust-lang.github.io/rustc-guide/) on its
 internals, how it works, and how to get started working on it. To learn
-more, you'll want to check that out.
\ No newline at end of file
+more, you'll want to check that out.
diff --git a/src/librustc/README.md b/src/librustc/README.md
index 9909ff91a18aa..c0e5c542bdc8b 100644
--- a/src/librustc/README.md
+++ b/src/librustc/README.md
@@ -1,3 +1,3 @@
 For more information about how rustc works, see the [rustc guide].
 
-[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/
+[rustc guide]: https://rust-lang.github.io/rustc-guide/
diff --git a/src/librustc/dep_graph/README.md b/src/librustc/dep_graph/README.md
index f1f383d7ad126..91a06e452e5fd 100644
--- a/src/librustc/dep_graph/README.md
+++ b/src/librustc/dep_graph/README.md
@@ -1,4 +1,4 @@
 To learn more about how dependency tracking works in rustc, see the [rustc
 guide].
 
-[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/query.html
+[rustc guide]: https://rust-lang.github.io/rustc-guide/query.html
diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs
index 63b749c548e24..4c94c993ab405 100644
--- a/src/librustc/dep_graph/graph.rs
+++ b/src/librustc/dep_graph/graph.rs
@@ -195,7 +195,7 @@ impl DepGraph {
     /// - If you need 3+ arguments, use a tuple for the
     ///   `arg` parameter.
     ///
-    /// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/incremental-compilation.html
+    /// [rustc guide]: https://rust-lang.github.io/rustc-guide/incremental-compilation.html
     pub fn with_task<'gcx, C, A, R>(&self,
                                    key: DepNode,
                                    cx: C,
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index e28193be34a44..1674320165e65 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -689,7 +689,7 @@ pub struct WhereEqPredicate {
 ///
 /// For more details, see the [rustc guide].
 ///
-/// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/hir.html
+/// [rustc guide]: https://rust-lang.github.io/rustc-guide/hir.html
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Crate {
     pub module: Mod,
diff --git a/src/librustc/infer/canonical/canonicalizer.rs b/src/librustc/infer/canonical/canonicalizer.rs
index ddb520775da0a..08cd3395ba16c 100644
--- a/src/librustc/infer/canonical/canonicalizer.rs
+++ b/src/librustc/infer/canonical/canonicalizer.rs
@@ -13,7 +13,7 @@
 //! For an overview of what canonicalization is and how it fits into
 //! rustc, check out the [chapter in the rustc guide][c].
 //!
-//! [c]: https://rust-lang-nursery.github.io/rustc-guide/traits/canonicalization.html
+//! [c]: https://rust-lang.github.io/rustc-guide/traits/canonicalization.html
 
 use infer::canonical::{
     Canonical, CanonicalTyVarKind, CanonicalVarInfo, CanonicalVarKind, Canonicalized,
@@ -44,7 +44,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
     /// To get a good understanding of what is happening here, check
     /// out the [chapter in the rustc guide][c].
     ///
-    /// [c]: https://rust-lang-nursery.github.io/rustc-guide/traits/canonicalization.html#canonicalizing-the-query
+    /// [c]: https://rust-lang.github.io/rustc-guide/traits/canonicalization.html#canonicalizing-the-query
     pub fn canonicalize_query<V>(
         &self,
         value: &V,
@@ -92,7 +92,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
     /// To get a good understanding of what is happening here, check
     /// out the [chapter in the rustc guide][c].
     ///
-    /// [c]: https://rust-lang-nursery.github.io/rustc-guide/traits/canonicalization.html#canonicalizing-the-query-result
+    /// [c]: https://rust-lang.github.io/rustc-guide/traits/canonicalization.html#canonicalizing-the-query-result
     pub fn canonicalize_response<V>(&self, value: &V) -> Canonicalized<'gcx, V>
     where
         V: TypeFoldable<'tcx> + Lift<'gcx>,
diff --git a/src/librustc/infer/canonical/mod.rs b/src/librustc/infer/canonical/mod.rs
index 230f8958b3385..6b0fa79b201fc 100644
--- a/src/librustc/infer/canonical/mod.rs
+++ b/src/librustc/infer/canonical/mod.rs
@@ -29,7 +29,7 @@
 //! For a more detailed look at what is happening here, check
 //! out the [chapter in the rustc guide][c].
 //!
-//! [c]: https://rust-lang-nursery.github.io/rustc-guide/traits/canonicalization.html
+//! [c]: https://rust-lang.github.io/rustc-guide/traits/canonicalization.html
 
 use infer::{InferCtxt, RegionVariableOrigin, TypeVariableOrigin};
 use rustc_data_structures::indexed_vec::IndexVec;
diff --git a/src/librustc/infer/canonical/query_response.rs b/src/librustc/infer/canonical/query_response.rs
index d32594ebdf366..8d2b1d74c554b 100644
--- a/src/librustc/infer/canonical/query_response.rs
+++ b/src/librustc/infer/canonical/query_response.rs
@@ -15,7 +15,7 @@
 //! For an overview of what canonicaliation is and how it fits into
 //! rustc, check out the [chapter in the rustc guide][c].
 //!
-//! [c]: https://rust-lang-nursery.github.io/rustc-guide/traits/canonicalization.html
+//! [c]: https://rust-lang.github.io/rustc-guide/traits/canonicalization.html
 
 use infer::canonical::substitute::substitute_value;
 use infer::canonical::{
@@ -184,7 +184,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
     /// To get a good understanding of what is happening here, check
     /// out the [chapter in the rustc guide][c].
     ///
-    /// [c]: https://rust-lang-nursery.github.io/rustc-guide/traits/canonicalization.html#processing-the-canonicalized-query-result
+    /// [c]: https://rust-lang.github.io/rustc-guide/traits/canonicalization.html#processing-the-canonicalized-query-result
     pub fn instantiate_query_response_and_region_obligations<R>(
         &self,
         cause: &ObligationCause<'tcx>,
diff --git a/src/librustc/infer/canonical/substitute.rs b/src/librustc/infer/canonical/substitute.rs
index e2110e148de52..ab575882f8a17 100644
--- a/src/librustc/infer/canonical/substitute.rs
+++ b/src/librustc/infer/canonical/substitute.rs
@@ -14,7 +14,7 @@
 //! For an overview of what canonicalization is and how it fits into
 //! rustc, check out the [chapter in the rustc guide][c].
 //!
-//! [c]: https://rust-lang-nursery.github.io/rustc-guide/traits/canonicalization.html
+//! [c]: https://rust-lang.github.io/rustc-guide/traits/canonicalization.html
 
 use infer::canonical::{Canonical, CanonicalVarValues};
 use ty::fold::TypeFoldable;
diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs
index 16140e748aa1e..cf91b85807632 100644
--- a/src/librustc/infer/higher_ranked/mod.rs
+++ b/src/librustc/infer/higher_ranked/mod.rs
@@ -329,7 +329,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     /// For more information about how placeholders and HRTBs work, see
     /// the [rustc guide].
     ///
-    /// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/traits/hrtb.html
+    /// [rustc guide]: https://rust-lang.github.io/rustc-guide/traits/hrtb.html
     pub fn replace_bound_vars_with_placeholders<T>(
         &self,
         binder: &ty::Binder<T>
diff --git a/src/librustc/infer/lexical_region_resolve/README.md b/src/librustc/infer/lexical_region_resolve/README.md
index 6e1c4191173bc..4483e522f3a1f 100644
--- a/src/librustc/infer/lexical_region_resolve/README.md
+++ b/src/librustc/infer/lexical_region_resolve/README.md
@@ -3,7 +3,7 @@
 > WARNING: This README is obsolete and will be removed soon! For
 > more info on how the current borrowck works, see the [rustc guide].
 
-[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir/borrowck.html
+[rustc guide]: https://rust-lang.github.io/rustc-guide/mir/borrowck.html
 
 ## Terminology
 
diff --git a/src/librustc/infer/region_constraints/README.md b/src/librustc/infer/region_constraints/README.md
index 61603e6dee686..775bbf955b830 100644
--- a/src/librustc/infer/region_constraints/README.md
+++ b/src/librustc/infer/region_constraints/README.md
@@ -3,7 +3,7 @@
 > WARNING: This README is obsolete and will be removed soon! For
 > more info on how the current borrowck works, see the [rustc guide].
 
-[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir/borrowck.html
+[rustc guide]: https://rust-lang.github.io/rustc-guide/mir/borrowck.html
 
 ## Terminology
 
@@ -18,7 +18,7 @@ constraints over the course of a function.  Finally, at the end of
 processing a function, we process and solve the constraints all at
 once.
 
-[ti]: https://rust-lang-nursery.github.io/rustc-guide/type-inference.html
+[ti]: https://rust-lang.github.io/rustc-guide/type-inference.html
 
 The constraints are always of one of three possible forms:
 
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index 0aa964a44fd2c..edc97238f0530 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -30,7 +30,7 @@
 //!
 //! For more information about how rustc works, see the [rustc guide].
 //!
-//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/
+//! [rustc guide]: https://rust-lang.github.io/rustc-guide/
 //!
 //! # Note
 //!
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index d00fbdeca21aa..35d1a4dd2cb7c 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -14,7 +14,7 @@
 //! For more information about how MIR-based region-checking works,
 //! see the [rustc guide].
 //!
-//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir/borrowck.html
+//! [rustc guide]: https://rust-lang.github.io/rustc-guide/mir/borrowck.html
 
 use ich::{StableHashingContext, NodeIdHashingMode};
 use util::nodemap::{FxHashMap, FxHashSet};
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index af1255c438a95..368f83eb61127 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -10,7 +10,7 @@
 
 //! MIR datatypes and passes. See the [rustc guide] for more info.
 //!
-//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir/index.html
+//! [rustc guide]: https://rust-lang.github.io/rustc-guide/mir/index.html
 
 use hir::def::CtorKind;
 use hir::def_id::DefId;
diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs
index b7a84c99308f8..4bf8ba0d6d1c8 100644
--- a/src/librustc/traits/coherence.rs
+++ b/src/librustc/traits/coherence.rs
@@ -11,8 +11,8 @@
 //! See rustc guide chapters on [trait-resolution] and [trait-specialization] for more info on how
 //! this works.
 //!
-//! [trait-resolution]: https://rust-lang-nursery.github.io/rustc-guide/traits/resolution.html
-//! [trait-specialization]: https://rust-lang-nursery.github.io/rustc-guide/traits/specialization.html
+//! [trait-resolution]: https://rust-lang.github.io/rustc-guide/traits/resolution.html
+//! [trait-specialization]: https://rust-lang.github.io/rustc-guide/traits/specialization.html
 
 use hir::def_id::{DefId, LOCAL_CRATE};
 use syntax_pos::DUMMY_SP;
diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs
index 8c3cd5e6612b9..e582a9020464d 100644
--- a/src/librustc/traits/mod.rs
+++ b/src/librustc/traits/mod.rs
@@ -10,7 +10,7 @@
 
 //! Trait Resolution. See [rustc guide] for more info on how this works.
 //!
-//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/traits/resolution.html
+//! [rustc guide]: https://rust-lang.github.io/rustc-guide/traits/resolution.html
 
 pub use self::SelectionError::*;
 pub use self::FulfillmentErrorCode::*;
diff --git a/src/librustc/traits/query/type_op/mod.rs b/src/librustc/traits/query/type_op/mod.rs
index d20d43cf7578c..f8f9650ebe1ae 100644
--- a/src/librustc/traits/query/type_op/mod.rs
+++ b/src/librustc/traits/query/type_op/mod.rs
@@ -53,7 +53,7 @@ pub trait TypeOp<'gcx, 'tcx>: Sized + fmt::Debug {
 /// first canonicalize the key and then invoke the query on the tcx,
 /// which produces the resulting query region constraints.
 ///
-/// [c]: https://rust-lang-nursery.github.io/rustc-guide/traits/canonicalization.html
+/// [c]: https://rust-lang.github.io/rustc-guide/traits/canonicalization.html
 pub trait QueryTypeOp<'gcx: 'tcx, 'tcx>:
     fmt::Debug + Sized + TypeFoldable<'tcx> + Lift<'gcx>
 {
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index 0f59f478cb415..fb4c9f3bad715 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -10,7 +10,7 @@
 
 //! See [rustc guide] for more info on how this works.
 //!
-//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/traits/resolution.html#selection
+//! [rustc guide]: https://rust-lang.github.io/rustc-guide/traits/resolution.html#selection
 
 use self::EvaluationResult::*;
 use self::SelectionCandidate::*;
@@ -1173,7 +1173,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
     // candidates. See [rustc guide] for more details.
     //
     // [rustc guide]:
-    // https://rust-lang-nursery.github.io/rustc-guide/traits/resolution.html#candidate-assembly
+    // https://rust-lang.github.io/rustc-guide/traits/resolution.html#candidate-assembly
 
     fn candidate_from_obligation<'o>(
         &mut self,
@@ -2720,7 +2720,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
     // type error.  See [rustc guide] for more details.
     //
     // [rustc guide]:
-    // https://rust-lang-nursery.github.io/rustc-guide/traits/resolution.html#confirmation
+    // https://rust-lang.github.io/rustc-guide/traits/resolution.html#confirmation
 
     fn confirm_candidate(
         &mut self,
diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs
index d3dc1655b0df2..19ef3171b13fc 100644
--- a/src/librustc/traits/specialize/mod.rs
+++ b/src/librustc/traits/specialize/mod.rs
@@ -17,7 +17,7 @@
 //! See the [rustc guide] for a bit more detail on how specialization
 //! fits together with the rest of the trait machinery.
 //!
-//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/traits/specialization.html
+//! [rustc guide]: https://rust-lang.github.io/rustc-guide/traits/specialization.html
 
 use super::{SelectionContext, FulfillmentContext};
 use super::util::impl_trait_ref_and_oblig;
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 22d5ea6e4bc93..9f26499e770da 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -876,7 +876,7 @@ pub struct FreeRegionInfo {
 /// various **compiler queries** that have been performed. See the
 /// [rustc guide] for more details.
 ///
-/// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/ty.html
+/// [rustc guide]: https://rust-lang.github.io/rustc-guide/ty.html
 #[derive(Copy, Clone)]
 pub struct TyCtxt<'a, 'gcx: 'tcx, 'tcx: 'a> {
     gcx: &'a GlobalCtxt<'gcx>,
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index 3056abba95626..a18e3a275467d 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -1138,7 +1138,7 @@ pub type Region<'tcx> = &'tcx RegionKind;
 ///
 /// [1]: http://smallcultfollowing.com/babysteps/blog/2013/10/29/intermingled-parameter-lists/
 /// [2]: http://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/
-/// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/traits/hrtb.html
+/// [rustc guide]: https://rust-lang.github.io/rustc-guide/traits/hrtb.html
 #[derive(Clone, PartialEq, Eq, Hash, Copy, RustcEncodable, RustcDecodable, PartialOrd, Ord)]
 pub enum RegionKind {
     // Region bound in a type or fn declaration which will be
diff --git a/src/librustc_borrowck/borrowck/README.md b/src/librustc_borrowck/borrowck/README.md
index 8bc0b4969b8f9..a05c56e3629a3 100644
--- a/src/librustc_borrowck/borrowck/README.md
+++ b/src/librustc_borrowck/borrowck/README.md
@@ -3,7 +3,7 @@
 > WARNING: This README is more or less obsolete, and will be removed
 > soon! The new system is described in the [rustc guide].
 
-[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir/borrowck.html
+[rustc guide]: https://rust-lang.github.io/rustc-guide/mir/borrowck.html
 
 This pass has the job of enforcing memory safety. This is a subtle
 topic. This docs aim to explain both the practice and the theory
diff --git a/src/librustc_codegen_llvm/README.md b/src/librustc_codegen_llvm/README.md
index 8d1c9a52b2428..dda2e5ac18f01 100644
--- a/src/librustc_codegen_llvm/README.md
+++ b/src/librustc_codegen_llvm/README.md
@@ -4,4 +4,4 @@ that runs towards the end of the compilation process.
 
 For more information about how codegen works, see the [rustc guide].
 
-[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/codegen.html
+[rustc guide]: https://rust-lang.github.io/rustc-guide/codegen.html
diff --git a/src/librustc_driver/README.md b/src/librustc_driver/README.md
index fef249a9e4eb8..c4d73953e9b2e 100644
--- a/src/librustc_driver/README.md
+++ b/src/librustc_driver/README.md
@@ -7,4 +7,4 @@ options).
 
 For more information about how the driver works, see the [rustc guide].
 
-[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/rustc-driver.html
+[rustc guide]: https://rust-lang.github.io/rustc-guide/rustc-driver.html
diff --git a/src/librustc_target/README.md b/src/librustc_target/README.md
index f5b1acb192133..a22000ea9d280 100644
--- a/src/librustc_target/README.md
+++ b/src/librustc_target/README.md
@@ -3,4 +3,4 @@ specific to different compilation targets and so forth.
 
 For more information about how rustc works, see the [rustc guide].
 
-[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/
+[rustc guide]: https://rust-lang.github.io/rustc-guide/
diff --git a/src/librustc_typeck/README.md b/src/librustc_typeck/README.md
index f00597cb27f0c..fdcbd935524db 100644
--- a/src/librustc_typeck/README.md
+++ b/src/librustc_typeck/README.md
@@ -1,5 +1,5 @@
 For high-level intro to how type checking works in rustc, see the
 [type checking] chapter of the [rustc guide].
 
-[type checking]: https://rust-lang-nursery.github.io/rustc-guide/type-checking.html
-[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/
+[type checking]: https://rust-lang.github.io/rustc-guide/type-checking.html
+[rustc guide]: https://rust-lang.github.io/rustc-guide/
diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs
index ac338ba667865..37f4ae56779b2 100644
--- a/src/librustc_typeck/check/method/mod.rs
+++ b/src/librustc_typeck/check/method/mod.rs
@@ -10,7 +10,7 @@
 
 //! Method lookup: the secret sauce of Rust. See the [rustc guide] chapter.
 //!
-//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/method-lookup.html
+//! [rustc guide]: https://rust-lang.github.io/rustc-guide/method-lookup.html
 
 use check::FnCtxt;
 use hir::def::Def;
diff --git a/src/librustc_typeck/variance/mod.rs b/src/librustc_typeck/variance/mod.rs
index 7cc56bc192bb2..e3c82d50a8d9b 100644
--- a/src/librustc_typeck/variance/mod.rs
+++ b/src/librustc_typeck/variance/mod.rs
@@ -11,7 +11,7 @@
 //! Module for inferring the variance of type and lifetime parameters. See the [rustc guide]
 //! chapter for more info.
 //!
-//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/variance.html
+//! [rustc guide]: https://rust-lang.github.io/rustc-guide/variance.html
 
 use arena;
 use rustc::hir;
diff --git a/src/librustc_typeck/variance/terms.rs b/src/librustc_typeck/variance/terms.rs
index 087d53b92d496..3692221a3fc3f 100644
--- a/src/librustc_typeck/variance/terms.rs
+++ b/src/librustc_typeck/variance/terms.rs
@@ -89,8 +89,8 @@ pub fn determine_parameters_to_be_inferred<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>
 
     // See the following for a discussion on dep-graph management.
     //
-    // - https://rust-lang-nursery.github.io/rustc-guide/query.html
-    // - https://rust-lang-nursery.github.io/rustc-guide/variance.html
+    // - https://rust-lang.github.io/rustc-guide/query.html
+    // - https://rust-lang.github.io/rustc-guide/variance.html
     tcx.hir.krate().visit_all_item_likes(&mut terms_cx);
 
     terms_cx
diff --git a/src/librustdoc/README.md b/src/librustdoc/README.md
index 2cfe43a8389bb..e4f7bc30e3fcf 100644
--- a/src/librustdoc/README.md
+++ b/src/librustdoc/README.md
@@ -1,3 +1,3 @@
 For more information about how `librustdoc` works, see the [rustc guide].
 
-[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/rustdoc.html
+[rustc guide]: https://rust-lang.github.io/rustc-guide/rustdoc.html
diff --git a/src/libsyntax/README.md b/src/libsyntax/README.md
index 7214203830e74..daa252ef4551b 100644
--- a/src/libsyntax/README.md
+++ b/src/libsyntax/README.md
@@ -5,5 +5,5 @@ lexer, macro expander, and utilities for traversing ASTs.
 For more information about how these things work in rustc, see the
 rustc guide:
 
-- [Parsing](https://rust-lang-nursery.github.io/rustc-guide/the-parser.html)
-- [Macro Expansion](https://rust-lang-nursery.github.io/rustc-guide/macro-expansion.html)
+- [Parsing](https://rust-lang.github.io/rustc-guide/the-parser.html)
+- [Macro Expansion](https://rust-lang.github.io/rustc-guide/macro-expansion.html)
diff --git a/src/test/COMPILER_TESTS.md b/src/test/COMPILER_TESTS.md
index 81a46ea0fe718..c4ca478134399 100644
--- a/src/test/COMPILER_TESTS.md
+++ b/src/test/COMPILER_TESTS.md
@@ -1,4 +1,4 @@
 # Compiler Test Documentation
 
 Documentation the compiler testing framework has moved to
-[the rustc guide](https://rust-lang-nursery.github.io/rustc-guide/tests/intro.html).
+[the rustc guide](https://rust-lang.github.io/rustc-guide/tests/intro.html).

From 6f028fe8e0db8c1251f24d694fc001aa933cf0ea Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar>
Date: Mon, 26 Nov 2018 13:58:46 -0800
Subject: [PATCH 35/50] Specify suggestion applicability

---
 src/libsyntax/parse/parser.rs | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index ab5afaf3d99fe..c224f18259294 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -5247,9 +5247,10 @@ impl<'a> Parser<'a> {
                 "lifetime parameters must be declared prior to type parameters",
             );
             if !suggestions.is_empty() {
-                err.multipart_suggestion(
+                err.multipart_suggestion_with_applicability(
                     "move the lifetime parameter prior to the first type parameter",
                     suggestions,
+                    Applicability::MachineApplicable,
                 );
             }
             err.emit();

From d4a6e739f3322c56e66fa8fef31569b7f16bc325 Mon Sep 17 00:00:00 2001
From: ljedrz <ljedrz@gmail.com>
Date: Fri, 9 Nov 2018 15:12:09 +0100
Subject: [PATCH 36/50] Use sort_by_cached_key when key the function is not
 trivial/free

---
 src/librustc/middle/resolve_lifetime.rs       | 2 +-
 src/librustc/traits/object_safety.rs          | 2 +-
 src/librustc_mir/monomorphize/partitioning.rs | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index 6ff450508d136..07054ee99af76 100644
--- a/src/librustc/middle/resolve_lifetime.rs
+++ b/src/librustc/middle/resolve_lifetime.rs
@@ -1573,7 +1573,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
             .collect();
 
         // ensure that we issue lints in a repeatable order
-        def_ids.sort_by_key(|&def_id| self.tcx.def_path_hash(def_id));
+        def_ids.sort_by_cached_key(|&def_id| self.tcx.def_path_hash(def_id));
 
         for def_id in def_ids {
             debug!(
diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs
index c79fa3861234f..2909daf22b3ba 100644
--- a/src/librustc/traits/object_safety.rs
+++ b/src/librustc/traits/object_safety.rs
@@ -409,7 +409,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
             .collect::<Vec<_>>();
 
         // existential predicates need to be in a specific order
-        associated_types.sort_by_key(|item| self.def_path_hash(item.def_id));
+        associated_types.sort_by_cached_key(|item| self.def_path_hash(item.def_id));
 
         let projection_predicates = associated_types.into_iter().map(|item| {
             ty::ExistentialPredicate::Projection(ty::ExistentialProjection {
diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs
index 6dba020120f84..3a6ee6da42215 100644
--- a/src/librustc_mir/monomorphize/partitioning.rs
+++ b/src/librustc_mir/monomorphize/partitioning.rs
@@ -985,7 +985,7 @@ fn collect_and_partition_mono_items<'a, 'tcx>(
                 output.push_str(" @@");
                 let mut empty = Vec::new();
                 let cgus = item_to_cgus.get_mut(i).unwrap_or(&mut empty);
-                cgus.as_mut_slice().sort_by_key(|&(ref name, _)| name.clone());
+                cgus.as_mut_slice().sort_by_cached_key(|&(ref name, _)| name.clone());
                 cgus.dedup();
                 for &(ref cgu_name, (linkage, _)) in cgus.iter() {
                     output.push_str(" ");

From 6739c0e935ecfc838f818c27bfaa5665b6831e69 Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume1.gomez@gmail.com>
Date: Tue, 27 Nov 2018 09:59:44 +0100
Subject: [PATCH 37/50] Add missing doc link

---
 src/libcore/iter/iterator.rs | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs
index fd4189ef50df5..3063cb1a7df44 100644
--- a/src/libcore/iter/iterator.rs
+++ b/src/libcore/iter/iterator.rs
@@ -519,7 +519,7 @@ pub trait Iterator {
     /// element.
     ///
     /// `map()` transforms one iterator into another, by means of its argument:
-    /// something that implements `FnMut`. It produces a new iterator which
+    /// something that implements [`FnMut`]. It produces a new iterator which
     /// calls this closure on each element of the original iterator.
     ///
     /// If you are good at thinking in types, you can think of `map()` like this:
@@ -533,6 +533,7 @@ pub trait Iterator {
     /// more idiomatic to use [`for`] than `map()`.
     ///
     /// [`for`]: ../../book/ch03-05-control-flow.html#looping-through-a-collection-with-for
+    /// [`FnMut`]: ../../std/ops/trait.FnMut.html
     ///
     /// # Examples
     ///

From a8f9302047c97a07ecce3a85cdf222ff4da0d1e7 Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Sat, 17 Nov 2018 13:57:53 +0100
Subject: [PATCH 38/50] avoid features_untracked

---
 src/librustc/ty/constness.rs                 |  2 +-
 src/librustc_mir/transform/qualify_consts.rs | 18 +++++++++---------
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/src/librustc/ty/constness.rs b/src/librustc/ty/constness.rs
index 47aea7a5f0796..e32913b8905b7 100644
--- a/src/librustc/ty/constness.rs
+++ b/src/librustc/ty/constness.rs
@@ -66,7 +66,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
             }
         } else {
             // users enabling the `const_fn` feature gate can do what they want
-            !self.sess.features_untracked().const_fn
+            !self.features().const_fn
         }
     }
 }
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index fc2c6c3ab1f37..09fe7b14c7973 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -357,7 +357,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
                 TerminatorKind::FalseUnwind { .. } => None,
 
                 TerminatorKind::Return => {
-                    if !self.tcx.sess.features_untracked().const_let {
+                    if !self.tcx.features().const_let {
                         // Check for unused values. This usually means
                         // there are extra statements in the AST.
                         for temp in mir.temps_iter() {
@@ -464,7 +464,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
             LocalKind::ReturnPointer => {
                 self.not_const();
             }
-            LocalKind::Var if !self.tcx.sess.features_untracked().const_let => {
+            LocalKind::Var if !self.tcx.features().const_let => {
                 if self.mode != Mode::Fn {
                     emit_feature_err(&self.tcx.sess.parse_sess, "const_let",
                                     self.span, GateIssue::Language,
@@ -558,7 +558,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
                                 Mode::Fn => {},
                                 _ => {
                                     if let ty::RawPtr(_) = base_ty.sty {
-                                        if !this.tcx.sess.features_untracked().const_raw_ptr_deref {
+                                        if !this.tcx.features().const_raw_ptr_deref {
                                             emit_feature_err(
                                                 &this.tcx.sess.parse_sess, "const_raw_ptr_deref",
                                                 this.span, GateIssue::Language,
@@ -581,7 +581,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
                                     match this.mode {
                                         Mode::Fn => this.not_const(),
                                         Mode::ConstFn => {
-                                            if !this.tcx.sess.features_untracked().const_fn_union {
+                                            if !this.tcx.features().const_fn_union {
                                                 emit_feature_err(
                                                     &this.tcx.sess.parse_sess, "const_fn_union",
                                                     this.span, GateIssue::Language,
@@ -807,7 +807,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
                         if let Mode::Fn = self.mode {
                             // in normal functions, mark such casts as not promotable
                             self.add(Qualif::NOT_CONST);
-                        } else if !self.tcx.sess.features_untracked().const_raw_ptr_to_usize_cast {
+                        } else if !self.tcx.features().const_raw_ptr_to_usize_cast {
                             // in const fn and constants require the feature gate
                             // FIXME: make it unsafe inside const fn and constants
                             emit_feature_err(
@@ -834,7 +834,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
                     if let Mode::Fn = self.mode {
                         // raw pointer operations are not allowed inside promoteds
                         self.add(Qualif::NOT_CONST);
-                    } else if !self.tcx.sess.features_untracked().const_compare_raw_pointers {
+                    } else if !self.tcx.features().const_compare_raw_pointers {
                         // require the feature gate inside constants and const fn
                         // FIXME: make it unsafe to use these operations
                         emit_feature_err(
@@ -933,7 +933,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
                                 if self.mode != Mode::Fn {
                                     is_const_fn = true;
                                     // const eval transmute calls only with the feature gate
-                                    if !self.tcx.sess.features_untracked().const_transmute {
+                                    if !self.tcx.features().const_transmute {
                                         emit_feature_err(
                                             &self.tcx.sess.parse_sess, "const_transmute",
                                             self.span, GateIssue::Language,
@@ -971,7 +971,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
                                 // FIXME: cannot allow this inside `allow_internal_unstable` because
                                 // that would make `panic!` insta stable in constants, since the
                                 // macro is marked with the attr
-                                if self.tcx.sess.features_untracked().const_panic {
+                                if self.tcx.features().const_panic {
                                     is_const_fn = true;
                                 } else {
                                     // don't allow panics in constants without the feature gate
@@ -1158,7 +1158,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
         if let (Mode::ConstFn, &Place::Local(index)) = (self.mode, dest) {
             if self.mir.local_kind(index) == LocalKind::Var &&
                self.const_fn_arg_vars.insert(index) &&
-               !self.tcx.sess.features_untracked().const_let {
+               !self.tcx.features().const_let {
 
                 // Direct use of an argument is permitted.
                 match *rvalue {

From c4e0b89454ae8eb8d888830fa2563f8d5c52fe07 Mon Sep 17 00:00:00 2001
From: Marc-Antoine Perennou <Marc-Antoine@Perennou.com>
Date: Sat, 24 Nov 2018 10:13:27 +0100
Subject: [PATCH 39/50] move stage0.txt to toplevel directory

This way all files needed by packagers now reside in toplevel

Signed-off-by: Marc-Antoine Perennou <Marc-Antoine@Perennou.com>
---
 config.toml.example             | 4 ++--
 src/bootstrap/bootstrap.py      | 2 +-
 src/bootstrap/bootstrap_test.py | 3 +--
 src/bootstrap/lib.rs            | 2 +-
 src/bootstrap/sanity.rs         | 2 +-
 src/stage0.txt => stage0.txt    | 0
 6 files changed, 6 insertions(+), 7 deletions(-)
 rename src/stage0.txt => stage0.txt (100%)

diff --git a/config.toml.example b/config.toml.example
index 8b11014edae79..fefbb227f00b9 100644
--- a/config.toml.example
+++ b/config.toml.example
@@ -112,11 +112,11 @@
 # for each target triple.
 #target = ["x86_64-unknown-linux-gnu"] # defaults to just the build triple
 
-# Instead of downloading the src/stage0.txt version of Cargo specified, use
+# Instead of downloading the stage0.txt version of Cargo specified, use
 # this Cargo binary instead to build all Rust code
 #cargo = "/path/to/bin/cargo"
 
-# Instead of downloading the src/stage0.txt version of the compiler
+# Instead of downloading the stage0.txt version of the compiler
 # specified, use this rustc binary instead as the stage0 snapshot compiler.
 #rustc = "/path/to/bin/rustc"
 
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index d143dffb24be5..b36c1bd7bb13b 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -154,7 +154,7 @@ def run(args, verbose=False, exception=False, **kwargs):
 
 def stage0_data(rust_root):
     """Build a dictionary from stage0.txt"""
-    nightlies = os.path.join(rust_root, "src/stage0.txt")
+    nightlies = os.path.join(rust_root, "stage0.txt")
     with open(nightlies, 'r') as nightlies:
         lines = [line.rstrip() for line in nightlies
                  if not line.startswith("#")]
diff --git a/src/bootstrap/bootstrap_test.py b/src/bootstrap/bootstrap_test.py
index 4db7e2ec016f0..43cbe9967e312 100644
--- a/src/bootstrap/bootstrap_test.py
+++ b/src/bootstrap/bootstrap_test.py
@@ -28,8 +28,7 @@ class Stage0DataTestCase(unittest.TestCase):
     def setUp(self):
         self.rust_root = tempfile.mkdtemp()
         os.mkdir(os.path.join(self.rust_root, "src"))
-        with open(os.path.join(self.rust_root, "src",
-                               "stage0.txt"), "w") as stage0:
+        with open(os.path.join(self.rust_root, "stage0.txt"), "w") as stage0:
             stage0.write("#ignore\n\ndate: 2017-06-15\nrustc: beta\ncargo: beta")
 
     def tearDown(self):
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 76697e482d3a8..548d5312dc7ce 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -41,7 +41,7 @@
 //! When you execute `x.py build`, the steps which are executed are:
 //!
 //! * First, the python script is run. This will automatically download the
-//!   stage0 rustc and cargo according to `src/stage0.txt`, or use the cached
+//!   stage0 rustc and cargo according to `stage0.txt`, or use the cached
 //!   versions if they're available. These are then used to compile rustbuild
 //!   itself (using Cargo). Finally, control is then transferred to rustbuild.
 //!
diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs
index 15d3bccba09cc..c62ce5a5b93a2 100644
--- a/src/bootstrap/sanity.rs
+++ b/src/bootstrap/sanity.rs
@@ -236,7 +236,7 @@ $ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake
 
     if build.config.channel == "stable" {
         let mut stage0 = String::new();
-        t!(t!(File::open(build.src.join("src/stage0.txt")))
+        t!(t!(File::open(build.src.join("stage0.txt")))
             .read_to_string(&mut stage0));
         if stage0.contains("\ndev:") {
             panic!("bootstrapping from a dev compiler in a stable release, but \
diff --git a/src/stage0.txt b/stage0.txt
similarity index 100%
rename from src/stage0.txt
rename to stage0.txt

From 73b656bbb306047d072b41321153b62c5a4a2b0d Mon Sep 17 00:00:00 2001
From: Marius Nuennerich <marius@nuenneri.ch>
Date: Tue, 27 Nov 2018 18:57:55 +0100
Subject: [PATCH 40/50] Fix small typo in comment

---
 src/libstd/thread/mod.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs
index 8a845efd41362..3a9f3ec5c6fc1 100644
--- a/src/libstd/thread/mod.rs
+++ b/src/libstd/thread/mod.rs
@@ -326,7 +326,7 @@ impl Builder {
     /// Sets the size of the stack (in bytes) for the new thread.
     ///
     /// The actual stack size may be greater than this value if
-    /// the platform specifies minimal stack size.
+    /// the platform specifies a minimal stack size.
     ///
     /// For more information about the stack size for threads, see
     /// [this module-level documentation][stack-size].

From c75ed34732f67ce41faf84e22e4896cabab14a40 Mon Sep 17 00:00:00 2001
From: Mark Mansi <markm@cs.wisc.edu>
Date: Sat, 24 Nov 2018 16:09:37 -0600
Subject: [PATCH 41/50] move feature gate to accepted

---
 src/libsyntax/feature_gate.rs | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 73567765a04c4..cd503f25cfe68 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -393,9 +393,6 @@ declare_features! (
     // `extern` in paths
     (active, extern_in_paths, "1.23.0", Some(55600), None),
 
-    // Use `?` as the Kleene "at most one" operator
-    (active, macro_at_most_once_rep, "1.25.0", Some(48075), None),
-
     // Infer static outlives requirements; RFC 2093
     (active, infer_static_outlives_requirements, "1.26.0", Some(54185), None),
 
@@ -689,6 +686,8 @@ declare_features! (
     (accepted, extern_crate_item_prelude, "1.31.0", Some(55599), None),
     // Allows use of the :literal macro fragment specifier (RFC 1576)
     (accepted, macro_literal_matcher, "1.31.0", Some(35625), None),
+    // Use `?` as the Kleene "at most one" operator
+    (accepted, macro_at_most_once_rep, "1.32.0", Some(48075), None),
 );
 
 // If you change this, please modify src/doc/unstable-book as well. You must

From a542e48871e040ea2db3b4fad5d88a83b6200855 Mon Sep 17 00:00:00 2001
From: Mark Mansi <markm@cs.wisc.edu>
Date: Sat, 24 Nov 2018 16:12:16 -0600
Subject: [PATCH 42/50] remove feature gate

---
 src/libsyntax/ext/tt/quoted.rs | 46 ++++++----------------------------
 src/libsyntax/feature_gate.rs  |  3 ---
 2 files changed, 7 insertions(+), 42 deletions(-)

diff --git a/src/libsyntax/ext/tt/quoted.rs b/src/libsyntax/ext/tt/quoted.rs
index 218486748315d..c8ece7b3a88fd 100644
--- a/src/libsyntax/ext/tt/quoted.rs
+++ b/src/libsyntax/ext/tt/quoted.rs
@@ -576,22 +576,7 @@ where
     let span = match parse_kleene_op(input, span) {
         // #1 is a `?` (needs feature gate)
         Ok(Ok((op, op1_span))) if op == KleeneOp::ZeroOrOne => {
-            if !features.macro_at_most_once_rep
-                && !attr::contains_name(attrs, "allow_internal_unstable")
-            {
-                let explain = feature_gate::EXPLAIN_MACRO_AT_MOST_ONCE_REP;
-                emit_feature_err(
-                    sess,
-                    "macro_at_most_once_rep",
-                    op1_span,
-                    GateIssue::Language,
-                    explain,
-                );
-
-                op1_span
-            } else {
-                return (None, op);
-            }
+            return (None, op);
         }
 
         // #1 is a `+` or `*` KleeneOp
@@ -602,22 +587,10 @@ where
             // #2 is the `?` Kleene op, which does not take a separator (error)
             Ok(Ok((op, op2_span))) if op == KleeneOp::ZeroOrOne => {
                 // Error!
-
-                if !features.macro_at_most_once_rep
-                    && !attr::contains_name(attrs, "allow_internal_unstable")
-                {
-                    // FIXME: when `?` as a Kleene op is stabilized, we only need the "does not
-                    // take a macro separator" error (i.e. the `else` case).
-                    sess.span_diagnostic
-                        .struct_span_err(op2_span, "expected `*` or `+`")
-                        .note("`?` is not a macro repetition operator")
-                        .emit();
-                } else {
-                    sess.span_diagnostic.span_err(
-                        span,
-                        "the `?` macro repetition operator does not take a separator",
-                    );
-                }
+                sess.span_diagnostic.span_err(
+                    span,
+                    "the `?` macro repetition operator does not take a separator",
+                );
 
                 // Return a dummy
                 return (None, KleeneOp::ZeroOrMore);
@@ -638,13 +611,8 @@ where
     };
 
     // If we ever get to this point, we have experienced an "unexpected token" error
-
-    if !features.macro_at_most_once_rep && !attr::contains_name(attrs, "allow_internal_unstable") {
-        sess.span_diagnostic.span_err(span, "expected `*` or `+`");
-    } else {
-        sess.span_diagnostic
-            .span_err(span, "expected one of: `*`, `+`, or `?`");
-    }
+    sess.span_diagnostic
+        .span_err(span, "expected one of: `*`, `+`, or `?`");
 
     // Return a dummy
     (None, KleeneOp::ZeroOrMore)
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index cd503f25cfe68..3bc349170514c 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -1426,9 +1426,6 @@ pub const EXPLAIN_DERIVE_UNDERSCORE: &'static str =
 pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &'static str =
     "unsized tuple coercion is not stable enough for use and is subject to change";
 
-pub const EXPLAIN_MACRO_AT_MOST_ONCE_REP: &'static str =
-    "using the `?` macro Kleene operator for \"at most one\" repetition is unstable";
-
 struct PostExpansionVisitor<'a> {
     context: &'a Context<'a>,
 }

From 32aafb220313fbc91e8f55b12886d77d3e1cf24b Mon Sep 17 00:00:00 2001
From: Mark Mansi <markm@cs.wisc.edu>
Date: Sat, 24 Nov 2018 16:20:25 -0600
Subject: [PATCH 43/50] remove some unused vars

---
 src/libsyntax/ext/tt/quoted.rs | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/libsyntax/ext/tt/quoted.rs b/src/libsyntax/ext/tt/quoted.rs
index c8ece7b3a88fd..edc431be3694b 100644
--- a/src/libsyntax/ext/tt/quoted.rs
+++ b/src/libsyntax/ext/tt/quoted.rs
@@ -11,13 +11,13 @@
 use ast::NodeId;
 use early_buffered_lints::BufferedEarlyLintId;
 use ext::tt::macro_parser;
-use feature_gate::{self, emit_feature_err, Features, GateIssue};
+use feature_gate::Features;
 use parse::{token, ParseSess};
 use print::pprust;
 use symbol::keywords;
 use syntax_pos::{edition::Edition, BytePos, Span};
 use tokenstream::{self, DelimSpan};
-use {ast, attr};
+use ast;
 
 use rustc_data_structures::sync::Lrc;
 use std::iter::Peekable;
@@ -566,8 +566,8 @@ fn parse_sep_and_kleene_op_2018<I>(
     input: &mut Peekable<I>,
     span: Span,
     sess: &ParseSess,
-    features: &Features,
-    attrs: &[ast::Attribute],
+    _features: &Features,
+    _attrs: &[ast::Attribute],
 ) -> (Option<token::Token>, KleeneOp)
 where
     I: Iterator<Item = tokenstream::TokenTree>,
@@ -575,7 +575,7 @@ where
     // We basically look at two token trees here, denoted as #1 and #2 below
     let span = match parse_kleene_op(input, span) {
         // #1 is a `?` (needs feature gate)
-        Ok(Ok((op, op1_span))) if op == KleeneOp::ZeroOrOne => {
+        Ok(Ok((op, _op1_span))) if op == KleeneOp::ZeroOrOne => {
             return (None, op);
         }
 
@@ -585,7 +585,7 @@ where
         // #1 is a separator followed by #2, a KleeneOp
         Ok(Err((tok, span))) => match parse_kleene_op(input, span) {
             // #2 is the `?` Kleene op, which does not take a separator (error)
-            Ok(Ok((op, op2_span))) if op == KleeneOp::ZeroOrOne => {
+            Ok(Ok((op, _op2_span))) if op == KleeneOp::ZeroOrOne => {
                 // Error!
                 sess.span_diagnostic.span_err(
                     span,

From e97edad935c8eb05d0c67475e81dbb0618ac72fb Mon Sep 17 00:00:00 2001
From: Mark Mansi <markm@cs.wisc.edu>
Date: Sat, 24 Nov 2018 16:27:13 -0600
Subject: [PATCH 44/50] update tests

---
 ...ost-once-rep-2015-ques-rep-feature-flag.rs | 28 -------
 ...once-rep-2015-ques-rep-feature-flag.stderr | 18 -----
 ...acro-at-most-once-rep-2018-feature-gate.rs | 45 -----------
 ...-at-most-once-rep-2018-feature-gate.stderr | 80 -------------------
 .../ui/macros/macro-at-most-once-rep-2018.rs  | 12 ++-
 .../macros/macro-at-most-once-rep-2018.stderr | 22 ++---
 6 files changed, 16 insertions(+), 189 deletions(-)
 delete mode 100644 src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep-feature-flag.rs
 delete mode 100644 src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep-feature-flag.stderr
 delete mode 100644 src/test/ui/macros/macro-at-most-once-rep-2018-feature-gate.rs
 delete mode 100644 src/test/ui/macros/macro-at-most-once-rep-2018-feature-gate.stderr

diff --git a/src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep-feature-flag.rs b/src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep-feature-flag.rs
deleted file mode 100644
index 63a4ef16a2581..0000000000000
--- a/src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep-feature-flag.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2012 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.
-
-// Test behavior of `?` macro _kleene op_ under the 2015 edition. Namely, it doesn't exist, even
-// with the feature flag.
-
-// gate-test-macro_at_most_once_rep
-// edition:2015
-
-#![feature(macro_at_most_once_rep)]
-
-macro_rules! bar {
-    ($(a)?) => {} //~ERROR expected `*` or `+`
-}
-
-macro_rules! baz {
-    ($(a),?) => {} //~ERROR expected `*` or `+`
-}
-
-fn main() {}
-
diff --git a/src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep-feature-flag.stderr b/src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep-feature-flag.stderr
deleted file mode 100644
index 5f687900421bf..0000000000000
--- a/src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep-feature-flag.stderr
+++ /dev/null
@@ -1,18 +0,0 @@
-error: expected `*` or `+`
-  --> $DIR/macro-at-most-once-rep-2015-ques-rep-feature-flag.rs:20:10
-   |
-LL |     ($(a)?) => {} //~ERROR expected `*` or `+`
-   |          ^
-   |
-   = note: `?` is not a macro repetition operator
-
-error: expected `*` or `+`
-  --> $DIR/macro-at-most-once-rep-2015-ques-rep-feature-flag.rs:24:11
-   |
-LL |     ($(a),?) => {} //~ERROR expected `*` or `+`
-   |           ^
-   |
-   = note: `?` is not a macro repetition operator
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/macros/macro-at-most-once-rep-2018-feature-gate.rs b/src/test/ui/macros/macro-at-most-once-rep-2018-feature-gate.rs
deleted file mode 100644
index ffabf9bcdf685..0000000000000
--- a/src/test/ui/macros/macro-at-most-once-rep-2018-feature-gate.rs
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2012 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 gate test for macro_at_most_once_rep under 2018 edition.
-
-// gate-test-macro_at_most_once_rep
-// edition:2018
-
-macro_rules! foo {
-    ($(a)?) => {}
-    //~^ERROR using the `?` macro Kleene operator for
-    //~|ERROR expected `*` or `+`
-}
-
-macro_rules! baz {
-    ($(a),?) => {} //~ERROR expected `*` or `+`
-}
-
-macro_rules! barplus {
-    ($(a)?+) => {}
-    //~^ERROR using the `?` macro Kleene operator for
-    //~|ERROR expected `*` or `+`
-}
-
-macro_rules! barstar {
-    ($(a)?*) => {}
-    //~^ERROR using the `?` macro Kleene operator for
-    //~|ERROR expected `*` or `+`
-}
-
-pub fn main() {
-    foo!();
-    foo!(a);
-    foo!(a?); //~ ERROR no rules expected the token `?`
-    foo!(a?a); //~ ERROR no rules expected the token `?`
-    foo!(a?a?a); //~ ERROR no rules expected the token `?`
-}
-
diff --git a/src/test/ui/macros/macro-at-most-once-rep-2018-feature-gate.stderr b/src/test/ui/macros/macro-at-most-once-rep-2018-feature-gate.stderr
deleted file mode 100644
index 27dc03e1c3981..0000000000000
--- a/src/test/ui/macros/macro-at-most-once-rep-2018-feature-gate.stderr
+++ /dev/null
@@ -1,80 +0,0 @@
-error[E0658]: using the `?` macro Kleene operator for "at most one" repetition is unstable (see issue #48075)
-  --> $DIR/macro-at-most-once-rep-2018-feature-gate.rs:17:10
-   |
-LL |     ($(a)?) => {}
-   |          ^
-   |
-   = help: add #![feature(macro_at_most_once_rep)] to the crate attributes to enable
-
-error: expected `*` or `+`
-  --> $DIR/macro-at-most-once-rep-2018-feature-gate.rs:17:10
-   |
-LL |     ($(a)?) => {}
-   |          ^
-
-error: expected `*` or `+`
-  --> $DIR/macro-at-most-once-rep-2018-feature-gate.rs:23:11
-   |
-LL |     ($(a),?) => {} //~ERROR expected `*` or `+`
-   |           ^
-   |
-   = note: `?` is not a macro repetition operator
-
-error[E0658]: using the `?` macro Kleene operator for "at most one" repetition is unstable (see issue #48075)
-  --> $DIR/macro-at-most-once-rep-2018-feature-gate.rs:27:10
-   |
-LL |     ($(a)?+) => {}
-   |          ^
-   |
-   = help: add #![feature(macro_at_most_once_rep)] to the crate attributes to enable
-
-error: expected `*` or `+`
-  --> $DIR/macro-at-most-once-rep-2018-feature-gate.rs:27:10
-   |
-LL |     ($(a)?+) => {}
-   |          ^
-
-error[E0658]: using the `?` macro Kleene operator for "at most one" repetition is unstable (see issue #48075)
-  --> $DIR/macro-at-most-once-rep-2018-feature-gate.rs:33:10
-   |
-LL |     ($(a)?*) => {}
-   |          ^
-   |
-   = help: add #![feature(macro_at_most_once_rep)] to the crate attributes to enable
-
-error: expected `*` or `+`
-  --> $DIR/macro-at-most-once-rep-2018-feature-gate.rs:33:10
-   |
-LL |     ($(a)?*) => {}
-   |          ^
-
-error: no rules expected the token `?`
-  --> $DIR/macro-at-most-once-rep-2018-feature-gate.rs:41:11
-   |
-LL | macro_rules! foo {
-   | ---------------- when calling this macro
-...
-LL |     foo!(a?); //~ ERROR no rules expected the token `?`
-   |           ^ no rules expected this token in macro call
-
-error: no rules expected the token `?`
-  --> $DIR/macro-at-most-once-rep-2018-feature-gate.rs:42:11
-   |
-LL | macro_rules! foo {
-   | ---------------- when calling this macro
-...
-LL |     foo!(a?a); //~ ERROR no rules expected the token `?`
-   |           ^ no rules expected this token in macro call
-
-error: no rules expected the token `?`
-  --> $DIR/macro-at-most-once-rep-2018-feature-gate.rs:43:11
-   |
-LL | macro_rules! foo {
-   | ---------------- when calling this macro
-...
-LL |     foo!(a?a?a); //~ ERROR no rules expected the token `?`
-   |           ^ no rules expected this token in macro call
-
-error: aborting due to 10 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/macros/macro-at-most-once-rep-2018.rs b/src/test/ui/macros/macro-at-most-once-rep-2018.rs
index 5dabe8d952801..d8012c05acf8f 100644
--- a/src/test/ui/macros/macro-at-most-once-rep-2018.rs
+++ b/src/test/ui/macros/macro-at-most-once-rep-2018.rs
@@ -12,22 +12,20 @@
 
 // edition:2018
 
-#![feature(macro_at_most_once_rep)]
-
 macro_rules! foo {
-    ($(a)?) => {}
+    ($(a)?) => {};
 }
 
 macro_rules! baz {
-    ($(a),?) => {} //~ERROR the `?` macro repetition operator
+    ($(a),?) => {}; //~ERROR the `?` macro repetition operator
 }
 
 macro_rules! barplus {
-    ($(a)?+) => {} // ok. matches "a+" and "+"
+    ($(a)?+) => {}; // ok. matches "a+" and "+"
 }
 
 macro_rules! barstar {
-    ($(a)?*) => {} // ok. matches "a*" and "*"
+    ($(a)?*) => {}; // ok. matches "a*" and "*"
 }
 
 pub fn main() {
@@ -41,7 +39,7 @@ pub fn main() {
     barplus!(a); //~ERROR unexpected end of macro invocation
     barplus!(a?); //~ ERROR no rules expected the token `?`
     barplus!(a?a); //~ ERROR no rules expected the token `?`
-    barplus!(a+);
+    barplus!(a);
     barplus!(+);
 
     barstar!(); //~ERROR unexpected end of macro invocation
diff --git a/src/test/ui/macros/macro-at-most-once-rep-2018.stderr b/src/test/ui/macros/macro-at-most-once-rep-2018.stderr
index d363b672680ee..efe0a2672c83c 100644
--- a/src/test/ui/macros/macro-at-most-once-rep-2018.stderr
+++ b/src/test/ui/macros/macro-at-most-once-rep-2018.stderr
@@ -1,11 +1,11 @@
 error: the `?` macro repetition operator does not take a separator
-  --> $DIR/macro-at-most-once-rep-2018.rs:22:10
+  --> $DIR/macro-at-most-once-rep-2018.rs:20:10
    |
 LL |     ($(a),?) => {} //~ERROR the `?` macro repetition operator
    |          ^
 
 error: no rules expected the token `?`
-  --> $DIR/macro-at-most-once-rep-2018.rs:36:11
+  --> $DIR/macro-at-most-once-rep-2018.rs:34:11
    |
 LL | macro_rules! foo {
    | ---------------- when calling this macro
@@ -14,7 +14,7 @@ LL |     foo!(a?); //~ ERROR no rules expected the token `?`
    |           ^ no rules expected this token in macro call
 
 error: no rules expected the token `?`
-  --> $DIR/macro-at-most-once-rep-2018.rs:37:11
+  --> $DIR/macro-at-most-once-rep-2018.rs:35:11
    |
 LL | macro_rules! foo {
    | ---------------- when calling this macro
@@ -23,7 +23,7 @@ LL |     foo!(a?a); //~ ERROR no rules expected the token `?`
    |           ^ no rules expected this token in macro call
 
 error: no rules expected the token `?`
-  --> $DIR/macro-at-most-once-rep-2018.rs:38:11
+  --> $DIR/macro-at-most-once-rep-2018.rs:36:11
    |
 LL | macro_rules! foo {
    | ---------------- when calling this macro
@@ -32,7 +32,7 @@ LL |     foo!(a?a?a); //~ ERROR no rules expected the token `?`
    |           ^ no rules expected this token in macro call
 
 error: unexpected end of macro invocation
-  --> $DIR/macro-at-most-once-rep-2018.rs:40:5
+  --> $DIR/macro-at-most-once-rep-2018.rs:38:5
    |
 LL | macro_rules! barplus {
    | -------------------- when calling this macro
@@ -50,7 +50,7 @@ LL |     barplus!(a); //~ERROR unexpected end of macro invocation
    |               ^ missing tokens in macro arguments
 
 error: no rules expected the token `?`
-  --> $DIR/macro-at-most-once-rep-2018.rs:42:15
+  --> $DIR/macro-at-most-once-rep-2018.rs:40:15
    |
 LL | macro_rules! barplus {
    | -------------------- when calling this macro
@@ -59,7 +59,7 @@ LL |     barplus!(a?); //~ ERROR no rules expected the token `?`
    |               ^ no rules expected this token in macro call
 
 error: no rules expected the token `?`
-  --> $DIR/macro-at-most-once-rep-2018.rs:43:15
+  --> $DIR/macro-at-most-once-rep-2018.rs:41:15
    |
 LL | macro_rules! barplus {
    | -------------------- when calling this macro
@@ -68,7 +68,7 @@ LL |     barplus!(a?a); //~ ERROR no rules expected the token `?`
    |               ^ no rules expected this token in macro call
 
 error: unexpected end of macro invocation
-  --> $DIR/macro-at-most-once-rep-2018.rs:47:5
+  --> $DIR/macro-at-most-once-rep-2018.rs:45:5
    |
 LL | macro_rules! barstar {
    | -------------------- when calling this macro
@@ -77,7 +77,7 @@ LL |     barstar!(); //~ERROR unexpected end of macro invocation
    |     ^^^^^^^^^^^ missing tokens in macro arguments
 
 error: unexpected end of macro invocation
-  --> $DIR/macro-at-most-once-rep-2018.rs:48:15
+  --> $DIR/macro-at-most-once-rep-2018.rs:46:14
    |
 LL | macro_rules! barstar {
    | -------------------- when calling this macro
@@ -86,7 +86,7 @@ LL |     barstar!(a); //~ERROR unexpected end of macro invocation
    |               ^ missing tokens in macro arguments
 
 error: no rules expected the token `?`
-  --> $DIR/macro-at-most-once-rep-2018.rs:49:15
+  --> $DIR/macro-at-most-once-rep-2018.rs:47:15
    |
 LL | macro_rules! barstar {
    | -------------------- when calling this macro
@@ -95,7 +95,7 @@ LL |     barstar!(a?); //~ ERROR no rules expected the token `?`
    |               ^ no rules expected this token in macro call
 
 error: no rules expected the token `?`
-  --> $DIR/macro-at-most-once-rep-2018.rs:50:15
+  --> $DIR/macro-at-most-once-rep-2018.rs:48:15
    |
 LL | macro_rules! barstar {
    | -------------------- when calling this macro

From f3b29ca1c21b1cd559441a57e1ff2b8a41d56e36 Mon Sep 17 00:00:00 2001
From: Mark Mansi <markm@cs.wisc.edu>
Date: Sat, 24 Nov 2018 16:29:43 -0600
Subject: [PATCH 45/50] remove unstable book entry

---
 .../macro-at-most-once-rep.md                 | 22 -------------------
 1 file changed, 22 deletions(-)
 delete mode 100644 src/doc/unstable-book/src/language-features/macro-at-most-once-rep.md

diff --git a/src/doc/unstable-book/src/language-features/macro-at-most-once-rep.md b/src/doc/unstable-book/src/language-features/macro-at-most-once-rep.md
deleted file mode 100644
index 251fc7209122c..0000000000000
--- a/src/doc/unstable-book/src/language-features/macro-at-most-once-rep.md
+++ /dev/null
@@ -1,22 +0,0 @@
-# `macro_at_most_once_rep`
-
-NOTE: This feature is only available in the 2018 Edition.
-
-The tracking issue for this feature is: #48075
-
-With this feature gate enabled, one can use `?` as a Kleene operator meaning "0
-or 1 repetitions" in a macro definition. Previously only `+` and `*` were allowed.
-
-For example:
-
-```rust,ignore
-#![feature(macro_at_most_once_rep)]
-
-macro_rules! foo {
-    (something $(,)?) // `?` indicates `,` is "optional"...
-        => {}
-}
-```
-
-------------------------
-

From 59ae93daed93024a3dd413132451f246863f6f97 Mon Sep 17 00:00:00 2001
From: Mark Mansi <markm@cs.wisc.edu>
Date: Sat, 24 Nov 2018 17:26:15 -0600
Subject: [PATCH 46/50] remove uses of feature gate

---
 src/doc/unstable-book/src/language-features/plugin.md           | 1 -
 src/libcore/lib.rs                                              | 1 -
 src/librustc/lib.rs                                             | 1 -
 src/librustc_lint/lib.rs                                        | 1 -
 src/librustc_metadata/lib.rs                                    | 1 -
 src/libsyntax/lib.rs                                            | 1 -
 src/test/compile-fail-fulldeps/auxiliary/lint_for_crate.rs      | 1 -
 .../compile-fail-fulldeps/auxiliary/lint_group_plugin_test.rs   | 1 -
 src/test/compile-fail-fulldeps/auxiliary/lint_plugin_test.rs    | 1 -
 src/test/run-pass-fulldeps/auxiliary/lint_for_crate.rs          | 1 -
 .../proc-macro/auxiliary/issue-40001-plugin.rs                  | 1 -
 src/test/run-pass/macros/macro-at-most-once-rep.rs              | 2 --
 src/test/ui-fulldeps/auxiliary/lint_group_plugin_test.rs        | 1 -
 src/test/ui-fulldeps/auxiliary/lint_plugin_test.rs              | 1 -
 src/test/ui-fulldeps/auxiliary/lint_tool_test.rs                | 1 -
 15 files changed, 16 deletions(-)

diff --git a/src/doc/unstable-book/src/language-features/plugin.md b/src/doc/unstable-book/src/language-features/plugin.md
index 74bdd4dc3b599..03ea392c86307 100644
--- a/src/doc/unstable-book/src/language-features/plugin.md
+++ b/src/doc/unstable-book/src/language-features/plugin.md
@@ -181,7 +181,6 @@ that warns about any item named `lintme`.
 ```rust,ignore
 #![feature(plugin_registrar)]
 #![feature(box_syntax, rustc_private)]
-#![feature(macro_at_most_once_rep)]
 
 extern crate syntax;
 
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index a02b5bc87c5e9..726e891df0ccf 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -93,7 +93,6 @@
 #![feature(never_type)]
 #![feature(nll)]
 #![feature(exhaustive_patterns)]
-#![feature(macro_at_most_once_rep)]
 #![feature(no_core)]
 #![feature(on_unimplemented)]
 #![feature(optin_builtin_traits)]
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index 0aa964a44fd2c..9ae59242fbfa5 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -67,7 +67,6 @@
 #![feature(integer_atomics)]
 #![feature(test)]
 #![feature(in_band_lifetimes)]
-#![feature(macro_at_most_once_rep)]
 #![feature(crate_visibility_modifier)]
 #![feature(transpose_result)]
 
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index 57cbecb5c67be..71efc5654eff3 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -29,7 +29,6 @@
 #![feature(nll)]
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
-#![feature(macro_at_most_once_rep)]
 
 #[macro_use]
 extern crate syntax;
diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs
index 0322c888ad5c9..ee99f7465b905 100644
--- a/src/librustc_metadata/lib.rs
+++ b/src/librustc_metadata/lib.rs
@@ -14,7 +14,6 @@
 
 #![feature(box_patterns)]
 #![feature(libc)]
-#![feature(macro_at_most_once_rep)]
 #![feature(nll)]
 #![feature(proc_macro_internals)]
 #![feature(proc_macro_quote)]
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index 9bbd59e09be15..ca9c5ad7b600e 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -20,7 +20,6 @@
        test(attr(deny(warnings))))]
 
 #![feature(crate_visibility_modifier)]
-#![feature(macro_at_most_once_rep)]
 #![feature(nll)]
 #![feature(rustc_attrs)]
 #![feature(rustc_diagnostic_macros)]
diff --git a/src/test/compile-fail-fulldeps/auxiliary/lint_for_crate.rs b/src/test/compile-fail-fulldeps/auxiliary/lint_for_crate.rs
index 460e28fc794f0..fc53031e7f226 100644
--- a/src/test/compile-fail-fulldeps/auxiliary/lint_for_crate.rs
+++ b/src/test/compile-fail-fulldeps/auxiliary/lint_for_crate.rs
@@ -12,7 +12,6 @@
 
 #![feature(plugin_registrar, rustc_private)]
 #![feature(box_syntax)]
-#![feature(macro_at_most_once_rep)]
 
 #[macro_use] extern crate rustc;
 extern crate rustc_plugin;
diff --git a/src/test/compile-fail-fulldeps/auxiliary/lint_group_plugin_test.rs b/src/test/compile-fail-fulldeps/auxiliary/lint_group_plugin_test.rs
index 1057649d969d1..f697642f8431d 100644
--- a/src/test/compile-fail-fulldeps/auxiliary/lint_group_plugin_test.rs
+++ b/src/test/compile-fail-fulldeps/auxiliary/lint_group_plugin_test.rs
@@ -12,7 +12,6 @@
 
 #![feature(plugin_registrar)]
 #![feature(box_syntax, rustc_private)]
-#![feature(macro_at_most_once_rep)]
 
 // Load rustc as a plugin to get macros
 #[macro_use]
diff --git a/src/test/compile-fail-fulldeps/auxiliary/lint_plugin_test.rs b/src/test/compile-fail-fulldeps/auxiliary/lint_plugin_test.rs
index b0183a3c56bc4..8647797270f9a 100644
--- a/src/test/compile-fail-fulldeps/auxiliary/lint_plugin_test.rs
+++ b/src/test/compile-fail-fulldeps/auxiliary/lint_plugin_test.rs
@@ -12,7 +12,6 @@
 
 #![feature(plugin_registrar)]
 #![feature(box_syntax, rustc_private)]
-#![feature(macro_at_most_once_rep)]
 
 extern crate syntax;
 
diff --git a/src/test/run-pass-fulldeps/auxiliary/lint_for_crate.rs b/src/test/run-pass-fulldeps/auxiliary/lint_for_crate.rs
index 00c419a8d09e8..9f6927d21640e 100644
--- a/src/test/run-pass-fulldeps/auxiliary/lint_for_crate.rs
+++ b/src/test/run-pass-fulldeps/auxiliary/lint_for_crate.rs
@@ -12,7 +12,6 @@
 
 #![feature(plugin_registrar, rustc_private)]
 #![feature(box_syntax)]
-#![feature(macro_at_most_once_rep)]
 
 #[macro_use] extern crate rustc;
 extern crate rustc_plugin;
diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/issue-40001-plugin.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/issue-40001-plugin.rs
index e0acf340a79fd..f4d3f2c94caf1 100644
--- a/src/test/run-pass-fulldeps/proc-macro/auxiliary/issue-40001-plugin.rs
+++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/issue-40001-plugin.rs
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 #![feature(box_syntax, plugin, plugin_registrar, rustc_private)]
-#![feature(macro_at_most_once_rep)]
 #![crate_type = "dylib"]
 
 #[macro_use]
diff --git a/src/test/run-pass/macros/macro-at-most-once-rep.rs b/src/test/run-pass/macros/macro-at-most-once-rep.rs
index c7129423cb651..563fd01c11147 100644
--- a/src/test/run-pass/macros/macro-at-most-once-rep.rs
+++ b/src/test/run-pass/macros/macro-at-most-once-rep.rs
@@ -22,8 +22,6 @@
 
 // edition:2018
 
-#![feature(macro_at_most_once_rep)]
-
 macro_rules! foo {
     ($($a:ident)? ; $num:expr) => { {
         let mut x = 0;
diff --git a/src/test/ui-fulldeps/auxiliary/lint_group_plugin_test.rs b/src/test/ui-fulldeps/auxiliary/lint_group_plugin_test.rs
index 1057649d969d1..f697642f8431d 100644
--- a/src/test/ui-fulldeps/auxiliary/lint_group_plugin_test.rs
+++ b/src/test/ui-fulldeps/auxiliary/lint_group_plugin_test.rs
@@ -12,7 +12,6 @@
 
 #![feature(plugin_registrar)]
 #![feature(box_syntax, rustc_private)]
-#![feature(macro_at_most_once_rep)]
 
 // Load rustc as a plugin to get macros
 #[macro_use]
diff --git a/src/test/ui-fulldeps/auxiliary/lint_plugin_test.rs b/src/test/ui-fulldeps/auxiliary/lint_plugin_test.rs
index b0183a3c56bc4..8647797270f9a 100644
--- a/src/test/ui-fulldeps/auxiliary/lint_plugin_test.rs
+++ b/src/test/ui-fulldeps/auxiliary/lint_plugin_test.rs
@@ -12,7 +12,6 @@
 
 #![feature(plugin_registrar)]
 #![feature(box_syntax, rustc_private)]
-#![feature(macro_at_most_once_rep)]
 
 extern crate syntax;
 
diff --git a/src/test/ui-fulldeps/auxiliary/lint_tool_test.rs b/src/test/ui-fulldeps/auxiliary/lint_tool_test.rs
index 7d2acd7aa4c86..0a449e338bd06 100644
--- a/src/test/ui-fulldeps/auxiliary/lint_tool_test.rs
+++ b/src/test/ui-fulldeps/auxiliary/lint_tool_test.rs
@@ -10,7 +10,6 @@
 
 #![feature(plugin_registrar)]
 #![feature(box_syntax, rustc_private)]
-#![feature(macro_at_most_once_rep)]
 
 extern crate syntax;
 

From aeede9eb468f373f2c3250899606b0a68e8b8a18 Mon Sep 17 00:00:00 2001
From: Mark Mansi <markm@cs.wisc.edu>
Date: Sat, 24 Nov 2018 18:40:03 -0600
Subject: [PATCH 47/50] fix test

---
 src/test/ui/macros/macro-at-most-once-rep-2018.rs     | 2 +-
 src/test/ui/macros/macro-at-most-once-rep-2018.stderr | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/test/ui/macros/macro-at-most-once-rep-2018.rs b/src/test/ui/macros/macro-at-most-once-rep-2018.rs
index d8012c05acf8f..78bdf8ff71b88 100644
--- a/src/test/ui/macros/macro-at-most-once-rep-2018.rs
+++ b/src/test/ui/macros/macro-at-most-once-rep-2018.rs
@@ -39,7 +39,7 @@ pub fn main() {
     barplus!(a); //~ERROR unexpected end of macro invocation
     barplus!(a?); //~ ERROR no rules expected the token `?`
     barplus!(a?a); //~ ERROR no rules expected the token `?`
-    barplus!(a);
+    barplus!(a+);
     barplus!(+);
 
     barstar!(); //~ERROR unexpected end of macro invocation
diff --git a/src/test/ui/macros/macro-at-most-once-rep-2018.stderr b/src/test/ui/macros/macro-at-most-once-rep-2018.stderr
index efe0a2672c83c..43779078ebc83 100644
--- a/src/test/ui/macros/macro-at-most-once-rep-2018.stderr
+++ b/src/test/ui/macros/macro-at-most-once-rep-2018.stderr
@@ -1,7 +1,7 @@
 error: the `?` macro repetition operator does not take a separator
   --> $DIR/macro-at-most-once-rep-2018.rs:20:10
    |
-LL |     ($(a),?) => {} //~ERROR the `?` macro repetition operator
+LL |     ($(a),?) => {}; //~ERROR the `?` macro repetition operator
    |          ^
 
 error: no rules expected the token `?`

From e63bd91895e640a5736ef37eb1d0dedc11fe3138 Mon Sep 17 00:00:00 2001
From: polyfloyd <floyd@polyfloyd.net>
Date: Tue, 27 Nov 2018 22:33:46 +0100
Subject: [PATCH 48/50] Fix a typo in the documentation of std::ffi

---
 src/libstd/ffi/mod.rs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/libstd/ffi/mod.rs b/src/libstd/ffi/mod.rs
index a3345df5e0d85..f1f3742996bda 100644
--- a/src/libstd/ffi/mod.rs
+++ b/src/libstd/ffi/mod.rs
@@ -112,12 +112,12 @@
 //! ## On Unix
 //!
 //! On Unix, [`OsStr`] implements the
-//! `std::os::unix:ffi::`[`OsStrExt`][unix.OsStrExt] trait, which
+//! `std::os::unix::ffi::`[`OsStrExt`][unix.OsStrExt] trait, which
 //! augments it with two methods, [`from_bytes`] and [`as_bytes`].
 //! These do inexpensive conversions from and to UTF-8 byte slices.
 //!
 //! Additionally, on Unix [`OsString`] implements the
-//! `std::os::unix:ffi::`[`OsStringExt`][unix.OsStringExt] trait,
+//! `std::os::unix::ffi::`[`OsStringExt`][unix.OsStringExt] trait,
 //! which provides [`from_vec`] and [`into_vec`] methods that consume
 //! their arguments, and take or produce vectors of [`u8`].
 //!

From d8190afbcb9b15eb8e04d3860a5bd018568a3980 Mon Sep 17 00:00:00 2001
From: Nikita Popov <nikita.ppv@gmail.com>
Date: Wed, 28 Nov 2018 00:25:40 +0100
Subject: [PATCH 49/50] Fix alignment of stores to scalar pair

The alignment for the second element of a scalar pair is not the
same as for the first element. Make sure it is computed correctly
based on the element size.
---
 src/librustc_codegen_ssa/mir/operand.rs | 20 +++++++++++++++-----
 src/test/codegen/issue-56267.rs         | 18 ++++++++++++++++++
 2 files changed, 33 insertions(+), 5 deletions(-)
 create mode 100644 src/test/codegen/issue-56267.rs

diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs
index 92d0219caf06b..fefbc14e4973c 100644
--- a/src/librustc_codegen_ssa/mir/operand.rs
+++ b/src/librustc_codegen_ssa/mir/operand.rs
@@ -331,11 +331,21 @@ impl<'a, 'tcx: 'a, V: CodegenObject> OperandValue<V> {
                 bx.store_with_flags(val, dest.llval, dest.align, flags);
             }
             OperandValue::Pair(a, b) => {
-                for (i, &x) in [a, b].iter().enumerate() {
-                    let llptr = bx.struct_gep(dest.llval, i as u64);
-                    let val = base::from_immediate(bx, x);
-                    bx.store_with_flags(val, llptr, dest.align, flags);
-                }
+                let (a_scalar, b_scalar) = match dest.layout.abi {
+                    layout::Abi::ScalarPair(ref a, ref b) => (a, b),
+                    _ => bug!("store_with_flags: invalid ScalarPair layout: {:#?}", dest.layout)
+                };
+                let b_offset = a_scalar.value.size(bx).align_to(b_scalar.value.align(bx).abi);
+
+                let llptr = bx.struct_gep(dest.llval, 0);
+                let val = base::from_immediate(bx, a);
+                let align = dest.align;
+                bx.store_with_flags(val, llptr, align, flags);
+
+                let llptr = bx.struct_gep(dest.llval, 1);
+                let val = base::from_immediate(bx, b);
+                let align = dest.align.restrict_for_offset(b_offset);
+                bx.store_with_flags(val, llptr, align, flags);
             }
         }
     }
diff --git a/src/test/codegen/issue-56267.rs b/src/test/codegen/issue-56267.rs
new file mode 100644
index 0000000000000..2c33f558931ed
--- /dev/null
+++ b/src/test/codegen/issue-56267.rs
@@ -0,0 +1,18 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type="rlib"]
+
+#[allow(dead_code)]
+pub struct Foo<T> {
+    foo: u64,
+    bar: T,
+}
+
+// The store writing to bar.1 should have alignment 4. Not checking
+// other stores here, as the alignment will be platform-dependent.
+
+// CHECK: store i32 [[TMP1:%.+]], i32* [[TMP2:%.+]], align 4
+#[no_mangle]
+pub fn test(x: (i32, i32)) -> Foo<(i32, i32)> {
+    Foo { foo: 0, bar: x }
+}

From 5d7717360c8f343f70a33455029355f00e39dea2 Mon Sep 17 00:00:00 2001
From: Mark Mansi <markm@cs.wisc.edu>
Date: Tue, 27 Nov 2018 18:21:10 -0600
Subject: [PATCH 50/50] fix test

---
 src/test/ui/macros/macro-at-most-once-rep-2018.stderr | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/test/ui/macros/macro-at-most-once-rep-2018.stderr b/src/test/ui/macros/macro-at-most-once-rep-2018.stderr
index 43779078ebc83..da76d1ff1a721 100644
--- a/src/test/ui/macros/macro-at-most-once-rep-2018.stderr
+++ b/src/test/ui/macros/macro-at-most-once-rep-2018.stderr
@@ -41,7 +41,7 @@ LL |     barplus!(); //~ERROR unexpected end of macro invocation
    |     ^^^^^^^^^^^ missing tokens in macro arguments
 
 error: unexpected end of macro invocation
-  --> $DIR/macro-at-most-once-rep-2018.rs:41:15
+  --> $DIR/macro-at-most-once-rep-2018.rs:39:15
    |
 LL | macro_rules! barplus {
    | -------------------- when calling this macro
@@ -77,7 +77,7 @@ LL |     barstar!(); //~ERROR unexpected end of macro invocation
    |     ^^^^^^^^^^^ missing tokens in macro arguments
 
 error: unexpected end of macro invocation
-  --> $DIR/macro-at-most-once-rep-2018.rs:46:14
+  --> $DIR/macro-at-most-once-rep-2018.rs:46:15
    |
 LL | macro_rules! barstar {
    | -------------------- when calling this macro