diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index 696d5fdd6cd45..aca3fbbca1357 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -74,7 +74,7 @@ pub enum InlineAttr { Never, } -#[derive(Clone, Encodable, Decodable, Debug)] +#[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq)] pub enum InstructionSetAttr { ArmA32, ArmT32, diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index 14dd245625d25..16e1a8a1242ae 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -8,9 +8,7 @@ use crate::value::Value; use libc::c_uint; use rustc_codegen_ssa::traits::*; use rustc_data_structures::const_cstr; -use rustc_hir as hir; use rustc_hir::def_id::DefId; -use rustc_hir::Node; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc_middle::mir::interpret::{ read_target_uint, Allocation, ErrorHandled, GlobalAlloc, Pointer, @@ -18,7 +16,6 @@ use rustc_middle::mir::interpret::{ use rustc_middle::mir::mono::MonoItem; use rustc_middle::ty::{self, Instance, Ty}; use rustc_middle::{bug, span_bug}; -use rustc_span::symbol::sym; use rustc_target::abi::{AddressSpace, Align, HasDataLayout, LayoutOf, Primitive, Scalar, Size}; use tracing::debug; @@ -209,70 +206,42 @@ impl CodegenCx<'ll, 'tcx> { let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all()); let sym = self.tcx.symbol_name(instance).name; + let fn_attrs = self.tcx.codegen_fn_attrs(def_id); - debug!("get_static: sym={} instance={:?}", sym, instance); + debug!("get_static: sym={} instance={:?} fn_attrs={:?}", sym, instance, fn_attrs); - let g = if let Some(local_def_id) = def_id.as_local() { - let id = self.tcx.hir().local_def_id_to_hir_id(local_def_id); + let g = if def_id.is_local() && !self.tcx.is_foreign_item(def_id) { let llty = self.layout_of(ty).llvm_type(self); - // FIXME: refactor this to work without accessing the HIR - let (g, attrs) = match self.tcx.hir().get(id) { - Node::Item(&hir::Item { attrs, kind: hir::ItemKind::Static(..), .. }) => { - if let Some(g) = self.get_declared_value(sym) { - if self.val_ty(g) != self.type_ptr_to(llty) { - span_bug!(self.tcx.def_span(def_id), "Conflicting types for static"); - } - } - - let g = self.declare_global(sym, llty); - - if !self.tcx.is_reachable_non_generic(local_def_id) { - unsafe { - llvm::LLVMRustSetVisibility(g, llvm::Visibility::Hidden); - } - } - - (g, attrs) + if let Some(g) = self.get_declared_value(sym) { + if self.val_ty(g) != self.type_ptr_to(llty) { + span_bug!(self.tcx.def_span(def_id), "Conflicting types for static"); } + } - Node::ForeignItem(&hir::ForeignItem { - ref attrs, - kind: hir::ForeignItemKind::Static(..), - .. - }) => { - let fn_attrs = self.tcx.codegen_fn_attrs(local_def_id); - (check_and_apply_linkage(&self, &fn_attrs, ty, sym, def_id), &**attrs) - } - - item => bug!("get_static: expected static, found {:?}", item), - }; - - debug!("get_static: sym={} attrs={:?}", sym, attrs); + let g = self.declare_global(sym, llty); - for attr in attrs { - if self.tcx.sess.check_name(attr, sym::thread_local) { - llvm::set_thread_local_mode(g, self.tls_model); + if !self.tcx.is_reachable_non_generic(def_id) { + unsafe { + llvm::LLVMRustSetVisibility(g, llvm::Visibility::Hidden); } } g } else { - // FIXME(nagisa): perhaps the map of externs could be offloaded to llvm somehow? - debug!("get_static: sym={} item_attr={:?}", sym, self.tcx.item_attrs(def_id)); + check_and_apply_linkage(&self, &fn_attrs, ty, sym, def_id) + }; - let attrs = self.tcx.codegen_fn_attrs(def_id); - let g = check_and_apply_linkage(&self, &attrs, ty, sym, def_id); - - // Thread-local statics in some other crate need to *always* be linked - // against in a thread-local fashion, so we need to be sure to apply the - // thread-local attribute locally if it was present remotely. If we - // don't do this then linker errors can be generated where the linker - // complains that one object files has a thread local version of the - // symbol and another one doesn't. - if attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL) { - llvm::set_thread_local_mode(g, self.tls_model); - } + // Thread-local statics in some other crate need to *always* be linked + // against in a thread-local fashion, so we need to be sure to apply the + // thread-local attribute locally if it was present remotely. If we + // don't do this then linker errors can be generated where the linker + // complains that one object files has a thread local version of the + // symbol and another one doesn't. + if fn_attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL) { + llvm::set_thread_local_mode(g, self.tls_model); + } + if !def_id.is_local() { let needs_dll_storage_attr = self.use_dll_storage_attrs && !self.tcx.is_foreign_item(def_id) && // ThinLTO can't handle this workaround in all cases, so we don't // emit the attrs. Instead we make them unnecessary by disallowing @@ -304,8 +273,7 @@ impl CodegenCx<'ll, 'tcx> { } } } - g - }; + } if self.use_dll_storage_attrs && self.tcx.is_dllimport_foreign_item(def_id) { // For foreign (native) libs we know the exact storage type to use. diff --git a/compiler/rustc_mir/src/transform/inline.rs b/compiler/rustc_mir/src/transform/inline.rs index dd9a514466d4c..1635a95f46ec8 100644 --- a/compiler/rustc_mir/src/transform/inline.rs +++ b/compiler/rustc_mir/src/transform/inline.rs @@ -281,6 +281,11 @@ impl Inliner<'tcx> { return false; } + if self.codegen_fn_attrs.instruction_set != codegen_fn_attrs.instruction_set { + debug!("`callee has incompatible instruction set - not inlining"); + return false; + } + let hinted = match codegen_fn_attrs.inline { // Just treat inline(always) as a hint for now, // there are cases that prevent inlining that we diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 9d55bafd2868e..3b02f74f2ca1f 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1111,10 +1111,9 @@ impl<'a> Resolver<'a> { _, ) = binding.kind { - let def_id = (&*self).parent(ctor_def_id).expect("no parent for a constructor"); + let def_id = self.parent(ctor_def_id).expect("no parent for a constructor"); let fields = self.field_names.get(&def_id)?; - let first_field = fields.first()?; // Handle `struct Foo()` - return Some(fields.iter().fold(first_field.span, |acc, field| acc.to(field.span))); + return fields.iter().map(|name| name.span).reduce(Span::to); // None for `struct Foo()` } None } diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index 5554a448b5c59..946267d17c018 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -460,7 +460,7 @@ impl fmt::Debug for RangeMut<'_, K, V> { } } -impl BTreeMap { +impl BTreeMap { /// Makes a new, empty `BTreeMap`. /// /// Does not allocate anything on its own. @@ -479,7 +479,10 @@ impl BTreeMap { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")] - pub const fn new() -> BTreeMap { + pub const fn new() -> BTreeMap + where + K: Ord, + { BTreeMap { root: None, length: 0 } } @@ -498,7 +501,10 @@ impl BTreeMap { /// assert!(a.is_empty()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn clear(&mut self) { + pub fn clear(&mut self) + where + K: Ord, + { *self = BTreeMap::new(); } @@ -522,7 +528,7 @@ impl BTreeMap { #[stable(feature = "rust1", since = "1.0.0")] pub fn get(&self, key: &Q) -> Option<&V> where - K: Borrow, + K: Borrow + Ord, Q: Ord, { let root_node = self.root.as_ref()?.reborrow(); @@ -550,7 +556,7 @@ impl BTreeMap { #[stable(feature = "map_get_key_value", since = "1.40.0")] pub fn get_key_value(&self, k: &Q) -> Option<(&K, &V)> where - K: Borrow, + K: Borrow + Ord, Q: Ord, { let root_node = self.root.as_ref()?.reborrow(); @@ -578,7 +584,10 @@ impl BTreeMap { /// assert_eq!(map.first_key_value(), Some((&1, &"b"))); /// ``` #[unstable(feature = "map_first_last", issue = "62924")] - pub fn first_key_value(&self) -> Option<(&K, &V)> { + pub fn first_key_value(&self) -> Option<(&K, &V)> + where + K: Ord, + { let root_node = self.root.as_ref()?.reborrow(); root_node.first_leaf_edge().right_kv().ok().map(Handle::into_kv) } @@ -604,7 +613,10 @@ impl BTreeMap { /// assert_eq!(*map.get(&2).unwrap(), "b"); /// ``` #[unstable(feature = "map_first_last", issue = "62924")] - pub fn first_entry(&mut self) -> Option> { + pub fn first_entry(&mut self) -> Option> + where + K: Ord, + { let (map, dormant_map) = DormantMutRef::new(self); let root_node = map.root.as_mut()?.borrow_mut(); let kv = root_node.first_leaf_edge().right_kv().ok()?; @@ -631,7 +643,10 @@ impl BTreeMap { /// assert!(map.is_empty()); /// ``` #[unstable(feature = "map_first_last", issue = "62924")] - pub fn pop_first(&mut self) -> Option<(K, V)> { + pub fn pop_first(&mut self) -> Option<(K, V)> + where + K: Ord, + { self.first_entry().map(|entry| entry.remove_entry()) } @@ -652,7 +667,10 @@ impl BTreeMap { /// assert_eq!(map.last_key_value(), Some((&2, &"a"))); /// ``` #[unstable(feature = "map_first_last", issue = "62924")] - pub fn last_key_value(&self) -> Option<(&K, &V)> { + pub fn last_key_value(&self) -> Option<(&K, &V)> + where + K: Ord, + { let root_node = self.root.as_ref()?.reborrow(); root_node.last_leaf_edge().left_kv().ok().map(Handle::into_kv) } @@ -678,7 +696,10 @@ impl BTreeMap { /// assert_eq!(*map.get(&2).unwrap(), "last"); /// ``` #[unstable(feature = "map_first_last", issue = "62924")] - pub fn last_entry(&mut self) -> Option> { + pub fn last_entry(&mut self) -> Option> + where + K: Ord, + { let (map, dormant_map) = DormantMutRef::new(self); let root_node = map.root.as_mut()?.borrow_mut(); let kv = root_node.last_leaf_edge().left_kv().ok()?; @@ -705,7 +726,10 @@ impl BTreeMap { /// assert!(map.is_empty()); /// ``` #[unstable(feature = "map_first_last", issue = "62924")] - pub fn pop_last(&mut self) -> Option<(K, V)> { + pub fn pop_last(&mut self) -> Option<(K, V)> + where + K: Ord, + { self.last_entry().map(|entry| entry.remove_entry()) } @@ -729,7 +753,7 @@ impl BTreeMap { #[stable(feature = "rust1", since = "1.0.0")] pub fn contains_key(&self, key: &Q) -> bool where - K: Borrow, + K: Borrow + Ord, Q: Ord, { self.get(key).is_some() @@ -758,7 +782,7 @@ impl BTreeMap { #[stable(feature = "rust1", since = "1.0.0")] pub fn get_mut(&mut self, key: &Q) -> Option<&mut V> where - K: Borrow, + K: Borrow + Ord, Q: Ord, { let root_node = self.root.as_mut()?.borrow_mut(); @@ -795,7 +819,10 @@ impl BTreeMap { /// assert_eq!(map[&37], "c"); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn insert(&mut self, key: K, value: V) -> Option { + pub fn insert(&mut self, key: K, value: V) -> Option + where + K: Ord, + { match self.entry(key) { Occupied(mut entry) => Some(entry.insert(value)), Vacant(entry) => { @@ -827,7 +854,7 @@ impl BTreeMap { #[stable(feature = "rust1", since = "1.0.0")] pub fn remove(&mut self, key: &Q) -> Option where - K: Borrow, + K: Borrow + Ord, Q: Ord, { self.remove_entry(key).map(|(_, v)| v) @@ -854,7 +881,7 @@ impl BTreeMap { #[stable(feature = "btreemap_remove_entry", since = "1.45.0")] pub fn remove_entry(&mut self, key: &Q) -> Option<(K, V)> where - K: Borrow, + K: Borrow + Ord, Q: Ord, { let (map, dormant_map) = DormantMutRef::new(self); @@ -886,6 +913,7 @@ impl BTreeMap { #[unstable(feature = "btree_retain", issue = "79025")] pub fn retain(&mut self, mut f: F) where + K: Ord, F: FnMut(&K, &mut V) -> bool, { self.drain_filter(|k, v| !f(k, v)); @@ -920,7 +948,10 @@ impl BTreeMap { /// assert_eq!(a[&5], "f"); /// ``` #[stable(feature = "btree_append", since = "1.11.0")] - pub fn append(&mut self, other: &mut Self) { + pub fn append(&mut self, other: &mut Self) + where + K: Ord, + { // Do we have to append anything at all? if other.is_empty() { return; @@ -971,7 +1002,7 @@ impl BTreeMap { pub fn range(&self, range: R) -> Range<'_, K, V> where T: Ord, - K: Borrow, + K: Borrow + Ord, R: RangeBounds, { if let Some(root) = &self.root { @@ -1017,7 +1048,7 @@ impl BTreeMap { pub fn range_mut(&mut self, range: R) -> RangeMut<'_, K, V> where T: Ord, - K: Borrow, + K: Borrow + Ord, R: RangeBounds, { if let Some(root) = &mut self.root { @@ -1048,7 +1079,10 @@ impl BTreeMap { /// assert_eq!(count["a"], 3); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn entry(&mut self, key: K) -> Entry<'_, K, V> { + pub fn entry(&mut self, key: K) -> Entry<'_, K, V> + where + K: Ord, + { // FIXME(@porglezomp) Avoid allocating if we don't insert let (map, dormant_map) = DormantMutRef::new(self); let root_node = Self::ensure_is_owned(&mut map.root).borrow_mut(); @@ -1092,7 +1126,7 @@ impl BTreeMap { #[stable(feature = "btree_split_off", since = "1.11.0")] pub fn split_off(&mut self, key: &Q) -> Self where - K: Borrow, + K: Borrow + Ord, { if self.is_empty() { return Self::new(); @@ -1150,12 +1184,16 @@ impl BTreeMap { #[unstable(feature = "btree_drain_filter", issue = "70530")] pub fn drain_filter(&mut self, pred: F) -> DrainFilter<'_, K, V, F> where + K: Ord, F: FnMut(&K, &mut V) -> bool, { DrainFilter { pred, inner: self.drain_filter_inner() } } - pub(super) fn drain_filter_inner(&mut self) -> DrainFilterInner<'_, K, V> { + pub(super) fn drain_filter_inner(&mut self) -> DrainFilterInner<'_, K, V> + where + K: Ord, + { if let Some(root) = self.root.as_mut() { let (root, dormant_root) = DormantMutRef::new(root); let front = root.borrow_mut().first_leaf_edge(); @@ -1188,7 +1226,10 @@ impl BTreeMap { /// ``` #[inline] #[unstable(feature = "map_into_keys_values", issue = "75294")] - pub fn into_keys(self) -> IntoKeys { + pub fn into_keys(self) -> IntoKeys + where + K: Ord, + { IntoKeys { inner: self.into_iter() } } @@ -1211,7 +1252,10 @@ impl BTreeMap { /// ``` #[inline] #[unstable(feature = "map_into_keys_values", issue = "75294")] - pub fn into_values(self) -> IntoValues { + pub fn into_values(self) -> IntoValues + where + K: Ord, + { IntoValues { inner: self.into_iter() } } } @@ -1968,9 +2012,9 @@ impl Debug for BTreeMap { } #[stable(feature = "rust1", since = "1.0.0")] -impl Index<&Q> for BTreeMap +impl Index<&Q> for BTreeMap where - K: Borrow, + K: Borrow + Ord, Q: Ord, { type Output = V; diff --git a/library/alloc/src/collections/btree/map/tests.rs b/library/alloc/src/collections/btree/map/tests.rs index cf6bf7c7c99ed..78edf11d3934b 100644 --- a/library/alloc/src/collections/btree/map/tests.rs +++ b/library/alloc/src/collections/btree/map/tests.rs @@ -1706,6 +1706,34 @@ fn test_send() { } } +#[allow(dead_code)] +fn test_ord_absence() { + fn map(mut map: BTreeMap) { + map.is_empty(); + map.len(); + map.iter(); + map.iter_mut(); + map.keys(); + map.values(); + map.values_mut(); + map.into_iter(); + } + + fn map_debug(mut map: BTreeMap) { + format!("{:?}", map); + format!("{:?}", map.iter()); + format!("{:?}", map.iter_mut()); + format!("{:?}", map.keys()); + format!("{:?}", map.values()); + format!("{:?}", map.values_mut()); + format!("{:?}", map.into_iter()); + } + + fn map_clone(mut map: BTreeMap) { + map.clone_from(&map.clone()); + } +} + #[allow(dead_code)] fn test_const() { const MAP: &'static BTreeMap<(), ()> = &BTreeMap::new(); diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs index d39eb1fd4f955..be4e50119c0d1 100644 --- a/library/alloc/src/collections/btree/set.rs +++ b/library/alloc/src/collections/btree/set.rs @@ -222,7 +222,7 @@ impl fmt::Debug for Union<'_, T> { // and it's a power of two to make that division cheap. const ITER_PERFORMANCE_TIPPING_SIZE_DIFF: usize = 16; -impl BTreeSet { +impl BTreeSet { /// Makes a new, empty `BTreeSet`. /// /// Does not allocate anything on its own. @@ -237,7 +237,10 @@ impl BTreeSet { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")] - pub const fn new() -> BTreeSet { + pub const fn new() -> BTreeSet + where + T: Ord, + { BTreeSet { map: BTreeMap::new() } } @@ -267,7 +270,7 @@ impl BTreeSet { pub fn range(&self, range: R) -> Range<'_, T> where K: Ord, - T: Borrow, + T: Borrow + Ord, R: RangeBounds, { Range { iter: self.map.range(range) } @@ -294,7 +297,10 @@ impl BTreeSet { /// assert_eq!(diff, [1]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn difference<'a>(&'a self, other: &'a BTreeSet) -> Difference<'a, T> { + pub fn difference<'a>(&'a self, other: &'a BTreeSet) -> Difference<'a, T> + where + T: Ord, + { let (self_min, self_max) = if let (Some(self_min), Some(self_max)) = (self.first(), self.last()) { (self_min, self_max) @@ -352,10 +358,10 @@ impl BTreeSet { /// assert_eq!(sym_diff, [1, 3]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn symmetric_difference<'a>( - &'a self, - other: &'a BTreeSet, - ) -> SymmetricDifference<'a, T> { + pub fn symmetric_difference<'a>(&'a self, other: &'a BTreeSet) -> SymmetricDifference<'a, T> + where + T: Ord, + { SymmetricDifference(MergeIterInner::new(self.iter(), other.iter())) } @@ -380,7 +386,10 @@ impl BTreeSet { /// assert_eq!(intersection, [2]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn intersection<'a>(&'a self, other: &'a BTreeSet) -> Intersection<'a, T> { + pub fn intersection<'a>(&'a self, other: &'a BTreeSet) -> Intersection<'a, T> + where + T: Ord, + { let (self_min, self_max) = if let (Some(self_min), Some(self_max)) = (self.first(), self.last()) { (self_min, self_max) @@ -428,7 +437,10 @@ impl BTreeSet { /// assert_eq!(union, [1, 2]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn union<'a>(&'a self, other: &'a BTreeSet) -> Union<'a, T> { + pub fn union<'a>(&'a self, other: &'a BTreeSet) -> Union<'a, T> + where + T: Ord, + { Union(MergeIterInner::new(self.iter(), other.iter())) } @@ -445,7 +457,10 @@ impl BTreeSet { /// assert!(v.is_empty()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn clear(&mut self) { + pub fn clear(&mut self) + where + T: Ord, + { self.map.clear() } @@ -467,7 +482,7 @@ impl BTreeSet { #[stable(feature = "rust1", since = "1.0.0")] pub fn contains(&self, value: &Q) -> bool where - T: Borrow, + T: Borrow + Ord, Q: Ord, { self.map.contains_key(value) @@ -491,7 +506,7 @@ impl BTreeSet { #[stable(feature = "set_recovery", since = "1.9.0")] pub fn get(&self, value: &Q) -> Option<&T> where - T: Borrow, + T: Borrow + Ord, Q: Ord, { Recover::get(&self.map, value) @@ -515,7 +530,10 @@ impl BTreeSet { /// assert_eq!(a.is_disjoint(&b), false); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn is_disjoint(&self, other: &BTreeSet) -> bool { + pub fn is_disjoint(&self, other: &BTreeSet) -> bool + where + T: Ord, + { self.intersection(other).next().is_none() } @@ -537,7 +555,10 @@ impl BTreeSet { /// assert_eq!(set.is_subset(&sup), false); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn is_subset(&self, other: &BTreeSet) -> bool { + pub fn is_subset(&self, other: &BTreeSet) -> bool + where + T: Ord, + { // Same result as self.difference(other).next().is_none() // but the code below is faster (hugely in some cases). if self.len() > other.len() { @@ -613,7 +634,10 @@ impl BTreeSet { /// assert_eq!(set.is_superset(&sub), true); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn is_superset(&self, other: &BTreeSet) -> bool { + pub fn is_superset(&self, other: &BTreeSet) -> bool + where + T: Ord, + { other.is_subset(self) } @@ -636,7 +660,10 @@ impl BTreeSet { /// assert_eq!(map.first(), Some(&1)); /// ``` #[unstable(feature = "map_first_last", issue = "62924")] - pub fn first(&self) -> Option<&T> { + pub fn first(&self) -> Option<&T> + where + T: Ord, + { self.map.first_key_value().map(|(k, _)| k) } @@ -659,7 +686,10 @@ impl BTreeSet { /// assert_eq!(map.last(), Some(&2)); /// ``` #[unstable(feature = "map_first_last", issue = "62924")] - pub fn last(&self) -> Option<&T> { + pub fn last(&self) -> Option<&T> + where + T: Ord, + { self.map.last_key_value().map(|(k, _)| k) } @@ -681,7 +711,10 @@ impl BTreeSet { /// assert!(set.is_empty()); /// ``` #[unstable(feature = "map_first_last", issue = "62924")] - pub fn pop_first(&mut self) -> Option { + pub fn pop_first(&mut self) -> Option + where + T: Ord, + { self.map.pop_first().map(|kv| kv.0) } @@ -703,7 +736,10 @@ impl BTreeSet { /// assert!(set.is_empty()); /// ``` #[unstable(feature = "map_first_last", issue = "62924")] - pub fn pop_last(&mut self) -> Option { + pub fn pop_last(&mut self) -> Option + where + T: Ord, + { self.map.pop_last().map(|kv| kv.0) } @@ -728,7 +764,10 @@ impl BTreeSet { /// assert_eq!(set.len(), 1); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn insert(&mut self, value: T) -> bool { + pub fn insert(&mut self, value: T) -> bool + where + T: Ord, + { self.map.insert(value, ()).is_none() } @@ -748,7 +787,10 @@ impl BTreeSet { /// assert_eq!(set.get(&[][..]).unwrap().capacity(), 10); /// ``` #[stable(feature = "set_recovery", since = "1.9.0")] - pub fn replace(&mut self, value: T) -> Option { + pub fn replace(&mut self, value: T) -> Option + where + T: Ord, + { Recover::replace(&mut self.map, value) } @@ -774,7 +816,7 @@ impl BTreeSet { #[stable(feature = "rust1", since = "1.0.0")] pub fn remove(&mut self, value: &Q) -> bool where - T: Borrow, + T: Borrow + Ord, Q: Ord, { self.map.remove(value).is_some() @@ -798,7 +840,7 @@ impl BTreeSet { #[stable(feature = "set_recovery", since = "1.9.0")] pub fn take(&mut self, value: &Q) -> Option where - T: Borrow, + T: Borrow + Ord, Q: Ord, { Recover::take(&mut self.map, value) @@ -823,6 +865,7 @@ impl BTreeSet { #[unstable(feature = "btree_retain", issue = "79025")] pub fn retain(&mut self, mut f: F) where + T: Ord, F: FnMut(&T) -> bool, { self.drain_filter(|v| !f(v)); @@ -857,7 +900,10 @@ impl BTreeSet { /// assert!(a.contains(&5)); /// ``` #[stable(feature = "btree_append", since = "1.11.0")] - pub fn append(&mut self, other: &mut Self) { + pub fn append(&mut self, other: &mut Self) + where + T: Ord, + { self.map.append(&mut other.map); } @@ -893,7 +939,7 @@ impl BTreeSet { #[stable(feature = "btree_split_off", since = "1.11.0")] pub fn split_off(&mut self, key: &Q) -> Self where - T: Borrow, + T: Borrow + Ord, { BTreeSet { map: self.map.split_off(key) } } @@ -928,13 +974,12 @@ impl BTreeSet { #[unstable(feature = "btree_drain_filter", issue = "70530")] pub fn drain_filter<'a, F>(&'a mut self, pred: F) -> DrainFilter<'a, T, F> where + T: Ord, F: 'a + FnMut(&T) -> bool, { DrainFilter { pred, inner: self.map.drain_filter_inner() } } -} -impl BTreeSet { /// Gets an iterator that visits the values in the `BTreeSet` in ascending order. /// /// # Examples diff --git a/library/alloc/src/collections/btree/set/tests.rs b/library/alloc/src/collections/btree/set/tests.rs index fd19c0078a748..79e469eb0db8b 100644 --- a/library/alloc/src/collections/btree/set/tests.rs +++ b/library/alloc/src/collections/btree/set/tests.rs @@ -639,6 +639,26 @@ fn test_send() { } } +#[allow(dead_code)] +fn test_ord_absence() { + fn set(set: BTreeSet) { + set.is_empty(); + set.len(); + set.iter(); + set.into_iter(); + } + + fn set_debug(set: BTreeSet) { + format!("{:?}", set); + format!("{:?}", set.iter()); + format!("{:?}", set.into_iter()); + } + + fn set_clone(mut set: BTreeSet) { + set.clone_from(&set.clone()); + } +} + #[test] fn test_append() { let mut a = BTreeSet::new(); diff --git a/library/core/src/iter/adapters/peekable.rs b/library/core/src/iter/adapters/peekable.rs index 2f8b9653c59da..43301444e3e2c 100644 --- a/library/core/src/iter/adapters/peekable.rs +++ b/library/core/src/iter/adapters/peekable.rs @@ -265,7 +265,6 @@ impl Peekable { /// # Examples /// Consume a number if it's equal to 0. /// ``` - /// #![feature(peekable_next_if)] /// let mut iter = (0..5).peekable(); /// // The first item of the iterator is 0; consume it. /// assert_eq!(iter.next_if(|&x| x == 0), Some(0)); @@ -277,14 +276,13 @@ impl Peekable { /// /// Consume any number less than 10. /// ``` - /// #![feature(peekable_next_if)] /// let mut iter = (1..20).peekable(); /// // Consume all numbers less than 10 /// while iter.next_if(|&x| x < 10).is_some() {} /// // The next value returned will be 10 /// assert_eq!(iter.next(), Some(10)); /// ``` - #[unstable(feature = "peekable_next_if", issue = "72480")] + #[stable(feature = "peekable_next_if", since = "1.51.0")] pub fn next_if(&mut self, func: impl FnOnce(&I::Item) -> bool) -> Option { match self.next() { Some(matched) if func(&matched) => Some(matched), @@ -302,7 +300,6 @@ impl Peekable { /// # Example /// Consume a number if it's equal to 0. /// ``` - /// #![feature(peekable_next_if)] /// let mut iter = (0..5).peekable(); /// // The first item of the iterator is 0; consume it. /// assert_eq!(iter.next_if_eq(&0), Some(0)); @@ -311,7 +308,7 @@ impl Peekable { /// // `next_if_eq` saves the value of the next item if it was not equal to `expected`. /// assert_eq!(iter.next(), Some(1)); /// ``` - #[unstable(feature = "peekable_next_if", issue = "72480")] + #[stable(feature = "peekable_next_if", since = "1.51.0")] pub fn next_if_eq(&mut self, expected: &T) -> Option where T: ?Sized, diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index 05bcd90d3ca76..3760f5c479481 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -172,11 +172,42 @@ use crate::ptr; /// /// ## Initializing a struct field-by-field /// -/// There is currently no supported way to create a raw pointer or reference -/// to a field of a struct inside `MaybeUninit`. That means it is not possible -/// to create a struct by calling `MaybeUninit::uninit::()` and then writing -/// to its fields. +/// You can use `MaybeUninit`, and the [`std::ptr::addr_of_mut`] macro, to initialize structs field by field: /// +/// ```rust +/// use std::mem::MaybeUninit; +/// use std::ptr::addr_of_mut; +/// +/// #[derive(Debug, PartialEq)] +/// pub struct Foo { +/// name: String, +/// list: Vec, +/// } +/// +/// let foo = { +/// let mut uninit: MaybeUninit = MaybeUninit::uninit(); +/// let ptr = uninit.as_mut_ptr(); +/// +/// // Initializing the `name` field +/// unsafe { addr_of_mut!((*ptr).name).write("Bob".to_string()); } +/// +/// // Initializing the `list` field +/// // If there is a panic here, then the `String` in the `name` field leaks. +/// unsafe { addr_of_mut!((*ptr).list).write(vec![0, 1, 2]); } +/// +/// // All the fields are initialized, so we call `assume_init` to get an initialized Foo. +/// unsafe { uninit.assume_init() } +/// }; +/// +/// assert_eq!( +/// foo, +/// Foo { +/// name: "Bob".to_string(), +/// list: vec![0, 1, 2] +/// } +/// ); +/// ``` +/// [`std::ptr::addr_of_mut`]: crate::ptr::addr_of_mut /// [ub]: ../../reference/behavior-considered-undefined.html /// /// # Layout diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index bc0e3e059c917..4dc86e0f5f40f 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -65,7 +65,6 @@ #![feature(unwrap_infallible)] #![feature(option_result_unwrap_unchecked)] #![feature(option_unwrap_none)] -#![feature(peekable_next_if)] #![feature(peekable_peek_mut)] #![feature(partition_point)] #![feature(once_cell)] diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 30ff124dac60f..eecfd337cdf84 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -296,7 +296,12 @@ fn run_test( } }); if let ErrorOutputType::HumanReadable(kind) = options.error_format { - let (_, color_config) = kind.unzip(); + let (short, color_config) = kind.unzip(); + + if short { + compiler.arg("--error-format").arg("short"); + } + match color_config { ColorConfig::Never => { compiler.arg("--color").arg("never"); diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 87a6098e4922b..18bc275572ff0 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -9,7 +9,6 @@ #![feature(in_band_lifetimes)] #![feature(nll)] #![feature(or_patterns)] -#![feature(peekable_next_if)] #![feature(test)] #![feature(crate_visibility_modifier)] #![feature(never_type)] diff --git a/src/test/mir-opt/inline/inline-instruction-set.rs b/src/test/mir-opt/inline/inline-instruction-set.rs new file mode 100644 index 0000000000000..be36ff50c7ef1 --- /dev/null +++ b/src/test/mir-opt/inline/inline-instruction-set.rs @@ -0,0 +1,54 @@ +// Checks that only functions with the compatible instruction_set attributes are inlined. +// +// compile-flags: --target thumbv4t-none-eabi +// needs-llvm-components: arm + +#![crate_type = "lib"] +#![feature(rustc_attrs)] +#![feature(no_core, lang_items)] +#![feature(isa_attribute)] +#![no_core] + +#[rustc_builtin_macro] +#[macro_export] +macro_rules! asm { + ("assembly template", + $(operands,)* + $(options($(option),*))? + ) => { + /* compiler built-in */ + }; +} + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} + +#[instruction_set(arm::a32)] +#[inline] +fn instruction_set_a32() {} + +#[instruction_set(arm::t32)] +#[inline] +fn instruction_set_t32() {} + +#[inline] +fn instruction_set_default() {} + +// EMIT_MIR inline_instruction_set.t32.Inline.diff +#[instruction_set(arm::t32)] +pub fn t32() { + instruction_set_a32(); + instruction_set_t32(); + // The default instruction set is currently + // conservatively assumed to be incompatible. + instruction_set_default(); +} + +// EMIT_MIR inline_instruction_set.default.Inline.diff +pub fn default() { + instruction_set_a32(); + instruction_set_t32(); + instruction_set_default(); +} diff --git a/src/test/mir-opt/inline/inline_instruction_set.default.Inline.diff b/src/test/mir-opt/inline/inline_instruction_set.default.Inline.diff new file mode 100644 index 0000000000000..334cf5a08e2c5 --- /dev/null +++ b/src/test/mir-opt/inline/inline_instruction_set.default.Inline.diff @@ -0,0 +1,45 @@ +- // MIR for `default` before Inline ++ // MIR for `default` after Inline + + fn default() -> () { + let mut _0: (); // return place in scope 0 at $DIR/inline-instruction-set.rs:50:18: 50:18 + let _1: (); // in scope 0 at $DIR/inline-instruction-set.rs:51:5: 51:26 + let _2: (); // in scope 0 at $DIR/inline-instruction-set.rs:52:5: 52:26 + let _3: (); // in scope 0 at $DIR/inline-instruction-set.rs:53:5: 53:30 ++ scope 1 (inlined instruction_set_default) { // at $DIR/inline-instruction-set.rs:53:5: 53:30 ++ } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/inline-instruction-set.rs:51:5: 51:26 + _1 = instruction_set_a32() -> bb1; // scope 0 at $DIR/inline-instruction-set.rs:51:5: 51:26 + // mir::Constant + // + span: $DIR/inline-instruction-set.rs:51:5: 51:24 + // + literal: Const { ty: fn() {instruction_set_a32}, val: Value(Scalar()) } + } + + bb1: { + StorageDead(_1); // scope 0 at $DIR/inline-instruction-set.rs:51:26: 51:27 + StorageLive(_2); // scope 0 at $DIR/inline-instruction-set.rs:52:5: 52:26 + _2 = instruction_set_t32() -> bb2; // scope 0 at $DIR/inline-instruction-set.rs:52:5: 52:26 + // mir::Constant + // + span: $DIR/inline-instruction-set.rs:52:5: 52:24 + // + literal: Const { ty: fn() {instruction_set_t32}, val: Value(Scalar()) } + } + + bb2: { + StorageDead(_2); // scope 0 at $DIR/inline-instruction-set.rs:52:26: 52:27 + StorageLive(_3); // scope 0 at $DIR/inline-instruction-set.rs:53:5: 53:30 +- _3 = instruction_set_default() -> bb3; // scope 0 at $DIR/inline-instruction-set.rs:53:5: 53:30 +- // mir::Constant +- // + span: $DIR/inline-instruction-set.rs:53:5: 53:28 +- // + literal: Const { ty: fn() {instruction_set_default}, val: Value(Scalar()) } +- } +- +- bb3: { ++ _3 = const (); // scope 1 at $DIR/inline-instruction-set.rs:53:5: 53:30 + StorageDead(_3); // scope 0 at $DIR/inline-instruction-set.rs:53:30: 53:31 + _0 = const (); // scope 0 at $DIR/inline-instruction-set.rs:50:18: 54:2 + return; // scope 0 at $DIR/inline-instruction-set.rs:54:2: 54:2 + } + } + diff --git a/src/test/mir-opt/inline/inline_instruction_set.t32.Inline.diff b/src/test/mir-opt/inline/inline_instruction_set.t32.Inline.diff new file mode 100644 index 0000000000000..920b68c9daa1e --- /dev/null +++ b/src/test/mir-opt/inline/inline_instruction_set.t32.Inline.diff @@ -0,0 +1,47 @@ +- // MIR for `t32` before Inline ++ // MIR for `t32` after Inline + + fn t32() -> () { + let mut _0: (); // return place in scope 0 at $DIR/inline-instruction-set.rs:41:14: 41:14 + let _1: (); // in scope 0 at $DIR/inline-instruction-set.rs:42:5: 42:26 + let _2: (); // in scope 0 at $DIR/inline-instruction-set.rs:43:5: 43:26 + let _3: (); // in scope 0 at $DIR/inline-instruction-set.rs:46:5: 46:30 ++ scope 1 (inlined instruction_set_t32) { // at $DIR/inline-instruction-set.rs:43:5: 43:26 ++ } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/inline-instruction-set.rs:42:5: 42:26 + _1 = instruction_set_a32() -> bb1; // scope 0 at $DIR/inline-instruction-set.rs:42:5: 42:26 + // mir::Constant + // + span: $DIR/inline-instruction-set.rs:42:5: 42:24 + // + literal: Const { ty: fn() {instruction_set_a32}, val: Value(Scalar()) } + } + + bb1: { + StorageDead(_1); // scope 0 at $DIR/inline-instruction-set.rs:42:26: 42:27 + StorageLive(_2); // scope 0 at $DIR/inline-instruction-set.rs:43:5: 43:26 +- _2 = instruction_set_t32() -> bb2; // scope 0 at $DIR/inline-instruction-set.rs:43:5: 43:26 +- // mir::Constant +- // + span: $DIR/inline-instruction-set.rs:43:5: 43:24 +- // + literal: Const { ty: fn() {instruction_set_t32}, val: Value(Scalar()) } +- } +- +- bb2: { ++ _2 = const (); // scope 1 at $DIR/inline-instruction-set.rs:43:5: 43:26 + StorageDead(_2); // scope 0 at $DIR/inline-instruction-set.rs:43:26: 43:27 + StorageLive(_3); // scope 0 at $DIR/inline-instruction-set.rs:46:5: 46:30 +- _3 = instruction_set_default() -> bb3; // scope 0 at $DIR/inline-instruction-set.rs:46:5: 46:30 ++ _3 = instruction_set_default() -> bb2; // scope 0 at $DIR/inline-instruction-set.rs:46:5: 46:30 + // mir::Constant + // + span: $DIR/inline-instruction-set.rs:46:5: 46:28 + // + literal: Const { ty: fn() {instruction_set_default}, val: Value(Scalar()) } + } + +- bb3: { ++ bb2: { + StorageDead(_3); // scope 0 at $DIR/inline-instruction-set.rs:46:30: 46:31 + _0 = const (); // scope 0 at $DIR/inline-instruction-set.rs:41:14: 47:2 + return; // scope 0 at $DIR/inline-instruction-set.rs:47:2: 47:2 + } + } + diff --git a/src/test/rustdoc-ui/issue-81662-shortness.rs b/src/test/rustdoc-ui/issue-81662-shortness.rs new file mode 100644 index 0000000000000..27a21a313bc55 --- /dev/null +++ b/src/test/rustdoc-ui/issue-81662-shortness.rs @@ -0,0 +1,12 @@ +// compile-flags:--test --error-format=short +// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR" +// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME" +// failure-status: 101 + +/// ```rust +/// foo(); +/// ``` +//~^^ ERROR cannot find function `foo` in this scope +fn foo() { + println!("Hello, world!"); +} diff --git a/src/test/rustdoc-ui/issue-81662-shortness.stdout b/src/test/rustdoc-ui/issue-81662-shortness.stdout new file mode 100644 index 0000000000000..748113be3a26d --- /dev/null +++ b/src/test/rustdoc-ui/issue-81662-shortness.stdout @@ -0,0 +1,16 @@ + +running 1 test +test $DIR/issue-81662-shortness.rs - foo (line 6) ... FAILED + +failures: + +---- $DIR/issue-81662-shortness.rs - foo (line 6) stdout ---- +$DIR/issue-81662-shortness.rs:7:1: error[E0425]: cannot find function `foo` in this scope +error: aborting due to previous error +Couldn't compile the test. + +failures: + $DIR/issue-81662-shortness.rs - foo (line 6) + +test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME +