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 comment has been minimized.
This comment has been minimized.
|
☔ The latest upstream changes (presumably #150810) made this pull request unmergeable. Please resolve the merge conflicts. |
0f3d022 to
26f84ae
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