diff --git a/RELEASES.md b/RELEASES.md
index 9d922f493d08b..cf80c166759bf 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1,3 +1,146 @@
+Version 1.28.0 (2018-08-02)
+===========================
+
+Language
+--------
+- [The `#[repr(transparent)]` attribute is now stable.][51562] This attribute
+  allows a Rust newtype wrapper (`struct NewType<T>(T);`) to be represented as
+  the inner type across Foreign Function Interface (FFI) boundaries.
+- [The keywords `pure`, `sizeof`, `alignof`, and `offsetof` have been unreserved
+  and can now be used as identifiers.][51196]
+- [The `GlobalAlloc` trait and `#[global_allocator]` attribute are now
+  stable.][51241] This will allow users to specify a global allocator for
+  their program.
+- [Unit test functions marked with the `#[test]` attribute can now return
+  `Result<(), E: Debug>` in addition to `()`.][51298]
+- [The `lifetime` specifier for `macro_rules!` is now stable.][50385] This
+  allows macros to easily target lifetimes.
+
+Compiler
+--------
+- [The `s` and `z` optimisation levels are now stable.][50265] These optimisations
+  prioritise making smaller binary sizes. `z` is the same as `s` with the
+  exception that it does not vectorise loops, which typically results in an even
+  smaller binary.
+- [The short error format is now stable.][49546] Specified with
+  `--error-format=short` this option will provide a more compressed output of
+  rust error messages.
+- [Added a lint warning when you have duplicated `macro_export`s.][50143]
+- [Reduced the number of allocations in the macro parser.][50855] This can
+  improve compile times of macro heavy crates on average by 5%.
+
+Libraries
+---------
+- [Implemented `Default` for `&mut str`.][51306]
+- [Implemented `From<bool>` for all integer and unsigned number types.][50554]
+- [Implemented `Extend` for `()`.][50234]
+- [The `Debug` implementation of `time::Duration` should now be more easily
+  human readable.][50364] Previously a `Duration` of one second would printed as
+  `Duration { secs: 1, nanos: 0 }` and will now be printed as `1s`.
+- [Implemented `From<&String>` for `Cow<str>`, `From<&Vec<T>>` for `Cow<[T]>`,
+  `From<Cow<CStr>>` for `CString`, `From<CString>, From<CStr>, From<&CString>`
+  for `Cow<CStr>`, `From<OsString>, From<OsStr>, From<&OsString>` for
+  `Cow<OsStr>`, `From<&PathBuf>` for `Cow<Path>`, and `From<Cow<Path>>`
+  for `PathBuf`.][50170]
+- [Implemented `Shl` and `Shr` for `Wrapping<u128>`
+  and `Wrapping<i128>`.][50465]
+- [`DirEntry::metadata` now uses `fstatat` instead of `lstat` when
+  possible.][51050] This can provide up to a 40% speed increase.
+- [Improved error messages when using `format!`.][50610]
+
+Stabilized APIs
+---------------
+- [`Iterator::step_by`]
+- [`Path::ancestors`]
+- [`btree_map::Entry::or_default`]
+- [`fmt::Alignment`]
+- [`hash_map::Entry::or_default`]
+- [`iter::repeat_with`]
+- [`num::NonZeroUsize`]
+- [`num::NonZeroU128`]
+- [`num::NonZeroU16`]
+- [`num::NonZeroU32`]
+- [`num::NonZeroU64`]
+- [`num::NonZeroU8`]
+- [`ops::RangeBounds`]
+- [`slice::SliceIndex`]
+- [`slice::from_mut`]
+- [`slice::from_ref`]
+- [`{Any + Send + Sync}::downcast_mut`]
+- [`{Any + Send + Sync}::downcast_ref`]
+- [`{Any + Send + Sync}::is`]
+
+Cargo
+-----
+- [Cargo will now no longer allow you to publish crates with build scripts that
+  modify the `src` directory.][cargo/5584] The `src` directory in a crate should be
+  considered to be immutable.
+
+Misc
+----
+- [The `suggestion_applicability` field in `rustc`'s json output is now
+  stable.][50486] This will allow dev tools to check whether a code suggestion
+  would apply to them.
+
+Compatibility Notes
+-------------------
+- [Rust will no longer consider trait objects with duplicated constraints to
+  have implementations.][51276] For example the below code will now fail
+  to compile.
+  ```rust
+  trait Trait {}
+
+  impl Trait + Send {
+      fn test(&self) { println!("one"); } //~ ERROR duplicate definitions with name `test`
+  }
+
+  impl Trait + Send + Send {
+      fn test(&self) { println!("two"); }
+  }
+  ```
+
+[49546]: https://github.com/rust-lang/rust/pull/49546/
+[50143]: https://github.com/rust-lang/rust/pull/50143/
+[50170]: https://github.com/rust-lang/rust/pull/50170/
+[50234]: https://github.com/rust-lang/rust/pull/50234/
+[50265]: https://github.com/rust-lang/rust/pull/50265/
+[50364]: https://github.com/rust-lang/rust/pull/50364/
+[50385]: https://github.com/rust-lang/rust/pull/50385/
+[50465]: https://github.com/rust-lang/rust/pull/50465/
+[50486]: https://github.com/rust-lang/rust/pull/50486/
+[50554]: https://github.com/rust-lang/rust/pull/50554/
+[50610]: https://github.com/rust-lang/rust/pull/50610/
+[50855]: https://github.com/rust-lang/rust/pull/50855/
+[51050]: https://github.com/rust-lang/rust/pull/51050/
+[51196]: https://github.com/rust-lang/rust/pull/51196/
+[51200]: https://github.com/rust-lang/rust/pull/51200/
+[51241]: https://github.com/rust-lang/rust/pull/51241/
+[51276]: https://github.com/rust-lang/rust/pull/51276/
+[51298]: https://github.com/rust-lang/rust/pull/51298/
+[51306]: https://github.com/rust-lang/rust/pull/51306/
+[51562]: https://github.com/rust-lang/rust/pull/51562/
+[cargo/5584]: https://github.com/rust-lang/cargo/pull/5584/
+[`Iterator::step_by`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.step_by
+[`Path::ancestors`]: https://doc.rust-lang.org/std/path/struct.Path.html#method.ancestors
+[`btree_map::Entry::or_default`]: https://doc.rust-lang.org/std/collections/btree_map/enum.Entry.html#method.or_default
+[`fmt::Alignment`]: https://doc.rust-lang.org/std/fmt/enum.Alignment.html
+[`hash_map::Entry::or_default`]: https://doc.rust-lang.org/std/collections/btree_map/enum.Entry.html#method.or_default
+[`iter::repeat_with`]: https://doc.rust-lang.org/std/iter/fn.repeat_with.html
+[`num::NonZeroUsize`]: https://doc.rust-lang.org/std/num/struct.NonZeroUsize.html
+[`num::NonZeroU128`]: https://doc.rust-lang.org/std/num/struct.NonZeroU128.html
+[`num::NonZeroU16`]: https://doc.rust-lang.org/std/num/struct.NonZeroU16.html
+[`num::NonZeroU32`]: https://doc.rust-lang.org/std/num/struct.NonZeroU32.html
+[`num::NonZeroU64`]: https://doc.rust-lang.org/std/num/struct.NonZeroU64.html
+[`num::NonZeroU8`]: https://doc.rust-lang.org/std/num/struct.NonZeroU8.html
+[`ops::RangeBounds`]: https://doc.rust-lang.org/std/ops/trait.RangeBounds.html
+[`slice::SliceIndex`]: https://doc.rust-lang.org/std/slice/trait.SliceIndex.html
+[`slice::from_mut`]: https://doc.rust-lang.org/std/slice/fn.from_mut.html
+[`slice::from_ref`]: https://doc.rust-lang.org/std/slice/fn.from_ref.html
+[`{Any + Send + Sync}::downcast_mut`]: https://doc.rust-lang.org/std/any/trait.Any.html#method.downcast_mut-2
+[`{Any + Send + Sync}::downcast_ref`]: https://doc.rust-lang.org/std/any/trait.Any.html#method.downcast_ref-2
+[`{Any + Send + Sync}::is`]: https://doc.rust-lang.org/std/any/trait.Any.html#method.is-2
+
+
 Version 1.27.0 (2018-06-21)
 ==========================
 
@@ -188,7 +331,7 @@ Language
 - [Closures now implement `Copy` and/or `Clone` if all captured variables
   implement either or both traits.][49299]
 - [The inclusive range syntax e.g. `for x in 0..=10` is now stable.][47813]
-- [Stablise `'_`. The underscore lifetime can be used anywhere where a
+- [The `'_` lifetime is now stable. The underscore lifetime can be used anywhere where a
   lifetime can be elided.][49458]
 - [`impl Trait` is now stable allowing you to have abstract types in returns
    or in function parameters.][49255] e.g. `fn foo() -> impl Iterator<Item=u8>` or
@@ -389,7 +532,7 @@ Version 1.25.0 (2018-03-29)
 
 Language
 --------
-- [Stabilised `#[repr(align(x))]`.][47006] [RFC 1358]
+- [The `#[repr(align(x))]` attribute is now stable.][47006] [RFC 1358]
 - [You can now use nested groups of imports.][47948]
   e.g. `use std::{fs::File, io::Read, path::{Path, PathBuf}};`
 - [You can now have `|` at the start of a match arm.][47947] e.g.
diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs
index 84173654655eb..8fb4e0d6a02e3 100644
--- a/src/libcore/mem.rs
+++ b/src/libcore/mem.rs
@@ -229,6 +229,8 @@ pub fn forget<T>(t: T) {
 /// 2. Round up the current size to the nearest multiple of the next field's [alignment].
 ///
 /// Finally, round the size of the struct to the nearest multiple of its [alignment].
+/// The alignment of the struct is usually the largest alignment of all its
+/// fields; this can be changed with the use of `repr(align(N))`.
 ///
 /// Unlike `C`, zero sized structs are not rounded up to one byte in size.
 ///
@@ -283,7 +285,8 @@ pub fn forget<T>(t: T) {
 /// // The size of the second field is 2, so add 2 to the size. Size is 4.
 /// // The alignment of the third field is 1, so add 0 to the size for padding. Size is 4.
 /// // The size of the third field is 1, so add 1 to the size. Size is 5.
-/// // Finally, the alignment of the struct is 2, so add 1 to the size for padding. Size is 6.
+/// // Finally, the alignment of the struct is 2 (because the largest alignment amongst its
+/// // fields is 2), so add 1 to the size for padding. Size is 6.
 /// assert_eq!(6, mem::size_of::<FieldStruct>());
 ///
 /// #[repr(C)]
diff --git a/src/libcore/num/flt2dec/strategy/dragon.rs b/src/libcore/num/flt2dec/strategy/dragon.rs
index 6aa4f297e75ba..9c9e531c593c6 100644
--- a/src/libcore/num/flt2dec/strategy/dragon.rs
+++ b/src/libcore/num/flt2dec/strategy/dragon.rs
@@ -9,9 +9,9 @@
 // except according to those terms.
 
 /*!
-Almost direct (but slightly optimized) Rust translation of Figure 3 of [1].
+Almost direct (but slightly optimized) Rust translation of Figure 3 of \[1\].
 
-[1] Burger, R. G. and Dybvig, R. K. 1996. Printing floating-point numbers
+\[1\] Burger, R. G. and Dybvig, R. K. 1996. Printing floating-point numbers
     quickly and accurately. SIGPLAN Not. 31, 5 (May. 1996), 108-116.
 */
 
diff --git a/src/libcore/num/flt2dec/strategy/grisu.rs b/src/libcore/num/flt2dec/strategy/grisu.rs
index cf70a1978f5e6..5c023a191db55 100644
--- a/src/libcore/num/flt2dec/strategy/grisu.rs
+++ b/src/libcore/num/flt2dec/strategy/grisu.rs
@@ -9,10 +9,10 @@
 // except according to those terms.
 
 /*!
-Rust adaptation of Grisu3 algorithm described in [1]. It uses about
+Rust adaptation of Grisu3 algorithm described in \[1\]. It uses about
 1KB of precomputed table, and in turn, it's very quick for most inputs.
 
-[1] Florian Loitsch. 2010. Printing floating-point numbers quickly and
+\[1\] Florian Loitsch. 2010. Printing floating-point numbers quickly and
     accurately with integers. SIGPLAN Not. 45, 6 (June 2010), 233-243.
 */
 
diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs
index e9d1fb8911504..1e2b18bf9b038 100644
--- a/src/libcore/sync/atomic.rs
+++ b/src/libcore/sync/atomic.rs
@@ -124,6 +124,7 @@ pub fn spin_loop_hint() {
 /// [`bool`]: ../../../std/primitive.bool.html
 #[cfg(target_has_atomic = "8")]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[repr(transparent)]
 pub struct AtomicBool {
     v: UnsafeCell<u8>,
 }
@@ -147,6 +148,7 @@ unsafe impl Sync for AtomicBool {}
 /// This type has the same in-memory representation as a `*mut T`.
 #[cfg(target_has_atomic = "ptr")]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[repr(transparent)]
 pub struct AtomicPtr<T> {
     p: UnsafeCell<*mut T>,
 }
@@ -976,6 +978,7 @@ macro_rules! atomic_int {
         ///
         /// [module-level documentation]: index.html
         #[$stable]
+        #[repr(transparent)]
         pub struct $atomic_type {
             v: UnsafeCell<$int_type>,
         }
diff --git a/src/librustc/infer/lexical_region_resolve/graphviz.rs b/src/librustc/infer/lexical_region_resolve/graphviz.rs
index d9d08294334db..d76d33b990222 100644
--- a/src/librustc/infer/lexical_region_resolve/graphviz.rs
+++ b/src/librustc/infer/lexical_region_resolve/graphviz.rs
@@ -39,14 +39,14 @@ use std::sync::atomic::{AtomicBool, Ordering};
 fn print_help_message() {
     println!("\
 -Z print-region-graph by default prints a region constraint graph for every \n\
-function body, to the path `/tmp/constraints.nodeXXX.dot`, where the XXX is \n\
+function body, to the path `constraints.nodeXXX.dot`, where the XXX is \n\
 replaced with the node id of the function under analysis.                   \n\
                                                                             \n\
 To select one particular function body, set `RUST_REGION_GRAPH_NODE=XXX`,   \n\
 where XXX is the node id desired.                                           \n\
                                                                             \n\
 To generate output to some path other than the default                      \n\
-`/tmp/constraints.nodeXXX.dot`, set `RUST_REGION_GRAPH=/path/desired.dot`;  \n\
+`constraints.nodeXXX.dot`, set `RUST_REGION_GRAPH=/path/desired.dot`;  \n\
 occurrences of the character `%` in the requested path will be replaced with\n\
 the node id of the function under analysis.                                 \n\
                                                                             \n\
@@ -90,7 +90,7 @@ pub fn maybe_print_constraints_for<'a, 'gcx, 'tcx>(
             }
 
             Ok(other_path) => other_path,
-            Err(_) => "/tmp/constraints.node%.dot".to_string(),
+            Err(_) => "constraints.node%.dot".to_string(),
         };
 
         if output_template.is_empty() {
diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs
index 7b4998e85881e..c71e49b0d8821 100644
--- a/src/librustc_codegen_llvm/builder.rs
+++ b/src/librustc_codegen_llvm/builder.rs
@@ -277,7 +277,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     }
 
     pub fn nswsub(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
-        self.count_insn("nwsub");
+        self.count_insn("nswsub");
         unsafe {
             llvm::LLVMBuildNSWSub(self.llbuilder, lhs, rhs, noname())
         }
@@ -291,14 +291,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     }
 
     pub fn fsub(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
-        self.count_insn("sub");
+        self.count_insn("fsub");
         unsafe {
             llvm::LLVMBuildFSub(self.llbuilder, lhs, rhs, noname())
         }
     }
 
     pub fn fsub_fast(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
-        self.count_insn("sub");
+        self.count_insn("fsub");
         unsafe {
             let instr = llvm::LLVMBuildFSub(self.llbuilder, lhs, rhs, noname());
             llvm::LLVMRustSetHasUnsafeAlgebra(instr);
@@ -1315,6 +1315,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     }
 
     pub fn add_incoming_to_phi(&self, phi: ValueRef, val: ValueRef, bb: BasicBlockRef) {
+        self.count_insn("addincoming");
         unsafe {
             llvm::LLVMAddIncoming(phi, &val, &bb, 1 as c_uint);
         }
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index a5db0d15d8ab3..1a66a2d2cb902 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -1905,8 +1905,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                     // highlighted text will always be `&<expr>` and
                     // thus can transform to `&mut` by slicing off
                     // first ASCII character and prepending "&mut ".
-                    let borrowed_expr = src[1..].to_string();
-                    return (assignment_rhs_span, format!("&mut {}", borrowed_expr));
+                    if src.starts_with('&') {
+                        let borrowed_expr = src[1..].to_string();
+                        return (assignment_rhs_span, format!("&mut {}", borrowed_expr));
+                    }
                 }
             }
 
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index e4afb9ae54b8a..41c08dbf4ab65 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -1669,6 +1669,8 @@ impl<'a> Settings<'a> {
             settings: vec![
                 ("item-declarations", "Auto-hide item declarations.", true),
                 ("item-attributes", "Auto-hide item attributes.", true),
+                ("trait-implementations", "Auto-hide trait implementations documentation",
+                 true),
                 ("go-to-only-result", "Directly go to item in search if there is only one result",
                  false),
             ],
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index f3c9ce424106d..3bd343c0c0b68 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -1938,17 +1938,19 @@
         if (collapse) {
             toggleAllDocs(pageId, true);
         }
-        onEach(document.getElementsByClassName("collapse-toggle"), function(e) {
-            // inherent impl ids are like 'impl' or impl-<number>'.
-            // they will never be hidden by default.
-            var n = e.parentNode;
-            if (n.id.match(/^impl(?:-\d+)?$/) === null) {
-                // Automatically minimize all non-inherent impls
-                if (collapse || hasClass(n, 'impl')) {
-                    collapseDocs(e, "hide", pageId);
+        if (getCurrentValue('rustdoc-trait-implementations') !== "false") {
+            onEach(document.getElementsByClassName("collapse-toggle"), function(e) {
+                // inherent impl ids are like 'impl' or impl-<number>'.
+                // they will never be hidden by default.
+                var n = e.parentNode;
+                if (n.id.match(/^impl(?:-\d+)?$/) === null) {
+                    // Automatically minimize all non-inherent impls
+                    if (collapse || hasClass(n, 'impl')) {
+                        collapseDocs(e, "hide", pageId);
+                    }
                 }
-            }
-        });
+            });
+        }
     }
 
     var x = document.getElementById('toggle-all-docs');
diff --git a/src/test/ui/suggestions/issue-51515.rs b/src/test/ui/suggestions/issue-51515.rs
new file mode 100644
index 0000000000000..3e0a3b757a3d6
--- /dev/null
+++ b/src/test/ui/suggestions/issue-51515.rs
@@ -0,0 +1,24 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(nll)]
+
+fn main() {
+    let foo = &16;
+    //~^ HELP consider changing this to be a mutable reference
+    //~| SUGGESTION &mut 16
+    *foo = 32;
+    //~^ ERROR cannot assign to `*foo` which is behind a `&` reference
+    let bar = foo;
+    //~^ HELP consider changing this to be a mutable reference
+    //~| SUGGESTION &mut i32
+    *bar = 64;
+    //~^ ERROR cannot assign to `*bar` which is behind a `&` reference
+}
diff --git a/src/test/ui/suggestions/issue-51515.stderr b/src/test/ui/suggestions/issue-51515.stderr
new file mode 100644
index 0000000000000..3e7349b5acabf
--- /dev/null
+++ b/src/test/ui/suggestions/issue-51515.stderr
@@ -0,0 +1,21 @@
+error[E0594]: cannot assign to `*foo` which is behind a `&` reference
+  --> $DIR/issue-51515.rs:17:5
+   |
+LL |     let foo = &16;
+   |               --- help: consider changing this to be a mutable reference: `&mut 16`
+...
+LL |     *foo = 32;
+   |     ^^^^^^^^^ `foo` is a `&` reference, so the data it refers to cannot be written
+
+error[E0594]: cannot assign to `*bar` which is behind a `&` reference
+  --> $DIR/issue-51515.rs:22:5
+   |
+LL |     let bar = foo;
+   |         --- help: consider changing this to be a mutable reference: `&mut i32`
+...
+LL |     *bar = 64;
+   |     ^^^^^^^^^ `bar` is a `&` reference, so the data it refers to cannot be written
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0594`.