diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index d8fc1faca3a39..2ce5bc8ed2f9d 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -432,7 +432,7 @@ impl [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 diff --git a/src/liballoc/str.rs b/src/liballoc/str.rs index 843a2f1f8e9fc..70860c09a2c31 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 604be7d5f68d0..8c542136a7fa6 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -817,7 +817,7 @@ pub trait PartialOrd: PartialEq { /// 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 fe728d42c76f7..95411b525d0db 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 698c97999c457..d406b3ce6ef6e 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 7e9140faa6411..4a11fb393899f 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -1739,11 +1739,11 @@ extern "rust-intrinsic" { pub fn mul_with_overflow(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(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(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(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(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(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(x: T, y: T) -> T; diff --git a/src/libcore/iter/traits/iterator.rs b/src/libcore/iter/traits/iterator.rs index daa880e7cd53b..c8829817e190c 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(self, other: I) -> Option @@ -3170,7 +3170,7 @@ pub trait Iterator { /// assert!(![1, 3, 2, 4].iter().is_sorted()); /// assert!([0].iter().is_sorted()); /// assert!(std::iter::empty::().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::().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 09f1eab2d4b9d..4ab82add32b53 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::() }; - /// 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 65ef7ba9ac768..20818a9b750f4 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::() }; - /// 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 c85064759ea03..7ba4004d8609c 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 adee8cea442b4..946a765e18f3b 100644 --- a/src/libcore/ops/range.rs +++ b/src/libcore/ops/range.rs @@ -139,10 +139,9 @@ impl> Range { /// ``` /// #![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> RangeInclusive { /// ``` /// #![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 a540016854df3..52e224d2a026f 100644 --- a/src/libcore/ptr/const_ptr.rs +++ b/src/libcore/ptr/const_ptr.rs @@ -659,8 +659,8 @@ impl *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 01d830ca18602..9f85d781d698a 100644 --- a/src/libcore/ptr/mut_ptr.rs +++ b/src/libcore/ptr/mut_ptr.rs @@ -847,8 +847,8 @@ impl *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 2140a7be9efe8..9be52e2dfb06b 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -2588,7 +2588,7 @@ impl [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 2ece2150e6bed..924a64847a794 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 b319ee76c819f..6005b607026fb 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 2d5564abfb2c8..9fd22c8b07bdd 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 f15c05d558d85..b90c59f580737 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 0c451998be435..758a0b39d43ee 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 80a1e2828090f..4fa74f93ddcb0 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>, +) -> 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>, @@ -98,6 +116,10 @@ pub fn elaborate_predicates<'tcx>( } impl Elaborator<'tcx> { + pub fn filter_to_traits(self) -> FilterToTraits { + 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>; + +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>, +) -> 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 { + base_iterator: I, +} + +impl FilterToTraits { + fn new(base: I) -> FilterToTraits { + FilterToTraits { base_iterator: base } + } +} + +impl<'tcx, I: Iterator>> Iterator for FilterToTraits { + type Item = ty::PolyTraitRef<'tcx>; + + fn next(&mut self) -> Option> { + 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) { + 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 e952051eb9f6d..4b92a2205c211 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 e74d27bafb2d9..0000000000000 --- 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 { - (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, >::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> { - 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, >::Idx) -> DebugFormatted, -{ - /// Generate the node label - fn node_label_internal( - &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, "")?; - for hdr in &HDRS { - write!(w, "", HDR_FMT, hdr)?; - } - write!(w, "")?; - - // Data row - self.node_label_verbose_row(n, w, block, body)?; - self.node_label_final_row(n, w, block, body)?; - write!(w, "
", HDRS.len())?; - write!(w, "{:?}", block.index())?; - write!(w, "
{}
")?; - - Ok(()) - } - - /// Builds the verbose row: full MIR data, and detailed gen/kill/entry sets. - fn node_label_verbose_row( - &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, "")?; - - 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, "{:?}
", e)?; - } - write!(w, "")?; - }; - } - - write!(w, "")?; - // Entry - dump_set_for!(entry_set_for, interpret_set); - - // MIR statements - write!(w, "")?; - { - let data = &body[block]; - for (i, statement) in data.statements.iter().enumerate() { - write!( - w, - "{}
", - dot::escape_html(&format!("{:3}: {:?}", i, statement)) - )?; - } - } - write!(w, "")?; - - // Gen - dump_set_for!(gen_set_for, interpret_hybrid_set); - - // Kill - dump_set_for!(kill_set_for, interpret_hybrid_set); - - write!(w, "")?; - - Ok(()) - } - - /// Builds the summary row: terminator, gen/kill/entry bit sets. - fn node_label_final_row( - &self, - n: &Node, - w: &mut W, - block: BasicBlock, - body: &Body<'_>, - ) -> io::Result<()> { - let i = n.index(); - - let flow = self.mbcx.flow_state(); - - write!(w, "")?; - - // Entry - let set = flow.sets.entry_set_for(i); - write!(w, "{:?}", dot::escape_html(&set.to_string()))?; - - // Terminator - write!(w, "")?; - { - 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, "")?; - - // Gen/Kill - let trans = flow.sets.trans_for(i); - write!(w, "{:?}", dot::escape_html(&format!("{:?}", trans.gen_set)))?; - write!(w, "{:?}", dot::escape_html(&format!("{:?}", trans.kill_set)))?; - - write!(w, "")?; - - 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::>().into() - } - - fn edges(&self) -> dot::Edges<'_, Edge> { - let body = self.mbcx.body(); - - body.basic_blocks().indices().flat_map(|bb| outgoing(body, bb)).collect::>().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 f382ef984be24..4c25363a6575f 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 6348673dab8b5..725c41c1e2c72 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>, -} - -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>> Extend for PredicateSet<'tcx> { - fn extend>(&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>, - 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>, -) -> 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>, -) -> 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 { - 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 `>::U: 'b`. - None - } - }) - .filter(|p| visited.insert(p)), - ); - } - } - } -} - -impl Iterator for Elaborator<'tcx> { - type Item = ty::Predicate<'tcx>; - - fn size_hint(&self) -> (usize, Option) { - (self.stack.len(), None) - } - - fn next(&mut self) -> Option> { - // 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>; - -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>, -) -> 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 { - base_iterator: I, -} - -impl FilterToTraits { - fn new(base: I) -> FilterToTraits { - FilterToTraits { base_iterator: base } - } -} - -impl<'tcx, I: Iterator>> Iterator for FilterToTraits { - type Item = ty::PolyTraitRef<'tcx>; - - fn next(&mut self) -> Option> { - 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) { - 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 20425aea8d517..ac8f305ae9127 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 a1128a589a64a..798738e50a754 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 e97831b2c2855..9339b14373105 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 3afcae7ae7516..a15dc8653e83a 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) -> io::Result { - 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)(); } ptr::null_mut() } diff --git a/src/libstd/sys/hermit/stack_overflow.rs b/src/libstd/sys/hermit/stack_overflow.rs index 65a1b17acce9a..121fe42011da5 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 c3c29c93826de..c7bea168f34d8 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, core_id: isize, ) -> io::Result { - 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)(); } } } diff --git a/src/libstd/sys/sgx/stack_overflow.rs b/src/libstd/sys/sgx/stack_overflow.rs index a2d13d11849e7..b96652a8330e9 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 674d4c7113801..aab5a92a7ad2a 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) -> io::Result { - 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)(); } ptr::null_mut() } diff --git a/src/libstd/sys/vxworks/thread.rs b/src/libstd/sys/vxworks/thread.rs index e0d104b5f3ec9..4d0196e4b4de5 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) -> io::Result { - 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)(); } ptr::null_mut() } diff --git a/src/libstd/sys/wasm/stack_overflow.rs b/src/libstd/sys/wasm/stack_overflow.rs index cbf62b6e5b7e3..32555394cd5a5 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 c828243a59b11..38839ea5e90ed 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) -> io::Result { - 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)(); } 0 } diff --git a/src/libstd/sys_common/thread.rs b/src/libstd/sys_common/thread.rs index 6ab0d5cbe9c96..f3a8bef8f718f 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)() -} - 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 0000000000000..e78231a68512d --- /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 0000000000000..d2fa7e58f6a9b --- /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 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 10b151ffa7565..41a7dfc3f379f 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 0000000000000..3561f40127737 --- /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 0000000000000..c3325fd80ca0c --- /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 A for T { + type Foo = (); +} + +fn foo() -> impl std::borrow::Borrow<::Foo> { + () +} + +fn main() { + foo(); +}