about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-05-30 11:56:32 +0000
committerbors <bors@rust-lang.org>2019-05-30 11:56:32 +0000
commitaee7012fab26d5e307a2fe767e4e7c847c5a45ee (patch)
treec960557e317e8e2d73db61fd13894d62884b2a66 /src
parentc28084ac16af4ab594b6860958df140e7c876a13 (diff)
parent528972a28aa9e7e303e2283a31469c12c3d87e23 (diff)
downloadrust-aee7012fab26d5e307a2fe767e4e7c847c5a45ee.tar.gz
rust-aee7012fab26d5e307a2fe767e4e7c847c5a45ee.zip
Auto merge of #61343 - Centril:rollup-dzsuo01, r=Centril
Rollup of 11 pull requests

Successful merges:

 - #60802 (upgrade rustdoc's `pulldown-cmark` to 0.5.2)
 - #60839 (Fix ICE with struct ctors and const generics.)
 - #60850 (Stabilize RefCell::try_borrow_unguarded)
 - #61231 (Fix linkage diagnostic so it doesn't ICE for external crates)
 - #61244 (Box::into_vec: use Box::into_raw instead of mem::forget)
 - #61279 (implicit `Option`-returning doctests)
 - #61280 (Revert "Disable solaris target since toolchain no longer builds")
 - #61284 (Update all s3 URLs used on CI with subdomains)
 - #61321 (libsyntax: introduce 'fn is_keyword_ahead(dist, keywords)'.)
 - #61322 (ci: display more debug information in the init_repo script)
 - #61333 (Fix ICE with APIT in a function with a const parameter)

Failed merges:

 - #61304 (Speed up Azure CI installing Windows dependencies)

r? @ghost
Diffstat (limited to 'src')
-rw-r--r--src/ci/docker/armhf-gnu/Dockerfile2
-rwxr-xr-xsrc/ci/docker/dist-various-1/install-mips-musl.sh2
-rwxr-xr-xsrc/ci/docker/dist-various-1/install-mipsel-musl.sh2
-rw-r--r--src/ci/docker/dist-various-2/Dockerfile12
-rwxr-xr-xsrc/ci/docker/dist-various-2/build-wasi-toolchain.sh2
-rwxr-xr-xsrc/ci/docker/dist-x86_64-linux/build-openssl.sh2
-rwxr-xr-xsrc/ci/docker/dist-x86_64-netbsd/build-netbsd-toolchain.sh2
-rw-r--r--src/ci/docker/scripts/emscripten.sh2
-rwxr-xr-xsrc/ci/docker/scripts/freebsd-toolchain.sh2
-rw-r--r--src/ci/docker/scripts/sccache.sh2
-rwxr-xr-xsrc/ci/init_repo.sh4
-rw-r--r--src/doc/rustdoc/src/documentation-tests.md13
-rw-r--r--src/doc/unstable-book/src/library-features/borrow-state.md7
-rw-r--r--src/liballoc/slice.rs9
-rw-r--r--src/libcore/cell.rs3
-rw-r--r--src/librustc/hir/lowering.rs12
-rw-r--r--src/librustc/hir/mod.rs7
-rw-r--r--src/librustc_codegen_llvm/consts.rs23
-rw-r--r--src/librustc_typeck/collect.rs98
-rw-r--r--src/librustdoc/Cargo.toml2
-rw-r--r--src/librustdoc/html/markdown.rs10
-rw-r--r--src/librustdoc/test.rs7
-rw-r--r--src/libsyntax/parse/parser.rs73
-rw-r--r--src/test/rustdoc/issue-60482.rs9
-rw-r--r--src/test/rustdoc/process-termination.rs12
-rw-r--r--src/test/ui/const-generics/apit-with-const-param.rs10
-rw-r--r--src/test/ui/const-generics/apit-with-const-param.stderr6
-rw-r--r--src/test/ui/const-generics/cannot-infer-type-for-const-param.rs5
-rw-r--r--src/test/ui/const-generics/cannot-infer-type-for-const-param.stderr21
-rw-r--r--src/test/ui/const-generics/issue-60818-struct-constructors.rs10
-rw-r--r--src/test/ui/const-generics/issue-60818-struct-constructors.stderr6
-rw-r--r--src/test/ui/linkage-attr/auxiliary/def_colliding_external.rs7
-rw-r--r--src/test/ui/linkage-attr/auxiliary/def_illtyped_external.rs5
-rw-r--r--src/test/ui/linkage-attr/linkage-detect-extern-generated-name-collision.rs21
-rw-r--r--src/test/ui/linkage-attr/linkage-detect-extern-generated-name-collision.stderr8
-rw-r--r--src/test/ui/linkage-attr/linkage-detect-local-generated-name-collision.rs23
-rw-r--r--src/test/ui/linkage-attr/linkage-detect-local-generated-name-collision.stderr8
-rw-r--r--src/test/ui/linkage-attr/linkage-requires-raw-ptr.rs10
-rw-r--r--src/test/ui/linkage-attr/linkage-requires-raw-ptr.stderr8
-rw-r--r--src/test/ui/linkage-attr/linkage2.rs (renamed from src/test/ui/linkage2.rs)2
-rw-r--r--src/test/ui/linkage-attr/linkage2.stderr (renamed from src/test/ui/linkage2.stderr)2
-rw-r--r--src/test/ui/linkage-attr/linkage3.rs (renamed from src/test/ui/linkage3.rs)0
-rw-r--r--src/test/ui/linkage-attr/linkage3.stderr (renamed from src/test/ui/linkage3.stderr)0
-rw-r--r--src/test/ui/linkage-attr/linkage4.rs (renamed from src/test/ui/linkage4.rs)0
-rw-r--r--src/test/ui/linkage-attr/linkage4.stderr (renamed from src/test/ui/linkage4.stderr)0
45 files changed, 308 insertions, 163 deletions
diff --git a/src/ci/docker/armhf-gnu/Dockerfile b/src/ci/docker/armhf-gnu/Dockerfile
index e4c2097f970..235920833f8 100644
--- a/src/ci/docker/armhf-gnu/Dockerfile
+++ b/src/ci/docker/armhf-gnu/Dockerfile
@@ -72,7 +72,7 @@ RUN arm-linux-gnueabihf-gcc addentropy.c -o rootfs/addentropy -static
 
 # TODO: What is this?!
 # Source of the file: https://github.com/vfdev-5/qemu-rpi2-vexpress/raw/master/vexpress-v2p-ca15-tc1.dtb
-RUN curl -O https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/vexpress-v2p-ca15-tc1.dtb
+RUN curl -O https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/vexpress-v2p-ca15-tc1.dtb
 
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
diff --git a/src/ci/docker/dist-various-1/install-mips-musl.sh b/src/ci/docker/dist-various-1/install-mips-musl.sh
index 8d05a046959..60a96e3b8e9 100755
--- a/src/ci/docker/dist-various-1/install-mips-musl.sh
+++ b/src/ci/docker/dist-various-1/install-mips-musl.sh
@@ -5,7 +5,7 @@ mkdir /usr/local/mips-linux-musl
 # originally from
 # https://downloads.openwrt.org/snapshots/trunk/ar71xx/generic/
 # OpenWrt-Toolchain-ar71xx-generic_gcc-5.3.0_musl-1.1.16.Linux-x86_64.tar.bz2
-URL="https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror"
+URL="https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror"
 FILE="OpenWrt-Toolchain-ar71xx-generic_gcc-5.3.0_musl-1.1.16.Linux-x86_64.tar.bz2"
 curl -L "$URL/$FILE" | tar xjf - -C /usr/local/mips-linux-musl --strip-components=2
 
diff --git a/src/ci/docker/dist-various-1/install-mipsel-musl.sh b/src/ci/docker/dist-various-1/install-mipsel-musl.sh
index 2c414744bf4..9ae41218ee4 100755
--- a/src/ci/docker/dist-various-1/install-mipsel-musl.sh
+++ b/src/ci/docker/dist-various-1/install-mipsel-musl.sh
@@ -5,7 +5,7 @@ mkdir /usr/local/mipsel-linux-musl
 # Note that this originally came from:
 # https://downloads.openwrt.org/snapshots/trunk/malta/generic/
 # OpenWrt-Toolchain-malta-le_gcc-5.3.0_musl-1.1.15.Linux-x86_64.tar.bz2
-URL="https://s3-us-west-1.amazonaws.com/rust-lang-ci2/libc"
+URL="https://rust-lang-ci2.s3.amazonaws.com/libc"
 FILE="OpenWrt-Toolchain-malta-le_gcc-5.3.0_musl-1.1.15.Linux-x86_64.tar.bz2"
 curl -L "$URL/$FILE" | tar xjf - -C /usr/local/mipsel-linux-musl --strip-components=2
 
diff --git a/src/ci/docker/dist-various-2/Dockerfile b/src/ci/docker/dist-various-2/Dockerfile
index bf449c83f12..53523d41a55 100644
--- a/src/ci/docker/dist-various-2/Dockerfile
+++ b/src/ci/docker/dist-various-2/Dockerfile
@@ -32,10 +32,9 @@ COPY dist-various-2/build-cloudabi-toolchain.sh /tmp/
 RUN /tmp/build-cloudabi-toolchain.sh x86_64-unknown-cloudabi
 COPY dist-various-2/build-fuchsia-toolchain.sh /tmp/
 RUN /tmp/build-fuchsia-toolchain.sh
-# FIXME(#61022) - reenable solaris
-# COPY dist-various-2/build-solaris-toolchain.sh /tmp/
-# RUN /tmp/build-solaris-toolchain.sh x86_64  amd64   solaris-i386
-# RUN /tmp/build-solaris-toolchain.sh sparcv9 sparcv9 solaris-sparc
+COPY dist-various-2/build-solaris-toolchain.sh /tmp/
+RUN /tmp/build-solaris-toolchain.sh x86_64  amd64   solaris-i386
+RUN /tmp/build-solaris-toolchain.sh sparcv9 sparcv9 solaris-sparc
 COPY dist-various-2/build-x86_64-fortanix-unknown-sgx-toolchain.sh /tmp/
 # We pass the commit id of the port of LLVM's libunwind to the build script.
 # Any update to the commit id here, should cause the container image to be re-built from this point on.
@@ -76,9 +75,8 @@ ENV TARGETS=x86_64-fuchsia
 ENV TARGETS=$TARGETS,aarch64-fuchsia
 ENV TARGETS=$TARGETS,wasm32-unknown-unknown
 ENV TARGETS=$TARGETS,wasm32-wasi
-# FIXME(#61022) - reenable solaris
-# ENV TARGETS=$TARGETS,sparcv9-sun-solaris
-# ENV TARGETS=$TARGETS,x86_64-sun-solaris
+ENV TARGETS=$TARGETS,sparcv9-sun-solaris
+ENV TARGETS=$TARGETS,x86_64-sun-solaris
 ENV TARGETS=$TARGETS,x86_64-unknown-linux-gnux32
 ENV TARGETS=$TARGETS,x86_64-unknown-cloudabi
 ENV TARGETS=$TARGETS,x86_64-fortanix-unknown-sgx
diff --git a/src/ci/docker/dist-various-2/build-wasi-toolchain.sh b/src/ci/docker/dist-various-2/build-wasi-toolchain.sh
index 98d6df043ba..7bf8946c4f1 100755
--- a/src/ci/docker/dist-various-2/build-wasi-toolchain.sh
+++ b/src/ci/docker/dist-various-2/build-wasi-toolchain.sh
@@ -5,7 +5,7 @@
 set -ex
 
 # Originally from https://releases.llvm.org/8.0.0/clang+llvm-8.0.0-x86_64-linux-gnu-ubuntu-14.04.tar.xz
-curl https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/clang%2Bllvm-8.0.0-x86_64-linux-gnu-ubuntu-14.04.tar.xz | \
+curl https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/clang%2Bllvm-8.0.0-x86_64-linux-gnu-ubuntu-14.04.tar.xz | \
   tar xJf -
 export PATH=`pwd`/clang+llvm-8.0.0-x86_64-linux-gnu-ubuntu-14.04/bin:$PATH
 
diff --git a/src/ci/docker/dist-x86_64-linux/build-openssl.sh b/src/ci/docker/dist-x86_64-linux/build-openssl.sh
index 7e391e21d13..13dae616905 100755
--- a/src/ci/docker/dist-x86_64-linux/build-openssl.sh
+++ b/src/ci/docker/dist-x86_64-linux/build-openssl.sh
@@ -4,7 +4,7 @@ set -ex
 source shared.sh
 
 VERSION=1.0.2k
-URL=https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/openssl-$VERSION.tar.gz
+URL=https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/openssl-$VERSION.tar.gz
 
 curl $URL | tar xzf -
 
diff --git a/src/ci/docker/dist-x86_64-netbsd/build-netbsd-toolchain.sh b/src/ci/docker/dist-x86_64-netbsd/build-netbsd-toolchain.sh
index b5377c64b1f..2e9b9dcc234 100755
--- a/src/ci/docker/dist-x86_64-netbsd/build-netbsd-toolchain.sh
+++ b/src/ci/docker/dist-x86_64-netbsd/build-netbsd-toolchain.sh
@@ -25,7 +25,7 @@ cd netbsd
 
 mkdir -p /x-tools/x86_64-unknown-netbsd/sysroot
 
-URL=https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror
+URL=https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror
 
 # Originally from ftp://ftp.netbsd.org/pub/NetBSD/NetBSD-$BSD/source/sets/*.tgz
 curl $URL/2018-03-01-netbsd-src.tgz | tar xzf -
diff --git a/src/ci/docker/scripts/emscripten.sh b/src/ci/docker/scripts/emscripten.sh
index d3b1cded6f5..47196e89396 100644
--- a/src/ci/docker/scripts/emscripten.sh
+++ b/src/ci/docker/scripts/emscripten.sh
@@ -18,7 +18,7 @@ exit 1
 }
 
 cd /
-curl -fL https://s3.amazonaws.com/mozilla-games/emscripten/releases/emsdk-portable.tar.gz | \
+curl -fL https://mozilla-games.s3.amazonaws.com/emscripten/releases/emsdk-portable.tar.gz | \
     tar -xz
 
 cd /emsdk-portable
diff --git a/src/ci/docker/scripts/freebsd-toolchain.sh b/src/ci/docker/scripts/freebsd-toolchain.sh
index b1ac490a878..8cef69d9c26 100755
--- a/src/ci/docker/scripts/freebsd-toolchain.sh
+++ b/src/ci/docker/scripts/freebsd-toolchain.sh
@@ -59,7 +59,7 @@ done
 
 # Originally downloaded from:
 # https://download.freebsd.org/ftp/releases/${freebsd_arch}/${freebsd_version}-RELEASE/base.txz
-URL=https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2019-04-04-freebsd-${freebsd_arch}-${freebsd_version}-RELEASE-base.txz
+URL=https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/2019-04-04-freebsd-${freebsd_arch}-${freebsd_version}-RELEASE-base.txz
 curl "$URL" | tar xJf - -C "$sysroot" --wildcards "${files_to_extract[@]}"
 
 # Fix up absolute symlinks from the system image.  This can be removed
diff --git a/src/ci/docker/scripts/sccache.sh b/src/ci/docker/scripts/sccache.sh
index 4c03419894e..194de3c339f 100644
--- a/src/ci/docker/scripts/sccache.sh
+++ b/src/ci/docker/scripts/sccache.sh
@@ -1,6 +1,6 @@
 set -ex
 
 curl -fo /usr/local/bin/sccache \
-  https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2018-04-02-sccache-x86_64-unknown-linux-musl
+  https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/2018-04-02-sccache-x86_64-unknown-linux-musl
 
 chmod +x /usr/local/bin/sccache
diff --git a/src/ci/init_repo.sh b/src/ci/init_repo.sh
index 3dfd3381576..8b635810825 100755
--- a/src/ci/init_repo.sh
+++ b/src/ci/init_repo.sh
@@ -1,5 +1,9 @@
 #!/usr/bin/env bash
 
+# FIXME(61301): we need to debug spurious failures with this on Windows on
+# Azure, so let's print more information in the logs.
+set -x
+
 set -o errexit
 set -o pipefail
 set -o nounset
diff --git a/src/doc/rustdoc/src/documentation-tests.md b/src/doc/rustdoc/src/documentation-tests.md
index c9acd3c307b..a896ce819ae 100644
--- a/src/doc/rustdoc/src/documentation-tests.md
+++ b/src/doc/rustdoc/src/documentation-tests.md
@@ -253,6 +253,19 @@ conversion, so type inference fails because the type is not unique. Please note
 that you must write the `(())` in one sequence without intermediate whitespace
 so that rustdoc understands you want an implicit `Result`-returning function.
 
+As of version 1.37.0, this simplification also works with `Option`s, which can
+be handy to test e.g. iterators or checked arithmetic, for example:
+
+```ignore
+/// ```
+/// let _ = &[].iter().next()?;
+///# Some(())
+/// ```
+```
+
+Note that the result must be a `Some(())` and this has to be written in one go.
+In this case disambiguating the result isn't required.
+
 ## Documenting macros
 
 Here’s an example of documenting a macro:
diff --git a/src/doc/unstable-book/src/library-features/borrow-state.md b/src/doc/unstable-book/src/library-features/borrow-state.md
deleted file mode 100644
index 304b8dffe98..00000000000
--- a/src/doc/unstable-book/src/library-features/borrow-state.md
+++ /dev/null
@@ -1,7 +0,0 @@
-# `borrow_state`
-
-The tracking issue for this feature is: [#27733]
-
-[#27733]: https://github.com/rust-lang/rust/issues/27733
-
-------------------------
diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs
index 8768f1ff081..aeb7f90d3e6 100644
--- a/src/liballoc/slice.rs
+++ b/src/liballoc/slice.rs
@@ -137,17 +137,16 @@ pub use hack::to_vec;
 // `core::slice::SliceExt` - we need to supply these functions for the
 // `test_permutations` test
 mod hack {
-    use core::mem;
-
     use crate::boxed::Box;
     use crate::vec::Vec;
     #[cfg(test)]
     use crate::string::ToString;
 
-    pub fn into_vec<T>(mut b: Box<[T]>) -> Vec<T> {
+    pub fn into_vec<T>(b: Box<[T]>) -> Vec<T> {
         unsafe {
-            let xs = Vec::from_raw_parts(b.as_mut_ptr(), b.len(), b.len());
-            mem::forget(b);
+            let len = b.len();
+            let b = Box::into_raw(b);
+            let xs = Vec::from_raw_parts(b as *mut T, len, len);
             xs
         }
     }
diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs
index 80341409037..9d26ecbacdc 100644
--- a/src/libcore/cell.rs
+++ b/src/libcore/cell.rs
@@ -967,7 +967,6 @@ impl<T: ?Sized> RefCell<T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(borrow_state)]
     /// use std::cell::RefCell;
     ///
     /// let c = RefCell::new(5);
@@ -982,7 +981,7 @@ impl<T: ?Sized> RefCell<T> {
     ///     assert!(unsafe { c.try_borrow_unguarded() }.is_ok());
     /// }
     /// ```
-    #[unstable(feature = "borrow_state", issue = "27733")]
+    #[stable(feature = "borrow_state", since = "1.37.0")]
     #[inline]
     pub unsafe fn try_borrow_unguarded(&self) -> Result<&T, BorrowError> {
         if !is_writing(self.borrow.get()) {
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index c5bcddcb266..08fbd0d20d7 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -1083,6 +1083,18 @@ impl<'a> LoweringContext<'a> {
             .chain(in_band_defs)
             .collect();
 
+        // FIXME(const_generics): the compiler doesn't always cope with
+        // unsorted generic parameters at the moment, so we make sure
+        // that they're ordered correctly here for now. (When we chain
+        // the `in_band_defs`, we might make the order unsorted.)
+        lowered_generics.params.sort_by_key(|param| {
+            match param.kind {
+                hir::GenericParamKind::Lifetime { .. } => ParamKindOrd::Lifetime,
+                hir::GenericParamKind::Type { .. } => ParamKindOrd::Type,
+                hir::GenericParamKind::Const { .. } => ParamKindOrd::Const,
+            }
+        });
+
         (lowered_generics, res)
     }
 
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index 1a6f5d3733e..f03a8ddc908 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -425,6 +425,13 @@ impl GenericArg {
             GenericArg::Const(c) => c.value.hir_id,
         }
     }
+
+    pub fn is_const(&self) -> bool {
+        match self {
+            GenericArg::Const(_) => true,
+            _ => false,
+        }
+    }
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs
index 5f47108309f..99b5cf42551 100644
--- a/src/librustc_codegen_llvm/consts.rs
+++ b/src/librustc_codegen_llvm/consts.rs
@@ -102,7 +102,7 @@ fn check_and_apply_linkage(
     attrs: &CodegenFnAttrs,
     ty: Ty<'tcx>,
     sym: LocalInternedString,
-    span: Option<Span>
+    span: Span
 ) -> &'ll Value {
     let llty = cx.layout_of(ty).llvm_type(cx);
     if let Some(linkage) = attrs.linkage {
@@ -116,11 +116,8 @@ fn check_and_apply_linkage(
         let llty2 = if let ty::RawPtr(ref mt) = ty.sty {
             cx.layout_of(mt.ty).llvm_type(cx)
         } else {
-            if let Some(span) = span {
-                cx.sess().span_fatal(span, "must have type `*const T` or `*mut T`")
-            } else {
-                bug!("must have type `*const T` or `*mut T`")
-            }
+            cx.sess().span_fatal(
+                span, "must have type `*const T` or `*mut T` due to `#[linkage]` attribute")
         };
         unsafe {
             // Declare a symbol `foo` with the desired linkage.
@@ -136,14 +133,7 @@ fn check_and_apply_linkage(
             let mut real_name = "_rust_extern_with_linkage_".to_string();
             real_name.push_str(&sym);
             let g2 = cx.define_global(&real_name, llty).unwrap_or_else(||{
-                if let Some(span) = span {
-                    cx.sess().span_fatal(
-                        span,
-                        &format!("symbol `{}` is already defined", &sym)
-                    )
-                } else {
-                    bug!("symbol `{}` is already defined", &sym)
-                }
+                cx.sess().span_fatal(span, &format!("symbol `{}` is already defined", &sym))
             });
             llvm::LLVMRustSetLinkage(g2, llvm::Linkage::InternalLinkage);
             llvm::LLVMSetInitializer(g2, g1);
@@ -240,7 +230,7 @@ impl CodegenCx<'ll, 'tcx> {
                     ref attrs, span, node: hir::ForeignItemKind::Static(..), ..
                 }) => {
                     let fn_attrs = self.tcx.codegen_fn_attrs(def_id);
-                    (check_and_apply_linkage(&self, &fn_attrs, ty, sym, Some(span)), attrs)
+                    (check_and_apply_linkage(&self, &fn_attrs, ty, sym, span), attrs)
                 }
 
                 item => bug!("get_static: expected static, found {:?}", item)
@@ -260,7 +250,8 @@ impl CodegenCx<'ll, 'tcx> {
             debug!("get_static: sym={} item_attr={:?}", sym, self.tcx.item_attrs(def_id));
 
             let attrs = self.tcx.codegen_fn_attrs(def_id);
-            let g = check_and_apply_linkage(&self, &attrs, ty, sym, None);
+            let span = self.tcx.def_span(def_id);
+            let g = check_and_apply_linkage(&self, &attrs, ty, sym, span);
 
             // Thread-local statics in some other crate need to *always* be linked
             // against in a thread-local fashion, so we need to be sure to apply the
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 00990a5c5b5..3806fd0998b 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -27,7 +27,7 @@ use rustc::ty::subst::{Subst, InternalSubsts};
 use rustc::ty::util::Discr;
 use rustc::ty::util::IntTypeExt;
 use rustc::ty::subst::UnpackedKind;
-use rustc::ty::{self, AdtKind, ToPolyTraitRef, Ty, TyCtxt};
+use rustc::ty::{self, AdtKind, DefIdTree, ToPolyTraitRef, Ty, TyCtxt};
 use rustc::ty::{ReprOptions, ToPredicate};
 use rustc::util::captures::Captures;
 use rustc::util::nodemap::FxHashMap;
@@ -1349,65 +1349,61 @@ pub fn checked_type_of<'a, 'tcx>(
 
                     match path {
                         QPath::Resolved(_, ref path) => {
-                            let mut arg_index = 0;
-                            let mut found_const = false;
-                            for seg in &path.segments {
-                                if let Some(generic_args) = &seg.args {
-                                    let args = &generic_args.args;
-                                    for arg in args {
-                                        if let GenericArg::Const(ct) = arg {
-                                            if ct.value.hir_id == hir_id {
-                                                found_const = true;
-                                                break;
-                                            }
-                                            arg_index += 1;
-                                        }
-                                    }
-                                }
-                            }
-                            // Sanity check to make sure everything is as expected.
-                            if !found_const {
-                                if !fail {
-                                    return None;
-                                }
-                                bug!("no arg matching AnonConst in path")
-                            }
-                            match path.res {
-                                // We've encountered an `AnonConst` in some path, so we need to
-                                // figure out which generic parameter it corresponds to and return
-                                // the relevant type.
-                                Res::Def(DefKind::Struct, def_id)
-                                | Res::Def(DefKind::Union, def_id)
-                                | Res::Def(DefKind::Enum, def_id)
-                                | Res::Def(DefKind::Fn, def_id) => {
-                                    let generics = tcx.generics_of(def_id);
-                                    let mut param_index = 0;
-                                    for param in &generics.params {
-                                        if let ty::GenericParamDefKind::Const = param.kind {
-                                            if param_index == arg_index {
-                                                return Some(tcx.type_of(param.def_id));
-                                            }
-                                            param_index += 1;
-                                        }
-                                    }
-                                    // This is no generic parameter associated with the arg. This is
-                                    // probably from an extra arg where one is not needed.
-                                    return Some(tcx.types.err);
-                                }
-                                Res::Err => tcx.types.err,
-                                x => {
+                            let arg_index = path.segments.iter()
+                                .filter_map(|seg| seg.args.as_ref())
+                                .map(|generic_args| generic_args.args.as_ref())
+                                .find_map(|args| {
+                                    args.iter()
+                                        .filter(|arg| arg.is_const())
+                                        .enumerate()
+                                        .filter(|(_, arg)| arg.id() == hir_id)
+                                        .map(|(index, _)| index)
+                                        .next()
+                                })
+                                .or_else(|| {
                                     if !fail {
-                                        return None;
+                                        None
+                                    } else {
+                                        bug!("no arg matching AnonConst in path")
                                     }
+                                })?;
+
+                            // We've encountered an `AnonConst` in some path, so we need to
+                            // figure out which generic parameter it corresponds to and return
+                            // the relevant type.
+                            let generics = match path.res {
+                                Res::Def(DefKind::Ctor(..), def_id) =>
+                                    tcx.generics_of(tcx.parent(def_id).unwrap()),
+                                Res::Def(_, def_id) =>
+                                    tcx.generics_of(def_id),
+                                Res::Err =>
+                                    return Some(tcx.types.err),
+                                _ if !fail =>
+                                    return None,
+                                x => {
                                     tcx.sess.delay_span_bug(
                                         DUMMY_SP,
                                         &format!(
                                             "unexpected const parent path def {:?}", x
                                         ),
                                     );
-                                    tcx.types.err
+                                    return Some(tcx.types.err);
                                 }
-                            }
+                            };
+
+                            generics.params.iter()
+                                .filter(|param| {
+                                    if let ty::GenericParamDefKind::Const = param.kind {
+                                        true
+                                    } else {
+                                        false
+                                    }
+                                })
+                                .nth(arg_index)
+                                .map(|param| tcx.type_of(param.def_id))
+                                // This is no generic parameter associated with the arg. This is
+                                // probably from an extra arg where one is not needed.
+                                .unwrap_or(tcx.types.err)
                         }
                         x => {
                             if !fail {
diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml
index 6cedab412df..b75212d606f 100644
--- a/src/librustdoc/Cargo.toml
+++ b/src/librustdoc/Cargo.toml
@@ -9,7 +9,7 @@ name = "rustdoc"
 path = "lib.rs"
 
 [dependencies]
-pulldown-cmark = { version = "0.4.1", default-features = false }
+pulldown-cmark = { version = "0.5.2", default-features = false }
 minifier = "0.0.30"
 tempfile = "3"
 parking_lot = "0.7"
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 12d10254c4d..334b8315650 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -351,9 +351,11 @@ impl<'a, 'b, 'ids, I: Iterator<Item = Event<'a>>> Iterator for HeadingLinks<'a,
         if let Some(Event::Start(Tag::Header(level))) = event {
             let mut id = String::new();
             for event in &mut self.inner {
-                match event {
+                match &event {
                     Event::End(Tag::Header(..)) => break,
-                    Event::Text(ref text) => id.extend(text.chars().filter_map(slugify)),
+                    Event::Text(text) | Event::Code(text) => {
+                        id.extend(text.chars().filter_map(slugify));
+                    }
                     _ => {},
                 }
                 self.buf.push_back(event);
@@ -402,7 +404,6 @@ fn check_if_allowed_tag(t: &Tag<'_>) -> bool {
         | Tag::Item
         | Tag::Emphasis
         | Tag::Strong
-        | Tag::Code
         | Tag::Link(..)
         | Tag::BlockQuote => true,
         _ => false,
@@ -790,9 +791,8 @@ pub fn plain_summary_line_full(md: &str, limit_length: bool) -> String {
             let next_event = next_event.unwrap();
             let (ret, is_in) = match next_event {
                 Event::Start(Tag::Paragraph) => (None, 1),
-                Event::Start(Tag::Code) => (Some("`".to_owned()), 1),
-                Event::End(Tag::Code) => (Some("`".to_owned()), -1),
                 Event::Start(Tag::Header(_)) => (None, 1),
+                Event::Code(code) => (Some(format!("`{}`", code)), 0),
                 Event::Text(ref s) if self.is_in > 0 => (Some(s.as_ref().to_owned()), 0),
                 Event::End(Tag::Paragraph) | Event::End(Tag::Header(_)) => (None, -1),
                 _ => (None, 0),
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index 9d1a0cc074c..5bce5d6ba5d 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -530,8 +530,13 @@ pub fn make_test(s: &str,
         prog.push_str(everything_else);
     } else {
         let returns_result = everything_else.trim_end().ends_with("(())");
+        let returns_option = everything_else.trim_end().ends_with("Some(())");
         let (main_pre, main_post) = if returns_result {
-            ("fn main() { fn _inner() -> Result<(), impl core::fmt::Debug> {",
+            (if returns_option {
+                "fn main() { fn _inner() -> Option<()> {"
+            } else {
+                "fn main() { fn _inner() -> Result<(), impl core::fmt::Debug> {"
+            },
              "}\n_inner().unwrap() }")
         } else {
             ("fn main() {\n", "\n}")
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 07efeaa4cf2..746e9cad496 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -1087,6 +1087,11 @@ impl<'a> Parser<'a> {
         }
     }
 
+    /// Returns whether any of the given keywords are `dist` tokens ahead of the current one.
+    fn is_keyword_ahead(&self, dist: usize, kws: &[Symbol]) -> bool {
+        self.look_ahead(dist, |t| kws.iter().any(|&kw| t.is_keyword(kw)))
+    }
+
     /// Is the current token one of the keywords that signals a bare function type?
     fn token_is_bare_fn_keyword(&mut self) -> bool {
         self.check_keyword(kw::Fn) ||
@@ -4270,7 +4275,7 @@ impl<'a> Parser<'a> {
         self.token.is_keyword(kw::Async) &&
         (
             ( // `async move {`
-                self.look_ahead(1, |t| t.is_keyword(kw::Move)) &&
+                self.is_keyword_ahead(1, &[kw::Move]) &&
                 self.look_ahead(2, |t| *t == token::OpenDelim(token::Brace))
             ) || ( // `async {`
                 self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace))
@@ -4280,12 +4285,12 @@ impl<'a> Parser<'a> {
 
     fn is_async_fn(&self) -> bool {
         self.token.is_keyword(kw::Async) &&
-            self.look_ahead(1, |t| t.is_keyword(kw::Fn))
+            self.is_keyword_ahead(1, &[kw::Fn])
     }
 
     fn is_do_catch_block(&self) -> bool {
         self.token.is_keyword(kw::Do) &&
-        self.look_ahead(1, |t| t.is_keyword(kw::Catch)) &&
+        self.is_keyword_ahead(1, &[kw::Catch]) &&
         self.look_ahead(2, |t| *t == token::OpenDelim(token::Brace)) &&
         !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL)
     }
@@ -4309,17 +4314,17 @@ impl<'a> Parser<'a> {
 
     fn is_existential_type_decl(&self) -> bool {
         self.token.is_keyword(kw::Existential) &&
-        self.look_ahead(1, |t| t.is_keyword(kw::Type))
+        self.is_keyword_ahead(1, &[kw::Type])
     }
 
     fn is_auto_trait_item(&self) -> bool {
         // auto trait
-        (self.token.is_keyword(kw::Auto)
-            && self.look_ahead(1, |t| t.is_keyword(kw::Trait)))
+        (self.token.is_keyword(kw::Auto) &&
+            self.is_keyword_ahead(1, &[kw::Trait]))
         || // unsafe auto trait
         (self.token.is_keyword(kw::Unsafe) &&
-         self.look_ahead(1, |t| t.is_keyword(kw::Auto)) &&
-         self.look_ahead(2, |t| t.is_keyword(kw::Trait)))
+         self.is_keyword_ahead(1, &[kw::Auto]) &&
+         self.is_keyword_ahead(2, &[kw::Trait]))
     }
 
     fn eat_macro_def(&mut self, attrs: &[Attribute], vis: &Visibility, lo: Span)
@@ -5486,7 +5491,7 @@ impl<'a> Parser<'a> {
                 (if isolated_self(self, 1) {
                     self.bump();
                     SelfKind::Region(None, Mutability::Immutable)
-                } else if self.look_ahead(1, |t| t.is_keyword(kw::Mut)) &&
+                } else if self.is_keyword_ahead(1, &[kw::Mut]) &&
                           isolated_self(self, 2) {
                     self.bump();
                     self.bump();
@@ -5497,7 +5502,7 @@ impl<'a> Parser<'a> {
                     let lt = self.expect_lifetime();
                     SelfKind::Region(Some(lt), Mutability::Immutable)
                 } else if self.look_ahead(1, |t| t.is_lifetime()) &&
-                          self.look_ahead(2, |t| t.is_keyword(kw::Mut)) &&
+                          self.is_keyword_ahead(2, &[kw::Mut]) &&
                           isolated_self(self, 3) {
                     self.bump();
                     let lt = self.expect_lifetime();
@@ -5676,8 +5681,7 @@ impl<'a> Parser<'a> {
     /// (returns `false` for things like `const fn`, etc.).
     fn is_const_item(&self) -> bool {
         self.token.is_keyword(kw::Const) &&
-            !self.look_ahead(1, |t| t.is_keyword(kw::Fn)) &&
-            !self.look_ahead(1, |t| t.is_keyword(kw::Unsafe))
+            !self.is_keyword_ahead(1, &[kw::Fn, kw::Unsafe])
     }
 
     /// Parses all the "front matter" for a `fn` declaration, up to
@@ -5955,7 +5959,7 @@ impl<'a> Parser<'a> {
              self.look_ahead(1, |t| t.is_lifetime() || t.is_ident()) &&
                 self.look_ahead(2, |t| t == &token::Gt || t == &token::Comma ||
                                        t == &token::Colon || t == &token::Eq) ||
-             self.look_ahead(1, |t| t.is_keyword(kw::Const)))
+            self.is_keyword_ahead(1, &[kw::Const]))
     }
 
     fn parse_impl_body(&mut self) -> PResult<'a, (Vec<ImplItem>, Vec<Attribute>)> {
@@ -6316,7 +6320,7 @@ impl<'a> Parser<'a> {
             // `()` or a tuple might be allowed. For example, `struct Struct(pub (), pub (usize));`.
             // Because of this, we only `bump` the `(` if we're assured it is appropriate to do so
             // by the following tokens.
-            if self.look_ahead(1, |t| t.is_keyword(kw::Crate)) &&
+            if self.is_keyword_ahead(1, &[kw::Crate]) &&
                 self.look_ahead(2, |t| t != &token::ModSep) // account for `pub(crate::foo)`
             {
                 // `pub(crate)`
@@ -6328,7 +6332,7 @@ impl<'a> Parser<'a> {
                     VisibilityKind::Crate(CrateSugar::PubCrate),
                 );
                 return Ok(vis)
-            } else if self.look_ahead(1, |t| t.is_keyword(kw::In)) {
+            } else if self.is_keyword_ahead(1, &[kw::In]) {
                 // `pub(in path)`
                 self.bump(); // `(`
                 self.bump(); // `in`
@@ -6340,8 +6344,7 @@ impl<'a> Parser<'a> {
                 });
                 return Ok(vis)
             } else if self.look_ahead(2, |t| t == &token::CloseDelim(token::Paren)) &&
-                      self.look_ahead(1, |t| t.is_keyword(kw::Super) ||
-                                             t.is_keyword(kw::SelfLower))
+                      self.is_keyword_ahead(1, &[kw::Super, kw::SelfLower])
             {
                 // `pub(self)` or `pub(super)`
                 self.bump(); // `(`
@@ -6380,13 +6383,16 @@ impl<'a> Parser<'a> {
     fn parse_defaultness(&mut self) -> Defaultness {
         // `pub` is included for better error messages
         if self.check_keyword(kw::Default) &&
-           self.look_ahead(1, |t| t.is_keyword(kw::Impl) ||
-                                  t.is_keyword(kw::Const) ||
-                                  t.is_keyword(kw::Fn) ||
-                                  t.is_keyword(kw::Unsafe) ||
-                                  t.is_keyword(kw::Extern) ||
-                                  t.is_keyword(kw::Type) ||
-                                  t.is_keyword(kw::Pub)) {
+            self.is_keyword_ahead(1, &[
+                kw::Impl,
+                kw::Const,
+                kw::Fn,
+                kw::Unsafe,
+                kw::Extern,
+                kw::Type,
+                kw::Pub,
+            ])
+        {
             self.bump(); // `default`
             Defaultness::Default
         } else {
@@ -6880,7 +6886,7 @@ impl<'a> Parser<'a> {
         //     Ident ["<"...">"] ["where" ...] ("=" | ":") Ty ";"
         if self.check_keyword(kw::Type) ||
            self.check_keyword(kw::Existential) &&
-                self.look_ahead(1, |t| t.is_keyword(kw::Type)) {
+                self.is_keyword_ahead(1, &[kw::Type]) {
             let existential = self.eat_keyword(kw::Existential);
             assert!(self.eat_keyword(kw::Type));
             Some(self.parse_existential_or_alias(existential))
@@ -7157,7 +7163,7 @@ impl<'a> Parser<'a> {
             let const_span = self.prev_span;
             if self.check_keyword(kw::Fn)
                 || (self.check_keyword(kw::Unsafe)
-                    && self.look_ahead(1, |t| t.is_keyword(kw::Fn))) {
+                    && self.is_keyword_ahead(1, &[kw::Fn])) {
                 // CONST FUNCTION ITEM
                 let unsafety = self.parse_unsafety();
                 self.bump();
@@ -7202,10 +7208,10 @@ impl<'a> Parser<'a> {
         // `unsafe async fn` or `async fn`
         if (
             self.check_keyword(kw::Unsafe) &&
-            self.look_ahead(1, |t| t.is_keyword(kw::Async))
+            self.is_keyword_ahead(1, &[kw::Async])
         ) || (
             self.check_keyword(kw::Async) &&
-            self.look_ahead(1, |t| t.is_keyword(kw::Fn))
+            self.is_keyword_ahead(1, &[kw::Fn])
         )
         {
             // ASYNC FUNCTION ITEM
@@ -7239,8 +7245,7 @@ impl<'a> Parser<'a> {
             return Ok(Some(item));
         }
         if self.check_keyword(kw::Unsafe) &&
-            (self.look_ahead(1, |t| t.is_keyword(kw::Trait)) ||
-            self.look_ahead(1, |t| t.is_keyword(kw::Auto)))
+            self.is_keyword_ahead(1, &[kw::Trait, kw::Auto])
         {
             // UNSAFE TRAIT ITEM
             self.bump(); // `unsafe`
@@ -7263,11 +7268,9 @@ impl<'a> Parser<'a> {
         }
         if self.check_keyword(kw::Impl) ||
            self.check_keyword(kw::Unsafe) &&
-                self.look_ahead(1, |t| t.is_keyword(kw::Impl)) ||
-           self.check_keyword(kw::Default) &&
-                self.look_ahead(1, |t| t.is_keyword(kw::Impl)) ||
+                self.is_keyword_ahead(1, &[kw::Impl]) ||
            self.check_keyword(kw::Default) &&
-                self.look_ahead(1, |t| t.is_keyword(kw::Unsafe)) {
+                self.is_keyword_ahead(1, &[kw::Impl, kw::Unsafe]) {
             // IMPL ITEM
             let defaultness = self.parse_defaultness();
             let unsafety = self.parse_unsafety();
@@ -7360,7 +7363,7 @@ impl<'a> Parser<'a> {
         }
         if self.check_keyword(kw::Trait)
             || (self.check_keyword(kw::Auto)
-                && self.look_ahead(1, |t| t.is_keyword(kw::Trait)))
+                && self.is_keyword_ahead(1, &[kw::Trait]))
         {
             let is_auto = if self.eat_keyword(kw::Trait) {
                 IsAuto::No
diff --git a/src/test/rustdoc/issue-60482.rs b/src/test/rustdoc/issue-60482.rs
new file mode 100644
index 00000000000..0fd1daa746d
--- /dev/null
+++ b/src/test/rustdoc/issue-60482.rs
@@ -0,0 +1,9 @@
+// This code caused a panic in `pulldown-cmark` 0.4.1.
+
+pub const BASIC_UNICODE: bool = true;
+
+
+/// # `BASIC_UNICODE`: `A` `|`
+/// ```text
+/// ```
+pub const BASIC_FONTS: bool = true;
diff --git a/src/test/rustdoc/process-termination.rs b/src/test/rustdoc/process-termination.rs
index 32258792b6e..31ae0143d47 100644
--- a/src/test/rustdoc/process-termination.rs
+++ b/src/test/rustdoc/process-termination.rs
@@ -21,4 +21,16 @@
 /// Err("This is returned from `main`, leading to panic")?;
 /// Ok::<(), &'static str>(())
 /// ```
+///
+/// This also works with `Option<()>`s now:
+///
+/// ```rust
+/// Some(())
+/// ```
+///
+/// ```rust,should_panic
+/// let x: &[u32] = &[];
+/// let _ = x.iter().next()?;
+/// Some(())
+/// ```
 pub fn check_process_termination() {}
diff --git a/src/test/ui/const-generics/apit-with-const-param.rs b/src/test/ui/const-generics/apit-with-const-param.rs
new file mode 100644
index 00000000000..70e718d8890
--- /dev/null
+++ b/src/test/ui/const-generics/apit-with-const-param.rs
@@ -0,0 +1,10 @@
+// run-pass
+
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+trait Trait {}
+
+fn f<const N: usize>(_: impl Trait) {}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/apit-with-const-param.stderr b/src/test/ui/const-generics/apit-with-const-param.stderr
new file mode 100644
index 00000000000..b3038ee6488
--- /dev/null
+++ b/src/test/ui/const-generics/apit-with-const-param.stderr
@@ -0,0 +1,6 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/apit-with-const-param.rs:3:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+
diff --git a/src/test/ui/const-generics/cannot-infer-type-for-const-param.rs b/src/test/ui/const-generics/cannot-infer-type-for-const-param.rs
index 26496ec4a90..f592e486be9 100644
--- a/src/test/ui/const-generics/cannot-infer-type-for-const-param.rs
+++ b/src/test/ui/const-generics/cannot-infer-type-for-const-param.rs
@@ -1,8 +1,9 @@
+// compile-pass
 #![feature(const_generics)]
 //~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
 
-// We should probably be able to infer the types here. However, this test is checking that we don't
-// get an ICE in this case. It may be modified later to not be an error.
+// This test confirms that the types can be inferred correctly for this example with const
+// generics. Previously this would ICE, and more recently error.
 
 struct Foo<const NUM_BYTES: usize>(pub [u8; NUM_BYTES]);
 
diff --git a/src/test/ui/const-generics/cannot-infer-type-for-const-param.stderr b/src/test/ui/const-generics/cannot-infer-type-for-const-param.stderr
index fb151648f2f..52907bbb677 100644
--- a/src/test/ui/const-generics/cannot-infer-type-for-const-param.stderr
+++ b/src/test/ui/const-generics/cannot-infer-type-for-const-param.stderr
@@ -1,25 +1,6 @@
 warning: the feature `const_generics` is incomplete and may cause the compiler to crash
-  --> $DIR/cannot-infer-type-for-const-param.rs:1:12
+  --> $DIR/cannot-infer-type-for-const-param.rs:2:12
    |
 LL | #![feature(const_generics)]
    |            ^^^^^^^^^^^^^^
 
-error[E0282]: type annotations needed
-  --> $DIR/cannot-infer-type-for-const-param.rs:10:19
-   |
-LL |     let _ = Foo::<3>([1, 2, 3]);
-   |                   ^ cannot infer type for `{integer}`
-
-error[E0308]: mismatched types
-  --> $DIR/cannot-infer-type-for-const-param.rs:10:22
-   |
-LL |     let _ = Foo::<3>([1, 2, 3]);
-   |                      ^^^^^^^^^ expected `3`, found `3usize`
-   |
-   = note: expected type `[u8; _]`
-              found type `[u8; 3]`
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0282, E0308.
-For more information about an error, try `rustc --explain E0282`.
diff --git a/src/test/ui/const-generics/issue-60818-struct-constructors.rs b/src/test/ui/const-generics/issue-60818-struct-constructors.rs
new file mode 100644
index 00000000000..0b4aeae7a4a
--- /dev/null
+++ b/src/test/ui/const-generics/issue-60818-struct-constructors.rs
@@ -0,0 +1,10 @@
+// compile-pass
+
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+struct Generic<const V: usize>;
+
+fn main() {
+    let _ = Generic::<0>;
+}
diff --git a/src/test/ui/const-generics/issue-60818-struct-constructors.stderr b/src/test/ui/const-generics/issue-60818-struct-constructors.stderr
new file mode 100644
index 00000000000..4b8f50b9b02
--- /dev/null
+++ b/src/test/ui/const-generics/issue-60818-struct-constructors.stderr
@@ -0,0 +1,6 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/issue-60818-struct-constructors.rs:3:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+
diff --git a/src/test/ui/linkage-attr/auxiliary/def_colliding_external.rs b/src/test/ui/linkage-attr/auxiliary/def_colliding_external.rs
new file mode 100644
index 00000000000..bbbfc485791
--- /dev/null
+++ b/src/test/ui/linkage-attr/auxiliary/def_colliding_external.rs
@@ -0,0 +1,7 @@
+#![feature(linkage)]
+#![crate_type = "lib"]
+
+extern {
+    #[linkage="external"]
+    pub static collision: *const i32;
+}
diff --git a/src/test/ui/linkage-attr/auxiliary/def_illtyped_external.rs b/src/test/ui/linkage-attr/auxiliary/def_illtyped_external.rs
new file mode 100644
index 00000000000..2300930e513
--- /dev/null
+++ b/src/test/ui/linkage-attr/auxiliary/def_illtyped_external.rs
@@ -0,0 +1,5 @@
+#![feature(linkage)]
+#![crate_type = "lib"]
+
+#[linkage="external"]
+pub static EXTERN: u32 = 0;
diff --git a/src/test/ui/linkage-attr/linkage-detect-extern-generated-name-collision.rs b/src/test/ui/linkage-attr/linkage-detect-extern-generated-name-collision.rs
new file mode 100644
index 00000000000..85a9a336b0d
--- /dev/null
+++ b/src/test/ui/linkage-attr/linkage-detect-extern-generated-name-collision.rs
@@ -0,0 +1,21 @@
+// rust-lang/rust#61232: We used to ICE when trying to detect a
+// collision on the symbol generated for the external linkage item in
+// an extern crate.
+
+// aux-build:def_colliding_external.rs
+
+extern crate def_colliding_external as dep1;
+
+#[no_mangle]
+pub static _rust_extern_with_linkage_collision: i32 = 0;
+
+mod dep2 {
+    #[no_mangle]
+    pub static collision: usize = 0;
+}
+
+fn main() {
+    unsafe {
+       println!("{:p}", &dep1::collision);
+    }
+}
diff --git a/src/test/ui/linkage-attr/linkage-detect-extern-generated-name-collision.stderr b/src/test/ui/linkage-attr/linkage-detect-extern-generated-name-collision.stderr
new file mode 100644
index 00000000000..dcb954a4bc0
--- /dev/null
+++ b/src/test/ui/linkage-attr/linkage-detect-extern-generated-name-collision.stderr
@@ -0,0 +1,8 @@
+error: symbol `collision` is already defined
+  --> $DIR/auxiliary/def_colliding_external.rs:6:5
+   |
+LL |     pub static collision: *const i32;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/linkage-attr/linkage-detect-local-generated-name-collision.rs b/src/test/ui/linkage-attr/linkage-detect-local-generated-name-collision.rs
new file mode 100644
index 00000000000..dc15798e16a
--- /dev/null
+++ b/src/test/ui/linkage-attr/linkage-detect-local-generated-name-collision.rs
@@ -0,0 +1,23 @@
+#![feature(linkage)]
+
+mod dep1 {
+    extern {
+        #[linkage="external"]
+        #[no_mangle]
+        pub static collision: *const i32; //~ ERROR symbol `collision` is already defined
+    }
+}
+
+#[no_mangle]
+pub static _rust_extern_with_linkage_collision: i32 = 0;
+
+mod dep2 {
+    #[no_mangle]
+    pub static collision: usize = 0;
+}
+
+fn main() {
+    unsafe {
+       println!("{:p}", &dep1::collision);
+    }
+}
diff --git a/src/test/ui/linkage-attr/linkage-detect-local-generated-name-collision.stderr b/src/test/ui/linkage-attr/linkage-detect-local-generated-name-collision.stderr
new file mode 100644
index 00000000000..117c76f7f26
--- /dev/null
+++ b/src/test/ui/linkage-attr/linkage-detect-local-generated-name-collision.stderr
@@ -0,0 +1,8 @@
+error: symbol `collision` is already defined
+  --> $DIR/linkage-detect-local-generated-name-collision.rs:7:9
+   |
+LL |         pub static collision: *const i32;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/linkage-attr/linkage-requires-raw-ptr.rs b/src/test/ui/linkage-attr/linkage-requires-raw-ptr.rs
new file mode 100644
index 00000000000..014c715be0d
--- /dev/null
+++ b/src/test/ui/linkage-attr/linkage-requires-raw-ptr.rs
@@ -0,0 +1,10 @@
+// rust-lang/rust#59548: We used to ICE when trying to use a static
+// with a type that violated its own `#[linkage]`.
+
+// aux-build:def_illtyped_external.rs
+
+extern crate def_illtyped_external as dep;
+
+fn main() {
+    println!("{:p}", &dep::EXTERN);
+}
diff --git a/src/test/ui/linkage-attr/linkage-requires-raw-ptr.stderr b/src/test/ui/linkage-attr/linkage-requires-raw-ptr.stderr
new file mode 100644
index 00000000000..a80b495f97f
--- /dev/null
+++ b/src/test/ui/linkage-attr/linkage-requires-raw-ptr.stderr
@@ -0,0 +1,8 @@
+error: must have type `*const T` or `*mut T` due to `#[linkage]` attribute
+  --> $DIR/auxiliary/def_illtyped_external.rs:5:1
+   |
+LL | pub static EXTERN: u32 = 0;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/linkage2.rs b/src/test/ui/linkage-attr/linkage2.rs
index f9ea5319d54..c8af1a69979 100644
--- a/src/test/ui/linkage2.rs
+++ b/src/test/ui/linkage-attr/linkage2.rs
@@ -7,7 +7,7 @@
 
 extern {
     #[linkage = "extern_weak"] static foo: i32;
-    //~^ ERROR: must have type `*const T` or `*mut T`
+    //~^ ERROR: must have type `*const T` or `*mut T` due to `#[linkage]` attribute
 }
 
 fn main() {
diff --git a/src/test/ui/linkage2.stderr b/src/test/ui/linkage-attr/linkage2.stderr
index 8326c0baccc..2654ffd67b6 100644
--- a/src/test/ui/linkage2.stderr
+++ b/src/test/ui/linkage-attr/linkage2.stderr
@@ -1,4 +1,4 @@
-error: must have type `*const T` or `*mut T`
+error: must have type `*const T` or `*mut T` due to `#[linkage]` attribute
   --> $DIR/linkage2.rs:9:32
    |
 LL |     #[linkage = "extern_weak"] static foo: i32;
diff --git a/src/test/ui/linkage3.rs b/src/test/ui/linkage-attr/linkage3.rs
index 1462079acf7..1462079acf7 100644
--- a/src/test/ui/linkage3.rs
+++ b/src/test/ui/linkage-attr/linkage3.rs
diff --git a/src/test/ui/linkage3.stderr b/src/test/ui/linkage-attr/linkage3.stderr
index b74fdc91429..b74fdc91429 100644
--- a/src/test/ui/linkage3.stderr
+++ b/src/test/ui/linkage-attr/linkage3.stderr
diff --git a/src/test/ui/linkage4.rs b/src/test/ui/linkage-attr/linkage4.rs
index 3b935f9723d..3b935f9723d 100644
--- a/src/test/ui/linkage4.rs
+++ b/src/test/ui/linkage-attr/linkage4.rs
diff --git a/src/test/ui/linkage4.stderr b/src/test/ui/linkage-attr/linkage4.stderr
index f2aab164bd7..f2aab164bd7 100644
--- a/src/test/ui/linkage4.stderr
+++ b/src/test/ui/linkage-attr/linkage4.stderr