Skip to content

Commit 8381174

Browse files
committed
remove trait-upcasting restriction on downstream users of provider
1 parent 97c9099 commit 8381174

File tree

2 files changed

+66
-9
lines changed

2 files changed

+66
-9
lines changed

library/core/src/any.rs

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,7 @@
110110
//! ## Examples
111111
//!
112112
//! ```
113-
//! # #![allow(incomplete_features)]
114113
//! # #![feature(provide_any)]
115-
//! # #![feature(trait_upcasting)]
116114
//! use std::any::{Provider, Demand, request_ref};
117115
//!
118116
//! // Definition of MyTrait
@@ -124,7 +122,7 @@
124122
//! impl dyn MyTrait + '_ {
125123
//! /// Common case: get a reference to a field of the error.
126124
//! pub fn get_context_ref<T: ?Sized + 'static>(&self) -> Option<&T> {
127-
//! request_ref::<T>(self)
125+
//! request_ref(|demand| self.provide(demand))
128126
//! }
129127
//! }
130128
//!
@@ -785,23 +783,32 @@ pub trait Provider {
785783

786784
/// Request a value from the `Provider`.
787785
#[unstable(feature = "provide_any", issue = "none")]
788-
pub fn request_value<'a, T: 'static>(provider: &'a dyn Provider) -> Option<T> {
789-
request_by_type_tag::<'a, tags::Value<T>>(provider)
786+
pub fn request_value<'a, T, F>(f: F) -> Option<T>
787+
where
788+
T: 'static,
789+
F: FnOnce(&mut Demand<'a>),
790+
{
791+
request_by_type_tag::<'a, tags::Value<T>, _>(f)
790792
}
791793

792794
/// Request a reference from the `Provider`.
793795
#[unstable(feature = "provide_any", issue = "none")]
794-
pub fn request_ref<'a, T: ?Sized + 'static>(provider: &'a dyn Provider) -> Option<&'a T> {
795-
request_by_type_tag::<'a, tags::Ref<tags::MaybeSizedValue<T>>>(provider)
796+
pub fn request_ref<'a, T, F>(f: F) -> Option<&'a T>
797+
where
798+
T: ?Sized + 'static,
799+
F: FnOnce(&mut Demand<'a>),
800+
{
801+
request_by_type_tag::<'a, tags::Ref<tags::MaybeSizedValue<T>>, _>(f)
796802
}
797803

798804
/// Request a specific value by tag from the `Provider`.
799-
fn request_by_type_tag<'a, I>(provider: &'a dyn Provider) -> Option<I::Reified>
805+
fn request_by_type_tag<'a, I, F>(f: F) -> Option<I::Reified>
800806
where
801807
I: tags::Type<'a>,
808+
F: FnOnce(&mut Demand<'a>),
802809
{
803810
let mut tagged = TaggedOption::<'a, I>(None);
804-
provider.provide(tagged.as_demand());
811+
f(tagged.as_demand());
805812
tagged.0
806813
}
807814

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// run-pass
2+
#![feature(provide_any)]
3+
use std::any::{Provider, Demand, request_ref, request_value};
4+
5+
// Definition of MyTrait
6+
trait MyTrait: Provider {
7+
// ...
8+
}
9+
10+
// Methods on `MyTrait` trait objects.
11+
impl dyn MyTrait + '_ {
12+
/// Common case: get a reference to a field of the error.
13+
pub fn get_context_ref<T: ?Sized + 'static>(&self) -> Option<&T> {
14+
request_ref(|demand| self.provide(demand))
15+
}
16+
17+
/// Common case: get a reference to a field of the error.
18+
pub fn get_context<T: 'static>(&self) -> Option<T> {
19+
request_value(|demand| self.provide(demand))
20+
}
21+
}
22+
23+
struct IsFatal;
24+
25+
struct SomeFatalError;
26+
27+
impl MyTrait for SomeFatalError {}
28+
29+
impl Provider for SomeFatalError {
30+
fn provide<'a>(&'a self, req: &mut Demand<'a>) {
31+
req.provide_ref(&IsFatal).provide_value(|| IsFatal);
32+
}
33+
}
34+
35+
struct SomeNonFatalError;
36+
37+
impl MyTrait for SomeNonFatalError {}
38+
39+
impl Provider for SomeNonFatalError {
40+
fn provide<'a>(&'a self, _req: &mut Demand<'a>) { }
41+
}
42+
43+
fn is_fatal(obj: &dyn MyTrait) -> bool {
44+
obj.get_context_ref::<IsFatal>().is_some() && obj.get_context::<IsFatal>().is_some()
45+
}
46+
47+
fn main() {
48+
assert!(is_fatal(&SomeFatalError));
49+
assert!(!is_fatal(&SomeNonFatalError));
50+
}

0 commit comments

Comments
 (0)