diff options
56 files changed, 603 insertions, 164 deletions
diff --git a/Cargo.lock b/Cargo.lock index e45926f832c..21158381858 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -304,6 +304,7 @@ dependencies = [ "num_cpus", "opener", "openssl", + "os_info", "percent-encoding 2.1.0", "pretty_env_logger", "rustc-workspace-hack", @@ -867,9 +868,9 @@ dependencies = [ [[package]] name = "curl" -version = "0.4.38" +version = "0.4.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "003cb79c1c6d1c93344c7e1201bb51c2148f24ec2bd9c253709d6b2efb796515" +checksum = "aaa3b8db7f3341ddef15786d250106334d4a6c4b0ae4a46cd77082777d9849b9" dependencies = [ "curl-sys", "libc", @@ -882,9 +883,9 @@ dependencies = [ [[package]] name = "curl-sys" -version = "0.4.48+curl-7.79.1" +version = "0.4.49+curl-7.79.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a77a741f832116da66aeb126b4f19190ecf46144a74a9bde43c2086f38da0e" +checksum = "e0f44960aea24a786a46907b8824ebc0e66ca06bf4e4978408c7499620343483" dependencies = [ "cc", "libc", @@ -1427,9 +1428,9 @@ dependencies = [ [[package]] name = "git2" -version = "0.13.17" +version = "0.13.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d250f5f82326884bd39c2853577e70a121775db76818ffa452ed1e80de12986" +checksum = "2a8057932925d3a9d9e4434ea016570d37420ddb1ceed45a174d577f24ed6700" dependencies = [ "bitflags", "libc", @@ -1888,9 +1889,9 @@ dependencies = [ [[package]] name = "libgit2-sys" -version = "0.12.18+1.1.0" +version = "0.12.24+1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3da6a42da88fc37ee1ecda212ffa254c25713532980005d5f7c0b0fbe7e6e885" +checksum = "ddbd6021eef06fb289a8f54b3c2acfdd85ff2a585dfbb24b8576325373d2152c" dependencies = [ "cc", "libc", @@ -2408,6 +2409,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd20eec3dbe4376829cb7d80ae6ac45e0a766831dca50202ff2d40db46a8a024" [[package]] +name = "os_info" +version = "3.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ac91020bfed8cc3f8aa450d4c3b5fa1d3373fc091c8a92009f3b27749d5a227" +dependencies = [ + "log", + "serde", + "winapi", +] + +[[package]] name = "output_vt100" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 9f7b8616d78..d5deacf3811 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -828,6 +828,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } fn fcmp(&mut self, op: RealPredicate, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { + let op = llvm::RealPredicate::from_generic(op); unsafe { llvm::LLVMBuildFCmp(self.llbuilder, op as c_uint, lhs, rhs, UNNAMED) } } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 63eca00de2a..4c9ae4faf72 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -223,6 +223,33 @@ pub enum RealPredicate { RealPredicateTrue = 15, } +impl RealPredicate { + pub fn from_generic(realp: rustc_codegen_ssa::common::RealPredicate) -> Self { + match realp { + rustc_codegen_ssa::common::RealPredicate::RealPredicateFalse => { + RealPredicate::RealPredicateFalse + } + rustc_codegen_ssa::common::RealPredicate::RealOEQ => RealPredicate::RealOEQ, + rustc_codegen_ssa::common::RealPredicate::RealOGT => RealPredicate::RealOGT, + rustc_codegen_ssa::common::RealPredicate::RealOGE => RealPredicate::RealOGE, + rustc_codegen_ssa::common::RealPredicate::RealOLT => RealPredicate::RealOLT, + rustc_codegen_ssa::common::RealPredicate::RealOLE => RealPredicate::RealOLE, + rustc_codegen_ssa::common::RealPredicate::RealONE => RealPredicate::RealONE, + rustc_codegen_ssa::common::RealPredicate::RealORD => RealPredicate::RealORD, + rustc_codegen_ssa::common::RealPredicate::RealUNO => RealPredicate::RealUNO, + rustc_codegen_ssa::common::RealPredicate::RealUEQ => RealPredicate::RealUEQ, + rustc_codegen_ssa::common::RealPredicate::RealUGT => RealPredicate::RealUGT, + rustc_codegen_ssa::common::RealPredicate::RealUGE => RealPredicate::RealUGE, + rustc_codegen_ssa::common::RealPredicate::RealULT => RealPredicate::RealULT, + rustc_codegen_ssa::common::RealPredicate::RealULE => RealPredicate::RealULE, + rustc_codegen_ssa::common::RealPredicate::RealUNE => RealPredicate::RealUNE, + rustc_codegen_ssa::common::RealPredicate::RealPredicateTrue => { + RealPredicate::RealPredicateTrue + } + } + } +} + /// LLVMTypeKind #[derive(Copy, Clone, PartialEq, Debug)] #[repr(C)] diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index e95493acbb7..0eacedc09ee 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -38,7 +38,7 @@ use rustc_macros::HashStable; use rustc_query_system::ich::StableHashingContext; use rustc_session::cstore::CrateStoreDyn; use rustc_span::symbol::{kw, Ident, Symbol}; -use rustc_span::Span; +use rustc_span::{sym, Span}; use rustc_target::abi::Align; use std::cmp::Ordering; @@ -1900,6 +1900,14 @@ impl<'tcx> TyCtxt<'tcx> { self.sess.contains_name(&self.get_attrs(did), attr) } + /// Determines whether an item is annotated with `doc(hidden)`. + pub fn is_doc_hidden(self, did: DefId) -> bool { + self.get_attrs(did) + .iter() + .filter_map(|attr| if attr.has_name(sym::doc) { attr.meta_item_list() } else { None }) + .any(|items| items.iter().any(|item| item.has_name(sym::hidden))) + } + /// Returns `true` if this is an `auto trait`. pub fn trait_is_auto(self, trait_def_id: DefId) -> bool { self.trait_def(trait_def_id).has_auto_impl diff --git a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs index 9e961f7ba5d..368e3957dd0 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs @@ -52,11 +52,11 @@ use rustc_data_structures::captures::Captures; use rustc_index::vec::Idx; use rustc_hir::{HirId, RangeEnd}; -use rustc_middle::mir::interpret::ConstValue; use rustc_middle::mir::Field; use rustc_middle::thir::{FieldPat, Pat, PatKind, PatRange}; use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::{self, Const, Ty, TyCtxt, VariantDef}; +use rustc_middle::{middle::stability::EvalResult, mir::interpret::ConstValue}; use rustc_session::lint; use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::{Integer, Size, VariantIdx}; @@ -675,6 +675,36 @@ impl<'tcx> Constructor<'tcx> { } } + /// Checks if the `Constructor` is a variant and `TyCtxt::eval_stability` returns + /// `EvalResult::Deny { .. }`. + /// + /// This means that the variant has a stdlib unstable feature marking it. + pub(super) fn is_unstable_variant(&self, pcx: PatCtxt<'_, '_, 'tcx>) -> bool { + if let Constructor::Variant(idx) = self { + if let ty::Adt(adt, _) = pcx.ty.kind() { + let variant_def_id = adt.variants[*idx].def_id; + // Filter variants that depend on a disabled unstable feature. + return matches!( + pcx.cx.tcx.eval_stability(variant_def_id, None, DUMMY_SP, None), + EvalResult::Deny { .. } + ); + } + } + false + } + + /// Checks if the `Constructor` is a `Constructor::Variant` with a `#[doc(hidden)]` + /// attribute. + pub(super) fn is_doc_hidden_variant(&self, pcx: PatCtxt<'_, '_, 'tcx>) -> bool { + if let Constructor::Variant(idx) = self { + if let ty::Adt(adt, _) = pcx.ty.kind() { + let variant_def_id = adt.variants[*idx].def_id; + return pcx.cx.tcx.is_doc_hidden(variant_def_id); + } + } + false + } + fn variant_index_for_adt(&self, adt: &'tcx ty::AdtDef) -> VariantIdx { match *self { Variant(idx) => idx, @@ -929,36 +959,33 @@ impl<'tcx> SplitWildcard<'tcx> { // witness. let is_declared_nonexhaustive = cx.is_foreign_non_exhaustive_enum(pcx.ty); + let is_exhaustive_pat_feature = cx.tcx.features().exhaustive_patterns; + // If `exhaustive_patterns` is disabled and our scrutinee is an empty enum, we treat it // as though it had an "unknown" constructor to avoid exposing its emptiness. The // exception is if the pattern is at the top level, because we want empty matches to be // considered exhaustive. - let is_secretly_empty = def.variants.is_empty() - && !cx.tcx.features().exhaustive_patterns - && !pcx.is_top_level; - - if is_secretly_empty { - smallvec![NonExhaustive] - } else if is_declared_nonexhaustive { - def.variants - .indices() - .map(|idx| Variant(idx)) - .chain(Some(NonExhaustive)) - .collect() - } else if cx.tcx.features().exhaustive_patterns { - // If `exhaustive_patterns` is enabled, we exclude variants known to be - // uninhabited. - def.variants - .iter_enumerated() - .filter(|(_, v)| { - !v.uninhabited_from(cx.tcx, substs, def.adt_kind(), cx.param_env) - .contains(cx.tcx, cx.module) - }) - .map(|(idx, _)| Variant(idx)) - .collect() - } else { - def.variants.indices().map(|idx| Variant(idx)).collect() + let is_secretly_empty = + def.variants.is_empty() && !is_exhaustive_pat_feature && !pcx.is_top_level; + + let mut ctors: SmallVec<[_; 1]> = def + .variants + .iter_enumerated() + .filter(|(_, v)| { + // If `exhaustive_patterns` is enabled, we exclude variants known to be + // uninhabited. + let is_uninhabited = is_exhaustive_pat_feature + && v.uninhabited_from(cx.tcx, substs, def.adt_kind(), cx.param_env) + .contains(cx.tcx, cx.module); + !is_uninhabited + }) + .map(|(idx, _)| Variant(idx)) + .collect(); + + if is_secretly_empty || is_declared_nonexhaustive { + ctors.push(NonExhaustive); } + ctors } ty::Char => { smallvec![ @@ -1068,7 +1095,7 @@ impl<'tcx> SplitWildcard<'tcx> { Missing { nonexhaustive_enum_missing_real_variants: self .iter_missing(pcx) - .any(|c| !c.is_non_exhaustive()), + .any(|c| !(c.is_non_exhaustive() || c.is_unstable_variant(pcx))), } } else { Missing { nonexhaustive_enum_missing_real_variants: false } @@ -1222,9 +1249,9 @@ impl<'p, 'tcx> Fields<'p, 'tcx> { /// Values and patterns can be represented as a constructor applied to some fields. This represents /// a pattern in this form. -/// This also keeps track of whether the pattern has been foundreachable during analysis. For this +/// This also keeps track of whether the pattern has been found reachable during analysis. For this /// reason we should be careful not to clone patterns for which we care about that. Use -/// `clone_and_forget_reachability` is you're sure. +/// `clone_and_forget_reachability` if you're sure. pub(crate) struct DeconstructedPat<'p, 'tcx> { ctor: Constructor<'tcx>, fields: Fields<'p, 'tcx>, diff --git a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs index 43adef3d03b..d959d2f7f6f 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs @@ -585,15 +585,33 @@ impl<'p, 'tcx> Usefulness<'p, 'tcx> { } else { let mut split_wildcard = SplitWildcard::new(pcx); split_wildcard.split(pcx, matrix.heads().map(DeconstructedPat::ctor)); + + // This lets us know if we skipped any variants because they are marked + // `doc(hidden)` or they are unstable feature gate (only stdlib types). + let mut hide_variant_show_wild = false; // Construct for each missing constructor a "wild" version of this // constructor, that matches everything that can be built with // it. For example, if `ctor` is a `Constructor::Variant` for // `Option::Some`, we get the pattern `Some(_)`. - split_wildcard + let mut new: Vec<DeconstructedPat<'_, '_>> = split_wildcard .iter_missing(pcx) - .cloned() - .map(|missing_ctor| DeconstructedPat::wild_from_ctor(pcx, missing_ctor)) - .collect() + .filter_map(|missing_ctor| { + // Check if this variant is marked `doc(hidden)` + if missing_ctor.is_doc_hidden_variant(pcx) + || missing_ctor.is_unstable_variant(pcx) + { + hide_variant_show_wild = true; + return None; + } + Some(DeconstructedPat::wild_from_ctor(pcx, missing_ctor.clone())) + }) + .collect(); + + if hide_variant_show_wild { + new.push(DeconstructedPat::wildcard(pcx.ty)); + } + + new }; witnesses @@ -851,8 +869,10 @@ fn is_useful<'p, 'tcx>( split_wildcard .iter_missing(pcx) // Filter out the `NonExhaustive` because we want to list only real - // variants. - .filter(|c| !c.is_non_exhaustive()) + // variants. Also remove any unstable feature gated variants. + // Because of how we computed `nonexhaustive_enum_missing_real_variants`, + // this will not return an empty `Vec`. + .filter(|c| !(c.is_non_exhaustive() || c.is_unstable_variant(pcx))) .cloned() .map(|missing_ctor| DeconstructedPat::wild_from_ctor(pcx, missing_ctor)) .collect::<Vec<_>>() diff --git a/compiler/rustc_query_impl/src/stats.rs b/compiler/rustc_query_impl/src/stats.rs index fa48df3ed45..c3bbd51f3d3 100644 --- a/compiler/rustc_query_impl/src/stats.rs +++ b/compiler/rustc_query_impl/src/stats.rs @@ -5,8 +5,6 @@ use rustc_query_system::query::{QueryCache, QueryCacheStore}; use std::any::type_name; use std::mem; -#[cfg(debug_assertions)] -use std::sync::atomic::Ordering; trait KeyStats { fn key_stats(&self, stats: &mut QueryStats); @@ -27,7 +25,6 @@ impl KeyStats for DefId { #[derive(Clone)] struct QueryStats { name: &'static str, - cache_hits: usize, key_size: usize, key_type: &'static str, value_size: usize, @@ -42,10 +39,6 @@ where { let mut stats = QueryStats { name, - #[cfg(debug_assertions)] - cache_hits: map.cache_hits.load(Ordering::Relaxed), - #[cfg(not(debug_assertions))] - cache_hits: 0, key_size: mem::size_of::<C::Key>(), key_type: type_name::<C::Key>(), value_size: mem::size_of::<C::Value>(), @@ -63,12 +56,6 @@ where pub fn print_stats(tcx: TyCtxt<'_>) { let queries = query_stats(tcx); - if cfg!(debug_assertions) { - let hits: usize = queries.iter().map(|s| s.cache_hits).sum(); - let results: usize = queries.iter().map(|s| s.entry_count).sum(); - eprintln!("\nQuery cache hit rate: {}", hits as f64 / (hits + results) as f64); - } - let mut query_key_sizes = queries.clone(); query_key_sizes.sort_by_key(|q| q.key_size); eprintln!("\nLarge query keys:"); @@ -83,20 +70,6 @@ pub fn print_stats(tcx: TyCtxt<'_>) { eprintln!(" {} - {} x {} - {}", q.name, q.value_size, q.entry_count, q.value_type); } - if cfg!(debug_assertions) { - let mut query_cache_hits = queries.clone(); - query_cache_hits.sort_by_key(|q| q.cache_hits); - eprintln!("\nQuery cache hits:"); - for q in query_cache_hits.iter().rev() { - eprintln!( - " {} - {} ({}%)", - q.name, - q.cache_hits, - q.cache_hits as f64 / (q.cache_hits + q.entry_count) as f64 - ); - } - } - let mut query_value_count = queries.clone(); query_value_count.sort_by_key(|q| q.entry_count); eprintln!("\nQuery value count:"); diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 75184cd6f51..07d72059975 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -26,24 +26,15 @@ use std::hash::{Hash, Hasher}; use std::mem; use std::num::NonZeroU32; use std::ptr; -#[cfg(debug_assertions)] -use std::sync::atomic::{AtomicUsize, Ordering}; pub struct QueryCacheStore<C: QueryCache> { cache: C, shards: Sharded<C::Sharded>, - #[cfg(debug_assertions)] - pub cache_hits: AtomicUsize, } impl<C: QueryCache + Default> Default for QueryCacheStore<C> { fn default() -> Self { - Self { - cache: C::default(), - shards: Default::default(), - #[cfg(debug_assertions)] - cache_hits: AtomicUsize::new(0), - } + Self { cache: C::default(), shards: Default::default() } } } @@ -377,10 +368,6 @@ where if unlikely!(tcx.profiler().enabled()) { tcx.profiler().query_cache_hit(index.into()); } - #[cfg(debug_assertions)] - { - cache.cache_hits.fetch_add(1, Ordering::Relaxed); - } tcx.dep_graph().read_index(index); on_hit(value) }) @@ -429,10 +416,6 @@ where if unlikely!(tcx.dep_context().profiler().enabled()) { tcx.dep_context().profiler().query_cache_hit(index.into()); } - #[cfg(debug_assertions)] - { - cache.cache_hits.fetch_add(1, Ordering::Relaxed); - } query_blocked_prof_timer.finish_with_query_invocation_id(index.into()); (v, Some(index)) @@ -705,10 +688,6 @@ where if unlikely!(tcx.dep_context().profiler().enabled()) { tcx.dep_context().profiler().query_cache_hit(index.into()); } - #[cfg(debug_assertions)] - { - cache.cache_hits.fetch_add(1, Ordering::Relaxed); - } }); let lookup = match cached { diff --git a/library/alloc/src/collections/binary_heap.rs b/library/alloc/src/collections/binary_heap.rs index cfb1cd09c39..9bded6c0f1c 100644 --- a/library/alloc/src/collections/binary_heap.rs +++ b/library/alloc/src/collections/binary_heap.rs @@ -1009,6 +1009,7 @@ impl<T> BinaryHeap<T> { /// /// 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 6dcba318c35..ea010c1f89d 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 2f4a131136e..493cf3117ed 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -2093,6 +2093,7 @@ impl<T: ?Sized> Weak<T> { /// ``` /// /// [`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<T> = NonNull::as_ptr(self.ptr); @@ -2229,6 +2230,8 @@ impl<T: ?Sized> Weak<T> { /// /// assert!(weak_five.upgrade().is_none()); /// ``` + #[must_use = "this returns a new `Rc`, \ + without modifying the original weak pointer"] #[stable(feature = "rc_weak", since = "1.4.0")] pub fn upgrade(&self) -> Option<Rc<T>> { let inner = self.inner()?; diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index f11fa92766f..f479bf231b3 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 1d4216d7d57..b75e9a2f3c7 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -146,7 +146,7 @@ macro_rules! acquire { /// use std::sync::Arc; /// /// let my_arc = Arc::new(()); -/// Arc::downgrade(&my_arc); +/// let my_weak = Arc::downgrade(&my_arc); /// ``` /// /// `Arc<T>`'s implementations of traits like `Clone` may also be called using @@ -827,6 +827,7 @@ impl<T: ?Sized> Arc<T> { /// 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<T> = NonNull::as_ptr(this.ptr); @@ -897,6 +898,8 @@ impl<T: ?Sized> Arc<T> { /// /// let weak_five = Arc::downgrade(&five); /// ``` + #[must_use = "this returns a new `Weak` pointer, \ + without modifying the original `Arc`"] #[stable(feature = "arc_weak", since = "1.4.0")] pub fn downgrade(this: &Self) -> Weak<T> { // This Relaxed is OK because we're checking the value in the CAS @@ -1724,6 +1727,7 @@ impl<T: ?Sized> Weak<T> { /// ``` /// /// [`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<T> = NonNull::as_ptr(self.ptr); @@ -1861,6 +1865,8 @@ impl<T: ?Sized> Weak<T> { /// /// assert!(weak_five.upgrade().is_none()); /// ``` + #[must_use = "this returns a new `Arc`, \ + without modifying the original weak pointer"] #[stable(feature = "arc_weak", since = "1.4.0")] pub fn upgrade(&self) -> Option<Arc<T>> { // We use a CAS loop to increment the strong count instead of a diff --git a/library/alloc/src/vec/drain.rs b/library/alloc/src/vec/drain.rs index fb32d144f87..e643940d017 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/alloc/layout.rs b/library/core/src/alloc/layout.rs index d4c8ea33501..780f82d8afa 100644 --- a/library/core/src/alloc/layout.rs +++ b/library/core/src/alloc/layout.rs @@ -112,6 +112,8 @@ impl Layout { /// The minimum byte alignment for a memory block of this layout. #[stable(feature = "alloc_layout", since = "1.28.0")] #[rustc_const_stable(feature = "const_alloc_layout", since = "1.50.0")] + #[must_use = "this returns the minimum alignment, \ + without modifying the layout"] #[inline] pub const fn align(&self) -> usize { self.align_.get() @@ -229,6 +231,8 @@ impl Layout { /// satisfy this constraint is to ensure `align <= self.align()`. #[unstable(feature = "alloc_layout_extra", issue = "55724")] #[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] + #[must_use = "this returns the padding needed, \ + without modifying the `Layout`"] #[inline] pub const fn padding_needed_for(&self, align: usize) -> usize { let len = self.size(); @@ -262,6 +266,8 @@ impl Layout { /// This is equivalent to adding the result of `padding_needed_for` /// to the layout's current size. #[stable(feature = "alloc_layout_manipulation", since = "1.44.0")] + #[must_use = "this returns a new `Layout`, \ + without modifying the original"] #[inline] pub fn pad_to_align(&self) -> Layout { let pad = self.padding_needed_for(self.align()); diff --git a/library/core/src/array/iter.rs b/library/core/src/array/iter.rs index 822747dd0e8..5d63cf03fcb 100644 --- a/library/core/src/array/iter.rs +++ b/library/core/src/array/iter.rs @@ -135,19 +135,12 @@ impl<T, const N: usize> Iterator for IntoIter<T, N> { Fold: FnMut(Acc, Self::Item) -> Acc, { let data = &mut self.data; - // FIXME: This uses try_fold(&mut iter) instead of fold(iter) because the latter - // would go through the blanket `impl Iterator for &mut I` implementation - // which lacks inline annotations on its methods and adding those would be a larger - // perturbation than using try_fold here. - // Whether it would be beneficial to add those annotations should be investigated separately. - (&mut self.alive) - .try_fold::<_, _, Result<_, !>>(init, |acc, idx| { - // SAFETY: idx is obtained by folding over the `alive` range, which implies the - // value is currently considered alive but as the range is being consumed each value - // we read here will only be read once and then considered dead. - Ok(fold(acc, unsafe { data.get_unchecked(idx).assume_init_read() })) - }) - .unwrap() + self.alive.by_ref().fold(init, |acc, idx| { + // SAFETY: idx is obtained by folding over the `alive` range, which implies the + // value is currently considered alive but as the range is being consumed each value + // we read here will only be read once and then considered dead. + fold(acc, unsafe { data.get_unchecked(idx).assume_init_read() }) + }) } fn count(self) -> usize { diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index d10563a4097..b8ad7720e0c 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/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 8f9b32e7750..f53d6cac7ed 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -3460,6 +3460,7 @@ pub trait Iterator { #[stable(feature = "rust1", since = "1.0.0")] impl<I: Iterator + ?Sized> Iterator for &mut I { type Item = I::Item; + #[inline] fn next(&mut self) -> Option<I::Item> { (**self).next() } diff --git a/library/core/src/option.rs b/library/core/src/option.rs index df8af22a317..401267f5613 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -657,6 +657,7 @@ impl<T> Option<T> { /// /// [&]: reference "shared reference" #[inline] + #[must_use] #[stable(feature = "pin", since = "1.33.0")] pub fn as_pin_ref(self: Pin<&Self>) -> Option<Pin<&T>> { // SAFETY: `x` is guaranteed to be pinned because it comes from `self` @@ -668,6 +669,7 @@ impl<T> Option<T> { /// /// [&mut]: reference "mutable reference" #[inline] + #[must_use] #[stable(feature = "pin", since = "1.33.0")] pub fn as_pin_mut(self: Pin<&mut Self>) -> Option<Pin<&mut T>> { // 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 87c8674af0d..af9daf82974 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -119,6 +119,7 @@ impl<T: Sized> NonNull<T> { /// /// [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<T> { // SAFETY: the caller must guarantee that `self` meets all the @@ -151,6 +152,7 @@ impl<T: Sized> NonNull<T> { /// /// [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<T> { // SAFETY: the caller must guarantee that `self` meets all the @@ -264,6 +266,7 @@ impl<T: ?Sized> NonNull<T> { /// ``` #[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<T: ?Sized> NonNull<T> { /// /// [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<T: ?Sized> NonNull<T> { /// /// [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<T> 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<T> { @@ -474,6 +480,7 @@ impl<T> 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<T> 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<T>] { // SAFETY: the caller must uphold the safety contract for `as_uninit_slice`. @@ -579,6 +587,7 @@ impl<T> 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<T>] { // 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 b3deddca18e..5baceefb504 100644 --- a/library/core/src/ptr/unique.rs +++ b/library/core/src/ptr/unique.rs @@ -112,6 +112,7 @@ impl<T: ?Sized> Unique<T> { /// 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<T: ?Sized> Unique<T> { /// 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 70e59cda63f..dbf97851b03 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 8db9edc6147..94cb81e9d41 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 14ce94c178c..607a0179ff4 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/poll.rs b/library/core/src/task/poll.rs index 3e0b3e89758..80e1458dc94 100644 --- a/library/core/src/task/poll.rs +++ b/library/core/src/task/poll.rs @@ -97,7 +97,7 @@ impl<T> Poll<T> { /// Extracts the successful type of a [`Poll<T>`]. /// /// When combined with the `?` operator, this function will - /// propogate any [`Poll::Pending`] values to the caller, and + /// propagate any [`Poll::Pending`] values to the caller, and /// extract the `T` from [`Poll::Ready`]. /// /// # Examples diff --git a/library/core/src/time.rs b/library/core/src/time.rs index 40c5338d13c..5a74f39e8bc 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 8b51c4450c2..78eb91e4193 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 de745f21649..3b0e8833144 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/fs.rs b/library/std/src/fs.rs index 85d35072923..9f45e89aa75 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -1005,6 +1005,7 @@ impl Metadata { /// Ok(()) /// } /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn is_dir(&self) -> bool { self.file_type().is_dir() @@ -1033,6 +1034,7 @@ impl Metadata { /// Ok(()) /// } /// ``` + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn is_file(&self) -> bool { self.file_type().is_file() @@ -1059,6 +1061,7 @@ impl Metadata { /// Ok(()) /// } /// ``` + #[must_use] #[unstable(feature = "is_symlink", issue = "85748")] pub fn is_symlink(&self) -> bool { self.file_type().is_symlink() @@ -1306,6 +1309,7 @@ impl FileType { /// Ok(()) /// } /// ``` + #[must_use] #[stable(feature = "file_type", since = "1.1.0")] pub fn is_dir(&self) -> bool { self.0.is_dir() @@ -1338,6 +1342,7 @@ impl FileType { /// Ok(()) /// } /// ``` + #[must_use] #[stable(feature = "file_type", since = "1.1.0")] pub fn is_file(&self) -> bool { self.0.is_file() @@ -1373,6 +1378,7 @@ impl FileType { /// Ok(()) /// } /// ``` + #[must_use] #[stable(feature = "file_type", since = "1.1.0")] pub fn is_symlink(&self) -> bool { self.0.is_symlink() diff --git a/library/std/src/net/addr.rs b/library/std/src/net/addr.rs index cd2007cc2cb..a689d2a56b7 100644 --- a/library/std/src/net/addr.rs +++ b/library/std/src/net/addr.rs @@ -232,6 +232,7 @@ impl SocketAddr { /// assert_eq!(socket.is_ipv4(), true); /// assert_eq!(socket.is_ipv6(), false); /// ``` + #[must_use] #[stable(feature = "sockaddr_checker", since = "1.16.0")] #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")] pub const fn is_ipv4(&self) -> bool { @@ -253,6 +254,7 @@ impl SocketAddr { /// assert_eq!(socket.is_ipv4(), false); /// assert_eq!(socket.is_ipv6(), true); /// ``` + #[must_use] #[stable(feature = "sockaddr_checker", since = "1.16.0")] #[rustc_const_unstable(feature = "const_socketaddr", issue = "82485")] pub const fn is_ipv6(&self) -> bool { diff --git a/library/std/src/net/ip.rs b/library/std/src/net/ip.rs index 99922eef61f..68b8bb8f3e1 100644 --- a/library/std/src/net/ip.rs +++ b/library/std/src/net/ip.rs @@ -233,6 +233,7 @@ impl IpAddr { /// ``` #[rustc_const_stable(feature = "const_ip", since = "1.50.0")] #[stable(feature = "ip_shared", since = "1.12.0")] + #[must_use] #[inline] pub const fn is_unspecified(&self) -> bool { match self { @@ -256,6 +257,7 @@ impl IpAddr { /// ``` #[rustc_const_stable(feature = "const_ip", since = "1.50.0")] #[stable(feature = "ip_shared", since = "1.12.0")] + #[must_use] #[inline] pub const fn is_loopback(&self) -> bool { match self { @@ -281,6 +283,7 @@ impl IpAddr { /// ``` #[rustc_const_unstable(feature = "const_ip", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] + #[must_use] #[inline] pub const fn is_global(&self) -> bool { match self { @@ -304,6 +307,7 @@ impl IpAddr { /// ``` #[rustc_const_stable(feature = "const_ip", since = "1.50.0")] #[stable(feature = "ip_shared", since = "1.12.0")] + #[must_use] #[inline] pub const fn is_multicast(&self) -> bool { match self { @@ -332,6 +336,7 @@ impl IpAddr { /// ``` #[rustc_const_unstable(feature = "const_ip", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] + #[must_use] #[inline] pub const fn is_documentation(&self) -> bool { match self { @@ -356,6 +361,7 @@ impl IpAddr { /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0x2, 0, 0, 0, 0, 0, 0)).is_benchmarking(), true); /// ``` #[unstable(feature = "ip", issue = "27709")] + #[must_use] #[inline] pub const fn is_benchmarking(&self) -> bool { match self { @@ -379,6 +385,7 @@ impl IpAddr { /// ``` #[rustc_const_stable(feature = "const_ip", since = "1.50.0")] #[stable(feature = "ipaddr_checker", since = "1.16.0")] + #[must_use] #[inline] pub const fn is_ipv4(&self) -> bool { matches!(self, IpAddr::V4(_)) @@ -399,6 +406,7 @@ impl IpAddr { /// ``` #[rustc_const_stable(feature = "const_ip", since = "1.50.0")] #[stable(feature = "ipaddr_checker", since = "1.16.0")] + #[must_use] #[inline] pub const fn is_ipv6(&self) -> bool { matches!(self, IpAddr::V6(_)) @@ -527,6 +535,7 @@ impl Ipv4Addr { /// ``` #[rustc_const_stable(feature = "const_ipv4", since = "1.32.0")] #[stable(feature = "ip_shared", since = "1.12.0")] + #[must_use] #[inline] pub const fn is_unspecified(&self) -> bool { self.inner.s_addr == 0 @@ -548,6 +557,7 @@ impl Ipv4Addr { /// ``` #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")] #[stable(since = "1.7.0", feature = "ip_17")] + #[must_use] #[inline] pub const fn is_loopback(&self) -> bool { self.octets()[0] == 127 @@ -578,6 +588,7 @@ impl Ipv4Addr { /// ``` #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")] #[stable(since = "1.7.0", feature = "ip_17")] + #[must_use] #[inline] pub const fn is_private(&self) -> bool { match self.octets() { @@ -605,6 +616,7 @@ impl Ipv4Addr { /// ``` #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")] #[stable(since = "1.7.0", feature = "ip_17")] + #[must_use] #[inline] pub const fn is_link_local(&self) -> bool { matches!(self.octets(), [169, 254, ..]) @@ -680,6 +692,7 @@ impl Ipv4Addr { /// ``` #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] + #[must_use] #[inline] pub const fn is_global(&self) -> bool { // check if this address is 192.0.0.9 or 192.0.0.10. These addresses are the only two @@ -720,6 +733,7 @@ impl Ipv4Addr { /// ``` #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] + #[must_use] #[inline] pub const fn is_shared(&self) -> bool { self.octets()[0] == 100 && (self.octets()[1] & 0b1100_0000 == 0b0100_0000) @@ -745,6 +759,7 @@ impl Ipv4Addr { /// ``` #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] + #[must_use] #[inline] pub const fn is_benchmarking(&self) -> bool { self.octets()[0] == 198 && (self.octets()[1] & 0xfe) == 18 @@ -779,6 +794,7 @@ impl Ipv4Addr { /// ``` #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] + #[must_use] #[inline] pub const fn is_reserved(&self) -> bool { self.octets()[0] & 240 == 240 && !self.is_broadcast() @@ -802,6 +818,7 @@ impl Ipv4Addr { /// ``` #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")] #[stable(since = "1.7.0", feature = "ip_17")] + #[must_use] #[inline] pub const fn is_multicast(&self) -> bool { self.octets()[0] >= 224 && self.octets()[0] <= 239 @@ -823,6 +840,7 @@ impl Ipv4Addr { /// ``` #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")] #[stable(since = "1.7.0", feature = "ip_17")] + #[must_use] #[inline] pub const fn is_broadcast(&self) -> bool { u32::from_be_bytes(self.octets()) == u32::from_be_bytes(Self::BROADCAST.octets()) @@ -850,6 +868,7 @@ impl Ipv4Addr { /// ``` #[rustc_const_stable(feature = "const_ipv4", since = "1.50.0")] #[stable(since = "1.7.0", feature = "ip_17")] + #[must_use] #[inline] pub const fn is_documentation(&self) -> bool { match self.octets() { @@ -1291,6 +1310,7 @@ impl Ipv6Addr { /// ``` #[rustc_const_stable(feature = "const_ipv6", since = "1.50.0")] #[stable(since = "1.7.0", feature = "ip_17")] + #[must_use] #[inline] pub const fn is_unspecified(&self) -> bool { u128::from_be_bytes(self.octets()) == u128::from_be_bytes(Ipv6Addr::UNSPECIFIED.octets()) @@ -1314,6 +1334,7 @@ impl Ipv6Addr { /// ``` #[rustc_const_stable(feature = "const_ipv6", since = "1.50.0")] #[stable(since = "1.7.0", feature = "ip_17")] + #[must_use] #[inline] pub const fn is_loopback(&self) -> bool { u128::from_be_bytes(self.octets()) == u128::from_be_bytes(Ipv6Addr::LOCALHOST.octets()) @@ -1340,6 +1361,7 @@ impl Ipv6Addr { /// ``` #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] + #[must_use] #[inline] pub const fn is_global(&self) -> bool { match self.multicast_scope() { @@ -1367,6 +1389,7 @@ impl Ipv6Addr { /// ``` #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] + #[must_use] #[inline] pub const fn is_unique_local(&self) -> bool { (self.segments()[0] & 0xfe00) == 0xfc00 @@ -1395,6 +1418,7 @@ impl Ipv6Addr { /// ``` #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] + #[must_use] #[inline] pub const fn is_unicast(&self) -> bool { !self.is_multicast() @@ -1446,6 +1470,7 @@ impl Ipv6Addr { /// ``` #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] + #[must_use] #[inline] pub const fn is_unicast_link_local(&self) -> bool { (self.segments()[0] & 0xffc0) == 0xfe80 @@ -1470,6 +1495,7 @@ impl Ipv6Addr { /// ``` #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] + #[must_use] #[inline] pub const fn is_documentation(&self) -> bool { (self.segments()[0] == 0x2001) && (self.segments()[1] == 0xdb8) @@ -1492,6 +1518,7 @@ impl Ipv6Addr { /// assert_eq!(Ipv6Addr::new(0x2001, 0x2, 0, 0, 0, 0, 0, 0).is_benchmarking(), true); /// ``` #[unstable(feature = "ip", issue = "27709")] + #[must_use] #[inline] pub const fn is_benchmarking(&self) -> bool { (self.segments()[0] == 0x2001) && (self.segments()[1] == 0x2) && (self.segments()[2] == 0) @@ -1529,6 +1556,7 @@ impl Ipv6Addr { /// ``` #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")] #[unstable(feature = "ip", issue = "27709")] + #[must_use] #[inline] pub const fn is_unicast_global(&self) -> bool { self.is_unicast() @@ -1590,6 +1618,7 @@ impl Ipv6Addr { /// ``` #[rustc_const_stable(feature = "const_ipv6", since = "1.50.0")] #[stable(since = "1.7.0", feature = "ip_17")] + #[must_use] #[inline] pub const fn is_multicast(&self) -> bool { (self.segments()[0] & 0xff00) == 0xff00 diff --git a/library/std/src/os/unix/net/addr.rs b/library/std/src/os/unix/net/addr.rs index 62bfde8bfd4..c9ccc26f4e1 100644 --- a/library/std/src/os/unix/net/addr.rs +++ b/library/std/src/os/unix/net/addr.rs @@ -156,6 +156,7 @@ impl SocketAddr { /// Ok(()) /// } /// ``` + #[must_use] #[stable(feature = "unix_socket", since = "1.10.0")] pub fn is_unnamed(&self) -> bool { if let AddressKind::Unnamed = self.address() { true } else { false } @@ -192,6 +193,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 a8a79fb9c8f..53064035475 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -215,6 +215,7 @@ impl<'a> Prefix<'a> { /// assert!(!Disk(b'C').is_verbatim()); /// ``` #[inline] + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn is_verbatim(&self) -> bool { use self::Prefix::*; @@ -247,6 +248,7 @@ impl<'a> Prefix<'a> { /// assert!(path::is_separator('/')); // '/' works for both Unix and Windows /// assert!(!path::is_separator('❤')); /// ``` +#[must_use] #[stable(feature = "rust1", since = "1.0.0")] pub fn is_separator(c: char) -> bool { c.is_ascii() && is_sep_byte(c as u8) @@ -427,6 +429,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 +679,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 +825,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 +1193,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 +1929,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 @@ -2011,6 +2018,7 @@ impl Path { /// /// [`has_root`]: Path::has_root #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] #[allow(deprecated)] pub fn is_absolute(&self) -> bool { if cfg!(target_os = "redox") { @@ -2035,6 +2043,7 @@ impl Path { /// /// [`is_absolute`]: Path::is_absolute #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] #[inline] pub fn is_relative(&self) -> bool { !self.is_absolute() @@ -2061,6 +2070,7 @@ impl Path { /// assert!(Path::new("/etc/passwd").has_root()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] #[inline] pub fn has_root(&self) -> bool { self.components().has_root() @@ -2511,6 +2521,8 @@ impl Path { /// println!("{}", path.display()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use = "this does not display the path, \ + it returns an object that can be displayed"] #[inline] pub fn display(&self) -> Display<'_> { Display { path: self } @@ -2698,6 +2710,7 @@ impl Path { /// a Unix-like system for example. See [`fs::File::open`] or /// [`fs::OpenOptions::open`] for more information. #[stable(feature = "path_ext", since = "1.5.0")] + #[must_use] pub fn is_file(&self) -> bool { fs::metadata(self).map(|m| m.is_file()).unwrap_or(false) } @@ -2724,6 +2737,7 @@ impl Path { /// check errors, call [`fs::metadata`] and handle its [`Result`]. Then call /// [`fs::Metadata::is_dir`] if it was [`Ok`]. #[stable(feature = "path_ext", since = "1.5.0")] + #[must_use] pub fn is_dir(&self) -> bool { fs::metadata(self).map(|m| m.is_dir()).unwrap_or(false) } @@ -2750,6 +2764,7 @@ impl Path { /// assert_eq!(link_path.exists(), false); /// ``` #[unstable(feature = "is_symlink", issue = "85748")] + #[must_use] pub fn is_symlink(&self) -> bool { fs::symlink_metadata(self).map(|m| m.is_symlink()).unwrap_or(false) } diff --git a/library/std/src/sync/barrier.rs b/library/std/src/sync/barrier.rs index 0e28a2d166f..133c3e46cd8 100644 --- a/library/std/src/sync/barrier.rs +++ b/library/std/src/sync/barrier.rs @@ -167,6 +167,7 @@ impl BarrierWaitResult { /// println!("{:?}", barrier_wait_result.is_leader()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] pub fn is_leader(&self) -> bool { self.0 } diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 7d404aff30e..82847d83ad2 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/doc/edition-guide b/src/doc/edition-guide -Subproject 2d9b1b9da706de24650fdc5c3b0182f55c82115 +Subproject 7c0088ca744d293a5f4b1e2ac378e7c23d30fe5 diff --git a/src/doc/embedded-book b/src/doc/embedded-book -Subproject 4c76da9ddb4650203c129fceffdea95a3466c20 +Subproject 270fccd339e5972d9c900e788f197e81a0bcd95 diff --git a/src/doc/nomicon b/src/doc/nomicon -Subproject 2747c4bb2cbc0639b733793ddb0bf4e9daa2634 +Subproject 2d66852a27c5d0ec50ae021820d1de22caa2b1b diff --git a/src/doc/reference b/src/doc/reference -Subproject 13747275bd14c2d2b453100498532f9ae550476 +Subproject b5c68b02984f74e99d1f1b332029e05f607e266 diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example -Subproject 28aca4a36962c709bce301c03114b5589381dfb +Subproject 9a60624fcad0140826c44389571dc622917cd63 diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide -Subproject d1f03cbaa39d9164f5fe4b9b93762668142e0da +Subproject fba15a46ca8efa97e8a955794724ac7ce27805b diff --git a/src/test/ui/pattern/usefulness/auxiliary/hidden.rs b/src/test/ui/pattern/usefulness/auxiliary/hidden.rs new file mode 100644 index 00000000000..742b7e82c16 --- /dev/null +++ b/src/test/ui/pattern/usefulness/auxiliary/hidden.rs @@ -0,0 +1,6 @@ +pub enum Foo { + A, + B, + #[doc(hidden)] + C, +} diff --git a/src/test/ui/pattern/usefulness/auxiliary/unstable.rs b/src/test/ui/pattern/usefulness/auxiliary/unstable.rs new file mode 100644 index 00000000000..3142489c861 --- /dev/null +++ b/src/test/ui/pattern/usefulness/auxiliary/unstable.rs @@ -0,0 +1,12 @@ +#![feature(staged_api)] +#![stable(feature = "stable_test_feature", since = "1.0.0")] + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +pub enum Foo { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + Stable, + #[stable(feature = "stable_test_feature", since = "1.0.0")] + Stable2, + #[unstable(feature = "unstable_test_feature", issue = "none")] + Unstable, +} diff --git a/src/test/ui/pattern/usefulness/doc-hidden-non-exhaustive.rs b/src/test/ui/pattern/usefulness/doc-hidden-non-exhaustive.rs new file mode 100644 index 00000000000..a1dcab09314 --- /dev/null +++ b/src/test/ui/pattern/usefulness/doc-hidden-non-exhaustive.rs @@ -0,0 +1,30 @@ +// aux-build:hidden.rs + +extern crate hidden; + +use hidden::Foo; + +fn main() { + match Foo::A { + Foo::A => {} + Foo::B => {} + } + //~^^^^ non-exhaustive patterns: `_` not covered + + match Foo::A { + Foo::A => {} + Foo::C => {} + } + //~^^^^ non-exhaustive patterns: `B` not covered + + match Foo::A { + Foo::A => {} + } + //~^^^ non-exhaustive patterns: `B` and `_` not covered + + match None { + None => {} + Some(Foo::A) => {} + } + //~^^^^ non-exhaustive patterns: `Some(B)` and `Some(_)` not covered +} diff --git a/src/test/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr b/src/test/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr new file mode 100644 index 00000000000..6c9539822b3 --- /dev/null +++ b/src/test/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr @@ -0,0 +1,54 @@ +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/doc-hidden-non-exhaustive.rs:8:11 + | +LL | match Foo::A { + | ^^^^^^ pattern `_` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + = note: the matched value is of type `Foo` + +error[E0004]: non-exhaustive patterns: `B` not covered + --> $DIR/doc-hidden-non-exhaustive.rs:14:11 + | +LL | match Foo::A { + | ^^^^^^ pattern `B` not covered + | + ::: $DIR/auxiliary/hidden.rs:3:5 + | +LL | B, + | - not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + = note: the matched value is of type `Foo` + +error[E0004]: non-exhaustive patterns: `B` and `_` not covered + --> $DIR/doc-hidden-non-exhaustive.rs:20:11 + | +LL | match Foo::A { + | ^^^^^^ patterns `B` and `_` not covered + | + ::: $DIR/auxiliary/hidden.rs:3:5 + | +LL | B, + | - not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + = note: the matched value is of type `Foo` + +error[E0004]: non-exhaustive patterns: `Some(B)` and `Some(_)` not covered + --> $DIR/doc-hidden-non-exhaustive.rs:25:11 + | +LL | match None { + | ^^^^ patterns `Some(B)` and `Some(_)` not covered + | + ::: $SRC_DIR/core/src/option.rs:LL:COL + | +LL | Some(#[stable(feature = "rust1", since = "1.0.0")] T), + | ---- not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + = note: the matched value is of type `Option<Foo>` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/pattern/usefulness/stable-gated-patterns.rs b/src/test/ui/pattern/usefulness/stable-gated-patterns.rs new file mode 100644 index 00000000000..2e023a3be4a --- /dev/null +++ b/src/test/ui/pattern/usefulness/stable-gated-patterns.rs @@ -0,0 +1,18 @@ +// aux-build:unstable.rs + +extern crate unstable; + +use unstable::Foo; + +fn main() { + match Foo::Stable { + Foo::Stable => {} + } + //~^^^ non-exhaustive patterns: `Stable2` and `_` not covered + + match Foo::Stable { + Foo::Stable => {} + Foo::Stable2 => {} + } + //~^^^^ non-exhaustive patterns: `_` not covered +} diff --git a/src/test/ui/pattern/usefulness/stable-gated-patterns.stderr b/src/test/ui/pattern/usefulness/stable-gated-patterns.stderr new file mode 100644 index 00000000000..9b42565ac73 --- /dev/null +++ b/src/test/ui/pattern/usefulness/stable-gated-patterns.stderr @@ -0,0 +1,26 @@ +error[E0004]: non-exhaustive patterns: `Stable2` and `_` not covered + --> $DIR/stable-gated-patterns.rs:8:11 + | +LL | match Foo::Stable { + | ^^^^^^^^^^^ patterns `Stable2` and `_` not covered + | + ::: $DIR/auxiliary/unstable.rs:9:5 + | +LL | Stable2, + | ------- not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + = note: the matched value is of type `Foo` + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/stable-gated-patterns.rs:13:11 + | +LL | match Foo::Stable { + | ^^^^^^^^^^^ pattern `_` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + = note: the matched value is of type `Foo` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/pattern/usefulness/unstable-gated-patterns.rs b/src/test/ui/pattern/usefulness/unstable-gated-patterns.rs new file mode 100644 index 00000000000..b9804b0ffe7 --- /dev/null +++ b/src/test/ui/pattern/usefulness/unstable-gated-patterns.rs @@ -0,0 +1,22 @@ +#![feature(unstable_test_feature)] + +// aux-build:unstable.rs + +extern crate unstable; + +use unstable::Foo; + +fn main() { + match Foo::Stable { + Foo::Stable => {} + Foo::Stable2 => {} + } + //~^^^^ non-exhaustive patterns: `Unstable` not covered + + // Ok: all variants are explicitly matched + match Foo::Stable { + Foo::Stable => {} + Foo::Stable2 => {} + Foo::Unstable => {} + } +} diff --git a/src/test/ui/pattern/usefulness/unstable-gated-patterns.stderr b/src/test/ui/pattern/usefulness/unstable-gated-patterns.stderr new file mode 100644 index 00000000000..f9c0196b765 --- /dev/null +++ b/src/test/ui/pattern/usefulness/unstable-gated-patterns.stderr @@ -0,0 +1,17 @@ +error[E0004]: non-exhaustive patterns: `Unstable` not covered + --> $DIR/unstable-gated-patterns.rs:10:11 + | +LL | match Foo::Stable { + | ^^^^^^^^^^^ pattern `Unstable` not covered + | + ::: $DIR/auxiliary/unstable.rs:11:5 + | +LL | Unstable, + | -------- not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + = note: the matched value is of type `Foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/rfc-2008-non-exhaustive/auxiliary/unstable.rs b/src/test/ui/rfc-2008-non-exhaustive/auxiliary/unstable.rs new file mode 100644 index 00000000000..de9d6f65945 --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/auxiliary/unstable.rs @@ -0,0 +1,29 @@ +#![feature(staged_api)] +#![stable(feature = "stable_test_feature", since = "1.0.0")] + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[non_exhaustive] +pub enum UnstableEnum { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + Stable, + #[stable(feature = "stable_test_feature", since = "1.0.0")] + Stable2, + #[unstable(feature = "unstable_test_feature", issue = "none")] + Unstable, +} + +#[stable(feature = "stable_test_feature", since = "1.0.0")] +#[non_exhaustive] +pub enum OnlyUnstableEnum { + #[unstable(feature = "unstable_test_feature", issue = "none")] + Unstable, + #[unstable(feature = "unstable_test_feature", issue = "none")] + Unstable2, +} + +impl OnlyUnstableEnum { + #[stable(feature = "stable_test_feature", since = "1.0.0")] + pub fn new() -> Self { + Self::Unstable + } +} diff --git a/src/test/ui/rfc-2008-non-exhaustive/reachable-patterns.rs b/src/test/ui/rfc-2008-non-exhaustive/omitted-patterns.rs index ce1b5c7c377..fe9734fdc08 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/reachable-patterns.rs +++ b/src/test/ui/rfc-2008-non-exhaustive/omitted-patterns.rs @@ -1,10 +1,11 @@ // Test that the `non_exhaustive_omitted_patterns` lint is triggered correctly. -#![feature(non_exhaustive_omitted_patterns_lint)] +#![feature(non_exhaustive_omitted_patterns_lint, unstable_test_feature)] // aux-build:enums.rs extern crate enums; - +// aux-build:unstable.rs +extern crate unstable; // aux-build:structs.rs extern crate structs; @@ -12,6 +13,7 @@ use enums::{ EmptyNonExhaustiveEnum, NestedNonExhaustive, NonExhaustiveEnum, NonExhaustiveSingleVariant, VariantNonExhaustive, }; +use unstable::{UnstableEnum, OnlyUnstableEnum}; use structs::{FunctionalRecord, MixedVisFields, NestedStruct, NormalStruct}; #[non_exhaustive] @@ -94,35 +96,6 @@ fn main() { //~^^ some variants are not matched explicitly //~^^^^^ some variants are not matched explicitly - // The io::ErrorKind has many `unstable` fields how do they interact with this - // lint - #[deny(non_exhaustive_omitted_patterns)] - match std::io::ErrorKind::Other { - std::io::ErrorKind::NotFound => {} - std::io::ErrorKind::PermissionDenied => {} - std::io::ErrorKind::ConnectionRefused => {} - std::io::ErrorKind::ConnectionReset => {} - std::io::ErrorKind::ConnectionAborted => {} - std::io::ErrorKind::NotConnected => {} - std::io::ErrorKind::AddrInUse => {} - std::io::ErrorKind::AddrNotAvailable => {} - std::io::ErrorKind::BrokenPipe => {} - std::io::ErrorKind::AlreadyExists => {} - std::io::ErrorKind::WouldBlock => {} - std::io::ErrorKind::InvalidInput => {} - std::io::ErrorKind::InvalidData => {} - std::io::ErrorKind::TimedOut => {} - std::io::ErrorKind::WriteZero => {} - std::io::ErrorKind::Interrupted => {} - std::io::ErrorKind::Other => {} - std::io::ErrorKind::UnexpectedEof => {} - std::io::ErrorKind::Unsupported => {} - std::io::ErrorKind::OutOfMemory => {} - // All stable variants are above and unstable in `_` - _ => {} - } - //~^^ some variants are not matched explicitly - #[warn(non_exhaustive_omitted_patterns)] match VariantNonExhaustive::Baz(1, 2) { VariantNonExhaustive::Baz(_, _) => {} @@ -163,4 +136,35 @@ fn main() { // Ok: we don't lint on `if let` expressions #[deny(non_exhaustive_omitted_patterns)] if let NonExhaustiveEnum::Tuple(_) = non_enum {} + + match UnstableEnum::Stable { + UnstableEnum::Stable => {} + UnstableEnum::Stable2 => {} + #[deny(non_exhaustive_omitted_patterns)] + _ => {} + } + //~^^ some variants are not matched explicitly + + #[deny(non_exhaustive_omitted_patterns)] + match UnstableEnum::Stable { + UnstableEnum::Stable => {} + UnstableEnum::Stable2 => {} + UnstableEnum::Unstable => {} + _ => {} + } + + // Ok: the feature is on and both variants are matched + #[deny(non_exhaustive_omitted_patterns)] + match OnlyUnstableEnum::Unstable { + OnlyUnstableEnum::Unstable => {} + OnlyUnstableEnum::Unstable2 => {} + _ => {} + } + + #[deny(non_exhaustive_omitted_patterns)] + match OnlyUnstableEnum::Unstable { + OnlyUnstableEnum::Unstable => {} + _ => {} + } + //~^^ some variants are not matched explicitly } diff --git a/src/test/ui/rfc-2008-non-exhaustive/reachable-patterns.stderr b/src/test/ui/rfc-2008-non-exhaustive/omitted-patterns.stderr index 5b21e0402b1..30f3f88ad91 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/reachable-patterns.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/omitted-patterns.stderr @@ -1,11 +1,11 @@ warning: some fields are not explicitly listed - --> $DIR/reachable-patterns.rs:129:9 + --> $DIR/omitted-patterns.rs:102:9 | LL | VariantNonExhaustive::Bar { x, .. } => {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `y` not listed | note: the lint level is defined here - --> $DIR/reachable-patterns.rs:126:12 + --> $DIR/omitted-patterns.rs:99:12 | LL | #[warn(non_exhaustive_omitted_patterns)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,13 +13,13 @@ LL | #[warn(non_exhaustive_omitted_patterns)] = note: the pattern is of type `VariantNonExhaustive` and the `non_exhaustive_omitted_patterns` attribute was found warning: some fields are not explicitly listed - --> $DIR/reachable-patterns.rs:134:9 + --> $DIR/omitted-patterns.rs:107:9 | LL | let FunctionalRecord { first_field, second_field, .. } = FunctionalRecord::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `third_field` not listed | note: the lint level is defined here - --> $DIR/reachable-patterns.rs:133:12 + --> $DIR/omitted-patterns.rs:106:12 | LL | #[warn(non_exhaustive_omitted_patterns)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -27,13 +27,13 @@ LL | #[warn(non_exhaustive_omitted_patterns)] = note: the pattern is of type `FunctionalRecord` and the `non_exhaustive_omitted_patterns` attribute was found warning: some fields are not explicitly listed - --> $DIR/reachable-patterns.rs:142:29 + --> $DIR/omitted-patterns.rs:115:29 | LL | let NestedStruct { bar: NormalStruct { first_field, .. }, .. } = NestedStruct::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `second_field` not listed | note: the lint level is defined here - --> $DIR/reachable-patterns.rs:141:12 + --> $DIR/omitted-patterns.rs:114:12 | LL | #[warn(non_exhaustive_omitted_patterns)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -41,7 +41,7 @@ LL | #[warn(non_exhaustive_omitted_patterns)] = note: the pattern is of type `NormalStruct` and the `non_exhaustive_omitted_patterns` attribute was found warning: some fields are not explicitly listed - --> $DIR/reachable-patterns.rs:142:9 + --> $DIR/omitted-patterns.rs:115:9 | LL | let NestedStruct { bar: NormalStruct { first_field, .. }, .. } = NestedStruct::default(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `foo` not listed @@ -50,13 +50,13 @@ LL | let NestedStruct { bar: NormalStruct { first_field, .. }, .. } = Nested = note: the pattern is of type `NestedStruct` and the `non_exhaustive_omitted_patterns` attribute was found error: some variants are not matched explicitly - --> $DIR/reachable-patterns.rs:56:9 + --> $DIR/omitted-patterns.rs:58:9 | LL | _ => {} | ^ pattern `Struct { .. }` not covered | note: the lint level is defined here - --> $DIR/reachable-patterns.rs:55:16 + --> $DIR/omitted-patterns.rs:57:16 | LL | #[deny(non_exhaustive_omitted_patterns)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -64,13 +64,13 @@ LL | #[deny(non_exhaustive_omitted_patterns)] = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found error: some variants are not matched explicitly - --> $DIR/reachable-patterns.rs:63:9 + --> $DIR/omitted-patterns.rs:65:9 | LL | _ => {} | ^ pattern `Tuple(_)` not covered | note: the lint level is defined here - --> $DIR/reachable-patterns.rs:62:16 + --> $DIR/omitted-patterns.rs:64:16 | LL | #[deny(non_exhaustive_omitted_patterns)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -78,13 +78,13 @@ LL | #[deny(non_exhaustive_omitted_patterns)] = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found error: some variants are not matched explicitly - --> $DIR/reachable-patterns.rs:73:9 + --> $DIR/omitted-patterns.rs:75:9 | LL | _ => {} | ^ pattern `Unit` not covered | note: the lint level is defined here - --> $DIR/reachable-patterns.rs:72:16 + --> $DIR/omitted-patterns.rs:74:16 | LL | #[deny(non_exhaustive_omitted_patterns)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -92,13 +92,13 @@ LL | #[deny(non_exhaustive_omitted_patterns)] = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found error: some variants are not matched explicitly - --> $DIR/reachable-patterns.rs:90:32 + --> $DIR/omitted-patterns.rs:92:32 | LL | NestedNonExhaustive::A(_) => {} | ^ patterns `Tuple(_)` and `Struct { .. }` not covered | note: the lint level is defined here - --> $DIR/reachable-patterns.rs:87:12 + --> $DIR/omitted-patterns.rs:89:12 | LL | #[deny(non_exhaustive_omitted_patterns)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -106,7 +106,7 @@ LL | #[deny(non_exhaustive_omitted_patterns)] = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found error: some variants are not matched explicitly - --> $DIR/reachable-patterns.rs:92:9 + --> $DIR/omitted-patterns.rs:94:9 | LL | _ => {} | ^ pattern `C` not covered @@ -115,32 +115,46 @@ LL | _ => {} = note: the matched value is of type `NestedNonExhaustive` and the `non_exhaustive_omitted_patterns` attribute was found error: some variants are not matched explicitly - --> $DIR/reachable-patterns.rs:122:9 + --> $DIR/omitted-patterns.rs:132:9 | LL | _ => {} - | ^ patterns `HostUnreachable`, `NetworkUnreachable`, `NetworkDown` and 18 more not covered + | ^ pattern `A(_)` not covered | note: the lint level is defined here - --> $DIR/reachable-patterns.rs:99:12 + --> $DIR/omitted-patterns.rs:130:12 | LL | #[deny(non_exhaustive_omitted_patterns)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: ensure that all variants are matched explicitly by adding the suggested match arms - = note: the matched value is of type `ErrorKind` and the `non_exhaustive_omitted_patterns` attribute was found + = note: the matched value is of type `NonExhaustiveSingleVariant` and the `non_exhaustive_omitted_patterns` attribute was found error: some variants are not matched explicitly - --> $DIR/reachable-patterns.rs:159:9 + --> $DIR/omitted-patterns.rs:144:9 | LL | _ => {} - | ^ pattern `A(_)` not covered + | ^ pattern `Unstable` not covered + | +note: the lint level is defined here + --> $DIR/omitted-patterns.rs:143:16 + | +LL | #[deny(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: ensure that all variants are matched explicitly by adding the suggested match arms + = note: the matched value is of type `UnstableEnum` and the `non_exhaustive_omitted_patterns` attribute was found + +error: some variants are not matched explicitly + --> $DIR/omitted-patterns.rs:167:9 + | +LL | _ => {} + | ^ pattern `Unstable2` not covered | note: the lint level is defined here - --> $DIR/reachable-patterns.rs:157:12 + --> $DIR/omitted-patterns.rs:164:12 | LL | #[deny(non_exhaustive_omitted_patterns)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: ensure that all variants are matched explicitly by adding the suggested match arms - = note: the matched value is of type `NonExhaustiveSingleVariant` and the `non_exhaustive_omitted_patterns` attribute was found + = note: the matched value is of type `OnlyUnstableEnum` and the `non_exhaustive_omitted_patterns` attribute was found -error: aborting due to 7 previous errors; 4 warnings emitted +error: aborting due to 8 previous errors; 4 warnings emitted diff --git a/src/test/ui/rfc-2008-non-exhaustive/stable-omitted-patterns.rs b/src/test/ui/rfc-2008-non-exhaustive/stable-omitted-patterns.rs new file mode 100644 index 00000000000..9621d28f8e2 --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/stable-omitted-patterns.rs @@ -0,0 +1,33 @@ +// Test that the `non_exhaustive_omitted_patterns` lint is triggered correctly with variants +// marked stable and unstable. + +#![feature(non_exhaustive_omitted_patterns_lint)] + +// aux-build:unstable.rs +extern crate unstable; + +use unstable::{UnstableEnum, OnlyUnstableEnum}; + +fn main() { + // OK: this matches all the stable variants + match UnstableEnum::Stable { + UnstableEnum::Stable => {} + UnstableEnum::Stable2 => {} + #[deny(non_exhaustive_omitted_patterns)] + _ => {} + } + + match UnstableEnum::Stable { + UnstableEnum::Stable => {} + #[deny(non_exhaustive_omitted_patterns)] + _ => {} + } + //~^^ some variants are not matched explicitly + + // Ok: although this is a bit odd, we don't have anything to report + // since there is no stable variants and the feature is off + #[deny(non_exhaustive_omitted_patterns)] + match OnlyUnstableEnum::new() { + _ => {} + } +} diff --git a/src/test/ui/rfc-2008-non-exhaustive/stable-omitted-patterns.stderr b/src/test/ui/rfc-2008-non-exhaustive/stable-omitted-patterns.stderr new file mode 100644 index 00000000000..b9a281974fa --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/stable-omitted-patterns.stderr @@ -0,0 +1,16 @@ +error: some variants are not matched explicitly + --> $DIR/stable-omitted-patterns.rs:23:9 + | +LL | _ => {} + | ^ pattern `Stable2` not covered + | +note: the lint level is defined here + --> $DIR/stable-omitted-patterns.rs:22:16 + | +LL | #[deny(non_exhaustive_omitted_patterns)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: ensure that all variants are matched explicitly by adding the suggested match arms + = note: the matched value is of type `UnstableEnum` and the `non_exhaustive_omitted_patterns` attribute was found + +error: aborting due to previous error + diff --git a/src/tools/cargo b/src/tools/cargo -Subproject d56b42c549dbb7e7d0f712c51b39400260d114d +Subproject c7957a74bdcf3b11e7154c1a9401735f23ebd48 diff --git a/src/tools/rustc-workspace-hack/Cargo.toml b/src/tools/rustc-workspace-hack/Cargo.toml index a28cf28841e..4bda3fb22c2 100644 --- a/src/tools/rustc-workspace-hack/Cargo.toml +++ b/src/tools/rustc-workspace-hack/Cargo.toml @@ -61,7 +61,9 @@ features = [ "wincrypt", "windef", "winioctl", + "winreg", "winsock2", + "winuser", "ws2def", "ws2ipdef", "ws2tcpip", |
