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