summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-04-03 20:56:05 +0000
committerbors <bors@rust-lang.org>2020-04-03 20:56:05 +0000
commit74bd074eefcf4915c73d1ab91bc90859664729e6 (patch)
tree4eb869837e228d81b08b2fb4db3ad1af00942039
parentf6fe99c798cb65280a9a56f442b371adcb7b8aa2 (diff)
parent4c41ea36cda77748b532cf6d989a8d5d2fcc872e (diff)
downloadrust-74bd074eefcf4915c73d1ab91bc90859664729e6.tar.gz
Auto merge of #70747 - Centril:rollup-2vx9bve, r=Centril
Rollup of 9 pull requests Successful merges: - #69860 (Use associated numeric consts in documentation) - #70576 (Update the description of the ticket to point at RFC 1721) - #70597 (Fix double-free and undefined behaviour in libstd::syn::unix::Thread::new) - #70640 (Hide `task_context` when lowering body) - #70641 (Remove duplicated code in trait selection) - #70707 (Remove unused graphviz emitter) - #70720 (Place TLS initializers with relocations in .tdata) - #70735 (Clean up E0502 explanation) - #70741 (Add test for #59023) Failed merges: r? @ghost
-rw-r--r--src/liballoc/slice.rs2
-rw-r--r--src/liballoc/str.rs2
-rw-r--r--src/libcore/cmp.rs2
-rw-r--r--src/libcore/fmt/mod.rs2
-rw-r--r--src/libcore/hint.rs2
-rw-r--r--src/libcore/intrinsics.rs12
-rw-r--r--src/libcore/iter/traits/iterator.rs8
-rw-r--r--src/libcore/num/f32.rs2
-rw-r--r--src/libcore/num/f64.rs2
-rw-r--r--src/libcore/num/mod.rs2
-rw-r--r--src/libcore/ops/range.rs10
-rw-r--r--src/libcore/ptr/const_ptr.rs4
-rw-r--r--src/libcore/ptr/mut_ptr.rs4
-rw-r--r--src/libcore/slice/mod.rs2
-rw-r--r--src/libcore/time.rs4
-rw-r--r--src/librustc_ast_lowering/item.rs2
-rw-r--r--src/librustc_codegen_llvm/consts.rs29
-rw-r--r--src/librustc_error_codes/error_codes/E0502.md3
-rw-r--r--src/librustc_infer/traits/mod.rs2
-rw-r--r--src/librustc_infer/traits/util.rs80
-rw-r--r--src/librustc_metadata/native_libs.rs9
-rw-r--r--src/librustc_mir/dataflow/graphviz.rs277
-rw-r--r--src/librustc_target/abi/mod.rs2
-rw-r--r--src/librustc_trait_selection/traits/util.rs297
-rw-r--r--src/libstd/f32.rs4
-rw-r--r--src/libstd/f64.rs4
-rw-r--r--src/libstd/sys/cloudabi/stack_overflow.rs8
-rw-r--r--src/libstd/sys/cloudabi/thread.rs15
-rw-r--r--src/libstd/sys/hermit/stack_overflow.rs8
-rw-r--r--src/libstd/sys/hermit/thread.rs19
-rw-r--r--src/libstd/sys/sgx/stack_overflow.rs8
-rw-r--r--src/libstd/sys/unix/thread.rs21
-rw-r--r--src/libstd/sys/vxworks/thread.rs21
-rw-r--r--src/libstd/sys/wasm/stack_overflow.rs8
-rw-r--r--src/libstd/sys/windows/thread.rs17
-rw-r--r--src/libstd/sys_common/thread.rs11
-rw-r--r--src/test/ui/async-await/issue-70594.rs12
-rw-r--r--src/test/ui/async-await/issue-70594.stderr44
-rw-r--r--src/test/ui/feature-gates/feature-gate-link_cfg.stderr2
-rw-r--r--src/test/ui/issues/issue-70673.rs12
-rw-r--r--src/test/ui/traits/impl_trait_as_trait_return_position.rs17
41 files changed, 283 insertions, 709 deletions
diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs
index d8fc1faca3a..2ce5bc8ed2f 100644
--- a/src/liballoc/slice.rs
+++ b/src/liballoc/slice.rs
@@ -432,7 +432,7 @@ impl<T> [T] {
///
/// ```should_panic
/// // this will panic at runtime
- /// b"0123456789abcdef".repeat(usize::max_value());
+ /// b"0123456789abcdef".repeat(usize::MAX);
/// ```
#[stable(feature = "repeat_generic_slice", since = "1.40.0")]
pub fn repeat(&self, n: usize) -> Vec<T>
diff --git a/src/liballoc/str.rs b/src/liballoc/str.rs
index 843a2f1f8e9..70860c09a2c 100644
--- a/src/liballoc/str.rs
+++ b/src/liballoc/str.rs
@@ -499,7 +499,7 @@ impl str {
///
/// ```should_panic
/// // this will panic at runtime
- /// "0123456789abcdef".repeat(usize::max_value());
+ /// "0123456789abcdef".repeat(usize::MAX);
/// ```
#[stable(feature = "repeat_str", since = "1.16.0")]
pub fn repeat(&self, n: usize) -> String {
diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs
index 604be7d5f68..8c542136a7f 100644
--- a/src/libcore/cmp.rs
+++ b/src/libcore/cmp.rs
@@ -817,7 +817,7 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
/// When comparison is impossible:
///
/// ```
- /// let result = std::f64::NAN.partial_cmp(&1.0);
+ /// let result = f64::NAN.partial_cmp(&1.0);
/// assert_eq!(result, None);
/// ```
#[must_use]
diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs
index fe728d42c76..95411b525d0 100644
--- a/src/libcore/fmt/mod.rs
+++ b/src/libcore/fmt/mod.rs
@@ -852,7 +852,7 @@ pub trait LowerHex {
/// }
/// }
///
-/// let l = Length(i32::max_value());
+/// let l = Length(i32::MAX);
///
/// assert_eq!(format!("l as hex is: {:X}", l), "l as hex is: 7FFFFFFF");
///
diff --git a/src/libcore/hint.rs b/src/libcore/hint.rs
index 698c97999c4..d406b3ce6ef 100644
--- a/src/libcore/hint.rs
+++ b/src/libcore/hint.rs
@@ -43,7 +43,7 @@ use crate::intrinsics;
///
/// assert_eq!(div_1(7, 0), 7);
/// assert_eq!(div_1(9, 1), 4);
-/// assert_eq!(div_1(11, std::u32::MAX), 0);
+/// assert_eq!(div_1(11, u32::MAX), 0);
/// ```
#[inline]
#[stable(feature = "unreachable", since = "1.27.0")]
diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs
index 7e9140faa64..4a11fb39389 100644
--- a/src/libcore/intrinsics.rs
+++ b/src/libcore/intrinsics.rs
@@ -1739,11 +1739,11 @@ extern "rust-intrinsic" {
pub fn mul_with_overflow<T: Copy>(x: T, y: T) -> (T, bool);
/// Performs an exact division, resulting in undefined behavior where
- /// `x % y != 0` or `y == 0` or `x == T::min_value() && y == -1`
+ /// `x % y != 0` or `y == 0` or `x == T::MIN && y == -1`
pub fn exact_div<T: Copy>(x: T, y: T) -> T;
/// Performs an unchecked division, resulting in undefined behavior
- /// where y = 0 or x = `T::min_value()` and y = -1
+ /// where y = 0 or x = `T::MIN` and y = -1
///
/// The stabilized versions of this intrinsic are available on the integer
/// primitives via the `checked_div` method. For example,
@@ -1751,7 +1751,7 @@ extern "rust-intrinsic" {
#[rustc_const_unstable(feature = "const_int_unchecked_arith", issue = "none")]
pub fn unchecked_div<T: Copy>(x: T, y: T) -> T;
/// Returns the remainder of an unchecked division, resulting in
- /// undefined behavior where y = 0 or x = `T::min_value()` and y = -1
+ /// undefined behavior where y = 0 or x = `T::MIN` and y = -1
///
/// The stabilized versions of this intrinsic are available on the integer
/// primitives via the `checked_rem` method. For example,
@@ -1777,17 +1777,17 @@ extern "rust-intrinsic" {
pub fn unchecked_shr<T: Copy>(x: T, y: T) -> T;
/// Returns the result of an unchecked addition, resulting in
- /// undefined behavior when `x + y > T::max_value()` or `x + y < T::min_value()`.
+ /// undefined behavior when `x + y > T::MAX` or `x + y < T::MIN`.
#[rustc_const_unstable(feature = "const_int_unchecked_arith", issue = "none")]
pub fn unchecked_add<T: Copy>(x: T, y: T) -> T;
/// Returns the result of an unchecked subtraction, resulting in
- /// undefined behavior when `x - y > T::max_value()` or `x - y < T::min_value()`.
+ /// undefined behavior when `x - y > T::MAX` or `x - y < T::MIN`.
#[rustc_const_unstable(feature = "const_int_unchecked_arith", issue = "none")]
pub fn unchecked_sub<T: Copy>(x: T, y: T) -> T;
/// Returns the result of an unchecked multiplication, resulting in
- /// undefined behavior when `x * y > T::max_value()` or `x * y < T::min_value()`.
+ /// undefined behavior when `x * y > T::MAX` or `x * y < T::MIN`.
#[rustc_const_unstable(feature = "const_int_unchecked_arith", issue = "none")]
pub fn unchecked_mul<T: Copy>(x: T, y: T) -> T;
diff --git a/src/libcore/iter/traits/iterator.rs b/src/libcore/iter/traits/iterator.rs
index daa880e7cd5..c8829817e19 100644
--- a/src/libcore/iter/traits/iterator.rs
+++ b/src/libcore/iter/traits/iterator.rs
@@ -198,7 +198,7 @@ pub trait Iterator {
/// // and the maximum possible lower bound
/// let iter = 0..;
///
- /// assert_eq!((usize::max_value(), None), iter.size_hint());
+ /// assert_eq!((usize::MAX, None), iter.size_hint());
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
@@ -2920,7 +2920,7 @@ pub trait Iterator {
/// assert_eq!([1.].iter().partial_cmp([1., 2.].iter()), Some(Ordering::Less));
/// assert_eq!([1., 2.].iter().partial_cmp([1.].iter()), Some(Ordering::Greater));
///
- /// assert_eq!([std::f64::NAN].iter().partial_cmp([1.].iter()), None);
+ /// assert_eq!([f64::NAN].iter().partial_cmp([1.].iter()), None);
/// ```
#[stable(feature = "iter_order", since = "1.5.0")]
fn partial_cmp<I>(self, other: I) -> Option<Ordering>
@@ -3170,7 +3170,7 @@ pub trait Iterator {
/// assert!(![1, 3, 2, 4].iter().is_sorted());
/// assert!([0].iter().is_sorted());
/// assert!(std::iter::empty::<i32>().is_sorted());
- /// assert!(![0.0, 1.0, std::f32::NAN].iter().is_sorted());
+ /// assert!(![0.0, 1.0, f32::NAN].iter().is_sorted());
/// ```
#[inline]
#[unstable(feature = "is_sorted", reason = "new API", issue = "53485")]
@@ -3197,7 +3197,7 @@ pub trait Iterator {
/// assert!(![1, 3, 2, 4].iter().is_sorted_by(|a, b| a.partial_cmp(b)));
/// assert!([0].iter().is_sorted_by(|a, b| a.partial_cmp(b)));
/// assert!(std::iter::empty::<i32>().is_sorted_by(|a, b| a.partial_cmp(b)));
- /// assert!(![0.0, 1.0, std::f32::NAN].iter().is_sorted_by(|a, b| a.partial_cmp(b)));
+ /// assert!(![0.0, 1.0, f32::NAN].iter().is_sorted_by(|a, b| a.partial_cmp(b)));
/// ```
///
/// [`is_sorted`]: trait.Iterator.html#method.is_sorted
diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs
index 09f1eab2d4b..4ab82add32b 100644
--- a/src/libcore/num/f32.rs
+++ b/src/libcore/num/f32.rs
@@ -470,7 +470,7 @@ impl f32 {
///
/// let value = -128.9_f32;
/// let rounded = unsafe { value.to_int_unchecked::<i8>() };
- /// assert_eq!(rounded, std::i8::MIN);
+ /// assert_eq!(rounded, i8::MIN);
/// ```
///
/// # Safety
diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs
index 65ef7ba9ac7..20818a9b750 100644
--- a/src/libcore/num/f64.rs
+++ b/src/libcore/num/f64.rs
@@ -484,7 +484,7 @@ impl f64 {
///
/// let value = -128.9_f32;
/// let rounded = unsafe { value.to_int_unchecked::<i8>() };
- /// assert_eq!(rounded, std::i8::MIN);
+ /// assert_eq!(rounded, i8::MIN);
/// ```
///
/// # Safety
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index c85064759ea..7ba4004d860 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -174,7 +174,7 @@ NonZeroI8 NonZeroI16 NonZeroI32 NonZeroI64 NonZeroI128 NonZeroIsize }
/// let zero = Wrapping(0u32);
/// let one = Wrapping(1u32);
///
-/// assert_eq!(std::u32::MAX, (zero - one).0);
+/// assert_eq!(u32::MAX, (zero - one).0);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default, Hash)]
diff --git a/src/libcore/ops/range.rs b/src/libcore/ops/range.rs
index adee8cea442..946a765e18f 100644
--- a/src/libcore/ops/range.rs
+++ b/src/libcore/ops/range.rs
@@ -139,10 +139,9 @@ impl<Idx: PartialOrd<Idx>> Range<Idx> {
/// ```
/// #![feature(range_is_empty)]
///
- /// use std::f32::NAN;
/// assert!(!(3.0..5.0).is_empty());
- /// assert!( (3.0..NAN).is_empty());
- /// assert!( (NAN..5.0).is_empty());
+ /// assert!( (3.0..f32::NAN).is_empty());
+ /// assert!( (f32::NAN..5.0).is_empty());
/// ```
#[unstable(feature = "range_is_empty", reason = "recently added", issue = "48111")]
pub fn is_empty(&self) -> bool {
@@ -496,10 +495,9 @@ impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
/// ```
/// #![feature(range_is_empty)]
///
- /// use std::f32::NAN;
/// assert!(!(3.0..=5.0).is_empty());
- /// assert!( (3.0..=NAN).is_empty());
- /// assert!( (NAN..=5.0).is_empty());
+ /// assert!( (3.0..=f32::NAN).is_empty());
+ /// assert!( (f32::NAN..=5.0).is_empty());
/// ```
///
/// This method returns `true` after iteration has finished:
diff --git a/src/libcore/ptr/const_ptr.rs b/src/libcore/ptr/const_ptr.rs
index a540016854d..52e224d2a02 100644
--- a/src/libcore/ptr/const_ptr.rs
+++ b/src/libcore/ptr/const_ptr.rs
@@ -659,8 +659,8 @@ impl<T: ?Sized> *const T {
/// `align`.
///
/// If it is not possible to align the pointer, the implementation returns
- /// `usize::max_value()`. It is permissible for the implementation to *always*
- /// return `usize::max_value()`. Only your algorithm's performance can depend
+ /// `usize::MAX`. It is permissible for the implementation to *always*
+ /// return `usize::MAX`. Only your algorithm's performance can depend
/// on getting a usable offset here, not its correctness.
///
/// The offset is expressed in number of `T` elements, and not bytes. The value returned can be
diff --git a/src/libcore/ptr/mut_ptr.rs b/src/libcore/ptr/mut_ptr.rs
index 01d830ca186..9f85d781d69 100644
--- a/src/libcore/ptr/mut_ptr.rs
+++ b/src/libcore/ptr/mut_ptr.rs
@@ -847,8 +847,8 @@ impl<T: ?Sized> *mut T {
/// `align`.
///
/// If it is not possible to align the pointer, the implementation returns
- /// `usize::max_value()`. It is permissible for the implementation to *always*
- /// return `usize::max_value()`. Only your algorithm's performance can depend
+ /// `usize::MAX`. It is permissible for the implementation to *always*
+ /// return `usize::MAX`. Only your algorithm's performance can depend
/// on getting a usable offset here, not its correctness.
///
/// The offset is expressed in number of `T` elements, and not bytes. The value returned can be
diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs
index 2140a7be9ef..9be52e2dfb0 100644
--- a/src/libcore/slice/mod.rs
+++ b/src/libcore/slice/mod.rs
@@ -2588,7 +2588,7 @@ impl<T> [T] {
/// assert!(![1, 3, 2, 4].is_sorted());
/// assert!([0].is_sorted());
/// assert!(empty.is_sorted());
- /// assert!(![0.0, 1.0, std::f32::NAN].is_sorted());
+ /// assert!(![0.0, 1.0, f32::NAN].is_sorted());
/// ```
#[inline]
#[unstable(feature = "is_sorted", reason = "new API", issue = "53485")]
diff --git a/src/libcore/time.rs b/src/libcore/time.rs
index 2ece2150e6b..924a64847a7 100644
--- a/src/libcore/time.rs
+++ b/src/libcore/time.rs
@@ -389,7 +389,7 @@ impl Duration {
/// use std::time::Duration;
///
/// assert_eq!(Duration::new(0, 0).checked_add(Duration::new(0, 1)), Some(Duration::new(0, 1)));
- /// assert_eq!(Duration::new(1, 0).checked_add(Duration::new(std::u64::MAX, 0)), None);
+ /// assert_eq!(Duration::new(1, 0).checked_add(Duration::new(u64::MAX, 0)), None);
/// ```
#[stable(feature = "duration_checked_ops", since = "1.16.0")]
#[inline]
@@ -460,7 +460,7 @@ impl Duration {
/// use std::time::Duration;
///
/// assert_eq!(Duration::new(0, 500_000_001).checked_mul(2), Some(Duration::new(1, 2)));
- /// assert_eq!(Duration::new(std::u64::MAX - 1, 0).checked_mul(2), None);
+ /// assert_eq!(Duration::new(u64::MAX - 1, 0).checked_mul(2), None);
/// ```
#[stable(feature = "duration_checked_ops", since = "1.16.0")]
#[inline]
diff --git a/src/librustc_ast_lowering/item.rs b/src/librustc_ast_lowering/item.rs
index b319ee76c81..6005b607026 100644
--- a/src/librustc_ast_lowering/item.rs
+++ b/src/librustc_ast_lowering/item.rs
@@ -972,8 +972,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
f: impl FnOnce(&mut Self) -> (&'hir [hir::Param<'hir>], hir::Expr<'hir>),
) -> hir::BodyId {
let prev_gen_kind = self.generator_kind.take();
+ let task_context = self.task_context.take();
let (parameters, result) = f(self);
let body_id = self.record_body(parameters, result);
+ self.task_context = task_context;
self.generator_kind = prev_gen_kind;
body_id
}
diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs
index 2d5564abfb2..9fd22c8b07b 100644
--- a/src/librustc_codegen_llvm/consts.rs
+++ b/src/librustc_codegen_llvm/consts.rs
@@ -436,24 +436,21 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> {
//
// We could remove this hack whenever we decide to drop macOS 10.10 support.
if self.tcx.sess.target.target.options.is_like_osx {
- assert_eq!(alloc.relocations().len(), 0);
-
- let is_zeroed = {
- // Treats undefined bytes as if they were defined with the byte value that
- // happens to be currently assigned in mir. This is valid since reading
- // undef bytes may yield arbitrary values.
- //
- // FIXME: ignore undef bytes even with representation `!= 0`.
- //
- // The `inspect` method is okay here because we checked relocations, and
- // because we are doing this access to inspect the final interpreter state
- // (not as part of the interpreter execution).
- alloc
+ // The `inspect` method is okay here because we checked relocations, and
+ // because we are doing this access to inspect the final interpreter state
+ // (not as part of the interpreter execution).
+ //
+ // FIXME: This check requires that the (arbitrary) value of undefined bytes
+ // happens to be zero. Instead, we should only check the value of defined bytes
+ // and set all undefined bytes to zero if this allocation is headed for the
+ // BSS.
+ let all_bytes_are_zero = alloc.relocations().is_empty()
+ && alloc
.inspect_with_undef_and_ptr_outside_interpreter(0..alloc.len())
.iter()
- .all(|b| *b == 0)
- };
- let sect_name = if is_zeroed {
+ .all(|&byte| byte == 0);
+
+ let sect_name = if all_bytes_are_zero {
CStr::from_bytes_with_nul_unchecked(b"__DATA,__thread_bss\0")
} else {
CStr::from_bytes_with_nul_unchecked(b"__DATA,__thread_data\0")
diff --git a/src/librustc_error_codes/error_codes/E0502.md b/src/librustc_error_codes/error_codes/E0502.md
index f15c05d558d..b90c59f5807 100644
--- a/src/librustc_error_codes/error_codes/E0502.md
+++ b/src/librustc_error_codes/error_codes/E0502.md
@@ -1,5 +1,4 @@
-This error indicates that you are trying to borrow a variable as mutable when it
-has already been borrowed as immutable.
+A variable already borrowed as immutable was borrowed as mutable.
Erroneous code example:
diff --git a/src/librustc_infer/traits/mod.rs b/src/librustc_infer/traits/mod.rs
index 0c451998be4..758a0b39d43 100644
--- a/src/librustc_infer/traits/mod.rs
+++ b/src/librustc_infer/traits/mod.rs
@@ -6,7 +6,7 @@ mod engine;
pub mod error_reporting;
mod project;
mod structural_impls;
-mod util;
+pub mod util;
use rustc_hir as hir;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
diff --git a/src/librustc_infer/traits/util.rs b/src/librustc_infer/traits/util.rs
index 80a1e282809..4fa74f93ddc 100644
--- a/src/librustc_infer/traits/util.rs
+++ b/src/librustc_infer/traits/util.rs
@@ -2,9 +2,12 @@ use smallvec::smallvec;
use rustc_data_structures::fx::FxHashSet;
use rustc_middle::ty::outlives::Component;
-use rustc_middle::ty::{self, ToPolyTraitRef, TyCtxt};
+use rustc_middle::ty::{self, ToPolyTraitRef, ToPredicate, TyCtxt, WithConstness};
-fn anonymize_predicate<'tcx>(tcx: TyCtxt<'tcx>, pred: &ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
+pub fn anonymize_predicate<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ pred: &ty::Predicate<'tcx>,
+) -> ty::Predicate<'tcx> {
match *pred {
ty::Predicate::Trait(ref data, constness) => {
ty::Predicate::Trait(tcx.anonymize_late_bound_regions(data), constness)
@@ -88,6 +91,21 @@ pub struct Elaborator<'tcx> {
visited: PredicateSet<'tcx>,
}
+pub fn elaborate_trait_ref<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ trait_ref: ty::PolyTraitRef<'tcx>,
+) -> Elaborator<'tcx> {
+ elaborate_predicates(tcx, vec![trait_ref.without_const().to_predicate()])
+}
+
+pub fn elaborate_trait_refs<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ trait_refs: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
+) -> Elaborator<'tcx> {
+ let predicates = trait_refs.map(|trait_ref| trait_ref.without_const().to_predicate()).collect();
+ elaborate_predicates(tcx, predicates)
+}
+
pub fn elaborate_predicates<'tcx>(
tcx: TyCtxt<'tcx>,
mut predicates: Vec<ty::Predicate<'tcx>>,
@@ -98,6 +116,10 @@ pub fn elaborate_predicates<'tcx>(
}
impl Elaborator<'tcx> {
+ pub fn filter_to_traits(self) -> FilterToTraits<Self> {
+ FilterToTraits::new(self)
+ }
+
fn elaborate(&mut self, predicate: &ty::Predicate<'tcx>) {
let tcx = self.visited.tcx;
match *predicate {
@@ -223,3 +245,57 @@ impl Iterator for Elaborator<'tcx> {
}
}
}
+
+///////////////////////////////////////////////////////////////////////////
+// Supertrait iterator
+///////////////////////////////////////////////////////////////////////////
+
+pub type Supertraits<'tcx> = FilterToTraits<Elaborator<'tcx>>;
+
+pub fn supertraits<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ trait_ref: ty::PolyTraitRef<'tcx>,
+) -> Supertraits<'tcx> {
+ elaborate_trait_ref(tcx, trait_ref).filter_to_traits()
+}
+
+pub fn transitive_bounds<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ bounds: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
+) -> Supertraits<'tcx> {
+ elaborate_trait_refs(tcx, bounds).filter_to_traits()
+}
+
+///////////////////////////////////////////////////////////////////////////
+// Other
+///////////////////////////////////////////////////////////////////////////
+
+/// A filter around an iterator of predicates that makes it yield up
+/// just trait references.
+pub struct FilterToTraits<I> {
+ base_iterator: I,
+}
+
+impl<I> FilterToTraits<I> {
+ fn new(base: I) -> FilterToTraits<I> {
+ FilterToTraits { base_iterator: base }
+ }
+}
+
+impl<'tcx, I: Iterator<Item = ty::Predicate<'tcx>>> Iterator for FilterToTraits<I> {
+ type Item = ty::PolyTraitRef<'tcx>;
+
+ fn next(&mut self) -> Option<ty::PolyTraitRef<'tcx>> {
+ while let Some(pred) = self.base_iterator.next() {
+ if let ty::Predicate::Trait(data, _) = pred {
+ return Some(data.to_poly_trait_ref());
+ }
+ }
+ None
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ let (_, upper) = self.base_iterator.size_hint();
+ (0, upper)
+ }
+}
diff --git a/src/librustc_metadata/native_libs.rs b/src/librustc_metadata/native_libs.rs
index e952051eb9f..4b92a2205c2 100644
--- a/src/librustc_metadata/native_libs.rs
+++ b/src/librustc_metadata/native_libs.rs
@@ -162,8 +162,13 @@ impl Collector<'tcx> {
}
}
if lib.cfg.is_some() && !self.tcx.features().link_cfg {
- feature_err(&self.tcx.sess.parse_sess, sym::link_cfg, span.unwrap(), "is unstable")
- .emit();
+ feature_err(
+ &self.tcx.sess.parse_sess,
+ sym::link_cfg,
+ span.unwrap(),
+ "kind=\"link_cfg\" is unstable",
+ )
+ .emit();
}
if lib.kind == cstore::NativeStaticNobundle && !self.tcx.features().static_nobundle {
feature_err(
diff --git a/src/librustc_mir/dataflow/graphviz.rs b/src/librustc_mir/dataflow/graphviz.rs
deleted file mode 100644
index e74d27bafb2..00000000000
--- a/src/librustc_mir/dataflow/graphviz.rs
+++ /dev/null
@@ -1,277 +0,0 @@
-//! Hook into libgraphviz for rendering dataflow graphs for MIR.
-
-use rustc_hir::def_id::DefId;
-use rustc_middle::mir::{BasicBlock, Body};
-
-use std::fs;
-use std::io;
-use std::marker::PhantomData;
-use std::path::Path;
-
-use crate::util::graphviz_safe_def_name;
-
-use super::DataflowBuilder;
-use super::DebugFormatted;
-use super::{BitDenotation, DataflowState};
-
-pub trait MirWithFlowState<'tcx> {
- type BD: BitDenotation<'tcx>;
- fn def_id(&self) -> DefId;
- fn body(&self) -> &Body<'tcx>;
- fn flow_state(&self) -> &DataflowState<'tcx, Self::BD>;
-}
-
-impl<'a, 'tcx, BD> MirWithFlowState<'tcx> for DataflowBuilder<'a, 'tcx, BD>
-where
- BD: BitDenotation<'tcx>,
-{
- type BD = BD;
- fn def_id(&self) -> DefId {
- self.def_id
- }
- fn body(&self) -> &Body<'tcx> {
- self.flow_state.body()
- }
- fn flow_state(&self) -> &DataflowState<'tcx, Self::BD> {
- &self.flow_state.flow_state
- }
-}
-
-struct Graph<'a, 'tcx, MWF, P>
-where
- MWF: MirWithFlowState<'tcx>,
-{
- mbcx: &'a MWF,
- phantom: PhantomData<&'tcx ()>,
- render_idx: P,
-}
-
-pub(crate) fn print_borrowck_graph_to<'a, 'tcx, BD, P>(
- mbcx: &DataflowBuilder<'a, 'tcx, BD>,
- path: &Path,
- render_idx: P,
-) -> io::Result<()>
-where
- BD: BitDenotation<'tcx>,
- P: Fn(&BD, BD::Idx) -> DebugFormatted,
-{
- let g = Graph { mbcx, phantom: PhantomData, render_idx };
- let mut v = Vec::new();
- dot::render(&g, &mut v)?;
- debug!("print_borrowck_graph_to path: {} def_id: {:?}", path.display(), mbcx.def_id);
- fs::write(path, v)
-}
-
-pub type Node = BasicBlock;
-
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
-pub struct Edge {
- source: BasicBlock,
- index: usize,
-}
-
-fn outgoing(body: &Body<'_>, bb: BasicBlock) -> Vec<Edge> {
- (0..body[bb].terminator().successors().count())
- .map(|index| Edge { source: bb, index })
- .collect()
-}
-
-impl<'a, 'tcx, MWF, P> dot::Labeller<'a> for Graph<'a, 'tcx, MWF, P>
-where
- MWF: MirWithFlowState<'tcx>,
- P: Fn(&MWF::BD, <MWF::BD as BitDenotation<'tcx>>::Idx) -> DebugFormatted,
-{
- type Node = Node;
- type Edge = Edge;
- fn graph_id(&self) -> dot::Id<'_> {
- let name = graphviz_safe_def_name(self.mbcx.def_id());
- dot::Id::new(format!("graph_for_def_id_{}", name)).unwrap()
- }
-
- fn node_id(&self, n: &Node) -> dot::Id<'_> {
- dot::Id::new(format!("bb_{}", n.index())).unwrap()
- }
-
- fn node_label(&self, n: &Node) -> dot::LabelText<'_> {
- // Node label is something like this:
- // +---------+----------------------------------+------------------+------------------+
- // | ENTRY | MIR | GEN | KILL |
- // +---------+----------------------------------+------------------+------------------+
- // | | 0: StorageLive(_7) | bb3[2]: reserved | bb2[0]: reserved |
- // | | 1: StorageLive(_8) | bb3[2]: active | bb2[0]: active |
- // | | 2: _8 = &mut _1 | | bb4[2]: reserved |
- // | | | | bb4[2]: active |
- // | | | | bb9[0]: reserved |
- // | | | | bb9[0]: active |
- // | | | | bb10[0]: reserved|
- // | | | | bb10[0]: active |
- // | | | | bb11[0]: reserved|
- // | | | | bb11[0]: active |
- // +---------+----------------------------------+------------------+------------------+
- // | [00-00] | _7 = const Foo::twiddle(move _8) | [0c-00] | [f3-0f] |
- // +---------+----------------------------------+------------------+------------------+
- let mut v = Vec::new();
- self.node_label_internal(n, &mut v, *n, self.mbcx.body()).unwrap();
- dot::LabelText::html(String::from_utf8(v).unwrap())
- }
-
- fn node_shape(&self, _n: &Node) -> Option<dot::LabelText<'_>> {
- Some(dot::LabelText::label("none"))
- }
-
- fn edge_label(&'a self, e: &Edge) -> dot::LabelText<'a> {
- let term = self.mbcx.body()[e.source].terminator();
- let label = &term.kind.fmt_successor_labels()[e.index];
- dot::LabelText::label(label.clone())
- }
-}
-
-impl<'a, 'tcx, MWF, P> Graph<'a, 'tcx, MWF, P>
-where
- MWF: MirWithFlowState<'tcx>,
- P: Fn(&MWF::BD, <MWF::BD as BitDenotation<'tcx>>::Idx) -> DebugFormatted,
-{
- /// Generate the node label
- fn node_label_internal<W: io::Write>(
- &self,
- n: &Node,
- w: &mut W,
- block: BasicBlock,
- body: &Body<'_>,
- ) -> io::Result<()> {
- // Header rows
- const HDRS: [&str; 4] = ["ENTRY", "MIR", "BLOCK GENS", "BLOCK KILLS"];
- const HDR_FMT: &str = "bgcolor=\"grey\"";
- write!(w, "<table><tr><td rowspan=\"{}\">", HDRS.len())?;
- write!(w, "{:?}", block.index())?;
- write!(w, "</td></tr><tr>")?;
- for hdr in &HDRS {
- write!(w, "<td {}>{}</td>", HDR_FMT, hdr)?;
- }
- write!(w, "</tr>")?;
-
- // Data row
- self.node_label_verbose_row(n, w, block, body)?;
- self.node_label_final_row(n, w, block, body)?;
- write!(w, "</table>")?;
-
- Ok(())
- }
-
- /// Builds the verbose row: full MIR data, and detailed gen/kill/entry sets.
- fn node_label_verbose_row<W: io::Write>(
- &self,
- n: &Node,
- w: &mut W,
- block: BasicBlock,
- body: &Body<'_>,
- ) -> io::Result<()> {
- let i = n.index();
-
- macro_rules! dump_set_for {
- ($set:ident, $interpret:ident) => {
- write!(w, "<td>")?;
-
- let flow = self.mbcx.flow_state();
- let entry_interp =
- flow.$interpret(&flow.operator, flow.sets.$set(i), &self.render_idx);
- for e in &entry_interp {
- write!(w, "{:?}<br/>", e)?;
- }
- write!(w, "</td>")?;
- };
- }
-
- write!(w, "<tr>")?;
- // Entry
- dump_set_for!(entry_set_for, interpret_set);
-
- // MIR statements
- write!(w, "<td>")?;
- {
- let data = &body[block];
- for (i, statement) in data.statements.iter().enumerate() {
- write!(
- w,
- "{}<br align=\"left\"/>",
- dot::escape_html(&format!("{:3}: {:?}", i, statement))
- )?;
- }
- }
- write!(w, "</td>")?;
-
- // Gen
- dump_set_for!(gen_set_for, interpret_hybrid_set);
-
- // Kill
- dump_set_for!(kill_set_for, interpret_hybrid_set);
-
- write!(w, "</tr>")?;
-
- Ok(())
- }
-
- /// Builds the summary row: terminator, gen/kill/entry bit sets.
- fn node_label_final_row<W: io::Write>(
- &self,
- n: &Node,
- w: &mut W,
- block: BasicBlock,
- body: &Body<'_>,
- ) -> io::Result<()> {
- let i = n.index();
-
- let flow = self.mbcx.flow_state();
-
- write!(w, "<tr>")?;
-
- // Entry
- let set = flow.sets.entry_set_for(i);
- write!(w, "<td>{:?}</td>", dot::escape_html(&set.to_string()))?;
-
- // Terminator
- write!(w, "<td>")?;
- {
- let data = &body[block];
- let mut terminator_head = String::new();
- data.terminator().kind.fmt_head(&mut terminator_head).unwrap();
- write!(w, "{}", dot::escape_html(&terminator_head))?;
- }
- write!(w, "</td>")?;
-
- // Gen/Kill
- let trans = flow.sets.trans_for(i);
- write!(w, "<td>{:?}</td>", dot::escape_html(&format!("{:?}", trans.gen_set)))?;
- write!(w, "<td>{:?}</td>", dot::escape_html(&format!("{:?}", trans.kill_set)))?;
-
- write!(w, "</tr>")?;
-
- Ok(())
- }
-}
-
-impl<'a, 'tcx, MWF, P> dot::GraphWalk<'a> for Graph<'a, 'tcx, MWF, P>
-where
- MWF: MirWithFlowState<'tcx>,
-{
- type Node = Node;
- type Edge = Edge;
- fn nodes(&self) -> dot::Nodes<'_, Node> {
- self.mbcx.body().basic_blocks().indices().collect::<Vec<_>>().into()
- }
-
- fn edges(&self) -> dot::Edges<'_, Edge> {
- let body = self.mbcx.body();
-
- body.basic_blocks().indices().flat_map(|bb| outgoing(body, bb)).collect::<Vec<_>>().into()
- }
-
- fn source(&self, edge: &Edge) -> Node {
- edge.source
- }
-
- fn target(&self, edge: &Edge) -> Node {
- let body = self.mbcx.body();
- *body[edge.source].terminator().successors().nth(edge.index).unwrap()
- }
-}
diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs
index f382ef984be..4c25363a657 100644
--- a/src/librustc_target/abi/mod.rs
+++ b/src/librustc_target/abi/mod.rs
@@ -577,7 +577,7 @@ pub struct Scalar {
pub value: Primitive,
/// Inclusive wrap-around range of valid values, that is, if
- /// start > end, it represents `start..=max_value()`,
+ /// start > end, it represents `start..=MAX`,
/// followed by `0..=end`.
///
/// That is, for an i8 primitive, a range of `254..=2` means following
diff --git a/src/librustc_trait_selection/traits/util.rs b/src/librustc_trait_selection/traits/util.rs
index 6348673dab8..725c41c1e2c 100644
--- a/src/librustc_trait_selection/traits/util.rs
+++ b/src/librustc_trait_selection/traits/util.rs
@@ -5,270 +5,11 @@ use smallvec::SmallVec;
use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def_id::DefId;
-use rustc_middle::ty::outlives::Component;
use rustc_middle::ty::subst::{GenericArg, Subst, SubstsRef};
-use rustc_middle::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, WithConstness};
+use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness};
use super::{Normalized, Obligation, ObligationCause, PredicateObligation, SelectionContext};
-
-fn anonymize_predicate<'tcx>(tcx: TyCtxt<'tcx>, pred: &ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
- match *pred {
- ty::Predicate::Trait(ref data, constness) => {
- ty::Predicate::Trait(tcx.anonymize_late_bound_regions(data), constness)
- }
-
- ty::Predicate::RegionOutlives(ref data) => {
- ty::Predicate::RegionOutlives(tcx.anonymize_late_bound_regions(data))
- }
-
- ty::Predicate::TypeOutlives(ref data) => {
- ty::Predicate::TypeOutlives(tcx.anonymize_late_bound_regions(data))
- }
-
- ty::Predicate::Projection(ref data) => {
- ty::Predicate::Projection(tcx.anonymize_late_bound_regions(data))
- }
-
- ty::Predicate::WellFormed(data) => ty::Predicate::WellFormed(data),
-
- ty::Predicate::ObjectSafe(data) => ty::Predicate::ObjectSafe(data),
-
- ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
- ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind)
- }
-
- ty::Predicate::Subtype(ref data) => {
- ty::Predicate::Subtype(tcx.anonymize_late_bound_regions(data))
- }
-
- ty::Predicate::ConstEvaluatable(def_id, substs) => {
- ty::Predicate::ConstEvaluatable(def_id, substs)
- }
- }
-}
-
-struct PredicateSet<'tcx> {
- tcx: TyCtxt<'tcx>,
- set: FxHashSet<ty::Predicate<'tcx>>,
-}
-
-impl PredicateSet<'tcx> {
- fn new(tcx: TyCtxt<'tcx>) -> Self {
- Self { tcx, set: Default::default() }
- }
-
- fn insert(&mut self, pred: &ty::Predicate<'tcx>) -> bool {
- // We have to be careful here because we want
- //
- // for<'a> Foo<&'a int>
- //
- // and
- //
- // for<'b> Foo<&'b int>
- //
- // to be considered equivalent. So normalize all late-bound
- // regions before we throw things into the underlying set.
- self.set.insert(anonymize_predicate(self.tcx, pred))
- }
-}
-
-impl<T: AsRef<ty::Predicate<'tcx>>> Extend<T> for PredicateSet<'tcx> {
- fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
- for pred in iter {
- self.insert(pred.as_ref());
- }
- }
-}
-
-///////////////////////////////////////////////////////////////////////////
-// `Elaboration` iterator
-///////////////////////////////////////////////////////////////////////////
-
-/// "Elaboration" is the process of identifying all the predicates that
-/// are implied by a source predicate. Currently, this basically means
-/// walking the "supertraits" and other similar assumptions. For example,
-/// if we know that `T: Ord`, the elaborator would deduce that `T: PartialOrd`
-/// holds as well. Similarly, if we have `trait Foo: 'static`, and we know that
-/// `T: Foo`, then we know that `T: 'static`.
-pub struct Elaborator<'tcx> {
- stack: Vec<ty::Predicate<'tcx>>,
- visited: PredicateSet<'tcx>,
-}
-
-pub fn elaborate_trait_ref<'tcx>(
- tcx: TyCtxt<'tcx>,
- trait_ref: ty::PolyTraitRef<'tcx>,
-) -> Elaborator<'tcx> {
- elaborate_predicates(tcx, vec![trait_ref.without_const().to_predicate()])
-}
-
-pub fn elaborate_trait_refs<'tcx>(
- tcx: TyCtxt<'tcx>,
- trait_refs: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
-) -> Elaborator<'tcx> {
- let predicates = trait_refs.map(|trait_ref| trait_ref.without_const().to_predicate()).collect();
- elaborate_predicates(tcx, predicates)
-}
-
-pub fn elaborate_predicates<'tcx>(
- tcx: TyCtxt<'tcx>,
- mut predicates: Vec<ty::Predicate<'tcx>>,
-) -> Elaborator<'tcx> {
- let mut visited = PredicateSet::new(tcx);
- predicates.retain(|pred| visited.insert(pred));
- Elaborator { stack: predicates, visited }
-}
-
-impl Elaborator<'tcx> {
- pub fn filter_to_traits(self) -> FilterToTraits<Self> {
- FilterToTraits::new(self)
- }
-
- fn elaborate(&mut self, predicate: &ty::Predicate<'tcx>) {
- let tcx = self.visited.tcx;
- match *predicate {
- ty::Predicate::Trait(ref data, _) => {
- // Get predicates declared on the trait.
- let predicates = tcx.super_predicates_of(data.def_id());
-
- let predicates = predicates
- .predicates
- .iter()
- .map(|(pred, _)| pred.subst_supertrait(tcx, &data.to_poly_trait_ref()));
- debug!("super_predicates: data={:?} predicates={:?}", data, predicates.clone());
-
- // Only keep those bounds that we haven't already seen.
- // This is necessary to prevent infinite recursion in some
- // cases. One common case is when people define
- // `trait Sized: Sized { }` rather than `trait Sized { }`.
- let visited = &mut self.visited;
- let predicates = predicates.filter(|pred| visited.insert(pred));
-
- self.stack.extend(predicates);
- }
- ty::Predicate::WellFormed(..) => {
- // Currently, we do not elaborate WF predicates,
- // although we easily could.
- }
- ty::Predicate::ObjectSafe(..) => {
- // Currently, we do not elaborate object-safe
- // predicates.
- }
- ty::Predicate::Subtype(..) => {
- // Currently, we do not "elaborate" predicates like `X <: Y`,
- // though conceivably we might.
- }
- ty::Predicate::Projection(..) => {
- // Nothing to elaborate in a projection predicate.
- }
- ty::Predicate::ClosureKind(..) => {
- // Nothing to elaborate when waiting for a closure's kind to be inferred.
- }
- ty::Predicate::ConstEvaluatable(..) => {
- // Currently, we do not elaborate const-evaluatable
- // predicates.
- }
- ty::Predicate::RegionOutlives(..) => {
- // Nothing to elaborate from `'a: 'b`.
- }
- ty::Predicate::TypeOutlives(ref data) => {
- // We know that `T: 'a` for some type `T`. We can
- // often elaborate this. For example, if we know that
- // `[U]: 'a`, that implies that `U: 'a`. Similarly, if
- // we know `&'a U: 'b`, then we know that `'a: 'b` and
- // `U: 'b`.
- //
- // We can basically ignore bound regions here. So for
- // example `for<'c> Foo<'a,'c>: 'b` can be elaborated to
- // `'a: 'b`.
-
- // Ignore `for<'a> T: 'a` -- we might in the future
- // consider this as evidence that `T: 'static`, but
- // I'm a bit wary of such constructions and so for now
- // I want to be conservative. --nmatsakis
- let ty_max = data.skip_binder().0;
- let r_min = data.skip_binder().1;
- if r_min.is_late_bound() {
- return;
- }
-
- let visited = &mut self.visited;
- let mut components = smallvec![];
- tcx.push_outlives_components(ty_max, &mut components);
- self.stack.extend(
- components
- .into_iter()
- .filter_map(|component| match component {
- Component::Region(r) => {
- if r.is_late_bound() {
- None
- } else {
- Some(ty::Predicate::RegionOutlives(ty::Binder::dummy(
- ty::OutlivesPredicate(r, r_min),
- )))
- }
- }
-
- Component::Param(p) => {
- let ty = tcx.mk_ty_param(p.index, p.name);
- Some(ty::Predicate::TypeOutlives(ty::Binder::dummy(
- ty::OutlivesPredicate(ty, r_min),
- )))
- }
-
- Component::UnresolvedInferenceVariable(_) => None,
-
- Component::Projection(_) | Component::EscapingProjection(_) => {
- // We can probably do more here. This
- // corresponds to a case like `<T as
- // Foo<'a>>::U: 'b`.
- None
- }
- })
- .filter(|p| visited.insert(p)),
- );
- }
- }
- }
-}
-
-impl Iterator for Elaborator<'tcx> {
- type Item = ty::Predicate<'tcx>;
-
- fn size_hint(&self) -> (usize, Option<usize>) {
- (self.stack.len(), None)
- }
-
- fn next(&mut self) -> Option<ty::Predicate<'tcx>> {
- // Extract next item from top-most stack frame, if any.
- if let Some(pred) = self.stack.pop() {
- self.elaborate(&pred);
- Some(pred)
- } else {
- None
- }
- }
-}
-
-///////////////////////////////////////////////////////////////////////////
-// Supertrait iterator
-///////////////////////////////////////////////////////////////////////////
-
-pub type Supertraits<'tcx> = FilterToTraits<Elaborator<'tcx>>;
-
-pub fn supertraits<'tcx>(
- tcx: TyCtxt<'tcx>,
- trait_ref: ty::PolyTraitRef<'tcx>,
-) -> Supertraits<'tcx> {
- elaborate_trait_ref(tcx, trait_ref).filter_to_traits()
-}
-
-pub fn transitive_bounds<'tcx>(
- tcx: TyCtxt<'tcx>,
- bounds: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
-) -> Supertraits<'tcx> {
- elaborate_trait_refs(tcx, bounds).filter_to_traits()
-}
+pub use rustc_infer::traits::util::*;
///////////////////////////////////////////////////////////////////////////
// `TraitAliasExpander` iterator
@@ -450,40 +191,6 @@ impl Iterator for SupertraitDefIds<'tcx> {
// Other
///////////////////////////////////////////////////////////////////////////
-/// A filter around an iterator of predicates that makes it yield up
-/// just trait references.
-pub struct FilterToTraits<I> {
- base_iterator: I,
-}
-
-impl<I> FilterToTraits<I> {
- fn new(base: I) -> FilterToTraits<I> {
- FilterToTraits { base_iterator: base }
- }
-}
-
-impl<'tcx, I: Iterator<Item = ty::Predicate<'tcx>>> Iterator for FilterToTraits<I> {
- type Item = ty::PolyTraitRef<'tcx>;
-
- fn next(&mut self) -> Option<ty::PolyTraitRef<'tcx>> {
- while let Some(pred) = self.base_iterator.next() {
- if let ty::Predicate::Trait(data, _) = pred {
- return Some(data.to_poly_trait_ref());
- }
- }
- None
- }
-
- fn size_hint(&self) -> (usize, Option<usize>) {
- let (_, upper) = self.base_iterator.size_hint();
- (0, upper)
- }
-}
-
-///////////////////////////////////////////////////////////////////////////
-// Other
-///////////////////////////////////////////////////////////////////////////
-
/// Instantiate all bound parameters of the impl with the given substs,
/// returning the resulting trait ref and all obligations that arise.
/// The obligations are closed under normalization.
diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs
index 20425aea8d5..ac8f305ae91 100644
--- a/src/libstd/f32.rs
+++ b/src/libstd/f32.rs
@@ -284,7 +284,7 @@ impl f32 {
/// assert_eq!(a.rem_euclid(-b), 3.0);
/// assert_eq!((-a).rem_euclid(-b), 1.0);
/// // limitation due to round-off error
- /// assert!((-std::f32::EPSILON).rem_euclid(3.0) != 0.0);
+ /// assert!((-f32::EPSILON).rem_euclid(3.0) != 0.0);
/// ```
#[must_use = "method returns a new number and does not mutate the original value"]
#[inline]
@@ -962,7 +962,7 @@ impl f32 {
/// assert!((-3.0f32).clamp(-2.0, 1.0) == -2.0);
/// assert!((0.0f32).clamp(-2.0, 1.0) == 0.0);
/// assert!((2.0f32).clamp(-2.0, 1.0) == 1.0);
- /// assert!((std::f32::NAN).clamp(-2.0, 1.0).is_nan());
+ /// assert!((f32::NAN).clamp(-2.0, 1.0).is_nan());
/// ```
#[must_use = "method returns a new number and does not mutate the original value"]
#[unstable(feature = "clamp", issue = "44095")]
diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs
index a1128a589a6..798738e50a7 100644
--- a/src/libstd/f64.rs
+++ b/src/libstd/f64.rs
@@ -280,7 +280,7 @@ impl f64 {
/// assert_eq!(a.rem_euclid(-b), 3.0);
/// assert_eq!((-a).rem_euclid(-b), 1.0);
/// // limitation due to round-off error
- /// assert!((-std::f64::EPSILON).rem_euclid(3.0) != 0.0);
+ /// assert!((-f64::EPSILON).rem_euclid(3.0) != 0.0);
/// ```
#[must_use = "method returns a new number and does not mutate the original value"]
#[inline]
@@ -928,7 +928,7 @@ impl f64 {
/// assert!((-3.0f64).clamp(-2.0, 1.0) == -2.0);
/// assert!((0.0f64).clamp(-2.0, 1.0) == 0.0);
/// assert!((2.0f64).clamp(-2.0, 1.0) == 1.0);
- /// assert!((std::f64::NAN).clamp(-2.0, 1.0).is_nan());
+ /// assert!((f64::NAN).clamp(-2.0, 1.0).is_nan());
/// ```
#[must_use = "method returns a new number and does not mutate the original value"]
#[unstable(feature = "clamp", issue = "44095")]
diff --git a/src/libstd/sys/cloudabi/stack_overflow.rs b/src/libstd/sys/cloudabi/stack_overflow.rs
index e97831b2c28..9339b143731 100644
--- a/src/libstd/sys/cloudabi/stack_overflow.rs
+++ b/src/libstd/sys/cloudabi/stack_overflow.rs
@@ -1,13 +1,5 @@
#![cfg_attr(test, allow(dead_code))]
-pub struct Handler;
-
-impl Handler {
- pub unsafe fn new() -> Handler {
- Handler
- }
-}
-
pub unsafe fn init() {}
pub unsafe fn cleanup() {}
diff --git a/src/libstd/sys/cloudabi/thread.rs b/src/libstd/sys/cloudabi/thread.rs
index 3afcae7ae75..a15dc8653e8 100644
--- a/src/libstd/sys/cloudabi/thread.rs
+++ b/src/libstd/sys/cloudabi/thread.rs
@@ -5,7 +5,6 @@ use crate::mem;
use crate::ptr;
use crate::sys::cloudabi::abi;
use crate::sys::time::checked_dur2intervals;
-use crate::sys_common::thread::*;
use crate::time::Duration;
pub const DEFAULT_MIN_STACK_SIZE: usize = 2 * 1024 * 1024;
@@ -22,7 +21,7 @@ unsafe impl Sync for Thread {}
impl Thread {
// unsafe: see thread::Builder::spawn_unchecked for safety requirements
pub unsafe fn new(stack: usize, p: Box<dyn FnOnce()>) -> io::Result<Thread> {
- let p = box p;
+ let p = Box::into_raw(box p);
let mut native: libc::pthread_t = mem::zeroed();
let mut attr: libc::pthread_attr_t = mem::zeroed();
assert_eq!(libc::pthread_attr_init(&mut attr), 0);
@@ -30,19 +29,25 @@ impl Thread {
let stack_size = cmp::max(stack, min_stack_size(&attr));
assert_eq!(libc::pthread_attr_setstacksize(&mut attr, stack_size), 0);
- let ret = libc::pthread_create(&mut native, &attr, thread_start, &*p as *const _ as *mut _);
+ let ret = libc::pthread_create(&mut native, &attr, thread_start, p as *mut _);
+ // Note: if the thread creation fails and this assert fails, then p will
+ // be leaked. However, an alternative design could cause double-free
+ // which is clearly worse.
assert_eq!(libc::pthread_attr_destroy(&mut attr), 0);
return if ret != 0 {
+ // The thread failed to start and as a result p was not consumed. Therefore, it is
+ // safe to reconstruct the box so that it gets deallocated.
+ drop(Box::from_raw(p));
Err(io::Error::from_raw_os_error(ret))
} else {
- mem::forget(p); // ownership passed to pthread_create
Ok(Thread { id: native })
};
extern "C" fn thread_start(main: *mut libc::c_void) -> *mut libc::c_void {
unsafe {
- start_thread(main as *mut u8);
+ // Let's run some code.
+ Box::from_raw(main as *mut Box<dyn FnOnce()>)();
}
ptr::null_mut()
}
diff --git a/src/libstd/sys/hermit/stack_overflow.rs b/src/libstd/sys/hermit/stack_overflow.rs
index 65a1b17acce..121fe42011d 100644
--- a/src/libstd/sys/hermit/stack_overflow.rs
+++ b/src/libstd/sys/hermit/stack_overflow.rs
@@ -1,11 +1,3 @@
-pub struct Handler;
-
-impl Handler {
- pub unsafe fn new() -> Handler {
- Handler
- }
-}
-
#[inline]
pub unsafe fn init() {}
diff --git a/src/libstd/sys/hermit/thread.rs b/src/libstd/sys/hermit/thread.rs
index c3c29c93826..c7bea168f34 100644
--- a/src/libstd/sys/hermit/thread.rs
+++ b/src/libstd/sys/hermit/thread.rs
@@ -8,8 +8,6 @@ use crate::sys::hermit::abi;
use crate::time::Duration;
use core::u32;
-use crate::sys_common::thread::*;
-
pub type Tid = abi::Tid;
/// Priority of a task
@@ -49,26 +47,29 @@ impl Thread {
p: Box<dyn FnOnce()>,
core_id: isize,
) -> io::Result<Thread> {
- let p = box p;
+ let p = Box::into_raw(box p);
let mut tid: Tid = u32::MAX;
let ret = abi::spawn(
&mut tid as *mut Tid,
thread_start,
- &*p as *const _ as *const u8 as usize,
+ p as usize,
Priority::into(NORMAL_PRIO),
core_id,
);
- return if ret == 0 {
- mem::forget(p); // ownership passed to pthread_create
- Ok(Thread { tid: tid })
- } else {
+ return if ret != 0 {
+ // The thread failed to start and as a result p was not consumed. Therefore, it is
+ // safe to reconstruct the box so that it gets deallocated.
+ drop(Box::from_raw(p));
Err(io::Error::new(io::ErrorKind::Other, "Unable to create thread!"))
+ } else {
+ Ok(Thread { tid: tid })
};
extern "C" fn thread_start(main: usize) {
unsafe {
- start_thread(main as *mut u8);
+ // Finally, let's run some code.
+ Box::from_raw(main as *mut Box<dyn FnOnce()>)();
}
}
}
diff --git a/src/libstd/sys/sgx/stack_overflow.rs b/src/libstd/sys/sgx/stack_overflow.rs
index a2d13d11849..b96652a8330 100644
--- a/src/libstd/sys/sgx/stack_overflow.rs
+++ b/src/libstd/sys/sgx/stack_overflow.rs
@@ -1,11 +1,3 @@
-pub struct Handler;
-
-impl Handler {
- pub unsafe fn new() -> Handler {
- Handler
- }
-}
-
#[cfg_attr(test, allow(dead_code))]
pub unsafe fn init() {}
diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs
index 674d4c71138..aab5a92a7ad 100644
--- a/src/libstd/sys/unix/thread.rs
+++ b/src/libstd/sys/unix/thread.rs
@@ -3,11 +3,9 @@ use crate::ffi::CStr;
use crate::io;
use crate::mem;
use crate::ptr;
-use crate::sys::os;
+use crate::sys::{os, stack_overflow};
use crate::time::Duration;
-use crate::sys_common::thread::*;
-
#[cfg(not(target_os = "l4re"))]
pub const DEFAULT_MIN_STACK_SIZE: usize = 2 * 1024 * 1024;
#[cfg(target_os = "l4re")]
@@ -43,7 +41,7 @@ unsafe fn pthread_attr_setstacksize(
impl Thread {
// unsafe: see thread::Builder::spawn_unchecked for safety requirements
pub unsafe fn new(stack: usize, p: Box<dyn FnOnce()>) -> io::Result<Thread> {
- let p = box p;
+ let p = Box::into_raw(box p);
let mut native: libc::pthread_t = mem::zeroed();
let mut attr: libc::pthread_attr_t = mem::zeroed();
assert_eq!(libc::pthread_attr_init(&mut attr), 0);
@@ -65,19 +63,28 @@ impl Thread {
}
};
- let ret = libc::pthread_create(&mut native, &attr, thread_start, &*p as *const _ as *mut _);
+ let ret = libc::pthread_create(&mut native, &attr, thread_start, p as *mut _);
+ // Note: if the thread creation fails and this assert fails, then p will
+ // be leaked. However, an alternative design could cause double-free
+ // which is clearly worse.
assert_eq!(libc::pthread_attr_destroy(&mut attr), 0);
return if ret != 0 {
+ // The thread failed to start and as a result p was not consumed. Therefore, it is
+ // safe to reconstruct the box so that it gets deallocated.
+ drop(Box::from_raw(p));
Err(io::Error::from_raw_os_error(ret))
} else {
- mem::forget(p); // ownership passed to pthread_create
Ok(Thread { id: native })
};
extern "C" fn thread_start(main: *mut libc::c_void) -> *mut libc::c_void {
unsafe {
- start_thread(main as *mut u8);
+ // Next, set up our stack overflow handler which may get triggered if we run
+ // out of stack.
+ let _handler = stack_overflow::Handler::new();
+ // Finally, let's run some code.
+ Box::from_raw(main as *mut Box<dyn FnOnce()>)();
}
ptr::null_mut()
}
diff --git a/src/libstd/sys/vxworks/thread.rs b/src/libstd/sys/vxworks/thread.rs
index e0d104b5f3e..4d0196e4b4d 100644
--- a/src/libstd/sys/vxworks/thread.rs
+++ b/src/libstd/sys/vxworks/thread.rs
@@ -3,11 +3,9 @@ use crate::ffi::CStr;
use crate::io;
use crate::mem;
use crate::ptr;
-use crate::sys::os;
+use crate::sys::{os, stack_overflow};
use crate::time::Duration;
-use crate::sys_common::thread::*;
-
pub const DEFAULT_MIN_STACK_SIZE: usize = 0x40000; // 256K
pub struct Thread {
@@ -31,7 +29,7 @@ unsafe fn pthread_attr_setstacksize(
impl Thread {
// unsafe: see thread::Builder::spawn_unchecked for safety requirements
pub unsafe fn new(stack: usize, p: Box<dyn FnOnce()>) -> io::Result<Thread> {
- let p = box p;
+ let p = Box::into_raw(box p);
let mut native: libc::pthread_t = mem::zeroed();
let mut attr: libc::pthread_attr_t = mem::zeroed();
assert_eq!(libc::pthread_attr_init(&mut attr), 0);
@@ -53,19 +51,28 @@ impl Thread {
}
};
- let ret = libc::pthread_create(&mut native, &attr, thread_start, &*p as *const _ as *mut _);
+ let ret = libc::pthread_create(&mut native, &attr, thread_start, p as *mut _);
+ // Note: if the thread creation fails and this assert fails, then p will
+ // be leaked. However, an alternative design could cause double-free
+ // which is clearly worse.
assert_eq!(libc::pthread_attr_destroy(&mut attr), 0);
return if ret != 0 {
+ // The thread failed to start and as a result p was not consumed. Therefore, it is
+ // safe to reconstruct the box so that it gets deallocated.
+ drop(Box::from_raw(p));
Err(io::Error::from_raw_os_error(ret))
} else {
- mem::forget(p); // ownership passed to pthread_create
Ok(Thread { id: native })
};
extern "C" fn thread_start(main: *mut libc::c_void) -> *mut libc::c_void {
unsafe {
- start_thread(main as *mut u8);
+ // Next, set up our stack overflow handler which may get triggered if we run
+ // out of stack.
+ let _handler = stack_overflow::Handler::new();
+ // Finally, let's run some code.
+ Box::from_raw(main as *mut Box<dyn FnOnce()>)();
}
ptr::null_mut()
}
diff --git a/src/libstd/sys/wasm/stack_overflow.rs b/src/libstd/sys/wasm/stack_overflow.rs
index cbf62b6e5b7..32555394cd5 100644
--- a/src/libstd/sys/wasm/stack_overflow.rs
+++ b/src/libstd/sys/wasm/stack_overflow.rs
@@ -1,11 +1,3 @@
-pub struct Handler;
-
-impl Handler {
- pub unsafe fn new() -> Handler {
- Handler
- }
-}
-
pub unsafe fn init() {}
pub unsafe fn cleanup() {}
diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs
index c828243a59b..38839ea5e90 100644
--- a/src/libstd/sys/windows/thread.rs
+++ b/src/libstd/sys/windows/thread.rs
@@ -1,10 +1,9 @@
use crate::ffi::CStr;
use crate::io;
-use crate::mem;
use crate::ptr;
use crate::sys::c;
use crate::sys::handle::Handle;
-use crate::sys_common::thread::*;
+use crate::sys::stack_overflow;
use crate::time::Duration;
use libc::c_void;
@@ -20,7 +19,7 @@ pub struct Thread {
impl Thread {
// unsafe: see thread::Builder::spawn_unchecked for safety requirements
pub unsafe fn new(stack: usize, p: Box<dyn FnOnce()>) -> io::Result<Thread> {
- let p = box p;
+ let p = Box::into_raw(box p);
// FIXME On UNIX, we guard against stack sizes that are too small but
// that's because pthreads enforces that stacks are at least
@@ -34,21 +33,27 @@ impl Thread {
ptr::null_mut(),
stack_size,
thread_start,
- &*p as *const _ as *mut _,
+ p as *mut _,
c::STACK_SIZE_PARAM_IS_A_RESERVATION,
ptr::null_mut(),
);
return if ret as usize == 0 {
+ // The thread failed to start and as a result p was not consumed. Therefore, it is
+ // safe to reconstruct the box so that it gets deallocated.
+ drop(Box::from_raw(p));
Err(io::Error::last_os_error())
} else {
- mem::forget(p); // ownership passed to CreateThread
Ok(Thread { handle: Handle::new(ret) })
};
extern "system" fn thread_start(main: *mut c_void) -> c::DWORD {
unsafe {
- start_thread(main as *mut u8);
+ // Next, set up our stack overflow handler which may get triggered if we run
+ // out of stack.
+ let _handler = stack_overflow::Handler::new();
+ // Finally, let's run some code.
+ Box::from_raw(main as *mut Box<dyn FnOnce()>)();
}
0
}
diff --git a/src/libstd/sys_common/thread.rs b/src/libstd/sys_common/thread.rs
index 6ab0d5cbe9c..f3a8bef8f71 100644
--- a/src/libstd/sys_common/thread.rs
+++ b/src/libstd/sys_common/thread.rs
@@ -1,18 +1,7 @@
use crate::env;
use crate::sync::atomic::{self, Ordering};
-use crate::sys::stack_overflow;
use crate::sys::thread as imp;
-#[allow(dead_code)]
-pub unsafe fn start_thread(main: *mut u8) {
- // Next, set up our stack overflow handler which may get triggered if we run
- // out of stack.
- let _handler = stack_overflow::Handler::new();
-
- // Finally, let's run some code.
- Box::from_raw(main as *mut Box<dyn FnOnce()>)()
-}
-
pub fn min_stack() -> usize {
static MIN: atomic::AtomicUsize = atomic::AtomicUsize::new(0);
match MIN.load(Ordering::SeqCst) {
diff --git a/src/test/ui/async-await/issue-70594.rs b/src/test/ui/async-await/issue-70594.rs
new file mode 100644
index 00000000000..e78231a6851
--- /dev/null
+++ b/src/test/ui/async-await/issue-70594.rs
@@ -0,0 +1,12 @@
+// edition:2018
+
+async fn fun() {
+ [1; ().await];
+ //~^ error: `await` is only allowed inside `async` functions and blocks
+ //~| error: `.await` is not allowed in a `const`
+ //~| error: `loop` is not allowed in a `const`
+ //~| error: `.await` is not allowed in a `const`
+ //~| error: the trait bound `(): std::future::Future` is not satisfied
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/issue-70594.stderr b/src/test/ui/async-await/issue-70594.stderr
new file mode 100644
index 00000000000..d2fa7e58f6a
--- /dev/null
+++ b/src/test/ui/async-await/issue-70594.stderr
@@ -0,0 +1,44 @@
+error[E0728]: `await` is only allowed inside `async` functions and blocks
+ --> $DIR/issue-70594.rs:4:9
+ |
+LL | async fn fun() {
+ | --- this is not `async`
+LL | [1; ().await];
+ | ^^^^^^^^ only allowed inside `async` functions and blocks
+
+error[E0744]: `.await` is not allowed in a `const`
+ --> $DIR/issue-70594.rs:4:9
+ |
+LL | [1; ().await];
+ | ^^^^^^^^
+
+error[E0658]: `loop` is not allowed in a `const`
+ --> $DIR/issue-70594.rs:4:9
+ |
+LL | [1; ().await];
+ | ^^^^^^^^
+ |
+ = note: see issue #52000 <https://github.com/rust-lang/rust/issues/52000> for more information
+ = help: add `#![feature(const_loop)]` to the crate attributes to enable
+
+error[E0744]: `.await` is not allowed in a `const`
+ --> $DIR/issue-70594.rs:4:9
+ |
+LL | [1; ().await];
+ | ^^^^^^^^
+
+error[E0277]: the trait bound `(): std::future::Future` is not satisfied
+ --> $DIR/issue-70594.rs:4:9
+ |
+LL | [1; ().await];
+ | ^^^^^^^^ the trait `std::future::Future` is not implemented for `()`
+ |
+ ::: $SRC_DIR/libcore/future/mod.rs:LL:COL
+ |
+LL | F: Future,
+ | ------ required by this bound in `std::future::poll_with_context`
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0277, E0658, E0728, E0744.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/feature-gates/feature-gate-link_cfg.stderr b/src/test/ui/feature-gates/feature-gate-link_cfg.stderr
index 10b151ffa75..41a7dfc3f37 100644
--- a/src/test/ui/feature-gates/feature-gate-link_cfg.stderr
+++ b/src/test/ui/feature-gates/feature-gate-link_cfg.stderr
@@ -1,4 +1,4 @@
-error[E0658]: is unstable
+error[E0658]: kind="link_cfg" is unstable
--> $DIR/feature-gate-link_cfg.rs:1:1
|
LL | #[link(name = "foo", cfg(foo))]
diff --git a/src/test/ui/issues/issue-70673.rs b/src/test/ui/issues/issue-70673.rs
new file mode 100644
index 00000000000..3561f401277
--- /dev/null
+++ b/src/test/ui/issues/issue-70673.rs
@@ -0,0 +1,12 @@
+// Regression test for https://github.com/rust-lang/rust/issues/70673.
+
+// run-pass
+
+#![feature(thread_local)]
+
+#[thread_local]
+static A: &u8 = &42;
+
+fn main() {
+ dbg!(*A);
+}
diff --git a/src/test/ui/traits/impl_trait_as_trait_return_position.rs b/src/test/ui/traits/impl_trait_as_trait_return_position.rs
new file mode 100644
index 00000000000..c3325fd80ca
--- /dev/null
+++ b/src/test/ui/traits/impl_trait_as_trait_return_position.rs
@@ -0,0 +1,17 @@
+// check-pass
+
+trait A {
+ type Foo;
+}
+
+impl<T> A for T {
+ type Foo = ();
+}
+
+fn foo() -> impl std::borrow::Borrow<<u8 as A>::Foo> {
+ ()
+}
+
+fn main() {
+ foo();
+}