diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index a03c561861e2b..9983b98b4f50c 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -201,7 +201,14 @@ language_item_table! { F64, sym::f64, f64_impl, Target::Impl, GenericRequirement::None; F32Runtime, sym::f32_runtime, f32_runtime_impl, Target::Impl, GenericRequirement::None; F64Runtime, sym::f64_runtime, f64_runtime_impl, Target::Impl, GenericRequirement::None; - + ErrorImpl, sym::error_impl, error_impl, Target::Impl, GenericRequirement::None; + ErrorAlloc, sym::error_alloc, error_alloc_impl, Target::Impl, GenericRequirement::None; + ErrorSend, sym::errorsend, errorsend_impl, Target::Impl, GenericRequirement::None; + ErrorSendAlloc, sym::errorsend_alloc, errorsend_alloc_impl, Target::Impl, GenericRequirement::None; + ErrorSendSync, sym::errorsendsync, errorsendsync_impl, Target::Impl, GenericRequirement::None; + ErrorSendSyncAlloc, sym::errorsendsync_alloc, errorsendsync_alloc_impl, Target::Impl, GenericRequirement::None; + + Error, sym::error, error_trait, Target::Trait, GenericRequirement::None; Sized, sym::sized, sized_trait, Target::Trait, GenericRequirement::Exact(0); Unsize, sym::unsize, unsize_trait, Target::Trait, GenericRequirement::Minimum(1); /// Trait injected by `#[derive(PartialEq)]`, (i.e. "Partial EQ"). @@ -211,6 +218,7 @@ language_item_table! { Copy, sym::copy, copy_trait, Target::Trait, GenericRequirement::Exact(0); Clone, sym::clone, clone_trait, Target::Trait, GenericRequirement::None; Sync, sym::sync, sync_trait, Target::Trait, GenericRequirement::Exact(0); + Send, sym::send, send_trait, Target::Trait, GenericRequirement::Exact(0); DiscriminantKind, sym::discriminant_kind, discriminant_kind_trait, Target::Trait, GenericRequirement::None; /// The associated item of the [`DiscriminantKind`] trait. Discriminant, sym::discriminant_type, discriminant_type, Target::AssocTy, GenericRequirement::None; diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index eb6063d76125b..186e81268f32b 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -595,6 +595,14 @@ symbols! { env, eq, ermsb_target_feature, + error, + error_alloc, + error_impl, + errorsend, + errorsend_alloc, + errorsendsync, + errorsendsync_alloc, + errorstatic, exact_div, except, exchange_malloc, @@ -1177,6 +1185,7 @@ symbols! { self_in_typedefs, self_struct_ctor, semitransparent, + send, shl, shl_assign, should_panic, diff --git a/compiler/rustc_typeck/src/check/method/probe.rs b/compiler/rustc_typeck/src/check/method/probe.rs index dc7243960946b..c2b3a96801ee2 100644 --- a/compiler/rustc_typeck/src/check/method/probe.rs +++ b/compiler/rustc_typeck/src/check/method/probe.rs @@ -616,7 +616,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let lang_items = self.tcx.lang_items(); match *self_ty.value.value.kind() { - ty::Dynamic(data, ..) if let Some(p) = data.principal() => { + ty::Dynamic(data, ..) if let Some(p) = data.principal_def_id() => { // Subtle: we can't use `instantiate_query_response` here: using it will // commit to all of the type equalities assumed by inference going through // autoderef (see the `method-probe-no-guessing` test). @@ -639,7 +639,50 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { .instantiate_canonical_with_fresh_inference_vars(self.span, self_ty); self.assemble_inherent_candidates_from_object(generalized_self_ty); - self.assemble_inherent_impl_candidates_for_type(p.def_id()); + + let error_def_id = self.tcx.require_lang_item(hir::LangItem::Error, None); + + if p != error_def_id { + self.assemble_inherent_impl_candidates_for_type(p); + } else { + let send_def_id = self.tcx.require_lang_item(hir::LangItem::Send, None); + let sync_def_id = self.tcx.require_lang_item(hir::LangItem::Sync, None); + + let (mut is_send, mut is_sync) = (false, false); + let bounds = data.auto_traits(); + + for bound in bounds { + if bound == send_def_id { + is_send = true; + } else if bound == sync_def_id { + is_sync = true; + } else { + panic!("unexpected bound: {:?}", bound); + } + } + + match (is_send, is_sync) { + (false, false) => { + let lang_def_id = lang_items.error_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + let lang_def_id = lang_items.error_alloc_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + (true, false) => { + let lang_def_id = lang_items.errorsend_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + let lang_def_id = lang_items.errorsend_alloc_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + (true, true) => { + let lang_def_id = lang_items.errorsendsync_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + let lang_def_id = lang_items.errorsendsync_alloc_impl(); + self.assemble_inherent_impl_for_primitive(lang_def_id); + } + (false, true) => panic!("unexpected combination of marker traits"), + } + } } ty::Adt(def, _) => { self.assemble_inherent_impl_candidates_for_type(def.did); diff --git a/compiler/rustc_typeck/src/coherence/inherent_impls.rs b/compiler/rustc_typeck/src/coherence/inherent_impls.rs index f4e5cce0129c9..dee0c02244d87 100644 --- a/compiler/rustc_typeck/src/coherence/inherent_impls.rs +++ b/compiler/rustc_typeck/src/coherence/inherent_impls.rs @@ -56,8 +56,58 @@ impl<'tcx> ItemLikeVisitor<'_> for InherentCollect<'tcx> { ty::Foreign(did) => { self.check_def_id(item, did); } - ty::Dynamic(data, ..) if data.principal_def_id().is_some() => { - self.check_def_id(item, data.principal_def_id().unwrap()); + ty::Dynamic(data, ..) if let Some(p) = data.principal_def_id() => { + let error_def_id = self.tcx.require_lang_item(hir::LangItem::Error, None); + + if p != error_def_id { + self.check_def_id(item, p); + } else { + let send_def_id = self.tcx.require_lang_item(hir::LangItem::Send, None); + let sync_def_id = self.tcx.require_lang_item(hir::LangItem::Sync, None); + let (mut is_send, mut is_sync) = (false, false); + let bounds = data.auto_traits(); + + for bound in bounds { + if bound == send_def_id { + is_send = true; + } else if bound == sync_def_id { + is_sync = true; + } else { + panic!("unexpected bound: {:?}", bound); + } + } + + match (is_send, is_sync) { + (false, false) => self.check_primitive_impl( + item.def_id, + lang_items.error_impl(), + lang_items.error_alloc_impl(), + "error_alloc_impl", + "dyn error", + item.span, + assoc_items, + ), + (true, false) => self.check_primitive_impl( + item.def_id, + lang_items.errorsend_impl(), + lang_items.errorsend_alloc_impl(), + "errorsend_alloc_impl", + "dyn error", + item.span, + assoc_items, + ), + (true, true) => self.check_primitive_impl( + item.def_id, + lang_items.errorsendsync_impl(), + lang_items.errorsendsync_alloc_impl(), + "errorsendsync_alloc_impl", + "dyn error", + item.span, + assoc_items, + ), + (false, true) => panic!("unexpected combination of marker traits"), + } + } } ty::Dynamic(..) => { struct_span_err!( diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index ab41f5646e5e5..781a30ddead68 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -132,11 +132,17 @@ #![stable(feature = "rust1", since = "1.0.0")] +#[cfg(not(bootstrap))] +use crate::string::String; use core::any::Any; use core::borrow; use core::cmp::Ordering; use core::convert::{From, TryFrom}; +#[cfg(not(bootstrap))] +use core::error::Error; use core::fmt; +#[cfg(not(bootstrap))] +use core::fmt::{Debug, Display}; use core::future::Future; use core::hash::{Hash, Hasher}; #[cfg(not(no_global_oom_handling))] @@ -1960,3 +1966,294 @@ impl Stream for Box { (**self).size_hint() } } + +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg(not(bootstrap))] +impl Error for Box { + #[allow(deprecated, deprecated_in_future)] + fn description(&self) -> &str { + Error::description(&**self) + } + #[allow(deprecated)] + fn cause(&self) -> Option<&dyn Error> { + Error::cause(&**self) + } + fn source(&self) -> Option<&(dyn Error + 'static)> { + Error::source(&**self) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg(not(bootstrap))] +impl<'a, E: Error + 'a> From for Box { + /// Converts a type of [`Error`] into a box of dyn [`Error`]. + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::fmt; + /// use std::mem; + /// + /// #[derive(Debug)] + /// struct AnError; + /// + /// impl fmt::Display for AnError { + /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + /// write!(f, "An error") + /// } + /// } + /// + /// impl Error for AnError {} + /// + /// let an_error = AnError; + /// assert!(0 == mem::size_of_val(&an_error)); + /// let a_boxed_error = Box::::from(an_error); + /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) + /// ``` + fn from(err: E) -> Box { + Box::new(err) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg(not(bootstrap))] +impl<'a, E: Error + Send + Sync + 'a> From for Box { + /// Converts a type of [`Error`] + [`Send`] + [`Sync`] into a box of + /// dyn [`Error`] + [`Send`] + [`Sync`]. + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::fmt; + /// use std::mem; + /// + /// #[derive(Debug)] + /// struct AnError; + /// + /// impl fmt::Display for AnError { + /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + /// write!(f, "An error") + /// } + /// } + /// + /// impl Error for AnError {} + /// + /// unsafe impl Send for AnError {} + /// + /// unsafe impl Sync for AnError {} + /// + /// let an_error = AnError; + /// assert!(0 == mem::size_of_val(&an_error)); + /// let a_boxed_error = Box::::from(an_error); + /// assert!( + /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) + /// ``` + fn from(err: E) -> Box { + Box::new(err) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg(not(bootstrap))] +impl From for Box { + /// Converts a [`String`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::mem; + /// + /// let a_string_error = "a string error".to_string(); + /// let a_boxed_error = Box::::from(a_string_error); + /// assert!( + /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) + /// ``` + #[inline] + fn from(err: String) -> Box { + struct StringError(String); + + impl Error for StringError { + #[allow(deprecated)] + fn description(&self) -> &str { + &self.0 + } + } + + impl Display for StringError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + Display::fmt(&self.0, f) + } + } + + // Purposefully skip printing "StringError(..)" + impl Debug for StringError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + Debug::fmt(&self.0, f) + } + } + + Box::new(StringError(err)) + } +} + +#[stable(feature = "string_box_error", since = "1.6.0")] +#[cfg(not(bootstrap))] +impl From for Box { + /// Converts a [`String`] into a box of dyn [`Error`]. + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::mem; + /// + /// let a_string_error = "a string error".to_string(); + /// let a_boxed_error = Box::::from(a_string_error); + /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) + /// ``` + fn from(str_err: String) -> Box { + let err1: Box = From::from(str_err); + let err2: Box = err1; + err2 + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg(not(bootstrap))] +impl<'a> From<&str> for Box { + /// Converts a [`str`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. + /// + /// [`str`]: prim@str + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::mem; + /// + /// let a_str_error = "a str error"; + /// let a_boxed_error = Box::::from(a_str_error); + /// assert!( + /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) + /// ``` + #[inline] + fn from(err: &str) -> Box { + From::from(String::from(err)) + } +} + +#[stable(feature = "string_box_error", since = "1.6.0")] +#[cfg(not(bootstrap))] +impl From<&str> for Box { + /// Converts a [`str`] into a box of dyn [`Error`]. + /// + /// [`str`]: prim@str + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::mem; + /// + /// let a_str_error = "a str error"; + /// let a_boxed_error = Box::::from(a_str_error); + /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) + /// ``` + fn from(err: &str) -> Box { + From::from(String::from(err)) + } +} + +#[stable(feature = "cow_box_error", since = "1.22.0")] +#[cfg(not(bootstrap))] +impl<'a, 'b> From> for Box { + /// Converts a [`Cow`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::mem; + /// use std::borrow::Cow; + /// + /// let a_cow_str_error = Cow::from("a str error"); + /// let a_boxed_error = Box::::from(a_cow_str_error); + /// assert!( + /// mem::size_of::>() == mem::size_of_val(&a_boxed_error)) + /// ``` + fn from(err: Cow<'b, str>) -> Box { + From::from(String::from(err)) + } +} + +#[stable(feature = "cow_box_error", since = "1.22.0")] +#[cfg(not(bootstrap))] +impl<'a> From> for Box { + /// Converts a [`Cow`] into a box of dyn [`Error`]. + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::mem; + /// use std::borrow::Cow; + /// + /// let a_cow_str_error = Cow::from("a str error"); + /// let a_boxed_error = Box::::from(a_cow_str_error); + /// assert!(mem::size_of::>() == mem::size_of_val(&a_boxed_error)) + /// ``` + fn from(err: Cow<'a, str>) -> Box { + From::from(String::from(err)) + } +} + +#[cfg(not(bootstrap))] +#[lang = "error_alloc"] +impl dyn Error { + #[inline] + #[stable(feature = "error_downcast", since = "1.3.0")] + /// Attempts to downcast the box to a concrete type. + pub fn downcast(self: Box) -> Result, Box> { + if self.is::() { + unsafe { + let raw: *mut dyn Error = Box::into_raw(self); + Ok(Box::from_raw(raw as *mut T)) + } + } else { + Err(self) + } + } +} + +#[cfg(not(bootstrap))] +#[lang = "errorsend_alloc"] +impl dyn Error + Send { + #[inline] + #[stable(feature = "error_downcast", since = "1.3.0")] + /// Attempts to downcast the box to a concrete type. + pub fn downcast(self: Box) -> Result, Box> { + let err: Box = self; + ::downcast(err).map_err(|s| unsafe { + // Reapply the `Send` marker. + mem::transmute::, Box>(s) + }) + } +} + +#[cfg(not(bootstrap))] +#[lang = "errorsendsync_alloc"] +impl dyn Error + Send + Sync { + #[inline] + #[stable(feature = "error_downcast", since = "1.3.0")] + /// Attempts to downcast the box to a concrete type. + pub fn downcast(self: Box) -> Result, Box> { + let err: Box = self; + ::downcast(err).map_err(|s| unsafe { + // Reapply the `Send + Sync` marker. + mem::transmute::, Box>(s) + }) + } +} diff --git a/library/alloc/src/collections/btree/map/entry.rs b/library/alloc/src/collections/btree/map/entry.rs index 5cef007a46f0d..119db51143a08 100644 --- a/library/alloc/src/collections/btree/map/entry.rs +++ b/library/alloc/src/collections/btree/map/entry.rs @@ -514,3 +514,14 @@ impl<'a, K: Ord, V> OccupiedEntry<'a, K, V> { old_kv } } + +#[unstable(feature = "map_try_insert", issue = "82766")] +#[cfg(not(bootstrap))] +impl<'a, K: Debug + Ord, V: Debug> core::error::Error + for crate::collections::btree_map::OccupiedError<'a, K, V> +{ + #[allow(deprecated)] + fn description(&self) -> &str { + "key already exists" + } +} diff --git a/library/alloc/src/collections/mod.rs b/library/alloc/src/collections/mod.rs index 1ea135a2aed82..6f62df6a9b95b 100644 --- a/library/alloc/src/collections/mod.rs +++ b/library/alloc/src/collections/mod.rs @@ -152,3 +152,7 @@ trait SpecExtend { /// Extends `self` with the contents of the given iterator. fn spec_extend(&mut self, iter: I); } + +#[stable(feature = "try_reserve", since = "1.57.0")] +#[cfg(not(bootstrap))] +impl core::error::Error for TryReserveError {} diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index b151842458d35..adacaa0371dc1 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -2858,3 +2858,21 @@ impl From for String { c.to_string() } } + +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg(not(bootstrap))] +impl core::error::Error for FromUtf8Error { + #[allow(deprecated)] + fn description(&self) -> &str { + "invalid utf-8" + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg(not(bootstrap))] +impl core::error::Error for FromUtf16Error { + #[allow(deprecated)] + fn description(&self) -> &str { + "invalid utf-16" + } +} diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 7c065f37d1fa8..28d23a8a686cc 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -39,6 +39,8 @@ use crate::rc::is_dangling; use crate::string::String; #[cfg(not(no_global_oom_handling))] use crate::vec::Vec; +#[cfg(not(bootstrap))] +use core::error::Error; #[cfg(test)] mod tests; @@ -2642,3 +2644,21 @@ fn data_offset_align(align: usize) -> isize { let layout = Layout::new::>(); (layout.size() + layout.padding_needed_for(align)) as isize } + +#[stable(feature = "arc_error", since = "1.52.0")] +#[cfg(not(bootstrap))] +impl Error for Arc { + #[allow(deprecated, deprecated_in_future)] + fn description(&self) -> &str { + Error::description(&**self) + } + + #[allow(deprecated)] + fn cause(&self) -> Option<&dyn Error> { + Error::cause(&**self) + } + + fn source(&self) -> Option<&(dyn Error + 'static)> { + Error::source(&**self) + } +} diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs index ea639268652c3..2eaf39838c161 100644 --- a/library/core/src/alloc/layout.rs +++ b/library/core/src/alloc/layout.rs @@ -442,3 +442,7 @@ impl fmt::Display for LayoutError { f.write_str("invalid parameters to Layout::from_size_align") } } + +#[stable(feature = "alloc_layout", since = "1.28.0")] +#[cfg(not(bootstrap))] +impl crate::error::Error for LayoutError {} diff --git a/library/core/src/alloc/mod.rs b/library/core/src/alloc/mod.rs index 1f1033b0437f8..22dd53fe37f19 100644 --- a/library/core/src/alloc/mod.rs +++ b/library/core/src/alloc/mod.rs @@ -404,3 +404,11 @@ where unsafe { (**self).shrink(ptr, old_layout, new_layout) } } } + +#[unstable( + feature = "allocator_api", + reason = "the precise API and guarantees it provides may be tweaked.", + issue = "32838" +)] +#[cfg(not(bootstrap))] +impl crate::error::Error for AllocError {} diff --git a/library/core/src/any.rs b/library/core/src/any.rs index 72528185707a6..f64dc48450b53 100644 --- a/library/core/src/any.rs +++ b/library/core/src/any.rs @@ -1,5 +1,9 @@ -//! This module implements the `Any` trait, which enables dynamic typing -//! of any `'static` type through runtime reflection. +//! This module contains the `Any` trait, which enables dynamic typing +//! of any `'static` type through runtime reflection. It also contains the +//! `Provider` trait and accompanying API, which enable trait objects to provide +//! data based on typed requests, an alternate form of runtime reflection. +//! +//! # `Any` and `TypeId` //! //! `Any` itself can be used to get a `TypeId`, and has more features when used //! as a trait object. As `&dyn Any` (a borrowed trait object), it has the `is` @@ -37,7 +41,7 @@ //! assert_eq!(boxed_id, TypeId::of::>()); //! ``` //! -//! # Examples +//! ## Examples //! //! Consider a situation where we want to log out a value passed to a function. //! We know the value we're working on implements Debug, but we don't know its @@ -81,6 +85,80 @@ //! do_work(&my_i8); //! } //! ``` +//! +//! # `Provider`, `TypeTag`, and `Requisition` +//! +//! `Provider` and the associated APIs support generic, type-driven access to data, and a mechanism +//! for implementers to provide such data. The key parts of the interface are the `Provider` +//! trait for objects which can provide data, and the [`request_by_type_tag`] function for +//! data from an object which implements `Provider`. Note that end users should not call +//! requesting `request_by_type_tag` directly, it is a helper function for intermediate implementers +//! to use to implement a user-facing interface. +//! +//! Typically, a data provider is a trait object of a trait which extends `Provider`. A user will +//! request data from the trait object by specifying the type or a type tag (a type tag is a type +//! used only as a type parameter to identify the type which the user wants to receive). +//! +//! ## Data flow +//! +//! * A user requests an object, which is delegated to `request_by_type_tag` +//! * `request_by_type_tag` creates a `Requisition` object and passes it to `Provider::provide` +//! * The object provider's implementation of `Provider::provide` tries providing values of +//! different types using `Requisition::provide_*`. If the type tag matches the type requested by +//! the user, it will be stored in the `Requisition` object. +//! * `request_by_type_tag` unpacks the `Requisition` object and returns any stored value to the +//! user. +//! +//! ## Examples +//! +//! ``` +//! # #![allow(incomplete_features)] +//! # #![feature(provide_any)] +//! # #![feature(trait_upcasting)] +//! use std::any::{Provider, Requisition, TypeTag, request_by_type_tag, tags}; +//! +//! // Definition of MyTrait +//! trait MyTrait: Provider { +//! // ... +//! } +//! +//! // Methods on `MyTrait` trait objects. +//! impl dyn MyTrait + '_ { +//! /// Common case: get a reference to a field of the error. +//! pub fn get_context_ref(&self) -> Option<&T> { +//! request_by_type_tag::<'_, tags::Ref>(self) +//! } +//! +//! /// Fully general, but uncommon case. Get context using a type tag, allows for fetching +//! /// context with complex lifetimes. +//! pub fn get_context_by_type_tag<'a, I: TypeTag<'a>>(&'a self) -> Option { +//! request_by_type_tag::<'_, I>(self) +//! } +//! } +//! +//! // Downstream implementation of `MyTrait` and `Provider`. +//! # struct SomeConcreteType { some_string: String } +//! impl MyTrait for SomeConcreteType { +//! // ... +//! } +//! +//! impl Provider for SomeConcreteType { +//! fn provide<'a>(&'a self, mut req: Requisition<'a, '_>) { +//! req.provide_ref::(&self.some_string); +//! } +//! } +//! +//! // Downstream usage of `MyTrait`. +//! fn use_my_trait(obj: &dyn MyTrait) { +//! // Request a &String from obj. +//! let _ = obj.get_context_ref::().unwrap(); +//! // Request a &String from obj using a type tag. +//! let _ = obj.get_context_by_type_tag::>().unwrap(); +//! } +//! ``` +//! +//! In this example, if the concrete type of `obj` in `use_my_trait` is `SomeConcreteType`, then +//! both the `get_context_*` calls will return a reference to `obj.some_string`. #![stable(feature = "rust1", since = "1.0.0")] @@ -700,3 +778,252 @@ pub const fn type_name() -> &'static str { pub const fn type_name_of_val(_val: &T) -> &'static str { type_name::() } + +/////////////////////////////////////////////////////////////////////////////// +// Provider trait +/////////////////////////////////////////////////////////////////////////////// + +/// Trait implemented by a type which can dynamically provide tagged values. +#[unstable(feature = "provide_any", issue = "none")] +pub trait Provider { + /// Object providers should implement this method to provide *all* values they are able to + /// provide using `req`. + #[unstable(feature = "provide_any", issue = "none")] + fn provide<'a>(&'a self, req: Requisition<'a, '_>); +} + +/// Request a specific value by a given tag from the `Provider`. +#[unstable(feature = "provide_any", issue = "none")] +pub fn request_by_type_tag<'a, I, P: Provider + ?Sized>(provider: &'a P) -> Option +where + I: TypeTag<'a>, +{ + let mut req: ConcreteRequisition<'a, I> = RequisitionImpl { tagged: TagValue(None) }; + provider.provide(Requisition(&mut req)); + req.tagged.0 +} + +/////////////////////////////////////////////////////////////////////////////// +// Type tags and the Tagged trait +/////////////////////////////////////////////////////////////////////////////// + +/// This trait is implemented by specific `TypeTag` types in order to allow +/// describing a type which can be requested for a given lifetime `'a`. +/// +/// A few example implementations for type-driven `TypeTag`s can be found in the +/// [`tags`] module, although crates may also implement their own tags for more +/// complex types with internal lifetimes. +#[unstable(feature = "provide_any", issue = "none")] +pub trait TypeTag<'a>: Sized + 'static { + /// The type of values which may be tagged by this `TypeTag` for the given + /// lifetime. + #[unstable(feature = "provide_any", issue = "none")] + type Type: 'a; +} + +#[unstable(feature = "provide_any", issue = "none")] +pub mod tags { + //! Type tags are used to identify a type using a separate value. This module includes type tags + //! for some very common types. + //! + //! Many users of the provider APIs will not need to use type tags at all. But if you want to + //! use them with more complex types (typically those including lifetime parameters), you will + //! need to write your own tags. + + use super::TypeTag; + use crate::marker::PhantomData; + + /// Type-based `TypeTag` for `&'a T` types. + #[derive(Debug)] + #[unstable(feature = "provide_any", issue = "none")] + pub struct Ref(PhantomData); + + #[unstable(feature = "provide_any", issue = "none")] + impl<'a, T: ?Sized + 'static> TypeTag<'a> for Ref { + type Type = &'a T; + } + + /// Type-based `TypeTag` for `&'a mut T` types. + #[derive(Debug)] + #[unstable(feature = "provide_any", issue = "none")] + pub struct RefMut(PhantomData); + + #[unstable(feature = "provide_any", issue = "none")] + impl<'a, T: ?Sized + 'static> TypeTag<'a> for RefMut { + type Type = &'a mut T; + } + + /// Type-based `TypeTag` for static `T` types. + #[derive(Debug)] + #[unstable(feature = "provide_any", issue = "none")] + pub struct Value(PhantomData); + + #[unstable(feature = "provide_any", issue = "none")] + impl<'a, T: 'static> TypeTag<'a> for Value { + type Type = T; + } + + /// Tag combinator to wrap the given tag's value in an `Option` + #[derive(Debug)] + #[unstable(feature = "provide_any", issue = "none")] + pub struct OptionTag(PhantomData); + + #[unstable(feature = "provide_any", issue = "none")] + impl<'a, I: TypeTag<'a>> TypeTag<'a> for OptionTag { + type Type = Option; + } + + /// Tag combinator to wrap the given tag's value in an `Result` + #[derive(Debug)] + #[unstable(feature = "provide_any", issue = "none")] + pub struct ResultTag(PhantomData, PhantomData); + + #[unstable(feature = "provide_any", issue = "none")] + impl<'a, I: TypeTag<'a>, E: TypeTag<'a>> TypeTag<'a> for ResultTag { + type Type = Result; + } +} + +/// Sealed trait representing a type-erased tagged object. +/// +/// This trait is exclusively implemented by the `TagValue` type, and cannot be +/// implemented outside of this crate due to being sealed. +unsafe trait Tagged<'a>: 'a { + /// The `TypeId` of the `TypeTag` this value was tagged with. + fn tag_id(&self) -> TypeId; +} + +/// A concrete tagged value for a given tag `I`. +/// +/// This is the only type which implements the `Tagged` trait, and encodes +/// additional information about the specific `TypeTag` into the type. This allows +/// for multiple different tags to support overlapping value ranges, for +/// example, both the `Ref` and `Value<&'static str>` tags can be used to +/// tag a value of type `&'static str`. +#[repr(transparent)] +struct TagValue<'a, I: TypeTag<'a>>(I::Type); + +unsafe impl<'a, I> Tagged<'a> for TagValue<'a, I> +where + I: TypeTag<'a>, +{ + fn tag_id(&self) -> TypeId { + TypeId::of::() + } +} + +macro_rules! tagged_methods { + ($($T: ty),*) => {$( + impl<'a> $T { + /// Returns `true` if the dynamic type is tagged with `I`. + #[inline] + fn is(&self) -> bool + where + I: TypeTag<'a>, + { + self.tag_id() == TypeId::of::() + } + + /// Returns some reference to the dynamic value if it is tagged with `I`, + /// or `None` if it isn't. + #[inline] + fn downcast_mut(&mut self) -> Option<&mut TagValue<'a, I>> + where + I: TypeTag<'a>, + { + if self.is::() { + // SAFETY: Just checked whether we're pointing to a + // `TagValue<'a, I>`. + unsafe { Some(&mut *(self as *mut Self as *mut TagValue<'a, I>)) } + } else { + None + } + } + } + )*}; +} + +tagged_methods!(dyn Tagged<'a>, dyn Tagged<'a> + Send); + +/////////////////////////////////////////////////////////////////////////////// +// Requisition and its methods +/////////////////////////////////////////////////////////////////////////////// + +/// A helper object for providing objects by type. +/// +/// An object provider provides values by calling this type's provide methods. +#[allow(missing_debug_implementations)] +#[unstable(feature = "provide_any", issue = "none")] +pub struct Requisition<'a, 'b>(&'b mut RequisitionImpl + 'a>); + +/// A helper object for providing objects by type. +/// +/// An object provider provides values by calling this type's provide methods. Since this version +/// is `Send` it can be sent between threads to facilitate data being accessed and provided on +/// different threads. However, this restricts the data which can be provided to `Send` data. +#[allow(missing_debug_implementations)] +#[unstable(feature = "provide_any", issue = "none")] +pub struct SendRequisition<'a, 'b>(&'b mut RequisitionImpl + 'a + Send>); + +macro_rules! req_methods { + ($($T: ident),*) => {$( + impl<'a, 'b> $T<'a, 'b> { + /// Provide a value or other type with only static lifetimes. + #[unstable(feature = "provide_any", issue = "none")] + pub fn provide_value(&mut self, f: F) -> &mut Self + where + T: 'static, + F: FnOnce() -> T, + { + self.provide_with::, F>(f) + } + + /// Provide a reference, note that the referee type must be bounded by `'static`, but may be unsized. + #[unstable(feature = "provide_any", issue = "none")] + pub fn provide_ref(&mut self, value: &'a T) -> &mut Self { + self.provide::>(value) + } + + /// Provide a value with the given `TypeTag`. + #[unstable(feature = "provide_any", issue = "none")] + pub fn provide(&mut self, value: I::Type) -> &mut Self + where + I: TypeTag<'a>, + { + if let Some(res @ TagValue(None)) = self.0.tagged.downcast_mut::>() { + res.0 = Some(value); + } + self + } + + /// Provide a value with the given `TypeTag`, using a closure to prevent unnecessary work. + #[unstable(feature = "provide_any", issue = "none")] + pub fn provide_with(&mut self, f: F) -> &mut Self + where + I: TypeTag<'a>, + F: FnOnce() -> I::Type, + { + if let Some(res @ TagValue(None)) = self.0.tagged.downcast_mut::>() { + res.0 = Some(f()); + } + self + } + } + )*}; +} + +req_methods!(Requisition, SendRequisition); + +/// A concrete request for a tagged value. Can be coerced to `Requisition` to be +/// passed to provider methods. +type ConcreteRequisition<'a, I> = RequisitionImpl>>; + +/// Implementation detail shared between `Requisition` and `ConcreteRequisition`. +/// +/// Generally this value is used through the `Requisition` type as an `&mut +/// Requisition<'a>` out parameter, or constructed with the `ConcreteRequisition<'a, I>` +/// type alias. +#[repr(transparent)] +struct RequisitionImpl { + tagged: T, +} diff --git a/library/core/src/error.rs b/library/core/src/error.rs new file mode 100644 index 0000000000000..0bc81c52137db --- /dev/null +++ b/library/core/src/error.rs @@ -0,0 +1,506 @@ +//! Traits for working with Errors. +use crate::any::{Provider, Requisition, TypeId}; +use crate::fmt::{Debug, Display}; +use crate::{array, cell, char, fmt, num, str, time}; + +/// `Error` is a trait representing the basic expectations for error values, +/// i.e., values of type `E` in [`Result`]. +/// +/// Errors must describe themselves through the [`Display`] and [`Debug`] +/// traits. Error messages are typically concise lowercase sentences without +/// trailing punctuation: +/// +/// ``` +/// let err = "NaN".parse::().unwrap_err(); +/// assert_eq!(err.to_string(), "invalid digit found in string"); +/// ``` +/// +/// Errors may provide cause chain information. [`Error::source()`] is generally +/// used when errors cross "abstraction boundaries". If one module must report +/// an error that is caused by an error from a lower-level module, it can allow +/// accessing that error via [`Error::source()`]. This makes it possible for the +/// high-level module to provide its own errors while also revealing some of the +/// implementation for debugging via `source` chains. +#[stable(feature = "rust1", since = "1.0.0")] +#[lang = "error"] +pub trait Error: Debug + Display + Provider { + /// The lower-level source of this error, if any. + /// + /// # Examples + /// + /// ``` + /// use std::error::Error; + /// use std::fmt; + /// + /// #[derive(Debug)] + /// struct SuperError { + /// side: SuperErrorSideKick, + /// } + /// + /// impl fmt::Display for SuperError { + /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + /// write!(f, "SuperError is here!") + /// } + /// } + /// + /// impl Error for SuperError { + /// fn source(&self) -> Option<&(dyn Error + 'static)> { + /// Some(&self.side) + /// } + /// } + /// + /// #[derive(Debug)] + /// struct SuperErrorSideKick; + /// + /// impl fmt::Display for SuperErrorSideKick { + /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + /// write!(f, "SuperErrorSideKick is here!") + /// } + /// } + /// + /// impl Error for SuperErrorSideKick {} + /// + /// fn get_super_error() -> Result<(), SuperError> { + /// Err(SuperError { side: SuperErrorSideKick }) + /// } + /// + /// fn main() { + /// match get_super_error() { + /// Err(e) => { + /// println!("Error: {}", e); + /// println!("Caused by: {}", e.source().unwrap()); + /// } + /// _ => println!("No error"), + /// } + /// } + /// ``` + #[stable(feature = "error_source", since = "1.30.0")] + fn source(&self) -> Option<&(dyn Error + 'static)> { + core::any::request_by_type_tag::<'_, core::any::tags::Ref, _>(self) + } + + /// Gets the `TypeId` of `self`. + #[doc(hidden)] + #[unstable( + feature = "error_type_id", + reason = "this is memory-unsafe to override in user code", + issue = "60784" + )] + fn type_id(&self, _: private::Internal) -> TypeId + where + Self: 'static, + { + TypeId::of::() + } + + /// ``` + /// if let Err(e) = "xc".parse::() { + /// // Print `e` itself, no need for description(). + /// eprintln!("Error: {}", e); + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_deprecated(since = "1.42.0", reason = "use the Display impl or to_string()")] + fn description(&self) -> &str { + "description() is deprecated; use Display" + } + + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_deprecated( + since = "1.33.0", + reason = "replaced by Error::source, which can support downcasting" + )] + #[allow(missing_docs)] + fn cause(&self) -> Option<&dyn Error> { + self.source() + } + + /// Provides type based access to context intended for error reports. + /// + /// Used in conjunction with [`context`] and [`context_ref`] to extract + /// references to member variables from `dyn Error` trait objects. + /// + /// # Example + /// + /// ```rust + /// #![feature(provide_any)] + /// #![feature(error_in_core)] + /// use core::fmt; + /// use core::any::Requisition; + /// + /// #[derive(Debug)] + /// struct MyBacktrace { + /// // ... + /// } + /// + /// impl MyBacktrace { + /// fn new() -> MyBacktrace { + /// // ... + /// # MyBacktrace {} + /// } + /// } + /// + /// #[derive(Debug)] + /// struct SourceError { + /// // ... + /// } + /// + /// impl fmt::Display for SourceError { + /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + /// write!(f, "Example Source Error") + /// } + /// } + /// + /// impl std::error::Error for SourceError {} + /// + /// #[derive(Debug)] + /// struct Error { + /// source: SourceError, + /// backtrace: MyBacktrace, + /// } + /// + /// impl fmt::Display for Error { + /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + /// write!(f, "Example Error") + /// } + /// } + /// + /// impl std::error::Error for Error { + /// fn provide<'a>(&'a self, mut req: Requisition<'a, '_>) { + /// req + /// .provide_ref::(&self.backtrace) + /// .provide_ref::(&self.source); + /// } + /// } + /// + /// fn main() { + /// let backtrace = MyBacktrace::new(); + /// let source = SourceError {}; + /// let error = Error { source, backtrace }; + /// let dyn_error = &error as &dyn std::error::Error; + /// let backtrace_ref = dyn_error.request_ref::().unwrap(); + /// + /// assert!(core::ptr::eq(&error.backtrace, backtrace_ref)); + /// } + /// ``` + #[unstable(feature = "provide_any", issue = "none")] + fn provide<'a>(&'a self, _req: Requisition<'a, '_>) { } +} + +impl Provider for T +where + T: Error, +{ + fn provide<'a>(&'a self, req: Requisition<'a, '_>) { + Error::provide(self, req); + } +} + +mod private { + // This is a hack to prevent `type_id` from being overridden by `Error` + // implementations, since that can enable unsound downcasting. + #[unstable(feature = "error_type_id", issue = "60784")] + #[derive(Debug)] + pub struct Internal; +} + +#[unstable(feature = "never_type", issue = "35121")] +impl Error for ! {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Error for str::ParseBoolError { + #[allow(deprecated)] + fn description(&self) -> &str { + "failed to parse bool" + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Error for str::Utf8Error { + #[allow(deprecated)] + fn description(&self) -> &str { + "invalid utf-8: corrupt contents" + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Error for num::ParseIntError { + #[allow(deprecated)] + fn description(&self) -> &str { + self.__description() + } +} + +#[stable(feature = "try_from", since = "1.34.0")] +impl Error for num::TryFromIntError { + #[allow(deprecated)] + fn description(&self) -> &str { + self.__description() + } +} + +#[stable(feature = "try_from", since = "1.34.0")] +impl Error for array::TryFromSliceError { + #[allow(deprecated)] + fn description(&self) -> &str { + self.__description() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Error for num::ParseFloatError { + #[allow(deprecated)] + fn description(&self) -> &str { + self.__description() + } +} + +#[stable(feature = "str_parse_error2", since = "1.8.0")] +impl Error for crate::convert::Infallible { + fn description(&self) -> &str { + match *self {} + } +} + +#[stable(feature = "decode_utf16", since = "1.9.0")] +impl Error for char::DecodeUtf16Error { + #[allow(deprecated)] + fn description(&self) -> &str { + "unpaired surrogate found" + } +} + +#[stable(feature = "error_by_ref", since = "1.51.0")] +impl<'a, T: Error + ?Sized> Error for &'a T { + #[allow(deprecated, deprecated_in_future)] + fn description(&self) -> &str { + Error::description(&**self) + } + + #[allow(deprecated)] + fn cause(&self) -> Option<&dyn Error> { + Error::cause(&**self) + } + + fn source(&self) -> Option<&(dyn Error + 'static)> { + Error::source(&**self) + } +} + +#[stable(feature = "fmt_error", since = "1.11.0")] +impl Error for fmt::Error { + #[allow(deprecated)] + fn description(&self) -> &str { + "an error occurred when formatting an argument" + } +} + +#[stable(feature = "try_borrow", since = "1.13.0")] +impl Error for cell::BorrowError { + #[allow(deprecated)] + fn description(&self) -> &str { + "already mutably borrowed" + } +} + +#[stable(feature = "try_borrow", since = "1.13.0")] +impl Error for cell::BorrowMutError { + #[allow(deprecated)] + fn description(&self) -> &str { + "already borrowed" + } +} + +#[stable(feature = "try_from", since = "1.34.0")] +impl Error for char::CharTryFromError { + #[allow(deprecated)] + fn description(&self) -> &str { + "converted integer out of range for `char`" + } +} + +#[stable(feature = "char_from_str", since = "1.20.0")] +impl Error for char::ParseCharError { + #[allow(deprecated)] + fn description(&self) -> &str { + self.__description() + } +} + +#[unstable(feature = "duration_checked_float", issue = "83400")] +impl Error for time::FromSecsError {} + +// Copied from `any.rs`. +#[lang = "error_impl"] +impl dyn Error + 'static { + /// Returns `true` if the boxed type is the same as `T` + #[stable(feature = "error_downcast", since = "1.3.0")] + #[inline] + pub fn is(&self) -> bool { + // Get `TypeId` of the type this function is instantiated with. + let t = TypeId::of::(); + + // Get `TypeId` of the type in the trait object. + let boxed = self.type_id(private::Internal); + + // Compare both `TypeId`s on equality. + t == boxed + } + + /// Returns some reference to the boxed value if it is of type `T`, or + /// `None` if it isn't. + #[stable(feature = "error_downcast", since = "1.3.0")] + #[inline] + pub fn downcast_ref(&self) -> Option<&T> { + if self.is::() { + // SAFETY: `is` ensures this type cast is correct + unsafe { Some(&*(self as *const dyn Error as *const T)) } + } else { + None + } + } + + /// Returns some mutable reference to the boxed value if it is of type `T`, or + /// `None` if it isn't. + #[stable(feature = "error_downcast", since = "1.3.0")] + #[inline] + pub fn downcast_mut(&mut self) -> Option<&mut T> { + if self.is::() { + // SAFETY: `is` ensures this type cast is correct + unsafe { Some(&mut *(self as *mut dyn Error as *mut T)) } + } else { + None + } + } + + /// Returns an iterator starting with the current error and continuing with + /// recursively calling [`Error::source`]. + /// + /// If you want to omit the current error and only use its sources, + /// use `skip(1)`. + /// + /// # Examples + /// + /// ``` + /// #![feature(error_iter)] + /// use std::error::Error; + /// use std::fmt; + /// + /// #[derive(Debug)] + /// struct A; + /// + /// #[derive(Debug)] + /// struct B(Option>); + /// + /// impl fmt::Display for A { + /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + /// write!(f, "A") + /// } + /// } + /// + /// impl fmt::Display for B { + /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + /// write!(f, "B") + /// } + /// } + /// + /// impl Error for A {} + /// + /// impl Error for B { + /// fn source(&self) -> Option<&(dyn Error + 'static)> { + /// self.0.as_ref().map(|e| e.as_ref()) + /// } + /// } + /// + /// let b = B(Some(Box::new(A))); + /// + /// // let err : Box = b.into(); // or + /// let err = &b as &(dyn Error); + /// + /// let mut iter = err.chain(); + /// + /// assert_eq!("B".to_string(), iter.next().unwrap().to_string()); + /// assert_eq!("A".to_string(), iter.next().unwrap().to_string()); + /// assert!(iter.next().is_none()); + /// assert!(iter.next().is_none()); + /// ``` + #[unstable(feature = "error_iter", issue = "58520")] + #[inline] + pub fn chain(&self) -> Chain<'_> { + Chain { current: Some(self) } + } + + /// Request a reference to context of type `T`. + pub fn request_ref(&self) -> Option<&T> { + core::any::request_by_type_tag::<'_, core::any::tags::Ref, _>(self) + } +} + +#[lang = "errorsend"] +impl dyn Error + 'static + Send { + /// Forwards to the method defined on the type `dyn Error`. + #[stable(feature = "error_downcast", since = "1.3.0")] + #[inline] + pub fn is(&self) -> bool { + ::is::(self) + } + + /// Forwards to the method defined on the type `dyn Error`. + #[stable(feature = "error_downcast", since = "1.3.0")] + #[inline] + pub fn downcast_ref(&self) -> Option<&T> { + ::downcast_ref::(self) + } + + /// Forwards to the method defined on the type `dyn Error`. + #[stable(feature = "error_downcast", since = "1.3.0")] + #[inline] + pub fn downcast_mut(&mut self) -> Option<&mut T> { + ::downcast_mut::(self) + } +} + +#[lang = "errorsendsync"] +impl dyn Error + 'static + Send + Sync { + /// Forwards to the method defined on the type `dyn Error`. + #[stable(feature = "error_downcast", since = "1.3.0")] + #[inline] + pub fn is(&self) -> bool { + ::is::(self) + } + + /// Forwards to the method defined on the type `dyn Error`. + #[stable(feature = "error_downcast", since = "1.3.0")] + #[inline] + pub fn downcast_ref(&self) -> Option<&T> { + ::downcast_ref::(self) + } + + /// Forwards to the method defined on the type `dyn Error`. + #[stable(feature = "error_downcast", since = "1.3.0")] + #[inline] + pub fn downcast_mut(&mut self) -> Option<&mut T> { + ::downcast_mut::(self) + } +} + +/// An iterator over an [`Error`] and its sources. +/// +/// If you want to omit the initial error and only process +/// its sources, use `skip(1)`. +#[unstable(feature = "error_iter", issue = "58520")] +#[derive(Clone, Debug)] +pub struct Chain<'a> { + current: Option<&'a (dyn Error + 'static)>, +} + +#[unstable(feature = "error_iter", issue = "58520")] +impl<'a> Iterator for Chain<'a> { + type Item = &'a (dyn Error + 'static); + + fn next(&mut self) -> Option { + let current = self.current; + self.current = self.current.and_then(Error::source); + current + } +} diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index da1baa36d6eae..e412b0d63b2f0 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -297,6 +297,9 @@ pub mod clone; pub mod cmp; pub mod convert; pub mod default; +#[unstable(feature = "error_in_core", issue = "none")] +#[cfg(not(bootstrap))] +pub mod error; pub mod marker; pub mod ops; diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 71eea43aa54e1..5bd5512aede34 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -35,6 +35,7 @@ use crate::hash::Hasher; message = "`{Self}` cannot be sent between threads safely", label = "`{Self}` cannot be sent between threads safely" )] +#[cfg_attr(not(bootstrap), lang = "send")] pub unsafe auto trait Send { // empty. } diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 1d4600fa4a2d7..e791a6771bf5f 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -2549,3 +2549,7 @@ impl_fn_for_zst! { unsafe { from_utf8_unchecked(bytes) } }; } + +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg(not(bootstrap))] +impl !crate::error::Error for &str {} diff --git a/library/core/tests/any.rs b/library/core/tests/any.rs index b36d6f0d40405..63cdd3a412b47 100644 --- a/library/core/tests/any.rs +++ b/library/core/tests/any.rs @@ -127,3 +127,25 @@ fn distinct_type_names() { assert_ne!(type_name_of_val(Velocity), type_name_of_val(Velocity(0.0, -9.8)),); } + +// Test the `Provider` API. + +struct SomeConcreteType { + some_string: String, +} + +impl Provider for SomeConcreteType { + fn provide<'a>(&'a self, mut req: Requisition<'a, '_>) { + req.provide_ref::(&self.some_string) + .provide_value::(|| "bye".to_owned()); + } +} + +#[test] +fn test_provider() { + let obj: &dyn Provider = &SomeConcreteType { some_string: "hello".to_owned() }; + + assert_eq!(&**request_by_type_tag::, _>(obj).unwrap(), "hello"); + assert_eq!(&*request_by_type_tag::, _>(obj).unwrap(), "bye"); + assert_eq!(request_by_type_tag::, _>(obj), None); +} diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index dacb33619f8c3..219ebf1e9e98a 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -82,6 +82,7 @@ #![feature(unzip_option)] #![feature(const_array_from_ref)] #![feature(const_slice_from_ref)] +#![feature(provide_any)] #![deny(unsafe_op_in_unsafe_fn)] extern crate test; diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 35f17aa781f4e..678bff275c9de 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -3085,3 +3085,14 @@ fn assert_covariance() { d } } + +#[unstable(feature = "map_try_insert", issue = "82766")] +#[cfg(not(bootstrap))] +impl<'a, K: Debug, V: Debug> crate::error::Error + for crate::collections::hash_map::OccupiedError<'a, K, V> +{ + #[allow(deprecated)] + fn description(&self) -> &str { + "key already exists" + } +} diff --git a/library/std/src/error.rs b/library/std/src/error.rs index 6ae0bc47a9462..6b84f45192b0d 100644 --- a/library/std/src/error.rs +++ b/library/std/src/error.rs @@ -16,23 +16,45 @@ #[cfg(test)] mod tests; +#[cfg(bootstrap)] use core::array; +#[cfg(bootstrap)] use core::convert::Infallible; +#[cfg(bootstrap)] use crate::alloc::{AllocError, LayoutError}; +#[cfg(bootstrap)] use crate::any::TypeId; +#[cfg(bootstrap)] use crate::backtrace::Backtrace; +#[cfg(bootstrap)] use crate::borrow::Cow; +#[cfg(bootstrap)] use crate::cell; +#[cfg(bootstrap)] use crate::char; -use crate::fmt::{self, Debug, Display}; +#[cfg(bootstrap)] +use crate::fmt; +use crate::fmt::Debug; +#[cfg(bootstrap)] +use crate::fmt::Display; +#[cfg(bootstrap)] use crate::mem::transmute; +#[cfg(bootstrap)] use crate::num; +#[cfg(bootstrap)] use crate::str; +#[cfg(bootstrap)] use crate::string; +#[cfg(bootstrap)] use crate::sync::Arc; +#[cfg(bootstrap)] use crate::time; +#[cfg(not(bootstrap))] +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::error::Error; + /// `Error` is a trait representing the basic expectations for error values, /// i.e., values of type `E` in [`Result`]. /// @@ -52,6 +74,7 @@ use crate::time; /// high-level module to provide its own errors while also revealing some of the /// implementation for debugging via `source` chains. #[stable(feature = "rust1", since = "1.0.0")] +#[cfg(bootstrap)] pub trait Error: Debug + Display { /// The lower-level source of this error, if any. /// @@ -159,6 +182,7 @@ pub trait Error: Debug + Display { } } +#[cfg(bootstrap)] mod private { // This is a hack to prevent `type_id` from being overridden by `Error` // implementations, since that can enable unsound downcasting. @@ -168,6 +192,7 @@ mod private { } #[stable(feature = "rust1", since = "1.0.0")] +#[cfg(bootstrap)] impl<'a, E: Error + 'a> From for Box { /// Converts a type of [`Error`] into a box of dyn [`Error`]. /// @@ -200,6 +225,7 @@ impl<'a, E: Error + 'a> From for Box { } #[stable(feature = "rust1", since = "1.0.0")] +#[cfg(bootstrap)] impl<'a, E: Error + Send + Sync + 'a> From for Box { /// Converts a type of [`Error`] + [`Send`] + [`Sync`] into a box of /// dyn [`Error`] + [`Send`] + [`Sync`]. @@ -238,6 +264,7 @@ impl<'a, E: Error + Send + Sync + 'a> From for Box for Box { /// Converts a [`String`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. /// @@ -281,6 +308,7 @@ impl From for Box { } #[stable(feature = "string_box_error", since = "1.6.0")] +#[cfg(bootstrap)] impl From for Box { /// Converts a [`String`] into a box of dyn [`Error`]. /// @@ -302,6 +330,7 @@ impl From for Box { } #[stable(feature = "rust1", since = "1.0.0")] +#[cfg(bootstrap)] impl<'a> From<&str> for Box { /// Converts a [`str`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. /// @@ -325,6 +354,7 @@ impl<'a> From<&str> for Box { } #[stable(feature = "string_box_error", since = "1.6.0")] +#[cfg(bootstrap)] impl From<&str> for Box { /// Converts a [`str`] into a box of dyn [`Error`]. /// @@ -346,6 +376,7 @@ impl From<&str> for Box { } #[stable(feature = "cow_box_error", since = "1.22.0")] +#[cfg(bootstrap)] impl<'a, 'b> From> for Box { /// Converts a [`Cow`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. /// @@ -367,6 +398,7 @@ impl<'a, 'b> From> for Box { } #[stable(feature = "cow_box_error", since = "1.22.0")] +#[cfg(bootstrap)] impl<'a> From> for Box { /// Converts a [`Cow`] into a box of dyn [`Error`]. /// @@ -387,6 +419,7 @@ impl<'a> From> for Box { } #[unstable(feature = "never_type", issue = "35121")] +#[cfg(bootstrap)] impl Error for ! {} #[unstable( @@ -394,12 +427,15 @@ impl Error for ! {} reason = "the precise API and guarantees it provides may be tweaked.", issue = "32838" )] +#[cfg(bootstrap)] impl Error for AllocError {} #[stable(feature = "alloc_layout", since = "1.28.0")] +#[cfg(bootstrap)] impl Error for LayoutError {} #[stable(feature = "rust1", since = "1.0.0")] +#[cfg(bootstrap)] impl Error for str::ParseBoolError { #[allow(deprecated)] fn description(&self) -> &str { @@ -408,6 +444,7 @@ impl Error for str::ParseBoolError { } #[stable(feature = "rust1", since = "1.0.0")] +#[cfg(bootstrap)] impl Error for str::Utf8Error { #[allow(deprecated)] fn description(&self) -> &str { @@ -416,6 +453,7 @@ impl Error for str::Utf8Error { } #[stable(feature = "rust1", since = "1.0.0")] +#[cfg(bootstrap)] impl Error for num::ParseIntError { #[allow(deprecated)] fn description(&self) -> &str { @@ -424,6 +462,7 @@ impl Error for num::ParseIntError { } #[stable(feature = "try_from", since = "1.34.0")] +#[cfg(bootstrap)] impl Error for num::TryFromIntError { #[allow(deprecated)] fn description(&self) -> &str { @@ -432,6 +471,7 @@ impl Error for num::TryFromIntError { } #[stable(feature = "try_from", since = "1.34.0")] +#[cfg(bootstrap)] impl Error for array::TryFromSliceError { #[allow(deprecated)] fn description(&self) -> &str { @@ -440,6 +480,7 @@ impl Error for array::TryFromSliceError { } #[stable(feature = "rust1", since = "1.0.0")] +#[cfg(bootstrap)] impl Error for num::ParseFloatError { #[allow(deprecated)] fn description(&self) -> &str { @@ -448,6 +489,7 @@ impl Error for num::ParseFloatError { } #[stable(feature = "rust1", since = "1.0.0")] +#[cfg(bootstrap)] impl Error for string::FromUtf8Error { #[allow(deprecated)] fn description(&self) -> &str { @@ -456,6 +498,7 @@ impl Error for string::FromUtf8Error { } #[stable(feature = "rust1", since = "1.0.0")] +#[cfg(bootstrap)] impl Error for string::FromUtf16Error { #[allow(deprecated)] fn description(&self) -> &str { @@ -464,6 +507,7 @@ impl Error for string::FromUtf16Error { } #[stable(feature = "str_parse_error2", since = "1.8.0")] +#[cfg(bootstrap)] impl Error for Infallible { fn description(&self) -> &str { match *self {} @@ -471,6 +515,7 @@ impl Error for Infallible { } #[stable(feature = "decode_utf16", since = "1.9.0")] +#[cfg(bootstrap)] impl Error for char::DecodeUtf16Error { #[allow(deprecated)] fn description(&self) -> &str { @@ -479,6 +524,7 @@ impl Error for char::DecodeUtf16Error { } #[unstable(feature = "map_try_insert", issue = "82766")] +#[cfg(bootstrap)] impl<'a, K: Debug + Ord, V: Debug> Error for crate::collections::btree_map::OccupiedError<'a, K, V> { @@ -489,6 +535,7 @@ impl<'a, K: Debug + Ord, V: Debug> Error } #[unstable(feature = "map_try_insert", issue = "82766")] +#[cfg(bootstrap)] impl<'a, K: Debug, V: Debug> Error for crate::collections::hash_map::OccupiedError<'a, K, V> { #[allow(deprecated)] fn description(&self) -> &str { @@ -497,6 +544,7 @@ impl<'a, K: Debug, V: Debug> Error for crate::collections::hash_map::OccupiedErr } #[stable(feature = "box_error", since = "1.8.0")] +#[cfg(bootstrap)] impl Error for Box { #[allow(deprecated, deprecated_in_future)] fn description(&self) -> &str { @@ -514,6 +562,7 @@ impl Error for Box { } #[stable(feature = "error_by_ref", since = "1.51.0")] +#[cfg(bootstrap)] impl<'a, T: Error + ?Sized> Error for &'a T { #[allow(deprecated, deprecated_in_future)] fn description(&self) -> &str { @@ -535,6 +584,7 @@ impl<'a, T: Error + ?Sized> Error for &'a T { } #[stable(feature = "arc_error", since = "1.52.0")] +#[cfg(bootstrap)] impl Error for Arc { #[allow(deprecated, deprecated_in_future)] fn description(&self) -> &str { @@ -556,6 +606,7 @@ impl Error for Arc { } #[stable(feature = "fmt_error", since = "1.11.0")] +#[cfg(bootstrap)] impl Error for fmt::Error { #[allow(deprecated)] fn description(&self) -> &str { @@ -564,6 +615,7 @@ impl Error for fmt::Error { } #[stable(feature = "try_borrow", since = "1.13.0")] +#[cfg(bootstrap)] impl Error for cell::BorrowError { #[allow(deprecated)] fn description(&self) -> &str { @@ -572,6 +624,7 @@ impl Error for cell::BorrowError { } #[stable(feature = "try_borrow", since = "1.13.0")] +#[cfg(bootstrap)] impl Error for cell::BorrowMutError { #[allow(deprecated)] fn description(&self) -> &str { @@ -580,6 +633,7 @@ impl Error for cell::BorrowMutError { } #[stable(feature = "try_from", since = "1.34.0")] +#[cfg(bootstrap)] impl Error for char::CharTryFromError { #[allow(deprecated)] fn description(&self) -> &str { @@ -588,6 +642,7 @@ impl Error for char::CharTryFromError { } #[stable(feature = "char_from_str", since = "1.20.0")] +#[cfg(bootstrap)] impl Error for char::ParseCharError { #[allow(deprecated)] fn description(&self) -> &str { @@ -596,12 +651,15 @@ impl Error for char::ParseCharError { } #[stable(feature = "try_reserve", since = "1.57.0")] +#[cfg(bootstrap)] impl Error for alloc::collections::TryReserveError {} #[unstable(feature = "duration_checked_float", issue = "83400")] +#[cfg(bootstrap)] impl Error for time::FromSecsError {} // Copied from `any.rs`. +#[cfg(bootstrap)] impl dyn Error + 'static { /// Returns `true` if the boxed type is the same as `T` #[stable(feature = "error_downcast", since = "1.3.0")] @@ -642,6 +700,7 @@ impl dyn Error + 'static { } } +#[cfg(bootstrap)] impl dyn Error + 'static + Send { /// Forwards to the method defined on the type `dyn Error`. #[stable(feature = "error_downcast", since = "1.3.0")] @@ -665,6 +724,7 @@ impl dyn Error + 'static + Send { } } +#[cfg(bootstrap)] impl dyn Error + 'static + Send + Sync { /// Forwards to the method defined on the type `dyn Error`. #[stable(feature = "error_downcast", since = "1.3.0")] @@ -688,6 +748,7 @@ impl dyn Error + 'static + Send + Sync { } } +#[cfg(bootstrap)] impl dyn Error { #[inline] #[stable(feature = "error_downcast", since = "1.3.0")] @@ -782,6 +843,7 @@ impl<'a> Iterator for Chain<'a> { } } +#[cfg(bootstrap)] impl dyn Error + Send { #[inline] #[stable(feature = "error_downcast", since = "1.3.0")] @@ -795,6 +857,7 @@ impl dyn Error + Send { } } +#[cfg(bootstrap)] impl dyn Error + Send + Sync { #[inline] #[stable(feature = "error_downcast", since = "1.3.0")] diff --git a/src/test/ui/error-trait/error-in-core-no-feature-indirect.rs b/src/test/ui/error-trait/error-in-core-no-feature-indirect.rs new file mode 100644 index 0000000000000..27e36f5d8b852 --- /dev/null +++ b/src/test/ui/error-trait/error-in-core-no-feature-indirect.rs @@ -0,0 +1,19 @@ +// edition:2021 +#![crate_type = "lib"] +#![no_std] + +use core::fmt; +use core::error; //~ ERROR use of unstable library feature 'error_in_core' + +#[derive(Debug)] +struct MyCoreError(()); + +impl fmt::Display for MyCoreError { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + unimplemented!() + } +} + +impl error::Error for MyCoreError {} + +fn main() {} diff --git a/src/test/ui/error-trait/error-in-core-no-feature-indirect.stderr b/src/test/ui/error-trait/error-in-core-no-feature-indirect.stderr new file mode 100644 index 0000000000000..8639f8bc7df79 --- /dev/null +++ b/src/test/ui/error-trait/error-in-core-no-feature-indirect.stderr @@ -0,0 +1,11 @@ +error[E0658]: use of unstable library feature 'error_in_core' + --> $DIR/error-in-core-no-feature-indirect.rs:6:5 + | +LL | use core::error; + | ^^^^^^^^^^^ + | + = help: add `#![feature(error_in_core)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/error-trait/error-in-core-no-feature.rs b/src/test/ui/error-trait/error-in-core-no-feature.rs new file mode 100644 index 0000000000000..66c29c9346938 --- /dev/null +++ b/src/test/ui/error-trait/error-in-core-no-feature.rs @@ -0,0 +1,18 @@ +// edition:2021 +#![crate_type = "lib"] +#![no_std] + +use core::fmt; + +#[derive(Debug)] +struct MyCoreError(()); + +impl fmt::Display for MyCoreError { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + unimplemented!() + } +} + +impl core::error::Error for MyCoreError {} //~ ERROR use of unstable library feature 'error_in_core' + +fn main() {}