Repository navigation
Tracking Issue for Provider API #96024
Description
Activity
- addedT-libs-api[DEPRECATED; DO NOT USE][DEPRECATED; DO NOT USE]C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCCategory: An issue tracking the progress of sth. like the implementation of an RFCB-RFC-approvedBlocker: Approved by a merged RFC but not yet implemented.Blocker: Approved by a merged RFC but not yet implemented.
on Apr 13, 2022 #98912 updates the
request_*functions to have an APIT (arg position impl trait) parameter instead of a standard generic parameter to remove unnecessary inferred parameters while turbofishing.Callers change:
let obj: Box<dyn Provider> = Box::new(SomeConcreteType { some_string: "hello".to_owned() }); // From assert_eq!(&**request_ref::<String, _>(&*obj).unwrap(), "hello"); // To assert_eq!(&**request_ref::<String>(&*obj).unwrap(), "hello");
One minor thing that weirds me out about this API is this impl:
rust/library/core/src/error.rs
Lines 197 to 199 in 02654a0
impl<E> Provider for E where E: Error + ?Sized, Since this is a blanket impl (
Selftype is a generic parameter), it is the one blanket impl thatProvideris ever going to be able to have, at least absent some far-future negative impls feature in the language. Any other blanket impl would be considered overlapping and violate coherence.But it's a blanket impl of
core::any::Provider, which is envisioned as being as general-purpose as theAnytrait, for types which implementcore::error::Error, which is a much narrower use case. In some sense this relationship is saying that "Errors are the one true canonical/privileged implementers of the Provider trait; any other application of Provider is second-class".I am wondering which one of the following would be feasible:
-
Yes, errors are the one privileged application of Provider, and while Provider may be useful for some other things sometimes, all of those are second-class.
a. Maybe move Provider to
core::errorto double down on this view? -
Remove the blanket impl. What are the things that make the blanket impl necessary for usability of this API, and can those be mitigated a different way?
Reacted by John Schug, Thom Chiovoloni, Jonas Bushart, JonasJebing, Charles Hall, Matt Bell, Max “Goldstein” Siling, Pâris DOUADY, Stijn, Ciren and 6 more-
We could go back to what we had before we move Error into core which was a provide impl just on dyn Error which caused some other paper cuts but I can't remember exactly what those issues were.
Another issue for the provider API that matters for non-error cases is the lack of support for &mut.
I think the initial proposal did support this, at some cost to complexity. While I don't know that we need to support it out of the gate (I've wanted it multiple times when playing around with the API), it would be good to be sure we know it would look like, so that if we want to add it in the future, that we have not painted ourselves into a corner where we cannot do so.
Reacted by Wyatt Herkamp, Yuxuan Shui, JonasJebing, Ciren, Js2xxx and Lyra Naeseth@thomcc I believe all we have to do is expose the tag APIs to support those cases. We didn't change the impl, only the exposed API.
- added 6 commits that reference this issue
on Sep 1, 2022 62 remaining items
@yaahc I think we've captured everything but
LLVM is unable to optimize multiple .provide_* calls into a switch table because each call fetches the type id from Erased::type_id separately each time and the compiler doesn't know that these calls all return the same value. This should be fixed. See Add provide_any module to core rfcs#3192 (comment) for one possible solution (although alternative solutions may be possible).
in the TODOs for the
error_generic_member_accesstracking issue so we should be able to close this tracking issue, right?- added a commit that references this issue
on Aug 1, 2023 How about add an optional key? Just like:
pub fn provide_value<T>(&mut self, key: Option<&str>, value: T) -> &mut Demand<'a>;
then we can provide multi value with the same type, such as:
struct Sth { foo: String, bar: String, } impl Provider for Sth { fn provide<'a>(&'a self, demand: &mut Demand<'a>) { demand .provide_value::<String>(Some("foo"), self.foo) .provide_value::<String>(Some("bar"), self.bar); } }
FEI, the Provider API has been rejected by the libs meeting folks. For more background, please see my earlier comment in this issue: #96024 (comment)
The TL;DR is that the
Providertrait has been rejected, leaving just theRequesttype (aka the type formerly known asDemand) and the newprovidemethod on theErrortrait. TheRequesttype and its associated internal-only machinery has been moved from thecore::anymodule intocore::error. This is the state of affairs in latest nightly after #113464 was merged earlier this week.The only thing that's left to do as far as this tracking issue is concerned is to close it (as far as I understand).
Reacted by TennyZhuang, Lily, jmjoy, Bugen Zhao, lena and Mykhailo HnapReacted by jmjoy and Jon GjengsetIs there any third-party crate to maintain the
Providertrait in the future? Although it may not be suitable to be merged in thestd::any, it's still a useful pattern in some scenarios.@TennyZhuang the closest thing I know of was mentioned in the notes for this feature's RFC, which can be found here: provide-any
I don't know how similar this is to what was unstable here in the standard library and there are no published crates.
There is also the supplier crate that I made in response to this feature being removed. I also consider it unstable but it's a direct lift and shift from the latest provider impl that std had in nightly
https://docs.rs/supplier/0.0.2/supplier/
I had plans to change the API but all my attempts so far have failed to be beneficial
Reacted by jmjoy and TennyZhuangReacted by Diana and TennyZhuang- added a commit that references this issue
on Oct 17, 2023 - added a commit that references this issue
on Dec 30, 2024 - addedT-libsRelevant to the library team, which will review and decide on the PR/issue.Relevant to the library team, which will review and decide on the PR/issue.and removedT-libs-api[DEPRECATED; DO NOT USE][DEPRECATED; DO NOT USE]
on Aug 12, 2026
View all comments
Feature gate:
#![feature(provide_any)]This is a tracking issue for RFC 3192
The initial motivating use case for this API is to provide the necessary functionality to add generic member access to the
Errortrait to generalize extracting context likeBacktraceand to make it possible to move theErrortrait intocorewhile leavingBacktraceinstd.Public API
Steps / History
Providertrait and merge its functionality intoError.demandorrequestand use that name consistently..provide_*calls into a switch table because each call fetches the type id fromErased::type_idseparately each time and the compiler doesn't know that these calls all return the same value. This should be fixed. See Add provide_any module to core rfcs#3192 (comment) for one possible solution (although alternative solutions may be possible).Unresolved Questions
demand_*orrequest_*?