Rollup merge of #78499 - SkiFire13:fix-string-retain, r=m-ou-se

Prevent String::retain from creating non-utf8 strings when abusing panic

Fixes #78498

The idea is the same as `Vec::drain`, set the len to 0 so that nobody can observe the broken invariant if it escapes the function (in this case if `f` panics)
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index c899084..2ecdff1 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -35,6 +35,8 @@
 #![feature(never_type)]
 #![feature(nll)]
 #![feature(or_patterns)]
+#![feature(half_open_range_patterns)]
+#![feature(exclusive_range_pattern)]
 #![recursion_limit = "256"]
 
 #[macro_use]
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index b502bd7..bd02503 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -439,7 +439,7 @@
                 cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, |lint| {
                     lint.build(&format!("literal out of range for `{}`", t.name_str()))
                         .note(&format!(
-                            "the literal `{}` does not fit into the type `{}` and will be converted to `std::{}::INFINITY`",
+                            "the literal `{}` does not fit into the type `{}` and will be converted to `{}::INFINITY`",
                             cx.sess()
                                 .source_map()
                                 .span_to_snippet(lit.span)
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index 2409069..17f0d56 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -250,13 +250,13 @@
                     has_emitted
                 }
                 ty::Array(ty, len) => match len.try_eval_usize(cx.tcx, cx.param_env) {
+                    // If the array is empty we don't lint, to avoid false positives
+                    Some(0) | None => false,
                     // If the array is definitely non-empty, we can do `#[must_use]` checking.
-                    Some(n) if n != 0 => {
+                    Some(n) => {
                         let descr_pre = &format!("{}array{} of ", descr_pre, plural_suffix,);
                         check_must_use_ty(cx, ty, expr, span, descr_pre, descr_post, n as usize + 1)
                     }
-                    // Otherwise, we don't lint, to avoid false positives.
-                    _ => false,
                 },
                 ty::Closure(..) => {
                     cx.struct_span_lint(UNUSED_MUST_USE, span, |lint| {
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index 3beb328..869aaa5 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -766,7 +766,7 @@
     LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Scope) {
   return wrap(Builder->createTypedef(
     unwrap<DIType>(Type), StringRef(Name, NameLen), unwrap<DIFile>(File),
-    LineNo, unwrap<DIScope>(Scope)));
+    LineNo, unwrapDIPtr<DIScope>(Scope)));
 }
 
 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreatePointerType(
diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index fa885ce..5ccadb7 100644
--- a/compiler/rustc_middle/src/lib.rs
+++ b/compiler/rustc_middle/src/lib.rs
@@ -47,6 +47,8 @@
 #![feature(associated_type_bounds)]
 #![feature(rustc_attrs)]
 #![feature(int_error_matching)]
+#![feature(half_open_range_patterns)]
+#![feature(exclusive_range_pattern)]
 #![recursion_limit = "512"]
 
 #[macro_use]
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
index bf1f5b8..2f7707b 100644
--- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
+++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
@@ -201,13 +201,13 @@
             ),
 
             Array(ty, len) => match len.try_eval_usize(tcx, param_env) {
+                Some(0) | None => DefIdForest::empty(),
                 // If the array is definitely non-empty, it's uninhabited if
                 // the type of its elements is uninhabited.
-                Some(n) if n != 0 => ty.uninhabited_from(tcx, param_env),
-                _ => DefIdForest::empty(),
+                Some(1..) => ty.uninhabited_from(tcx, param_env),
             },
 
-            // References to uninitialised memory is valid for any type, including
+            // References to uninitialised memory are valid for any type, including
             // uninhabited types, in unsafe code, so we treat all references as
             // inhabited.
             // The precise semantics of inhabitedness with respect to references is currently
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 0fd48d0..431fa30 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -1834,10 +1834,10 @@
             }
             ty::Array(ty, len) => {
                 match len.try_eval_usize(tcx, ParamEnv::empty()) {
+                    Some(0) | None => false,
                     // If the array is definitely non-empty, it's uninhabited if
                     // the type of its elements is uninhabited.
-                    Some(n) if n != 0 => ty.conservative_is_privately_uninhabited(tcx),
-                    _ => false,
+                    Some(1..) => ty.conservative_is_privately_uninhabited(tcx),
                 }
             }
             ty::Ref(..) => {
diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs
index 12a268d..55ee4e5 100644
--- a/compiler/rustc_session/src/filesearch.rs
+++ b/compiler/rustc_session/src/filesearch.rs
@@ -153,14 +153,14 @@
     const SECONDARY_LIB_DIR: &str = "lib";
 
     match option_env!("CFG_LIBDIR_RELATIVE") {
-        Some(libdir) if libdir != "lib" => libdir.into(),
-        _ => {
+        None | Some("lib") => {
             if sysroot.join(PRIMARY_LIB_DIR).join(RUST_LIB_DIR).exists() {
                 PRIMARY_LIB_DIR.into()
             } else {
                 SECONDARY_LIB_DIR.into()
             }
         }
+        Some(libdir) => libdir.into(),
     }
 }
 
diff --git a/compiler/rustc_span/src/caching_source_map_view.rs b/compiler/rustc_span/src/caching_source_map_view.rs
index 68b0bd1..15dd00f 100644
--- a/compiler/rustc_span/src/caching_source_map_view.rs
+++ b/compiler/rustc_span/src/caching_source_map_view.rs
@@ -1,13 +1,25 @@
 use crate::source_map::SourceMap;
 use crate::{BytePos, SourceFile};
 use rustc_data_structures::sync::Lrc;
+use std::ops::Range;
 
 #[derive(Clone)]
 struct CacheEntry {
     time_stamp: usize,
     line_number: usize,
-    line_start: BytePos,
-    line_end: BytePos,
+    // The line's byte position range in the `SourceMap`. This range will fail to contain a valid
+    // position in certain edge cases. Spans often start/end one past something, and when that
+    // something is the last character of a file (this can happen when a file doesn't end in a
+    // newline, for example), we'd still like for the position to be considered within the last
+    // line. However, it isn't according to the exclusive upper bound of this range. We cannot
+    // change the upper bound to be inclusive, because for most lines, the upper bound is the same
+    // as the lower bound of the next line, so there would be an ambiguity.
+    //
+    // Since the containment aspect of this range is only used to see whether or not the cache
+    // entry contains a position, the only ramification of the above is that we will get cache
+    // misses for these rare positions. A line lookup for the position via `SourceMap::lookup_line`
+    // after a cache miss will produce the last line number, as desired.
+    line: Range<BytePos>,
     file: Lrc<SourceFile>,
     file_index: usize,
 }
@@ -26,8 +38,7 @@
         let entry = CacheEntry {
             time_stamp: 0,
             line_number: 0,
-            line_start: BytePos(0),
-            line_end: BytePos(0),
+            line: BytePos(0)..BytePos(0),
             file: first_file,
             file_index: 0,
         };
@@ -47,13 +58,13 @@
 
         // Check if the position is in one of the cached lines
         for cache_entry in self.line_cache.iter_mut() {
-            if pos >= cache_entry.line_start && pos < cache_entry.line_end {
+            if cache_entry.line.contains(&pos) {
                 cache_entry.time_stamp = self.time_stamp;
 
                 return Some((
                     cache_entry.file.clone(),
                     cache_entry.line_number,
-                    pos - cache_entry.line_start,
+                    pos - cache_entry.line.start,
                 ));
             }
         }
@@ -69,13 +80,13 @@
         let cache_entry = &mut self.line_cache[oldest];
 
         // If the entry doesn't point to the correct file, fix it up
-        if pos < cache_entry.file.start_pos || pos >= cache_entry.file.end_pos {
+        if !file_contains(&cache_entry.file, pos) {
             let file_valid;
             if self.source_map.files().len() > 0 {
                 let file_index = self.source_map.lookup_source_file_idx(pos);
                 let file = self.source_map.files()[file_index].clone();
 
-                if pos >= file.start_pos && pos < file.end_pos {
+                if file_contains(&file, pos) {
                     cache_entry.file = file;
                     cache_entry.file_index = file_index;
                     file_valid = true;
@@ -95,10 +106,19 @@
         let line_bounds = cache_entry.file.line_bounds(line_index);
 
         cache_entry.line_number = line_index + 1;
-        cache_entry.line_start = line_bounds.0;
-        cache_entry.line_end = line_bounds.1;
+        cache_entry.line = line_bounds;
         cache_entry.time_stamp = self.time_stamp;
 
-        Some((cache_entry.file.clone(), cache_entry.line_number, pos - cache_entry.line_start))
+        Some((cache_entry.file.clone(), cache_entry.line_number, pos - cache_entry.line.start))
     }
 }
+
+#[inline]
+fn file_contains(file: &SourceFile, pos: BytePos) -> bool {
+    // `SourceMap::lookup_source_file_idx` and `SourceFile::contains` both consider the position
+    // one past the end of a file to belong to it. Normally, that's what we want. But for the
+    // purposes of converting a byte position to a line and column number, we can't come up with a
+    // line and column number if the file is empty, because an empty file doesn't contain any
+    // lines. So for our purposes, we don't consider empty files to contain any byte position.
+    file.contains(pos) && !file.is_empty()
+}
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index 79363c3..0e30272 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -52,7 +52,7 @@
 use std::cmp::{self, Ordering};
 use std::fmt;
 use std::hash::Hash;
-use std::ops::{Add, Sub};
+use std::ops::{Add, Range, Sub};
 use std::path::{Path, PathBuf};
 use std::str::FromStr;
 
@@ -1426,24 +1426,33 @@
         if line_index >= 0 { Some(line_index as usize) } else { None }
     }
 
-    pub fn line_bounds(&self, line_index: usize) -> (BytePos, BytePos) {
-        if self.start_pos == self.end_pos {
-            return (self.start_pos, self.end_pos);
+    pub fn line_bounds(&self, line_index: usize) -> Range<BytePos> {
+        if self.is_empty() {
+            return self.start_pos..self.end_pos;
         }
 
         assert!(line_index < self.lines.len());
         if line_index == (self.lines.len() - 1) {
-            (self.lines[line_index], self.end_pos)
+            self.lines[line_index]..self.end_pos
         } else {
-            (self.lines[line_index], self.lines[line_index + 1])
+            self.lines[line_index]..self.lines[line_index + 1]
         }
     }
 
+    /// Returns whether or not the file contains the given `SourceMap` byte
+    /// position. The position one past the end of the file is considered to be
+    /// contained by the file. This implies that files for which `is_empty`
+    /// returns true still contain one byte position according to this function.
     #[inline]
     pub fn contains(&self, byte_pos: BytePos) -> bool {
         byte_pos >= self.start_pos && byte_pos <= self.end_pos
     }
 
+    #[inline]
+    pub fn is_empty(&self) -> bool {
+        self.start_pos == self.end_pos
+    }
+
     /// Calculates the original byte position relative to the start of the file
     /// based on the given byte position.
     pub fn original_relative_byte_pos(&self, pos: BytePos) -> BytePos {
diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs
index d2ac24b..c52fd0b 100644
--- a/compiler/rustc_trait_selection/src/traits/object_safety.rs
+++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs
@@ -461,10 +461,17 @@
 
             let param_env = tcx.param_env(method.def_id);
 
-            let abi_of_ty = |ty: Ty<'tcx>| -> &Abi {
+            let abi_of_ty = |ty: Ty<'tcx>| -> Option<&Abi> {
                 match tcx.layout_of(param_env.and(ty)) {
-                    Ok(layout) => &layout.abi,
-                    Err(err) => bug!("error: {}\n while computing layout for type {:?}", err, ty),
+                    Ok(layout) => Some(&layout.abi),
+                    Err(err) => {
+                        // #78372
+                        tcx.sess.delay_span_bug(
+                            tcx.def_span(method.def_id),
+                            &format!("error: {}\n while computing layout for type {:?}", err, ty),
+                        );
+                        None
+                    }
                 }
             };
 
@@ -473,7 +480,7 @@
                 receiver_for_self_ty(tcx, receiver_ty, tcx.mk_unit(), method.def_id);
 
             match abi_of_ty(unit_receiver_ty) {
-                &Abi::Scalar(..) => (),
+                Some(Abi::Scalar(..)) => (),
                 abi => {
                     tcx.sess.delay_span_bug(
                         tcx.def_span(method.def_id),
@@ -493,13 +500,12 @@
                 receiver_for_self_ty(tcx, receiver_ty, trait_object_ty, method.def_id);
 
             match abi_of_ty(trait_object_receiver) {
-                &Abi::ScalarPair(..) => (),
+                Some(Abi::ScalarPair(..)) => (),
                 abi => {
                     tcx.sess.delay_span_bug(
                         tcx.def_span(method.def_id),
                         &format!(
-                            "receiver when `Self = {}` should have a ScalarPair ABI; \
-                                 found {:?}",
+                            "receiver when `Self = {}` should have a ScalarPair ABI; found {:?}",
                             trait_object_ty, abi
                         ),
                     );
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index 997dd97..1512235 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -724,15 +724,10 @@
         // Box is recognized as a "unique pointer" by Stacked Borrows, but internally it is a
         // raw pointer for the type system. Turning it directly into a raw pointer would not be
         // recognized as "releasing" the unique pointer to permit aliased raw accesses,
-        // so all raw pointer methods have to leak the box. Turning *that* to a raw pointer
+        // so all raw pointer methods have to go through `Box::leak`. Turning *that* to a raw pointer
         // behaves correctly.
-        let b = mem::ManuallyDrop::new(b);
-
-        // The box is unitiliazed later when moving out the allocator. The pointer is stored
-        // beforehand.
-        let ptr = b.0;
         let alloc = unsafe { ptr::read(&b.1) };
-        (ptr, alloc)
+        (Unique::from(Box::leak(b)), alloc)
     }
 
     /// Returns a reference to the underlying allocator.
diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs
index 72e5e0a..6dcd0c6 100644
--- a/library/alloc/src/rc.rs
+++ b/library/alloc/src/rc.rs
@@ -11,7 +11,7 @@
 //! is no exception: you cannot generally obtain a mutable reference to
 //! something inside an [`Rc`]. If you need mutability, put a [`Cell`]
 //! or [`RefCell`] inside the [`Rc`]; see [an example of mutability
-//! inside an Rc][mutability].
+//! inside an `Rc`][mutability].
 //!
 //! [`Rc`] uses non-atomic reference counting. This means that overhead is very
 //! low, but an [`Rc`] cannot be sent between threads, and consequently [`Rc`]
@@ -35,15 +35,29 @@
 //! `Rc<T>` automatically dereferences to `T` (via the [`Deref`] trait),
 //! so you can call `T`'s methods on a value of type [`Rc<T>`][`Rc`]. To avoid name
 //! clashes with `T`'s methods, the methods of [`Rc<T>`][`Rc`] itself are associated
-//! functions, called using function-like syntax:
+//! functions, called using [fully qualified syntax]:
 //!
 //! ```
 //! use std::rc::Rc;
-//! let my_rc = Rc::new(());
 //!
+//! let my_rc = Rc::new(());
 //! Rc::downgrade(&my_rc);
 //! ```
 //!
+//! `Rc<T>`'s implementations of traits like `Clone` may also be called using
+//! fully qualified syntax. Some people prefer to use fully qualified syntax,
+//! while others prefer using method-call syntax.
+//!
+//! ```
+//! use std::rc::Rc;
+//!
+//! let rc = Rc::new(());
+//! // Method-call syntax
+//! let rc2 = rc.clone();
+//! // Fully qualified syntax
+//! let rc3 = Rc::clone(&rc);
+//! ```
+//!
 //! [`Weak<T>`][`Weak`] does not auto-dereference to `T`, because the inner value may have
 //! already been dropped.
 //!
@@ -54,6 +68,7 @@
 //!
 //! ```
 //! use std::rc::Rc;
+//!
 //! let foo = Rc::new(vec![1.0, 2.0, 3.0]);
 //! // The two syntaxes below are equivalent.
 //! let a = foo.clone();
@@ -218,7 +233,7 @@
 //! [`Cell`]: core::cell::Cell
 //! [`RefCell`]: core::cell::RefCell
 //! [send]: core::marker::Send
-//! [arc]: ../../std/sync/struct.Arc.html
+//! [arc]: crate::sync::Arc
 //! [`Deref`]: core::ops::Deref
 //! [downgrade]: Rc::downgrade
 //! [upgrade]: Weak::upgrade
@@ -272,10 +287,9 @@
 ///
 /// The inherent methods of `Rc` are all associated functions, which means
 /// that you have to call them as e.g., [`Rc::get_mut(&mut value)`][get_mut] instead of
-/// `value.get_mut()`. This avoids conflicts with methods of the inner
-/// type `T`.
+/// `value.get_mut()`. This avoids conflicts with methods of the inner type `T`.
 ///
-/// [get_mut]: #method.get_mut
+/// [get_mut]: Rc::get_mut
 #[cfg_attr(not(test), rustc_diagnostic_item = "Rc")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Rc<T: ?Sized> {
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index 73ff795..5ab930a 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -129,15 +129,29 @@
 /// `Arc<T>` automatically dereferences to `T` (via the [`Deref`][deref] trait),
 /// so you can call `T`'s methods on a value of type `Arc<T>`. To avoid name
 /// clashes with `T`'s methods, the methods of `Arc<T>` itself are associated
-/// functions, called using function-like syntax:
+/// functions, called using [fully qualified syntax]:
 ///
 /// ```
 /// use std::sync::Arc;
-/// let my_arc = Arc::new(());
 ///
+/// let my_arc = Arc::new(());
 /// Arc::downgrade(&my_arc);
 /// ```
 ///
+/// `Arc<T>`'s implementations of traits like `Clone` may also be called using
+/// fully qualified syntax. Some people prefer to use fully qualified syntax,
+/// while others prefer using method-call syntax.
+///
+/// ```
+/// use std::sync::Arc;
+///
+/// let arc = Arc::new(());
+/// // Method-call syntax
+/// let arc2 = arc.clone();
+/// // Fully qualified syntax
+/// let arc3 = Arc::clone(&arc);
+/// ```
+///
 /// [`Weak<T>`][Weak] does not auto-dereference to `T`, because the inner value may have
 /// already been dropped.
 ///
@@ -154,6 +168,7 @@
 /// [`RefCell<T>`]: core::cell::RefCell
 /// [`std::sync`]: ../../std/sync/index.html
 /// [`Arc::clone(&from)`]: Arc::clone
+/// [fully qualified syntax]: https://doc.rust-lang.org/book/ch19-03-advanced-traits.html#fully-qualified-syntax-for-disambiguation-calling-methods-with-the-same-name
 ///
 /// # Examples
 ///
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index f514a90..79ae1d5 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -1768,8 +1768,10 @@
 
     /// Returns a subslice with the prefix removed.
     ///
-    /// This method returns [`None`] if slice does not start with `prefix`.
-    /// Also it returns the original slice if `prefix` is an empty slice.
+    /// If the slice starts with `prefix`, returns the subslice after the prefix, wrapped in `Some`.
+    /// If `prefix` is empty, simply returns the original slice.
+    ///
+    /// If the slice does not start with `prefix`, returns `None`.
     ///
     /// # Examples
     ///
@@ -1799,8 +1801,10 @@
 
     /// Returns a subslice with the suffix removed.
     ///
-    /// This method returns [`None`] if slice does not end with `suffix`.
-    /// Also it returns the original slice if `suffix` is an empty slice
+    /// If the slice ends with `suffix`, returns the subslice before the suffix, wrapped in `Some`.
+    /// If `suffix` is empty, simply returns the original slice.
+    ///
+    /// If the slice does not end with `suffix`, returns `None`.
     ///
     /// # Examples
     ///
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index ee9c09f..b36d9f5 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -1965,11 +1965,10 @@
 
     /// Returns a string slice with the prefix removed.
     ///
-    /// If the string starts with the pattern `prefix`, `Some` is returned with the substring where
-    /// the prefix is removed. Unlike `trim_start_matches`, this method removes the prefix exactly
-    /// once.
+    /// If the string starts with the pattern `prefix`, returns substring after the prefix, wrapped
+    /// in `Some`.  Unlike `trim_start_matches`, this method removes the prefix exactly once.
     ///
-    /// If the string does not start with `prefix`, `None` is returned.
+    /// If the string does not start with `prefix`, returns `None`.
     ///
     /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a
     /// function or closure that determines if a character matches.
@@ -1993,11 +1992,10 @@
 
     /// Returns a string slice with the suffix removed.
     ///
-    /// If the string ends with the pattern `suffix`, `Some` is returned with the substring where
-    /// the suffix is removed. Unlike `trim_end_matches`, this method removes the suffix exactly
-    /// once.
+    /// If the string ends with the pattern `suffix`, returns the substring before the suffix,
+    /// wrapped in `Some`.  Unlike `trim_end_matches`, this method removes the suffix exactly once.
     ///
-    /// If the string does not end with `suffix`, `None` is returned.
+    /// If the string does not end with `suffix`, returns `None`.
     ///
     /// The [pattern] can be a `&str`, [`char`], a slice of [`char`]s, or a
     /// function or closure that determines if a character matches.
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile
index fe956b9..7651947 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile
@@ -1,5 +1,6 @@
-FROM ubuntu:19.10
+FROM ubuntu:20.04
 
+ARG DEBIAN_FRONTEND=noninteractive
 RUN apt-get update && apt-get install -y --no-install-recommends \
   g++ \
   make \
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile
index 527b539..88c182a 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu/Dockerfile
@@ -1,5 +1,6 @@
-FROM ubuntu:19.10
+FROM ubuntu:20.04
 
+ARG DEBIAN_FRONTEND=noninteractive
 RUN apt-get update && apt-get install -y --no-install-recommends \
   g++ \
   make \
diff --git a/src/test/ui/issues/issue-78372.rs b/src/test/ui/issues/issue-78372.rs
new file mode 100644
index 0000000..77a8c92
--- /dev/null
+++ b/src/test/ui/issues/issue-78372.rs
@@ -0,0 +1,14 @@
+use std::ops::DispatchFromDyn; //~ ERROR use of unstable library feature 'dispatch_from_dyn'
+struct Smaht<T, MISC>(PhantomData); //~ ERROR cannot find type `PhantomData` in this scope
+impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {} //~ ERROR cannot find type `U` in this scope
+//~^ ERROR cannot find type `MISC` in this scope
+//~| ERROR use of unstable library feature 'dispatch_from_dyn'
+//~| ERROR the trait `DispatchFromDyn` may only be implemented for a coercion between structures
+//~| ERROR type parameter `T` must be covered by another type when it appears before the first
+trait Foo: X<u32> {}
+trait X<T> {
+    fn foo(self: Smaht<Self, T>);
+}
+trait Marker {}
+impl Marker for dyn Foo {}
+fn main() {}
diff --git a/src/test/ui/issues/issue-78372.stderr b/src/test/ui/issues/issue-78372.stderr
new file mode 100644
index 0000000..9267e83
--- /dev/null
+++ b/src/test/ui/issues/issue-78372.stderr
@@ -0,0 +1,62 @@
+error[E0412]: cannot find type `PhantomData` in this scope
+  --> $DIR/issue-78372.rs:2:23
+   |
+LL | struct Smaht<T, MISC>(PhantomData);
+   |                       ^^^^^^^^^^^ not found in this scope
+   |
+help: consider importing this struct
+   |
+LL | use std::marker::PhantomData;
+   |
+
+error[E0412]: cannot find type `U` in this scope
+  --> $DIR/issue-78372.rs:3:31
+   |
+LL | impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {}
+   |      -                        ^ help: a type parameter with a similar name exists: `T`
+   |      |
+   |      similarly named type parameter `T` defined here
+
+error[E0412]: cannot find type `MISC` in this scope
+  --> $DIR/issue-78372.rs:3:34
+   |
+LL | impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {}
+   |       -                          ^^^^ not found in this scope
+   |       |
+   |       help: you might be missing a type parameter: `, MISC`
+
+error[E0658]: use of unstable library feature 'dispatch_from_dyn'
+  --> $DIR/issue-78372.rs:1:5
+   |
+LL | use std::ops::DispatchFromDyn;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add `#![feature(dispatch_from_dyn)]` to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'dispatch_from_dyn'
+  --> $DIR/issue-78372.rs:3:9
+   |
+LL | impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {}
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add `#![feature(dispatch_from_dyn)]` to the crate attributes to enable
+
+error[E0378]: the trait `DispatchFromDyn` may only be implemented for a coercion between structures
+  --> $DIR/issue-78372.rs:3:1
+   |
+LL | impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Smaht<[type error], [type error]>`)
+  --> $DIR/issue-78372.rs:3:6
+   |
+LL | impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {}
+   |      ^ type parameter `T` must be covered by another type when it appears before the first local type (`Smaht<[type error], [type error]>`)
+   |
+   = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type
+   = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last
+
+error: aborting due to 7 previous errors
+
+Some errors have detailed explanations: E0210, E0378, E0412, E0658.
+For more information about an error, try `rustc --explain E0210`.
diff --git a/src/test/ui/lint/lint-type-overflow2.stderr b/src/test/ui/lint/lint-type-overflow2.stderr
index 61e33b7..0f16229 100644
--- a/src/test/ui/lint/lint-type-overflow2.stderr
+++ b/src/test/ui/lint/lint-type-overflow2.stderr
@@ -17,7 +17,7 @@
 LL |     let x = -3.40282357e+38_f32;
    |              ^^^^^^^^^^^^^^^^^^
    |
-   = note: the literal `3.40282357e+38_f32` does not fit into the type `f32` and will be converted to `std::f32::INFINITY`
+   = note: the literal `3.40282357e+38_f32` does not fit into the type `f32` and will be converted to `f32::INFINITY`
 
 error: literal out of range for `f32`
   --> $DIR/lint-type-overflow2.rs:10:14
@@ -25,7 +25,7 @@
 LL |     let x =  3.40282357e+38_f32;
    |              ^^^^^^^^^^^^^^^^^^
    |
-   = note: the literal `3.40282357e+38_f32` does not fit into the type `f32` and will be converted to `std::f32::INFINITY`
+   = note: the literal `3.40282357e+38_f32` does not fit into the type `f32` and will be converted to `f32::INFINITY`
 
 error: literal out of range for `f64`
   --> $DIR/lint-type-overflow2.rs:11:14
@@ -33,7 +33,7 @@
 LL |     let x = -1.7976931348623159e+308_f64;
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: the literal `1.7976931348623159e+308_f64` does not fit into the type `f64` and will be converted to `std::f64::INFINITY`
+   = note: the literal `1.7976931348623159e+308_f64` does not fit into the type `f64` and will be converted to `f64::INFINITY`
 
 error: literal out of range for `f64`
   --> $DIR/lint-type-overflow2.rs:12:14
@@ -41,7 +41,7 @@
 LL |     let x =  1.7976931348623159e+308_f64;
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: the literal `1.7976931348623159e+308_f64` does not fit into the type `f64` and will be converted to `std::f64::INFINITY`
+   = note: the literal `1.7976931348623159e+308_f64` does not fit into the type `f64` and will be converted to `f64::INFINITY`
 
 error: aborting due to 5 previous errors
 
diff --git a/src/tools/cargo b/src/tools/cargo
index dd83ae5..becb4c2 160000
--- a/src/tools/cargo
+++ b/src/tools/cargo
@@ -1 +1 @@
-Subproject commit dd83ae55c871d94f060524656abab62ec40b4c40
+Subproject commit becb4c282b8f37469efb8f5beda45a5501f9d367