From 8381174caa76696995ce75548a431b097bff85e6 Mon Sep 17 00:00:00 2001 From: Jane Lusby Date: Tue, 29 Mar 2022 14:34:24 -0700 Subject: [PATCH] remove trait-upcasting restriction on downstream users of provider --- library/core/src/any.rs | 25 ++++++---- .../ui/provider/provider_as_supertrait.rs | 50 +++++++++++++++++++ 2 files changed, 66 insertions(+), 9 deletions(-) create mode 100644 src/test/ui/provider/provider_as_supertrait.rs diff --git a/library/core/src/any.rs b/library/core/src/any.rs index 4689b95b9776b..0b3e678004b86 100644 --- a/library/core/src/any.rs +++ b/library/core/src/any.rs @@ -110,9 +110,7 @@ //! ## Examples //! //! ``` -//! # #![allow(incomplete_features)] //! # #![feature(provide_any)] -//! # #![feature(trait_upcasting)] //! use std::any::{Provider, Demand, request_ref}; //! //! // Definition of MyTrait @@ -124,7 +122,7 @@ //! impl dyn MyTrait + '_ { //! /// Common case: get a reference to a field of the error. //! pub fn get_context_ref(&self) -> Option<&T> { -//! request_ref::(self) +//! request_ref(|demand| self.provide(demand)) //! } //! } //! @@ -785,23 +783,32 @@ pub trait Provider { /// Request a value from the `Provider`. #[unstable(feature = "provide_any", issue = "none")] -pub fn request_value<'a, T: 'static>(provider: &'a dyn Provider) -> Option { - request_by_type_tag::<'a, tags::Value>(provider) +pub fn request_value<'a, T, F>(f: F) -> Option +where + T: 'static, + F: FnOnce(&mut Demand<'a>), +{ + request_by_type_tag::<'a, tags::Value, _>(f) } /// Request a reference from the `Provider`. #[unstable(feature = "provide_any", issue = "none")] -pub fn request_ref<'a, T: ?Sized + 'static>(provider: &'a dyn Provider) -> Option<&'a T> { - request_by_type_tag::<'a, tags::Ref>>(provider) +pub fn request_ref<'a, T, F>(f: F) -> Option<&'a T> +where + T: ?Sized + 'static, + F: FnOnce(&mut Demand<'a>), +{ + request_by_type_tag::<'a, tags::Ref>, _>(f) } /// Request a specific value by tag from the `Provider`. -fn request_by_type_tag<'a, I>(provider: &'a dyn Provider) -> Option +fn request_by_type_tag<'a, I, F>(f: F) -> Option where I: tags::Type<'a>, + F: FnOnce(&mut Demand<'a>), { let mut tagged = TaggedOption::<'a, I>(None); - provider.provide(tagged.as_demand()); + f(tagged.as_demand()); tagged.0 } diff --git a/src/test/ui/provider/provider_as_supertrait.rs b/src/test/ui/provider/provider_as_supertrait.rs new file mode 100644 index 0000000000000..8437eabdcdf5a --- /dev/null +++ b/src/test/ui/provider/provider_as_supertrait.rs @@ -0,0 +1,50 @@ +// run-pass +#![feature(provide_any)] +use std::any::{Provider, Demand, request_ref, request_value}; + +// 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_ref(|demand| self.provide(demand)) + } + + /// Common case: get a reference to a field of the error. + pub fn get_context(&self) -> Option { + request_value(|demand| self.provide(demand)) + } +} + +struct IsFatal; + +struct SomeFatalError; + +impl MyTrait for SomeFatalError {} + +impl Provider for SomeFatalError { + fn provide<'a>(&'a self, req: &mut Demand<'a>) { + req.provide_ref(&IsFatal).provide_value(|| IsFatal); + } +} + +struct SomeNonFatalError; + +impl MyTrait for SomeNonFatalError {} + +impl Provider for SomeNonFatalError { + fn provide<'a>(&'a self, _req: &mut Demand<'a>) { } +} + +fn is_fatal(obj: &dyn MyTrait) -> bool { + obj.get_context_ref::().is_some() && obj.get_context::().is_some() +} + +fn main() { + assert!(is_fatal(&SomeFatalError)); + assert!(!is_fatal(&SomeNonFatalError)); +}