-
-
Notifications
You must be signed in to change notification settings - Fork 14.1k
implement error multi provider #149615
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
implement error multi provider #149615
Conversation
|
rust-analyzer is developed in its own repository. If possible, consider making this change to rust-lang/rust-analyzer instead. cc @rust-lang/rust-analyzer |
This comment was marked as resolved.
This comment was marked as resolved.
API Sketch
The fn retrieve_ref<R: ?Sized + 'static>(&mut self) -> Option<R>
where
R: ?Sized + 'static;
fn retrieve_value<V: 'static>(&mut self) -> Option<V>and the following new structs, all
The
An example use looks like: #![feature(error_generic_member_access)]
use core::fmt;
use core::error::{Error, MultiResponse, Request};
#[derive(Debug)]
struct MyError {
str_field: &'static str,
val_field: MyExitCode,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
struct MyExitCode(u32);
impl fmt::Display for MyError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Example Error")
}
}
impl Error for MyError {
fn provide<'a>(&'a self, request: &mut Request<'a>) {
request
.provide_ref::<str>(self.str_field)
.provide_value::<MyExitCode>(self.val_field);
}
}
fn main() {
let e = MyError {
str_field: "hello",
val_field: MyExitCode(3),
};
let mut request= core::error::MultiRequestBuilder::new()
// request by reference
.with_ref::<str>()
// and by value
.with_value::<MyExitCode>()
// and some type that isn't in the error
.with_value::<String>()
.request(&e);
assert_eq!(request.retrieve_value::<MyExitCode>(, Some(MyExitCode(3)));
assert_eq!(request.retrieve_ref::<str>(), Some("hello"));
assert_eq!(request.retrieve_value::<String>(), None);
}Alternatives
|
3afed4d to
a87888f
Compare
|
done the rebase |
This comment was marked as resolved.
This comment was marked as resolved.
Will do that |
a87888f to
bc38a1b
Compare
|
The alternative would look like this: #![feature(error_generic_member_access)]
use core::fmt;
use core::error::{Error, MultiResponse, Request};
#[derive(Debug)]
struct MyError {
str_field: &'static str,
val_field: MyExitCode,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
struct MyExitCode(u32);
impl fmt::Display for MyError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Example Error")
}
}
impl Error for MyError {
fn provide<'a>(&'a self, request: &mut Request<'a>) {
request
.provide_ref::<str>(self.str_field)
.provide_value::<MyExitCode>(self.val_field);
}
}
fn main() {
let e = MyError {
str_field: "hello",
val_field: MyExitCode(3),
};
let mut str_val = None;
let mut exit_code_val = None;
let mut string_val = None;
let mut value = core::error::MultiRequestBuilder::new()
// request by reference
.with_ref::<str>(&mut str_val)
// and by value
.with_value::<MyExitCode>(&mut exit_code_val)
// and some type that isn't in the error
.with_value::<String>(&mut string_val)
.request(&e);
assert_eq!(exit_code_val, Some(MyExitCode(3)));
assert_eq!(str_val, Some("hello"));
assert_eq!(string_val, None);
}Does feel somewhat better. Should we switch? In some sense like the builder not having mutable references to things, but this does feel OK. |
This comment has been minimized.
This comment has been minimized.
bc38a1b to
a3209a5
Compare
|
Updated API to avoid the unneeded |
|
Moved the multiprovider to the provide module |
dcd4716 to
ce862ae
Compare
|
This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed. Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers. |
Implement an error multi provider which allows retrieving multiple types from an Error without
O(n^2)performance.This does make the current
RequestAPI slightly slower in some cases because it ends up loading the type id from memory multiple times. I do think there are a few ways around this that require some compiler support - for example, we could somehow store the type id in the vtable. However, the currentRequestAPI is very rarely hot so I do not think this is a big problem, and it will not actually become super-slow, it will just perform several reads and branches which are normally fairly fast operations.cc https://rust-lang.zulipchat.com/#narrow/channel/219381-t-libs/topic/Pushing.20error_generic_member_access.20forward/with/538480946
cc #99301
This still needs to be cleaned up a little, and I'm not that sure this is the best API, but it works and I want to put it for review
r? @the8472