diff --git a/Cargo.toml b/Cargo.toml index 42dd5d7ef432e..8d6afd2b44837 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -89,6 +89,15 @@ gimli.debug = 0 miniz_oxide.debug = 0 object.debug = 0 +# The only package that ever uses debug builds is bootstrap. +# We care a lot about bootstrap's compile times, so don't include debug info for +# dependencies, only bootstrap itself. +[profile.dev] +debug = 0 +[profile.dev.package] +# Only use debuginfo=1 to further reduce compile times. +bootstrap.debug = 1 + # We want the RLS to use the version of Cargo that we've got vendored in this # repository to ensure that the same exact version of Cargo is used by both the # RLS and the Cargo binary itself. The RLS depends on Cargo as a git repository diff --git a/RELEASES.md b/RELEASES.md index ef1377a4a32df..269740c171cfb 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -64,7 +64,6 @@ Stabilised APIs - [`VecDeque::shrink_to`] - [`HashMap::shrink_to`] - [`HashSet::shrink_to`] -- [`task::ready!`] These APIs are now usable in const contexts: @@ -128,7 +127,6 @@ and related tools. [`VecDeque::shrink_to`]: https://doc.rust-lang.org/stable/std/collections/struct.VecDeque.html#method.shrink_to [`HashMap::shrink_to`]: https://doc.rust-lang.org/stable/std/collections/hash_map/struct.HashMap.html#method.shrink_to [`HashSet::shrink_to`]: https://doc.rust-lang.org/stable/std/collections/hash_set/struct.HashSet.html#method.shrink_to -[`task::ready!`]: https://doc.rust-lang.org/stable/std/task/macro.ready.html [`std::mem::transmute`]: https://doc.rust-lang.org/stable/std/mem/fn.transmute.html [`slice::first`]: https://doc.rust-lang.org/stable/std/primitive.slice.html#method.first [`slice::split_first`]: https://doc.rust-lang.org/stable/std/primitive.slice.html#method.split_first diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 55790bd2daa9b..07eadce17738e 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1153,28 +1153,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { .convert_all(data); } - /// Convenient wrapper around `relate_tys::relate_types` -- see - /// that fn for docs. - fn relate_types( - &mut self, - a: Ty<'tcx>, - v: ty::Variance, - b: Ty<'tcx>, - locations: Locations, - category: ConstraintCategory, - ) -> Fallible<()> { - relate_tys::relate_types( - self.infcx, - self.param_env, - a, - v, - b, - locations, - category, - self.borrowck_context, - ) - } - /// Try to relate `sub <: sup` fn sub_types( &mut self, diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index b788529dc1cd4..415d1abaa8b08 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -1,5 +1,5 @@ use rustc_infer::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelatingDelegate}; -use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin}; +use rustc_infer::infer::NllRegionVariableOrigin; use rustc_middle::mir::ConstraintCategory; use rustc_middle::ty::relate::TypeRelation; use rustc_middle::ty::{self, Const, Ty}; @@ -7,48 +7,38 @@ use rustc_trait_selection::traits::query::Fallible; use crate::constraints::OutlivesConstraint; use crate::diagnostics::UniverseInfo; -use crate::type_check::{BorrowCheckContext, Locations}; - -/// Adds sufficient constraints to ensure that `a R b` where `R` depends on `v`: -/// -/// - "Covariant" `a <: b` -/// - "Invariant" `a == b` -/// - "Contravariant" `a :> b` -/// -/// N.B., the type `a` is permitted to have unresolved inference -/// variables, but not the type `b`. -#[instrument(skip(infcx, param_env, borrowck_context), level = "debug")] -pub(super) fn relate_types<'tcx>( - infcx: &InferCtxt<'_, 'tcx>, - param_env: ty::ParamEnv<'tcx>, - a: Ty<'tcx>, - v: ty::Variance, - b: Ty<'tcx>, - locations: Locations, - category: ConstraintCategory, - borrowck_context: &mut BorrowCheckContext<'_, 'tcx>, -) -> Fallible<()> { - TypeRelating::new( - infcx, - NllTypeRelatingDelegate::new( - infcx, - borrowck_context, - param_env, - locations, - category, - UniverseInfo::relate(a, b), - ), - v, - ) - .relate(a, b)?; - Ok(()) +use crate::type_check::{Locations, TypeChecker}; + +impl<'a, 'tcx> TypeChecker<'a, 'tcx> { + /// Adds sufficient constraints to ensure that `a R b` where `R` depends on `v`: + /// + /// - "Covariant" `a <: b` + /// - "Invariant" `a == b` + /// - "Contravariant" `a :> b` + /// + /// N.B., the type `a` is permitted to have unresolved inference + /// variables, but not the type `b`. + #[instrument(skip(self), level = "debug")] + pub(super) fn relate_types( + &mut self, + a: Ty<'tcx>, + v: ty::Variance, + b: Ty<'tcx>, + locations: Locations, + category: ConstraintCategory, + ) -> Fallible<()> { + TypeRelating::new( + self.infcx, + NllTypeRelatingDelegate::new(self, locations, category, UniverseInfo::relate(a, b)), + v, + ) + .relate(a, b)?; + Ok(()) + } } struct NllTypeRelatingDelegate<'me, 'bccx, 'tcx> { - infcx: &'me InferCtxt<'me, 'tcx>, - borrowck_context: &'me mut BorrowCheckContext<'bccx, 'tcx>, - - param_env: ty::ParamEnv<'tcx>, + type_checker: &'me mut TypeChecker<'bccx, 'tcx>, /// Where (and why) is this relation taking place? locations: Locations, @@ -63,25 +53,24 @@ struct NllTypeRelatingDelegate<'me, 'bccx, 'tcx> { impl NllTypeRelatingDelegate<'me, 'bccx, 'tcx> { fn new( - infcx: &'me InferCtxt<'me, 'tcx>, - borrowck_context: &'me mut BorrowCheckContext<'bccx, 'tcx>, - param_env: ty::ParamEnv<'tcx>, + type_checker: &'me mut TypeChecker<'bccx, 'tcx>, locations: Locations, category: ConstraintCategory, universe_info: UniverseInfo<'tcx>, ) -> Self { - Self { infcx, borrowck_context, param_env, locations, category, universe_info } + Self { type_checker, locations, category, universe_info } } } impl TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> { fn param_env(&self) -> ty::ParamEnv<'tcx> { - self.param_env + self.type_checker.param_env } fn create_next_universe(&mut self) -> ty::UniverseIndex { - let universe = self.infcx.create_next_universe(); - self.borrowck_context + let universe = self.type_checker.infcx.create_next_universe(); + self.type_checker + .borrowck_context .constraints .universe_causes .insert(universe, self.universe_info.clone()); @@ -90,15 +79,18 @@ impl TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> { fn next_existential_region_var(&mut self, from_forall: bool) -> ty::Region<'tcx> { let origin = NllRegionVariableOrigin::Existential { from_forall }; - self.infcx.next_nll_region_var(origin) + self.type_checker.infcx.next_nll_region_var(origin) } fn next_placeholder_region(&mut self, placeholder: ty::PlaceholderRegion) -> ty::Region<'tcx> { - self.borrowck_context.constraints.placeholder_region(self.infcx, placeholder) + self.type_checker + .borrowck_context + .constraints + .placeholder_region(self.type_checker.infcx, placeholder) } fn generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> { - self.infcx.next_nll_region_var_in_universe( + self.type_checker.infcx.next_nll_region_var_in_universe( NllRegionVariableOrigin::Existential { from_forall: false }, universe, ) @@ -110,15 +102,17 @@ impl TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> { sub: ty::Region<'tcx>, info: ty::VarianceDiagInfo<'tcx>, ) { - let sub = self.borrowck_context.universal_regions.to_region_vid(sub); - let sup = self.borrowck_context.universal_regions.to_region_vid(sup); - self.borrowck_context.constraints.outlives_constraints.push(OutlivesConstraint { - sup, - sub, - locations: self.locations, - category: self.category, - variance_info: info, - }); + let sub = self.type_checker.borrowck_context.universal_regions.to_region_vid(sub); + let sup = self.type_checker.borrowck_context.universal_regions.to_region_vid(sup); + self.type_checker.borrowck_context.constraints.outlives_constraints.push( + OutlivesConstraint { + sup, + sub, + locations: self.locations, + category: self.category, + variance_info: info, + }, + ); } // We don't have to worry about the equality of consts during borrow checking diff --git a/compiler/rustc_index/src/vec.rs b/compiler/rustc_index/src/vec.rs index e9efa2f255d14..69578e85f2781 100644 --- a/compiler/rustc_index/src/vec.rs +++ b/compiler/rustc_index/src/vec.rs @@ -738,6 +738,12 @@ impl IndexVec> { self.ensure_contains_elem(index, || None); self[index].get_or_insert_with(value) } + + #[inline] + pub fn remove(&mut self, index: I) -> Option { + self.ensure_contains_elem(index, || None); + self[index].take() + } } impl IndexVec { diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs index 4a82252a32b13..a0ceb567f25a6 100644 --- a/compiler/rustc_passes/src/check_const.rs +++ b/compiler/rustc_passes/src/check_const.rs @@ -8,7 +8,6 @@ //! through, but errors for structured control flow in a `const` should be emitted here. use rustc_attr as attr; -use rustc_data_structures::stable_set::FxHashSet; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; @@ -83,30 +82,39 @@ impl<'tcx> hir::itemlikevisit::ItemLikeVisitor<'tcx> for CheckConstTraitVisitor< let _: Option<_> = try { if let hir::ItemKind::Impl(ref imp) = item.kind { if let hir::Constness::Const = imp.constness { - let did = imp.of_trait.as_ref()?.trait_def_id()?; - let mut to_implement = FxHashSet::default(); - - for did in self.tcx.associated_item_def_ids(did) { + let trait_def_id = imp.of_trait.as_ref()?.trait_def_id()?; + let ancestors = self + .tcx + .trait_def(trait_def_id) + .ancestors(self.tcx, item.def_id.to_def_id()) + .ok()?; + let mut to_implement = Vec::new(); + + for trait_item in self.tcx.associated_items(trait_def_id).in_definition_order() + { if let ty::AssocItem { kind: ty::AssocKind::Fn, ident, defaultness, .. - } = self.tcx.associated_item(*did) + } = trait_item { // we can ignore functions that do not have default bodies: // if those are unimplemented it will be catched by typeck. - if defaultness.has_value() - && !self.tcx.has_attr(*did, sym::default_method_body_is_const) + if !defaultness.has_value() + || self + .tcx + .has_attr(trait_item.def_id, sym::default_method_body_is_const) { - to_implement.insert(ident); + continue; } - } - } - for it in imp - .items - .iter() - .filter(|it| matches!(it.kind, hir::AssocItemKind::Fn { .. })) - { - to_implement.remove(&it.ident); + let is_implemented = ancestors + .leaf_def(self.tcx, trait_item.ident, trait_item.kind) + .map(|node_item| !node_item.defining_node.is_from_trait()) + .unwrap_or(false); + + if !is_implemented { + to_implement.push(ident.to_string()); + } + } } // all nonconst trait functions (not marked with #[default_method_body_is_const]) @@ -118,7 +126,7 @@ impl<'tcx> hir::itemlikevisit::ItemLikeVisitor<'tcx> for CheckConstTraitVisitor< item.span, "const trait implementations may not use non-const default functions", ) - .note(&format!("`{}` not implemented", to_implement.into_iter().map(|id| id.to_string()).collect::>().join("`, `"))) + .note(&format!("`{}` not implemented", to_implement.join("`, `"))) .emit(); } } diff --git a/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs index b5eb74f708d5c..0373035a09ad8 100644 --- a/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs +++ b/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs @@ -3,6 +3,7 @@ use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::itemlikevisit::ItemLikeVisitor; +use rustc_index::vec::IndexVec; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::Symbol; use rustc_trait_selection::traits::{self, SkipLeakCheck}; @@ -158,14 +159,18 @@ impl ItemLikeVisitor<'v> for InherentOverlapChecker<'tcx> { // This is advantageous to running the algorithm over the // entire graph when there are many connected regions. + rustc_index::newtype_index! { + pub struct RegionId { + ENCODABLE = custom + } + } struct ConnectedRegion { idents: SmallVec<[Symbol; 8]>, impl_blocks: FxHashSet, } - // Highest connected region id - let mut highest_region_id = 0; + let mut connected_regions: IndexVec = Default::default(); + // Reverse map from the Symbol to the connected region id. let mut connected_region_ids = FxHashMap::default(); - let mut connected_regions = FxHashMap::default(); for (i, &(&_impl_def_id, impl_items)) in impls_items.iter().enumerate() { if impl_items.len() == 0 { @@ -173,7 +178,7 @@ impl ItemLikeVisitor<'v> for InherentOverlapChecker<'tcx> { } // First obtain a list of existing connected region ids let mut idents_to_add = SmallVec::<[Symbol; 8]>::new(); - let ids = impl_items + let mut ids = impl_items .in_definition_order() .filter_map(|item| { let entry = connected_region_ids.entry(item.ident.name); @@ -184,62 +189,64 @@ impl ItemLikeVisitor<'v> for InherentOverlapChecker<'tcx> { None } }) - .collect::>(); - match ids.len() { - 0 | 1 => { - let id_to_set = if ids.is_empty() { - // Create a new connected region - let region = ConnectedRegion { + .collect::>(); + // Sort the id list so that the algorithm is deterministic + ids.sort_unstable(); + let ids = ids; + match &ids[..] { + // Create a new connected region + [] => { + let id_to_set = connected_regions.next_index(); + // Update the connected region ids + for ident in &idents_to_add { + connected_region_ids.insert(*ident, id_to_set); + } + connected_regions.insert( + id_to_set, + ConnectedRegion { idents: idents_to_add, impl_blocks: std::iter::once(i).collect(), - }; - connected_regions.insert(highest_region_id, region); - (highest_region_id, highest_region_id += 1).0 - } else { - // Take the only id inside the list - let id_to_set = *ids.iter().next().unwrap(); - let region = connected_regions.get_mut(&id_to_set).unwrap(); - region.impl_blocks.insert(i); - region.idents.extend_from_slice(&idents_to_add); - id_to_set - }; - let (_id, region) = connected_regions.iter().next().unwrap(); + }, + ); + } + // Take the only id inside the list + &[id_to_set] => { + let region = connected_regions[id_to_set].as_mut().unwrap(); + region.impl_blocks.insert(i); + region.idents.extend_from_slice(&idents_to_add); // Update the connected region ids - for ident in region.idents.iter() { + for ident in &idents_to_add { connected_region_ids.insert(*ident, id_to_set); } } - _ => { - // We have multiple connected regions to merge. - // In the worst case this might add impl blocks - // one by one and can thus be O(n^2) in the size - // of the resulting final connected region, but - // this is no issue as the final step to check - // for overlaps runs in O(n^2) as well. - - // Take the smallest id from the list - let id_to_set = *ids.iter().min().unwrap(); - - // Sort the id list so that the algorithm is deterministic - let mut ids = ids.into_iter().collect::>(); - ids.sort_unstable(); - - let mut region = connected_regions.remove(&id_to_set).unwrap(); - region.idents.extend_from_slice(&idents_to_add); + // We have multiple connected regions to merge. + // In the worst case this might add impl blocks + // one by one and can thus be O(n^2) in the size + // of the resulting final connected region, but + // this is no issue as the final step to check + // for overlaps runs in O(n^2) as well. + &[id_to_set, ..] => { + let mut region = connected_regions.remove(id_to_set).unwrap(); region.impl_blocks.insert(i); + region.idents.extend_from_slice(&idents_to_add); + // Update the connected region ids + for ident in &idents_to_add { + connected_region_ids.insert(*ident, id_to_set); + } + // Remove other regions from ids. for &id in ids.iter() { if id == id_to_set { continue; } - let r = connected_regions.remove(&id).unwrap(); - // Update the connected region ids + let r = connected_regions.remove(id).unwrap(); for ident in r.idents.iter() { connected_region_ids.insert(*ident, id_to_set); } region.idents.extend_from_slice(&r.idents); region.impl_blocks.extend(r.impl_blocks); } + connected_regions.insert(id_to_set, region); } } @@ -254,16 +261,22 @@ impl ItemLikeVisitor<'v> for InherentOverlapChecker<'tcx> { let avg = impls.len() / connected_regions.len(); let s = connected_regions .iter() - .map(|r| r.1.impl_blocks.len() as isize - avg as isize) + .flatten() + .map(|r| r.impl_blocks.len() as isize - avg as isize) .map(|v| v.abs() as usize) .sum::(); s / connected_regions.len() }, - connected_regions.iter().map(|r| r.1.impl_blocks.len()).max().unwrap() + connected_regions + .iter() + .flatten() + .map(|r| r.impl_blocks.len()) + .max() + .unwrap() ); // List of connected regions is built. Now, run the overlap check // for each pair of impl blocks in the same connected region. - for (_id, region) in connected_regions.into_iter() { + for region in connected_regions.into_iter().flatten() { let mut impl_blocks = region.impl_blocks.into_iter().collect::>(); impl_blocks.sort_unstable(); diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs index 65eedd2daafa8..971776c882a15 100644 --- a/compiler/rustc_typeck/src/lib.rs +++ b/compiler/rustc_typeck/src/lib.rs @@ -63,6 +63,7 @@ This API is completely unstable and subject to change. #![feature(in_band_lifetimes)] #![feature(is_sorted)] #![feature(iter_zip)] +#![feature(min_specialization)] #![feature(nll)] #![feature(try_blocks)] #![feature(never_type)] diff --git a/library/alloc/src/collections/binary_heap.rs b/library/alloc/src/collections/binary_heap.rs index cfb1cd09c3975..9bded6c0f1cf2 100644 --- a/library/alloc/src/collections/binary_heap.rs +++ b/library/alloc/src/collections/binary_heap.rs @@ -1009,6 +1009,7 @@ impl BinaryHeap { /// /// io::sink().write(heap.as_slice()).unwrap(); /// ``` + #[must_use] #[unstable(feature = "binary_heap_as_slice", issue = "83659")] pub fn as_slice(&self) -> &[T] { self.data.as_slice() diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs index 6dcba318c3598..ea010c1f89d24 100644 --- a/library/alloc/src/collections/linked_list.rs +++ b/library/alloc/src/collections/linked_list.rs @@ -1385,6 +1385,7 @@ impl<'a, T> CursorMut<'a, T> { /// The lifetime of the returned `Cursor` is bound to that of the /// `CursorMut`, which means it cannot outlive the `CursorMut` and that the /// `CursorMut` is frozen for the lifetime of the `Cursor`. + #[must_use] #[unstable(feature = "linked_list_cursors", issue = "58533")] pub fn as_cursor(&self) -> Cursor<'_, T> { Cursor { list: self.list, current: self.current, index: self.index } diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 2f4a131136e92..eba75d4dd692c 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -2093,6 +2093,7 @@ impl Weak { /// ``` /// /// [`null`]: ptr::null + #[must_use] #[stable(feature = "rc_as_ptr", since = "1.45.0")] pub fn as_ptr(&self) -> *const T { let ptr: *mut RcBox = NonNull::as_ptr(self.ptr); diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index f11fa92766f1f..f479bf231b376 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -803,6 +803,7 @@ impl String { /// assert_eq!("foo", s.as_str()); /// ``` #[inline] + #[must_use] #[stable(feature = "string_as_str", since = "1.7.0")] pub fn as_str(&self) -> &str { self @@ -823,6 +824,7 @@ impl String { /// assert_eq!("FOOBAR", s_mut_str); /// ``` #[inline] + #[must_use] #[stable(feature = "string_as_str", since = "1.7.0")] pub fn as_mut_str(&mut self) -> &mut str { self @@ -1163,6 +1165,7 @@ impl String { /// assert_eq!(&[104, 101, 108, 108, 111], s.as_bytes()); /// ``` #[inline] + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn as_bytes(&self) -> &[u8] { &self.vec @@ -1766,6 +1769,7 @@ impl FromUtf8Error { /// /// assert_eq!(&[0, 159], value.unwrap_err().as_bytes()); /// ``` + #[must_use] #[stable(feature = "from_utf8_error_as_bytes", since = "1.26.0")] pub fn as_bytes(&self) -> &[u8] { &self.bytes[..] @@ -2782,6 +2786,7 @@ impl<'a> Drain<'a> { /// let _ = drain.next().unwrap(); /// assert_eq!(drain.as_str(), "bc"); /// ``` + #[must_use] #[stable(feature = "string_drain_as_str", since = "1.55.0")] pub fn as_str(&self) -> &str { self.iter.as_str() diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 1d4216d7d571a..730e65db24fa2 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -827,6 +827,7 @@ impl Arc { /// assert_eq!(x_ptr, Arc::as_ptr(&y)); /// assert_eq!(unsafe { &*x_ptr }, "hello"); /// ``` + #[must_use] #[stable(feature = "rc_as_ptr", since = "1.45.0")] pub fn as_ptr(this: &Self) -> *const T { let ptr: *mut ArcInner = NonNull::as_ptr(this.ptr); @@ -1724,6 +1725,7 @@ impl Weak { /// ``` /// /// [`null`]: core::ptr::null "ptr::null" + #[must_use] #[stable(feature = "weak_into_raw", since = "1.45.0")] pub fn as_ptr(&self) -> *const T { let ptr: *mut ArcInner = NonNull::as_ptr(self.ptr); diff --git a/library/alloc/src/vec/drain.rs b/library/alloc/src/vec/drain.rs index fb32d144f872c..e643940d017ba 100644 --- a/library/alloc/src/vec/drain.rs +++ b/library/alloc/src/vec/drain.rs @@ -52,6 +52,7 @@ impl<'a, T, A: Allocator> Drain<'a, T, A> { /// let _ = drain.next().unwrap(); /// assert_eq!(drain.as_slice(), &['b', 'c']); /// ``` + #[must_use] #[stable(feature = "vec_drain_as_slice", since = "1.46.0")] pub fn as_slice(&self) -> &[T] { self.iter.as_slice() diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs index abeeef1a17ee0..83a73d9cbe506 100644 --- a/library/core/src/convert/mod.rs +++ b/library/core/src/convert/mod.rs @@ -273,6 +273,7 @@ pub trait AsMut { #[stable(feature = "rust1", since = "1.0.0")] pub trait Into: Sized { /// Performs the conversion. + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] fn into(self) -> T; } @@ -367,6 +368,7 @@ pub trait Into: Sized { pub trait From: Sized { /// Performs the conversion. #[lang = "from"] + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] fn from(_: T) -> Self; } diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index d10563a40976d..b8ad7720e0c55 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -491,6 +491,7 @@ impl<'a> Arguments<'a> { /// ``` #[stable(feature = "fmt_as_str", since = "1.52.0")] #[rustc_const_unstable(feature = "const_arguments_as_str", issue = "none")] + #[must_use] #[inline] pub const fn as_str(&self) -> Option<&'static str> { match (self.pieces, self.args) { diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index b9772eaa67813..624e87955022f 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -291,6 +291,7 @@ impl MaybeUninit { /// [`assume_init`]: MaybeUninit::assume_init #[stable(feature = "maybe_uninit", since = "1.36.0")] #[rustc_const_stable(feature = "const_maybe_uninit", since = "1.36.0")] + #[must_use = "use `forget` to avoid running Drop code"] #[inline(always)] pub const fn new(val: T) -> MaybeUninit { MaybeUninit { value: ManuallyDrop::new(val) } diff --git a/library/core/src/option.rs b/library/core/src/option.rs index df8af22a317bc..401267f5613ee 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -657,6 +657,7 @@ impl Option { /// /// [&]: reference "shared reference" #[inline] + #[must_use] #[stable(feature = "pin", since = "1.33.0")] pub fn as_pin_ref(self: Pin<&Self>) -> Option> { // SAFETY: `x` is guaranteed to be pinned because it comes from `self` @@ -668,6 +669,7 @@ impl Option { /// /// [&mut]: reference "mutable reference" #[inline] + #[must_use] #[stable(feature = "pin", since = "1.33.0")] pub fn as_pin_mut(self: Pin<&mut Self>) -> Option> { // SAFETY: `get_unchecked_mut` is never used to move the `Option` inside `self`. diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 87c8674af0dc5..af9daf8297401 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -119,6 +119,7 @@ impl NonNull { /// /// [the module documentation]: crate::ptr#safety #[inline] + #[must_use] #[unstable(feature = "ptr_as_uninit", issue = "75402")] pub unsafe fn as_uninit_ref<'a>(&self) -> &'a MaybeUninit { // SAFETY: the caller must guarantee that `self` meets all the @@ -151,6 +152,7 @@ impl NonNull { /// /// [the module documentation]: crate::ptr#safety #[inline] + #[must_use] #[unstable(feature = "ptr_as_uninit", issue = "75402")] pub unsafe fn as_uninit_mut<'a>(&mut self) -> &'a mut MaybeUninit { // SAFETY: the caller must guarantee that `self` meets all the @@ -264,6 +266,7 @@ impl NonNull { /// ``` #[stable(feature = "nonnull", since = "1.25.0")] #[rustc_const_stable(feature = "const_nonnull_as_ptr", since = "1.32.0")] + #[must_use] #[inline] pub const fn as_ptr(self) -> *mut T { self.pointer as *mut T @@ -310,6 +313,7 @@ impl NonNull { /// /// [the module documentation]: crate::ptr#safety #[stable(feature = "nonnull", since = "1.25.0")] + #[must_use] #[inline] pub unsafe fn as_ref<'a>(&self) -> &'a T { // SAFETY: the caller must guarantee that `self` meets all the @@ -359,6 +363,7 @@ impl NonNull { /// /// [the module documentation]: crate::ptr#safety #[stable(feature = "nonnull", since = "1.25.0")] + #[must_use] #[inline] pub unsafe fn as_mut<'a>(&mut self) -> &'a mut T { // SAFETY: the caller must guarantee that `self` meets all the @@ -455,6 +460,7 @@ impl NonNull<[T]> { /// assert_eq!(slice.as_non_null_ptr(), NonNull::new(1 as *mut i8).unwrap()); /// ``` #[inline] + #[must_use] #[unstable(feature = "slice_ptr_get", issue = "74265")] #[rustc_const_unstable(feature = "slice_ptr_get", issue = "74265")] pub const fn as_non_null_ptr(self) -> NonNull { @@ -474,6 +480,7 @@ impl NonNull<[T]> { /// assert_eq!(slice.as_mut_ptr(), 1 as *mut i8); /// ``` #[inline] + #[must_use] #[unstable(feature = "slice_ptr_get", issue = "74265")] #[rustc_const_unstable(feature = "slice_ptr_get", issue = "74265")] pub const fn as_mut_ptr(self) -> *mut T { @@ -518,6 +525,7 @@ impl NonNull<[T]> { /// /// [valid]: crate::ptr#safety #[inline] + #[must_use] #[unstable(feature = "ptr_as_uninit", issue = "75402")] pub unsafe fn as_uninit_slice<'a>(&self) -> &'a [MaybeUninit] { // SAFETY: the caller must uphold the safety contract for `as_uninit_slice`. @@ -579,6 +587,7 @@ impl NonNull<[T]> { /// # Ok::<_, std::alloc::AllocError>(()) /// ``` #[inline] + #[must_use] #[unstable(feature = "ptr_as_uninit", issue = "75402")] pub unsafe fn as_uninit_slice_mut<'a>(&self) -> &'a mut [MaybeUninit] { // SAFETY: the caller must uphold the safety contract for `as_uninit_slice_mut`. diff --git a/library/core/src/ptr/unique.rs b/library/core/src/ptr/unique.rs index b3deddca18efe..5baceefb504a5 100644 --- a/library/core/src/ptr/unique.rs +++ b/library/core/src/ptr/unique.rs @@ -112,6 +112,7 @@ impl Unique { /// The resulting lifetime is bound to self so this behaves "as if" /// it were actually an instance of T that is getting borrowed. If a longer /// (unbound) lifetime is needed, use `&*my_ptr.as_ptr()`. + #[must_use] #[inline] pub unsafe fn as_ref(&self) -> &T { // SAFETY: the caller must guarantee that `self` meets all the @@ -124,6 +125,7 @@ impl Unique { /// The resulting lifetime is bound to self so this behaves "as if" /// it were actually an instance of T that is getting borrowed. If a longer /// (unbound) lifetime is needed, use `&mut *my_ptr.as_ptr()`. + #[must_use] #[inline] pub unsafe fn as_mut(&mut self) -> &mut T { // SAFETY: the caller must guarantee that `self` meets all the diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index 70e59cda63f26..dbf97851b03e4 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -124,6 +124,7 @@ impl<'a, T> Iter<'a, T> { /// // Now `as_slice` returns "[2, 3]": /// println!("{:?}", iter.as_slice()); /// ``` + #[must_use] #[stable(feature = "iter_to_slice", since = "1.4.0")] pub fn as_slice(&self) -> &'a [T] { self.make_slice() @@ -298,6 +299,7 @@ impl<'a, T> IterMut<'a, T> { /// // Now `as_slice` returns "[2, 3]": /// assert_eq!(iter.as_slice(), &[2, 3]); /// ``` + #[must_use] #[stable(feature = "slice_iter_mut_as_slice", since = "1.53.0")] pub fn as_slice(&self) -> &[T] { self.make_slice() diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs index 8db9edc61472f..94cb81e9d41a1 100644 --- a/library/core/src/str/iter.rs +++ b/library/core/src/str/iter.rs @@ -109,6 +109,7 @@ impl<'a> Chars<'a> { /// assert_eq!(chars.as_str(), ""); /// ``` #[stable(feature = "iter_to_slice", since = "1.4.0")] + #[must_use] #[inline] pub fn as_str(&self) -> &'a str { // SAFETY: `Chars` is only made from a str, which guarantees the iter is valid UTF-8. @@ -185,6 +186,7 @@ impl<'a> CharIndices<'a> { /// This has the same lifetime as the original slice, and so the /// iterator can continue to be used while this exists. #[stable(feature = "iter_to_slice", since = "1.4.0")] + #[must_use] #[inline] pub fn as_str(&self) -> &'a str { self.iter.as_str() @@ -1247,6 +1249,7 @@ impl<'a> SplitWhitespace<'a> { /// assert_eq!(split.as_str(), ""); /// ``` #[inline] + #[must_use] #[unstable(feature = "str_split_whitespace_as_str", issue = "77998")] pub fn as_str(&self) -> &'a str { self.inner.iter.as_str() @@ -1302,6 +1305,7 @@ impl<'a> SplitAsciiWhitespace<'a> { /// assert_eq!(split.as_str(), ""); /// ``` #[inline] + #[must_use] #[unstable(feature = "str_split_whitespace_as_str", issue = "77998")] pub fn as_str(&self) -> &'a str { if self.inner.iter.iter.finished { diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 14ce94c178c5b..607a0179ff4b9 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -230,6 +230,7 @@ impl str { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "str_as_bytes", since = "1.39.0")] + #[must_use] #[inline(always)] #[allow(unused_attributes)] pub const fn as_bytes(&self) -> &[u8] { @@ -274,6 +275,7 @@ impl str { /// assert_eq!("🍔∈🌏", s); /// ``` #[stable(feature = "str_mut_extras", since = "1.20.0")] + #[must_use] #[inline(always)] pub unsafe fn as_bytes_mut(&mut self) -> &mut [u8] { // SAFETY: the cast from `&str` to `&[u8]` is safe since `str` @@ -304,6 +306,7 @@ impl str { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "rustc_str_as_ptr", since = "1.32.0")] + #[must_use] #[inline] pub const fn as_ptr(&self) -> *const u8 { self as *const str as *const u8 @@ -318,6 +321,7 @@ impl str { /// It is your responsibility to make sure that the string slice only gets /// modified in a way that it remains valid UTF-8. #[stable(feature = "str_as_mut_ptr", since = "1.36.0")] + #[must_use] #[inline] pub fn as_mut_ptr(&mut self) -> *mut u8 { self as *mut str as *mut u8 diff --git a/library/core/src/task/mod.rs b/library/core/src/task/mod.rs index 5f077f77bbc9f..71a67a2793a46 100644 --- a/library/core/src/task/mod.rs +++ b/library/core/src/task/mod.rs @@ -11,5 +11,7 @@ mod wake; pub use self::wake::{Context, RawWaker, RawWakerVTable, Waker}; mod ready; -#[stable(feature = "ready_macro", since = "1.56.0")] +#[unstable(feature = "ready_macro", issue = "70922")] pub use ready::ready; +#[unstable(feature = "poll_ready", issue = "89780")] +pub use ready::Ready; diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs index 57416aeb7018f..3e0b3e89758a6 100644 --- a/library/core/src/task/poll.rs +++ b/library/core/src/task/poll.rs @@ -3,6 +3,7 @@ use crate::convert; use crate::ops::{self, ControlFlow}; use crate::result::Result; +use crate::task::Ready; /// Indicates whether a value is available or if the current task has been /// scheduled to receive a wakeup instead. @@ -92,6 +93,38 @@ impl Poll { pub const fn is_pending(&self) -> bool { !self.is_ready() } + + /// Extracts the successful type of a [`Poll`]. + /// + /// When combined with the `?` operator, this function will + /// propogate any [`Poll::Pending`] values to the caller, and + /// extract the `T` from [`Poll::Ready`]. + /// + /// # Examples + /// + /// ```rust + /// #![feature(poll_ready)] + /// + /// use std::task::{Context, Poll}; + /// use std::future::{self, Future}; + /// use std::pin::Pin; + /// + /// pub fn do_poll(cx: &mut Context<'_>) -> Poll<()> { + /// let mut fut = future::ready(42); + /// let fut = Pin::new(&mut fut); + /// + /// let num = fut.poll(cx).ready()?; + /// # drop(num); + /// // ... use num + /// + /// Poll::Ready(()) + /// } + /// ``` + #[inline] + #[unstable(feature = "poll_ready", issue = "89780")] + pub fn ready(self) -> Ready { + Ready(self) + } } impl Poll> { diff --git a/library/core/src/task/ready.rs b/library/core/src/task/ready.rs index 2834ca5fe2224..174ca67546033 100644 --- a/library/core/src/task/ready.rs +++ b/library/core/src/task/ready.rs @@ -1,3 +1,8 @@ +use core::convert; +use core::fmt; +use core::ops::{ControlFlow, FromResidual, Try}; +use core::task::Poll; + /// Extracts the successful type of a [`Poll`]. /// /// This macro bakes in propagation of [`Pending`] signals by returning early. @@ -8,6 +13,8 @@ /// # Examples /// /// ``` +/// #![feature(ready_macro)] +/// /// use std::task::{ready, Context, Poll}; /// use std::future::{self, Future}; /// use std::pin::Pin; @@ -27,6 +34,7 @@ /// The `ready!` call expands to: /// /// ``` +/// # #![feature(ready_macro)] /// # use std::task::{Context, Poll}; /// # use std::future::{self, Future}; /// # use std::pin::Pin; @@ -45,7 +53,7 @@ /// # Poll::Ready(()) /// # } /// ``` -#[stable(feature = "ready_macro", since = "1.56.0")] +#[unstable(feature = "ready_macro", issue = "70922")] #[rustc_macro_transparency = "semitransparent"] pub macro ready($e:expr) { match $e { @@ -55,3 +63,55 @@ pub macro ready($e:expr) { } } } + +/// Extracts the successful type of a [`Poll`]. +/// +/// See [`Poll::ready`] for details. +#[unstable(feature = "poll_ready", issue = "89780")] +pub struct Ready(pub(crate) Poll); + +#[unstable(feature = "poll_ready", issue = "89780")] +impl Try for Ready { + type Output = T; + type Residual = Ready; + + #[inline] + fn from_output(output: Self::Output) -> Self { + Ready(Poll::Ready(output)) + } + + #[inline] + fn branch(self) -> ControlFlow { + match self.0 { + Poll::Ready(v) => ControlFlow::Continue(v), + Poll::Pending => ControlFlow::Break(Ready(Poll::Pending)), + } + } +} + +#[unstable(feature = "poll_ready", issue = "89780")] +impl FromResidual for Ready { + #[inline] + fn from_residual(residual: Ready) -> Self { + match residual.0 { + Poll::Pending => Ready(Poll::Pending), + } + } +} + +#[unstable(feature = "poll_ready", issue = "89780")] +impl FromResidual> for Poll { + #[inline] + fn from_residual(residual: Ready) -> Self { + match residual.0 { + Poll::Pending => Poll::Pending, + } + } +} + +#[unstable(feature = "poll_ready", issue = "89780")] +impl fmt::Debug for Ready { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("Ready").finish() + } +} diff --git a/library/core/src/time.rs b/library/core/src/time.rs index 40c5338d13cfd..5a74f39e8bc8b 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -334,6 +334,7 @@ impl Duration { /// [`subsec_nanos`]: Duration::subsec_nanos #[stable(feature = "duration", since = "1.3.0")] #[rustc_const_stable(feature = "duration", since = "1.32.0")] + #[must_use] #[inline] pub const fn as_secs(&self) -> u64 { self.secs @@ -417,6 +418,7 @@ impl Duration { /// ``` #[stable(feature = "duration_as_u128", since = "1.33.0")] #[rustc_const_stable(feature = "duration_as_u128", since = "1.33.0")] + #[must_use] #[inline] pub const fn as_millis(&self) -> u128 { self.secs as u128 * MILLIS_PER_SEC as u128 + (self.nanos / NANOS_PER_MILLI) as u128 @@ -434,6 +436,7 @@ impl Duration { /// ``` #[stable(feature = "duration_as_u128", since = "1.33.0")] #[rustc_const_stable(feature = "duration_as_u128", since = "1.33.0")] + #[must_use] #[inline] pub const fn as_micros(&self) -> u128 { self.secs as u128 * MICROS_PER_SEC as u128 + (self.nanos / NANOS_PER_MICRO) as u128 @@ -451,6 +454,7 @@ impl Duration { /// ``` #[stable(feature = "duration_as_u128", since = "1.33.0")] #[rustc_const_stable(feature = "duration_as_u128", since = "1.33.0")] + #[must_use] #[inline] pub const fn as_nanos(&self) -> u128 { self.secs as u128 * NANOS_PER_SEC as u128 + self.nanos as u128 @@ -674,6 +678,7 @@ impl Duration { /// assert_eq!(dur.as_secs_f64(), 2.7); /// ``` #[stable(feature = "duration_float", since = "1.38.0")] + #[must_use] #[inline] #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] pub const fn as_secs_f64(&self) -> f64 { @@ -692,6 +697,7 @@ impl Duration { /// assert_eq!(dur.as_secs_f32(), 2.7); /// ``` #[stable(feature = "duration_float", since = "1.38.0")] + #[must_use] #[inline] #[rustc_const_unstable(feature = "duration_consts_2", issue = "72440")] pub const fn as_secs_f32(&self) -> f32 { diff --git a/library/std/src/ffi/c_str.rs b/library/std/src/ffi/c_str.rs index 8b51c4450c2aa..78eb91e41936b 100644 --- a/library/std/src/ffi/c_str.rs +++ b/library/std/src/ffi/c_str.rs @@ -297,6 +297,7 @@ impl FromVecWithNulError { /// /// assert_eq!(&bytes[..], value.unwrap_err().as_bytes()); /// ``` + #[must_use] pub fn as_bytes(&self) -> &[u8] { &self.bytes[..] } @@ -618,6 +619,7 @@ impl CString { /// assert_eq!(bytes, &[b'f', b'o', b'o']); /// ``` #[inline] + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn as_bytes(&self) -> &[u8] { // SAFETY: CString has a length at least 1 @@ -637,6 +639,7 @@ impl CString { /// assert_eq!(bytes, &[b'f', b'o', b'o', b'\0']); /// ``` #[inline] + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn as_bytes_with_nul(&self) -> &[u8] { &self.inner @@ -655,6 +658,7 @@ impl CString { /// CStr::from_bytes_with_nul(b"foo\0").expect("CStr::from_bytes_with_nul failed")); /// ``` #[inline] + #[must_use] #[stable(feature = "as_c_str", since = "1.20.0")] pub fn as_c_str(&self) -> &CStr { &*self @@ -1313,6 +1317,7 @@ impl CStr { /// This way, the lifetime of the [`CString`] in `hello` encompasses /// the lifetime of `ptr` and the `unsafe` block. #[inline] + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_str_as_ptr", since = "1.32.0")] pub const fn as_ptr(&self) -> *const c_char { diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index de745f2164962..3b0e88331449e 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -137,6 +137,7 @@ impl OsString { /// assert_eq!(os_string.as_os_str(), os_str); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] #[inline] pub fn as_os_str(&self) -> &OsStr { self diff --git a/library/std/src/os/unix/net/addr.rs b/library/std/src/os/unix/net/addr.rs index 62bfde8bfd436..d741096893a69 100644 --- a/library/std/src/os/unix/net/addr.rs +++ b/library/std/src/os/unix/net/addr.rs @@ -192,6 +192,7 @@ impl SocketAddr { /// } /// ``` #[stable(feature = "unix_socket", since = "1.10.0")] + #[must_use] pub fn as_pathname(&self) -> Option<&Path> { if let AddressKind::Pathname(path) = self.address() { Some(path) } else { None } } diff --git a/library/std/src/path.rs b/library/std/src/path.rs index a8a79fb9c8fbb..d9f18db2fa7ff 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -427,6 +427,7 @@ impl<'a> PrefixComponent<'a> { /// Returns the raw [`OsStr`] slice for this prefix. #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] #[inline] pub fn as_os_str(&self) -> &'a OsStr { self.raw @@ -676,6 +677,7 @@ impl<'a> Components<'a> { /// /// assert_eq!(Path::new("foo/bar.txt"), components.as_path()); /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn as_path(&self) -> &'a Path { let mut comps = self.clone(); @@ -821,6 +823,7 @@ impl<'a> Iter<'a> { /// assert_eq!(Path::new("foo/bar.txt"), iter.as_path()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] #[inline] pub fn as_path(&self) -> &'a Path { self.inner.as_path() @@ -1188,6 +1191,7 @@ impl PathBuf { /// assert_eq!(Path::new("/test"), p.as_path()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] #[inline] pub fn as_path(&self) -> &Path { self @@ -1923,6 +1927,7 @@ impl Path { /// assert_eq!(os_str, std::ffi::OsStr::new("foo.txt")); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] #[inline] pub fn as_os_str(&self) -> &OsStr { &self.inner diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 7d404aff30e07..82847d83ad225 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -1031,6 +1031,7 @@ impl ThreadId { /// value is entirely opaque -- only equality testing is stable. Note that /// it is not guaranteed which values new threads will return, and this may /// change across Rust versions. + #[must_use] #[unstable(feature = "thread_id_value", issue = "67939")] pub fn as_u64(&self) -> NonZeroU64 { self.0 diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 817850b1ec7eb..1859130a7af5a 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -933,10 +933,9 @@ def build_bootstrap(self): env["LIBRARY_PATH"] = os.path.join(self.bin_root(True), "lib") + \ (os.pathsep + env["LIBRARY_PATH"]) \ if "LIBRARY_PATH" in env else "" + # preserve existing RUSTFLAGS env.setdefault("RUSTFLAGS", "") - env["RUSTFLAGS"] += " -Cdebuginfo=2" - build_section = "target.{}".format(self.build) target_features = [] if self.get_toml("crt-static", build_section) == "true": diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 1f2109879d121..7df7a36f540dd 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -1342,12 +1342,6 @@ impl<'a> Builder<'a> { rustdocflags.arg("-Dwarnings"); } - // FIXME(#58633) hide "unused attribute" errors in incremental - // builds of the standard library, as the underlying checks are - // not yet properly integrated with incremental recompilation. - if mode == Mode::Std && compiler.stage == 0 && self.config.incremental { - lint_flags.push("-Aunused-attributes"); - } // This does not use RUSTFLAGS due to caching issues with Cargo. // Clippy is treated as an "in tree" tool, but shares the same // cache as other "submodule" tools. With these options set in diff --git a/src/test/debuginfo/function-names.rs b/src/test/debuginfo/function-names.rs index dec25bb4c203c..61d5fc93cd2ad 100644 --- a/src/test/debuginfo/function-names.rs +++ b/src/test/debuginfo/function-names.rs @@ -9,36 +9,37 @@ // gdb-command:info functions -q function_names::main // gdb-check:[...]static fn function_names::main(); // gdb-command:info functions -q function_names::generic_func<* -// gdb-check:[...]static fn function_names::generic_func(i32) -> i32; +// gdb-check:[...]static fn function_names::generic_func(i32) -> i32; // Implementations // gdb-command:info functions -q function_names::.*::impl_function.* -// gdb-check:[...]static fn function_names::GenericStruct::impl_function(); +// gdb-check:[...]static fn function_names::GenericStruct::impl_function(); // gdb-check:[...]static fn function_names::Mod1::TestStruct2::impl_function(); // gdb-check:[...]static fn function_names::TestStruct1::impl_function(); // Trait implementations // gdb-command:info functions -q function_names::.*::trait_function.* -// gdb-check:[...]static fn as function_names::TestTrait1>::trait_function(); -// gdb-check:[...]static fn as function_names::TestTrait1>::trait_function(); -// gdb-check:[...]static fn ::trait_function(); -// gdb-check:[...]static fn ::trait_function(); +// gdb-check:[...]static fn function_names::Mod1::{impl#1}::trait_function(); +// gdb-check:[...]static fn function_names::{impl#1}::trait_function(); +// gdb-check:[...]static fn function_names::{impl#3}::trait_function(); +// gdb-check:[...]static fn function_names::{impl#5}::trait_function3(); +// gdb-check:[...]static fn function_names::{impl#6}::trait_function(); // Closure -// gdb-command:info functions -q function_names::.*::{{closure.* -// gdb-check:[...]static fn function_names::GenericStruct::impl_function::{{closure}}(*mut function_names::{impl#2}::impl_function::{closure#0}); -// gdb-check:[...]static fn function_names::generic_func::{{closure}}(*mut function_names::generic_func::{closure#0}); -// gdb-check:[...]static fn function_names::main::{{closure}}(*mut function_names::main::{closure#0}); +// gdb-command:info functions -q function_names::.*::{closure.* +// gdb-check:[...]static fn function_names::generic_func::{closure#0}(*mut function_names::generic_func::{closure#0}); +// gdb-check:[...]static fn function_names::main::{closure#0}(*mut function_names::main::{closure#0}); +// gdb-check:[...]static fn function_names::{impl#2}::impl_function::{closure#0}(*mut function_names::{impl#2}::impl_function::{closure#0}); // Generator // Generators don't seem to appear in GDB's symbol table. // Const generic parameter // gdb-command:info functions -q function_names::const_generic_fn.* -// gdb-check:[...]static fn function_names::const_generic_fn_bool(); -// gdb-check:[...]static fn function_names::const_generic_fn_non_int(); -// gdb-check:[...]static fn function_names::const_generic_fn_signed_int(); -// gdb-check:[...]static fn function_names::const_generic_fn_unsigned_int(); +// gdb-check:[...]static fn function_names::const_generic_fn_bool(); +// gdb-check:[...]static fn function_names::const_generic_fn_non_int<{CONST#fe3cfa0214ac55c7}>(); +// gdb-check:[...]static fn function_names::const_generic_fn_signed_int<-7>(); +// gdb-check:[...]static fn function_names::const_generic_fn_unsigned_int<14>(); // === CDB TESTS =================================================================================== @@ -103,7 +104,7 @@ fn main() { GenericStruct::::trait_function3(); // Generic function - let _ = generic_func(42); + let _ = generic_func(42i32); // Closure let closure = || { TestStruct1 }; diff --git a/src/test/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr b/src/test/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr index f374266626bcc..614cdff1f8022 100644 --- a/src/test/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr +++ b/src/test/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `E: From<()>` is not satisfied - --> $DIR/never-value-fallback-issue-66757.rs:27:5 + --> $DIR/never-value-fallback-issue-66757.rs:28:5 | LL | >::from(never); | ^^^^^^^^^^^^^^^^^^^^ the trait `From<()>` is not implemented for `E` diff --git a/src/test/ui/never_type/never-value-fallback-issue-66757.rs b/src/test/ui/never_type/never-value-fallback-issue-66757.rs index 6dc7e6ad2d93d..fc6fe6eb5cc02 100644 --- a/src/test/ui/never_type/never-value-fallback-issue-66757.rs +++ b/src/test/ui/never_type/never-value-fallback-issue-66757.rs @@ -22,6 +22,7 @@ impl From for E { #[allow(unreachable_code)] #[allow(dead_code)] +#[allow(unused_must_use)] fn foo(never: !) { >::from(never); // Ok >::from(never); //[nofallback]~ ERROR trait bound `E: From<()>` is not satisfied diff --git a/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn.rs b/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.rs similarity index 89% rename from src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn.rs rename to src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.rs index 59de9e9571944..8eefb375b8c1b 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.rs @@ -1,4 +1,5 @@ #![feature(const_trait_impl)] +#![feature(const_fn_trait_bound)] trait Tr { fn req(&self); @@ -18,11 +19,6 @@ impl const Tr for S { fn req(&self) {} } //~^^ ERROR const trait implementations may not use non-const default functions -impl const Tr for u8 { - fn req(&self) {} - fn prov(&self) {} -} - impl const Tr for u16 { fn prov(&self) {} fn default() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn.stderr b/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.stderr similarity index 84% rename from src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn.stderr rename to src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.stderr index 5301e0ad12ef1..a091679704111 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-fail.stderr @@ -1,5 +1,5 @@ error: const trait implementations may not use non-const default functions - --> $DIR/impl-with-default-fn.rs:17:1 + --> $DIR/impl-with-default-fn-fail.rs:18:1 | LL | / impl const Tr for S { LL | | fn req(&self) {} @@ -9,7 +9,7 @@ LL | | } = note: `prov` not implemented error: const trait implementations may not use non-const default functions - --> $DIR/impl-with-default-fn.rs:32:1 + --> $DIR/impl-with-default-fn-fail.rs:28:1 | LL | / impl const Tr for u32 { LL | | fn req(&self) {} @@ -20,7 +20,7 @@ LL | | } = note: `prov` not implemented error[E0046]: not all trait items implemented, missing: `req` - --> $DIR/impl-with-default-fn.rs:26:1 + --> $DIR/impl-with-default-fn-fail.rs:22:1 | LL | fn req(&self); | -------------- `req` from trait diff --git a/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-pass.rs b/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-pass.rs new file mode 100644 index 0000000000000..ba3fec0882b02 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/impl-with-default-fn-pass.rs @@ -0,0 +1,34 @@ +// check-pass + +#![feature(const_trait_impl)] +#![feature(const_fn_trait_bound)] + +trait Tr { + fn req(&self); + + fn prov(&self) { + println!("lul"); + self.req(); + } + + #[default_method_body_is_const] + fn default() {} +} + +impl const Tr for u8 { + fn req(&self) {} + fn prov(&self) {} +} + +macro_rules! impl_tr { + ($ty: ty) => { + impl const Tr for $ty { + fn req(&self) {} + fn prov(&self) {} + } + } +} + +impl_tr!(u64); + +fn main() {}