diff --git a/RELEASES.md b/RELEASES.md
index c9ff49287637d..9fd796fd775bf 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1,3 +1,143 @@
+Version 1.48.0 (2020-11-19)
+==========================
+
+Language
+--------
+
+- [The `unsafe` keyword is now syntactically permitted on modules.][75857] This
+  is still rejected *semantically*, but can now be parsed by procedural macros.
+
+Compiler
+--------
+- [Stabilised the `-C link-self-contained=<yes|no>` compiler flag.][76158] This tells
+  `rustc` whether to link its own C runtime and libraries or to rely on a external 
+  linker to find them. (Supported only on `windows-gnu`, `linux-musl`, and `wasi` platforms.)
+- [You can now use `-C target-feature=+crt-static` on `linux-gnu` targets.][77386]
+  Note: If you're using cargo you must explicitly pass the `--target` flag.
+- [Added tier 2\* support for `aarch64-unknown-linux-musl`.][76420]
+
+\* Refer to Rust's [platform support page][forge-platform-support] for more
+information on Rust's tiered platform support.
+
+Libraries
+---------
+- [`io::Write` is now implemented for `&ChildStdin` `&Sink`, `&Stdout`,
+  and `&Stderr`.][76275]
+- [All arrays of any length now implement `TryFrom<Vec<T>>`.][76310]
+- [The `matches!` macro now supports having a trailing comma.][74880]
+- [`Vec<A>` now implements `PartialEq<[B]>` where `A: PartialEq<B>`.][74194]
+- [The `RefCell::{replace, replace_with, clone}` methods now all use `#[track_caller]`.][77055]
+
+Stabilized APIs
+---------------
+- [`slice::as_ptr_range`]
+- [`slice::as_mut_ptr_range`]
+- [`VecDeque::make_contiguous`]
+- [`future::pending`]
+- [`future::ready`]
+
+The following previously stable methods are now `const fn`'s:
+
+- [`Option::is_some`]
+- [`Option::is_none`]
+- [`Option::as_ref`]
+- [`Result::is_ok`]
+- [`Result::is_err`]
+- [`Result::as_ref`]
+- [`Ordering::reverse`]
+- [`Ordering::then`]
+
+Cargo
+-----
+
+Rustdoc
+-------
+- [You can now link to items in `rustdoc` using the intra-doc link
+  syntax.][74430] E.g. ``/// Uses [`std::future`]`` will automatically generate
+  a link to `std::future`'s documentation. See ["Linking to items by
+  name"][intradoc-links] for more information.
+- [You can now specify `#[doc(alias = "<alias>")]` on items to add search aliases
+  when searching through `rustdoc`'s UI.][75740]
+
+Compatibility Notes
+-------------------
+- [Promotion of references to `'static` lifetime inside `const fn` now follows the
+  same rules as inside a `fn` body.][75502] In particular, `&foo()` will not be
+  promoted to `'static` lifetime any more inside `const fn`s.
+- [Associated type bindings on trait objects are now verified to meet the bounds
+  declared on the trait when checking that they implement the trait.][27675]
+- [When trait bounds on associated types or opaque types are ambiguous, the
+  compiler no longer makes an arbitrary choice on which bound to use.][54121]
+- [Fixed recursive nonterminals not being expanded in macros during
+  pretty-print/reparse check.][77153] This may cause errors if your macro wasn't
+  correctly handling recursive nonterminal tokens.
+- [`&mut` references to non zero-sized types are no longer promoted.][75585]
+- [`rustc` will now warn if you use attributes like `#[link_name]` or `#[cold]`
+  in places where they have no effect.][73461]
+- [Updated `_mm256_extract_epi8` and `_mm256_extract_epi16` signatures in
+  `arch::{x86, x86_64}` to return `i32` to match the vendor signatures.][73166]
+- [`mem::uninitialized` will now panic if any inner types inside a struct or enum
+  disallow zero-initialization.][71274]
+- [`#[target_feature]` will now error if used in a place where it has no effect.][78143]
+- [Foreign exceptions are now caught by `catch_unwind` and will cause an abort.][70212]
+  Note: This behaviour is not guaranteed and is still considered undefined behaviour,
+  see the [`catch_unwind`] documentation for further information.
+  
+
+
+Internal Only
+-------------
+These changes provide no direct user facing benefits, but represent significant
+improvements to the internals and overall performance of rustc and
+related tools.
+
+- [Building `rustc` from source now uses `ninja` by default over `make`.][74922]
+  You can continue building with `make` by setting `ninja=false` in
+  your `config.toml`.
+- [cg_llvm: `fewer_names` in `uncached_llvm_type`][76030]
+- [Made `ensure_sufficient_stack()` non-generic][76680]
+
+[78143]: https://github.com/rust-lang/rust/issues/78143
+[76680]: https://github.com/rust-lang/rust/pull/76680/
+[76030]: https://github.com/rust-lang/rust/pull/76030/
+[70212]: https://github.com/rust-lang/rust/pull/70212/
+[27675]: https://github.com/rust-lang/rust/issues/27675/
+[54121]: https://github.com/rust-lang/rust/issues/54121/  
+[71274]: https://github.com/rust-lang/rust/pull/71274/
+[77386]: https://github.com/rust-lang/rust/pull/77386/
+[77153]: https://github.com/rust-lang/rust/pull/77153/
+[77055]: https://github.com/rust-lang/rust/pull/77055/
+[76275]: https://github.com/rust-lang/rust/pull/76275/
+[76310]: https://github.com/rust-lang/rust/pull/76310/
+[76420]: https://github.com/rust-lang/rust/pull/76420/
+[76158]: https://github.com/rust-lang/rust/pull/76158/
+[75857]: https://github.com/rust-lang/rust/pull/75857/
+[75585]: https://github.com/rust-lang/rust/pull/75585/
+[75740]: https://github.com/rust-lang/rust/pull/75740/
+[75502]: https://github.com/rust-lang/rust/pull/75502/
+[74880]: https://github.com/rust-lang/rust/pull/74880/
+[74922]: https://github.com/rust-lang/rust/pull/74922/
+[74430]: https://github.com/rust-lang/rust/pull/74430/
+[74194]: https://github.com/rust-lang/rust/pull/74194/
+[73461]: https://github.com/rust-lang/rust/pull/73461/
+[73166]: https://github.com/rust-lang/rust/pull/73166/
+[intradoc-links]: https://doc.rust-lang.org/rustdoc/linking-to-items-by-name.html
+[`catch_unwind`]: https://doc.rust-lang.org/std/panic/fn.catch_unwind.html
+[`Option::is_some`]: https://doc.rust-lang.org/std/option/enum.Option.html#method.is_some
+[`Option::is_none`]: https://doc.rust-lang.org/std/option/enum.Option.html#method.is_none
+[`Option::as_ref`]: https://doc.rust-lang.org/std/option/enum.Option.html#method.as_ref
+[`Result::is_ok`]: https://doc.rust-lang.org/std/result/enum.Result.html#method.is_ok
+[`Result::is_err`]: https://doc.rust-lang.org/std/result/enum.Result.html#method.is_err
+[`Result::as_ref`]: https://doc.rust-lang.org/std/result/enum.Result.html#method.as_ref
+[`Ordering::reverse`]: https://doc.rust-lang.org/std/cmp/enum.Ordering.html#method.reverse
+[`Ordering::then`]: https://doc.rust-lang.org/std/cmp/enum.Ordering.html#method.then
+[`slice::as_ptr_range`]: https://doc.rust-lang.org/std/primitive.slice.html#method.as_ptr_range
+[`slice::as_mut_ptr_range`]: https://doc.rust-lang.org/std/primitive.slice.html#method.as_mut_ptr_range
+[`VecDeque::make_contiguous`]: https://doc.rust-lang.org/std/collections/struct.VecDeque.html#method.make_contiguous
+[`future::pending`]: https://doc.rust-lang.org/std/future/fn.pending.html
+[`future::ready`]: https://doc.rust-lang.org/std/future/fn.ready.html
+
+
 Version 1.47.0 (2020-10-08)
 ==========================
 
@@ -90,6 +230,7 @@ Compatibility Notes
 
 Internal Only
 --------
+
 - [Improved default settings for bootstrapping in `x.py`.][73964] You can read details about this change in the ["Changes to `x.py` defaults"](https://blog.rust-lang.org/inside-rust/2020/08/30/changes-to-x-py-defaults.html) post on the Inside Rust blog.
 
 [1.47.0-cfg]: https://docs.microsoft.com/en-us/windows/win32/secbp/control-flow-guard
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index 5ce5737f318c7..29fccc0533bfe 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -1336,7 +1336,13 @@ impl Step for Rls {
         let rls = builder
             .ensure(tool::Rls { compiler, target, extra_features: Vec::new() })
             .or_else(|| {
-                missing_tool("RLS", builder.build.config.missing_tools);
+                // We ignore failure on aarch64 Windows because RLS currently
+                // fails to build, due to winapi 0.2 not supporting aarch64.
+                missing_tool(
+                    "RLS",
+                    builder.build.config.missing_tools
+                        || (target.triple.contains("aarch64") && target.triple.contains("windows")),
+                );
                 None
             })?;
 
@@ -2357,6 +2363,25 @@ fn maybe_install_llvm(builder: &Builder<'_>, target: TargetSelection, dst_libdir
         return;
     }
 
+    if let Some(config) = builder.config.target_config.get(&target) {
+        if config.llvm_config.is_some() && !builder.config.llvm_from_ci {
+            // If the LLVM was externally provided, then we don't currently copy
+            // artifacts into the sysroot. This is not necessarily the right
+            // choice (in particular, it will require the LLVM dylib to be in
+            // the linker's load path at runtime), but the common use case for
+            // external LLVMs is distribution provided LLVMs, and in that case
+            // they're usually in the standard search path (e.g., /usr/lib) and
+            // copying them here is going to cause problems as we may end up
+            // with the wrong files and isn't what distributions want.
+            //
+            // This behavior may be revisited in the future though.
+            //
+            // If the LLVM is coming from ourselves (just from CI) though, we
+            // still want to install it, as it otherwise won't be available.
+            return;
+        }
+    }
+
     // On macOS, rustc (and LLVM tools) link to an unversioned libLLVM.dylib
     // instead of libLLVM-11-rust-....dylib, as on linux. It's not entirely
     // clear why this is the case, though. llvm-config will emit the versioned
diff --git a/src/ci/run.sh b/src/ci/run.sh
index 181a7fcb73266..8681f84f6ab0a 100755
--- a/src/ci/run.sh
+++ b/src/ci/run.sh
@@ -63,7 +63,7 @@ fi
 #
 # FIXME: need a scheme for changing this `nightly` value to `beta` and `stable`
 #        either automatically or manually.
-export RUST_RELEASE_CHANNEL=nightly
+export RUST_RELEASE_CHANNEL=beta
 
 # Always set the release channel for bootstrap; this is normally not important (i.e., only dist
 # builds would seem to matter) but in practice bootstrap wants to know whether we're targeting
diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs
index 4769edc50ff07..b5fe593dc0105 100644
--- a/src/librustdoc/html/highlight.rs
+++ b/src/librustdoc/html/highlight.rs
@@ -46,7 +46,9 @@ fn write_header(out: &mut String, class: Option<&str>) {
 }
 
 fn write_code(out: &mut String, src: &str) {
-    Classifier::new(src).highlight(&mut |highlight| {
+    // This replace allows to fix how the code source with DOS backline characters is displayed.
+    let src = src.replace("\r\n", "\n");
+    Classifier::new(&src).highlight(&mut |highlight| {
         match highlight {
             Highlight::Token { text, class } => string(out, Escape(text), class),
             Highlight::EnterSpan { class } => enter_span(out, class),
diff --git a/src/librustdoc/html/highlight/fixtures/dos_line.html b/src/librustdoc/html/highlight/fixtures/dos_line.html
new file mode 100644
index 0000000000000..4400f85681d8a
--- /dev/null
+++ b/src/librustdoc/html/highlight/fixtures/dos_line.html
@@ -0,0 +1,3 @@
+<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">foo</span>() {
+<span class="macro">println</span><span class="macro">!</span>(<span class="string">&quot;foo&quot;</span>);
+}
diff --git a/src/librustdoc/html/highlight/tests.rs b/src/librustdoc/html/highlight/tests.rs
index c79471b1fae6b..f57f52d6f0875 100644
--- a/src/librustdoc/html/highlight/tests.rs
+++ b/src/librustdoc/html/highlight/tests.rs
@@ -1,17 +1,6 @@
 use super::write_code;
 use expect_test::expect_file;
 
-#[test]
-fn test_html_highlighting() {
-    let src = include_str!("fixtures/sample.rs");
-    let html = {
-        let mut out = String::new();
-        write_code(&mut out, src);
-        format!("{}<pre><code>{}</code></pre>\n", STYLE, out)
-    };
-    expect_file!["fixtures/sample.html"].assert_eq(&html);
-}
-
 const STYLE: &str = r#"
 <style>
 .kw { color: #8959A8; }
@@ -23,3 +12,24 @@ const STYLE: &str = r#"
 .question-mark { color: #ff9011; }
 </style>
 "#;
+
+#[test]
+fn test_html_highlighting() {
+    let src = include_str!("fixtures/sample.rs");
+    let html = {
+        let mut out = String::new();
+        write_code(&mut out, src);
+        format!("{}<pre><code>{}</code></pre>\n", STYLE, out)
+    };
+    expect_file!["fixtures/sample.html"].assert_eq(&html);
+}
+
+#[test]
+fn test_dos_backline() {
+    let src = "pub fn foo() {\r\n\
+    println!(\"foo\");\r\n\
+}\r\n";
+    let mut html = String::new();
+    write_code(&mut html, src);
+    expect_file!["fixtures/dos_line.html"].assert_eq(&html);
+}
diff --git a/src/stage0.txt b/src/stage0.txt
index 9eaa58dd43869..e5fe11004ab6c 100644
--- a/src/stage0.txt
+++ b/src/stage0.txt
@@ -12,15 +12,15 @@
 # source tarball for a stable release you'll likely see `1.x.0` for rustc and
 # `0.(x+1).0` for Cargo where they were released on `date`.
 
-date: 2020-10-16
-rustc: beta
-cargo: beta
+date: 2020-11-16
+rustc: 1.48.0
+cargo: 1.48.0
 
 # We use a nightly rustfmt to format the source because it solves some
 # bootstrapping issues with use of new syntax in this repo. If you're looking at
 # the beta/stable branch, this key should be omitted, as we don't want to depend
 # on rustfmt from nightly there.
-rustfmt: nightly-2020-10-12
+#rustfmt: nightly-2020-10-12
 
 # When making a stable release the process currently looks like:
 #
@@ -40,4 +40,4 @@ rustfmt: nightly-2020-10-12
 # looking at a beta source tarball and it's uncommented we'll shortly comment it
 # out.
 
-#dev: 1
+dev: 1
diff --git a/src/test/ui-fulldeps/session-derive-errors.stderr b/src/test/ui-fulldeps/session-derive-errors.stderr
index c1be151f1c1ce..303268fae27a1 100644
--- a/src/test/ui-fulldeps/session-derive-errors.stderr
+++ b/src/test/ui-fulldeps/session-derive-errors.stderr
@@ -1,25 +1,20 @@
 error: `#[derive(SessionDiagnostic)]` can only be used on structs
   --> $DIR/session-derive-errors.rs:28:1
    |
-LL | / #[error = "E0123"]
-LL | |
-LL | | enum SessionDiagnosticOnEnum {
-LL | |     Foo,
-LL | |     Bar,
-LL | | }
-   | |_^
+LL | #[error = "E0123"]
+   | ^
 
 error: `#[label = ...]` is not a valid SessionDiagnostic struct attribute
   --> $DIR/session-derive-errors.rs:37:1
    |
 LL | #[label = "This is in the wrong place"]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^
 
 error: `#[suggestion = ...]` is not a valid SessionDiagnostic field attribute
   --> $DIR/session-derive-errors.rs:44:5
    |
 LL |     #[suggestion = "this is the wrong kind of attribute"]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^
 
 error: `error` specified multiple times
   --> $DIR/session-derive-errors.rs:52:11
@@ -37,7 +32,7 @@ error: `code` not specified
   --> $DIR/session-derive-errors.rs:67:1
    |
 LL | struct ErrorCodeNotProvided {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^
    |
    = help: use the [code = "..."] attribute to set this diagnostic's error code 
 
@@ -45,13 +40,13 @@ error: the `#[message = "..."]` attribute can only be applied to fields of type
   --> $DIR/session-derive-errors.rs:95:5
    |
 LL |     #[message = "this message is applied to a String field"]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^
 
 error: `name` doesn't refer to a field on this type
   --> $DIR/session-derive-errors.rs:102:1
    |
 LL | #[message = "This error has a field, and references {name}"]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^
 
 error: invalid format string: expected `'}'` but string was terminated
   --> $DIR/session-derive-errors.rs:110:1
@@ -77,59 +72,53 @@ error: The `#[label = ...]` attribute can only be applied to fields of type Span
   --> $DIR/session-derive-errors.rs:138:5
    |
 LL |     #[label = "See here"]
-   |     ^^^^^^^^^^^^^^^^^^^^^
+   |     ^
 
 error: `nonsense` is not a valid key for `#[suggestion(...)]`
   --> $DIR/session-derive-errors.rs:163:18
    |
 LL |     #[suggestion(nonsense = "This is nonsense")]
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                  ^^^^^^^^
 
 error: `msg` is not a valid key for `#[suggestion(...)]`
   --> $DIR/session-derive-errors.rs:171:18
    |
 LL |     #[suggestion(msg = "This is a suggestion")]
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                  ^^^
 
 error: missing suggestion message
   --> $DIR/session-derive-errors.rs:179:7
    |
 LL |     #[suggestion(code = "This is suggested code")]
-   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |       ^^^^^^^^^^
    |
    = help: provide a suggestion message using #[suggestion(message = "...")]
 
 error: wrong field type for suggestion
   --> $DIR/session-derive-errors.rs:194:5
    |
-LL | /     #[suggestion(message = "This is a message", code = "This is suggested code")]
-LL | |
-LL | |     suggestion: Applicability,
-   | |_____________________________^
+LL |     #[suggestion(message = "This is a message", code = "This is suggested code")]
+   |     ^
    |
    = help: #[suggestion(...)] should be applied to fields of type Span or (Span, Applicability)
 
 error: type of field annotated with `#[suggestion(...)]` contains more than one Span
   --> $DIR/session-derive-errors.rs:209:5
    |
-LL | /     #[suggestion(message = "This is a message", code = "This is suggested code")]
-LL | |
-LL | |     suggestion: (Span, Span, Applicability),
-   | |___________________________________________^
+LL |     #[suggestion(message = "This is a message", code = "This is suggested code")]
+   |     ^
 
 error: type of field annotated with `#[suggestion(...)]` contains more than one Applicability
   --> $DIR/session-derive-errors.rs:217:5
    |
-LL | /     #[suggestion(message = "This is a message", code = "This is suggested code")]
-LL | |
-LL | |     suggestion: (Applicability, Applicability, Span),
-   | |____________________________________________________^
+LL |     #[suggestion(message = "This is a message", code = "This is suggested code")]
+   |     ^
 
 error: invalid annotation list `#[label(...)]`
   --> $DIR/session-derive-errors.rs:225:7
    |
 LL |     #[label("wrong kind of annotation for label")]
-   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |       ^^^^^
 
 error: aborting due to 18 previous errors
 
diff --git a/src/tools/build-manifest/src/versions.rs b/src/tools/build-manifest/src/versions.rs
index f1a42e7145f90..11575139adcf6 100644
--- a/src/tools/build-manifest/src/versions.rs
+++ b/src/tools/build-manifest/src/versions.rs
@@ -7,7 +7,6 @@ use std::path::{Path, PathBuf};
 use tar::Archive;
 
 const DEFAULT_TARGET: &str = "x86_64-unknown-linux-gnu";
-const RUSTC_VERSION: &str = include_str!("../../../version");
 
 #[derive(Debug, Hash, Eq, PartialEq, Clone)]
 pub(crate) enum PkgType {
@@ -177,10 +176,10 @@ impl Versions {
     ) -> Result<String, Error> {
         let component_name = package.tarball_component_name();
         let version = match self.channel.as_str() {
-            "stable" => RUSTC_VERSION.into(),
+            "stable" => self.rustc_version().into(),
             "beta" => "beta".into(),
             "nightly" => "nightly".into(),
-            _ => format!("{}-dev", RUSTC_VERSION),
+            _ => format!("{}-dev", self.rustc_version()),
         };
 
         if package.target_independent() {
@@ -199,6 +198,7 @@ impl Versions {
     }
 
     pub(crate) fn rustc_version(&self) -> &str {
-        RUSTC_VERSION
+        const RUSTC_VERSION: &str = include_str!("../../../version");
+        RUSTC_VERSION.trim()
     }
 }