You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -288,7 +289,33 @@ Extending the API of `Error` is a primary motivation for this RFC, but those ext
288
289
289
290
It was suggested by @Plecra in the [comments](https://github.com/rust-lang/rfcs/pull/2895#issuecomment-735713486) of RFC 2895, that this mechanism could be used for providing data from a future's `Context` object. That is a more demanding application since it is likely to require `&mut` references, objects with complex lifetimes, and possibly even closures to be returned. That has motivated seeking a general API for `provide_any`, rather than only supporting `'static` lifetimes.
290
291
292
+
Recommendations for how to use the API, in particular when to provide or request a value using a plain type, type tag, or special purpose newtype. See the appendix for discussion and examples.
293
+
291
294
# Future possibilities
292
295
[future-possibilities]: #future-possibilities
293
296
294
297
A possible extension to this work is full downcasting using type tags - a proper alternative to `Any`. Such downcasting is available in dyno and is an implementation detail of the proof of concept implementation for this RFC. It is not part of `provide_any`'s interface in order to minimise the proposal and avoid overlap with `Any`, however, I don't see any technical issues with exposing such functionality in the future if there is demand.
298
+
299
+
# Appendix: using tags or newtypes
300
+
301
+
One issue with using type-based provision is that an object might reasonably provide many different values with the same type. If the object intends to provide multiple values with the same type, then it must distinguish them. Even if it doesn't, the user might request a value expecting one thing and get another with the same type, leading to logic errors (e.g., requesting a string from `MyError` expecting an error code and getting a suggestion message).
302
+
303
+
There are two possible solutions (both of these use the API as proposed, neither requires extensions): wrap values in value-specific newtypes, or use value-specific type tags.
304
+
305
+
I'll explain these options in the context of the `MyError` example.
306
+
307
+
Using newtypes, the `MyError` author would provide a `Suggestion` newtype: `pub struct Suggestion(pub String)`. A user would use `get_context::<Suggestion>()` (or otherwise specify the type, e.g., `let s: Suggestion = e.get_context().unwrap();`) and would receive a `Suggestion` which they would then have to unpack to retrieve the string value. This approach only works for owned `String`s: newtypes cannot wrap unsized values, and keeping a reference in the newtype would require using an explicit tag, making the newtype option strictly worse than the type tag option.
308
+
309
+
Using type tags, the `MyError` author would provide a `SuggestionTag` type tag:
310
+
311
+
```rust
312
+
pubstructSuggestionTag;
313
+
314
+
impl<'a> TypeTag<'a> forSuggestionTag {
315
+
typeType=&'astr;
316
+
}
317
+
```
318
+
319
+
The user would use `get_context_by_type_tag::<SuggestionTag>` to retrieve the suggestion. This approach supports references, so the suggestion message does not need to be cloned, and returns the string directly to the user without them having to unpack a newtype. However, it does require the user to understand the type tag concept.
320
+
321
+
Note that the type tags option relies on their being a potential many-to-one relationship between type tags and types.
0 commit comments