Skip to content

Commit 57bc12f

Browse files
author
Ariel Ben-Yehuda
committed
address review comments
1 parent fb7c2f5 commit 57bc12f

File tree

4 files changed

+102
-106
lines changed

4 files changed

+102
-106
lines changed

library/core/src/error/provide.rs

Lines changed: 56 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -526,10 +526,10 @@ pub struct EmptyMultiRequestBuilder;
526526
pub struct ChainValMultiRequestBuilder<T, NEXT>(PhantomData<(T, NEXT)>);
527527

528528
#[unstable(feature = "error_generic_member_access", issue = "99301")]
529-
#[derive(Copy, Clone, Debug)]
530529
/// Case of [IntoMultiRequest] that retrieves a type by value.
531530
///
532531
/// Create via [MultiRequestBuilder::with_ref].
532+
#[derive(Copy, Clone, Debug)]
533533
pub struct ChainRefMultiRequestBuilder<T: ?Sized, NEXT>(PhantomData<(*const T, NEXT)>);
534534

535535
/// Internal trait for types that represent a request for multiple provided
@@ -553,9 +553,9 @@ mod private {
553553
}
554554

555555
#[unstable(feature = "error_generic_member_access", issue = "99301")]
556-
#[allow(private_bounds)]
556+
#[allow(private_bounds, private_interfaces)]
557557
pub trait MultiResponseInner<'a> {
558-
fn consume_with<I>(&mut self, fulfil: impl FnOnce(I::Reified)) -> &mut Self
558+
fn retrieve<I>(&mut self) -> Option<I::Reified>
559559
where
560560
I: super::tags::Type<'a>;
561561
}
@@ -671,13 +671,9 @@ where
671671
#[unstable(feature = "error_generic_member_access", issue = "99301")]
672672
#[allow(private_bounds)]
673673
pub trait MultiResponse<'a> {
674-
/// Retrieve a reference with the type `R` from this multi response,
675-
///
676-
/// The reference will be passed to `fulfil` if present. This function
677-
/// consumes the reference, so the next call to `retrieve_ref`
678-
/// with the same type will not call `fulfil`.
674+
/// Retrieve a reference with the type `R` from this multi response.
679675
///
680-
/// This function returns `self` to allow easy chained use.
676+
/// If there is no reference of type `R` in the response, returns None.
681677
///
682678
/// # Examples
683679
///
@@ -689,25 +685,19 @@ pub trait MultiResponse<'a> {
689685
/// use core::error::{Error, MultiRequestBuilder, MultiResponse};
690686
///
691687
/// fn get_str(e: &dyn Error) -> Option<&str> {
692-
/// let mut result = None;
693688
/// MultiRequestBuilder::new()
694689
/// .with_ref::<str>()
695690
/// .request(e)
696-
/// .retrieve_ref(|res| result = Some(res));
697-
/// result
691+
/// .retrieve_ref::<str>()
698692
/// }
699693
/// ```
700-
fn retrieve_ref<R>(&mut self, fulfil: impl FnOnce(&'a R)) -> &mut Self
694+
fn retrieve_ref<R>(&mut self) -> Option<&'a R>
701695
where
702696
R: ?Sized + 'static;
703697

704-
/// Retrieve a value with the type `V` from this multi response,
698+
/// Retrieve a value with the type `V` from this multi response.
705699
///
706-
/// The value will be passed to `fulfil` if present. This function
707-
/// consumes the value, so the next call to `retrieve_value`
708-
/// with the same type will not call `fulfil`.
709-
///
710-
/// This function returns `self` to allow easy chained use.
700+
/// If there is no value of type `V` in the response, returns None.
711701
///
712702
/// # Examples
713703
///
@@ -719,43 +709,41 @@ pub trait MultiResponse<'a> {
719709
/// use core::error::{Error, MultiRequestBuilder, MultiResponse};
720710
///
721711
/// fn get_string(e: &dyn Error) -> Option<String> {
722-
/// let mut result = None;
723712
/// MultiRequestBuilder::new()
724713
/// .with_value::<String>()
725714
/// .request(e)
726-
/// .retrieve_value(|res| result = Some(res));
727-
/// result
715+
/// .retrieve_value::<String>()
728716
/// }
729717
/// ```
730-
fn retrieve_value<V>(&mut self, fulfil: impl FnOnce(V)) -> &mut Self
718+
fn retrieve_value<V>(&mut self) -> Option<V>
731719
where
732720
V: 'static;
733721
}
734722

735723
#[unstable(feature = "error_generic_member_access", issue = "99301")]
736724
impl<'a, T: private::MultiResponseInner<'a>> MultiResponse<'a> for T {
737-
fn retrieve_ref<R>(&mut self, fulfil: impl FnOnce(&'a R)) -> &mut Self
725+
fn retrieve_ref<R>(&mut self) -> Option<&'a R>
738726
where
739727
R: ?Sized + 'static,
740728
{
741-
self.consume_with::<tags::Ref<tags::MaybeSizedValue<R>>>(fulfil)
729+
self.retrieve::<tags::Ref<tags::MaybeSizedValue<R>>>()
742730
}
743731

744-
fn retrieve_value<V>(&mut self, fulfil: impl FnOnce(V)) -> &mut Self
732+
fn retrieve_value<V>(&mut self) -> Option<V>
745733
where
746734
V: 'static,
747735
{
748-
self.consume_with::<tags::Value<V>>(fulfil)
736+
self.retrieve::<tags::Value<V>>()
749737
}
750738
}
751739
#[unstable(feature = "error_generic_member_access", issue = "99301")]
740+
#[allow(private_bounds, private_interfaces)]
752741
impl<'a> private::MultiResponseInner<'a> for EmptyMultiResponse {
753-
#[allow(private_bounds)]
754-
fn consume_with<I>(&mut self, _fulfil: impl FnOnce(I::Reified)) -> &mut Self
742+
fn retrieve<I>(&mut self) -> Option<I::Reified>
755743
where
756744
I: tags::Type<'a>,
757745
{
758-
self
746+
None
759747
}
760748
}
761749

@@ -765,7 +753,7 @@ where
765753
J: tags::Type<'a>,
766754
NEXT: private::MultiResponseInner<'a>,
767755
{
768-
fn consume_with<I>(&mut self, fulfil: impl FnOnce(I::Reified)) -> &mut Self
756+
fn retrieve<I>(&mut self) -> Option<I::Reified>
769757
where
770758
I: tags::Type<'a>,
771759
{
@@ -777,28 +765,25 @@ where
777765
let cur =
778766
&mut *(&mut self.cur as *mut Option<J::Reified> as *mut Option<I::Reified>);
779767
if let Some(val) = cur.take() {
780-
fulfil(val);
781-
return self;
768+
return Some(val);
782769
}
783770
}
784771
}
785-
self.next.consume_with::<I>(fulfil);
786-
self
772+
self.next.retrieve::<I>()
787773
}
788774
}
789775
#[unstable(feature = "error_generic_member_access", issue = "99301")]
776+
#[allow(private_bounds, private_interfaces)]
790777
impl<'a, T, NEXT> private::MultiResponseInner<'a> for ChainValMultiResponse<'a, T, NEXT>
791778
where
792779
T: 'static,
793780
NEXT: private::MultiResponseInner<'a>,
794781
{
795-
#[allow(private_bounds)]
796-
fn consume_with<I>(&mut self, fulfil: impl FnOnce(I::Reified)) -> &mut Self
782+
fn retrieve<I>(&mut self) -> Option<I::Reified>
797783
where
798784
I: tags::Type<'a>,
799785
{
800-
self.inner.consume_with::<I>(fulfil);
801-
self
786+
self.inner.retrieve::<I>()
802787
}
803788
}
804789
#[unstable(feature = "error_generic_member_access", issue = "99301")]
@@ -823,18 +808,17 @@ where
823808
}
824809

825810
#[unstable(feature = "error_generic_member_access", issue = "99301")]
811+
#[allow(private_bounds, private_interfaces)]
826812
impl<'a, T, NEXT> private::MultiResponseInner<'a> for ChainRefMultiResponse<'a, T, NEXT>
827813
where
828814
T: 'static + ?Sized,
829815
NEXT: private::MultiResponseInner<'a>,
830816
{
831-
#[allow(private_bounds)]
832-
fn consume_with<I>(&mut self, fulfil: impl FnOnce(I::Reified)) -> &mut Self
817+
fn retrieve<I>(&mut self) -> Option<I::Reified>
833818
where
834819
I: tags::Type<'a>,
835820
{
836-
self.inner.consume_with::<I>(fulfil);
837-
self
821+
self.inner.retrieve::<I>()
838822
}
839823
}
840824
#[unstable(feature = "error_generic_member_access", issue = "99301")]
@@ -903,7 +887,6 @@ where
903887
}
904888

905889
#[unstable(feature = "error_generic_member_access", issue = "99301")]
906-
#[derive(Copy, Clone, Debug)]
907890
/// A [MultiRequestBuilder] is used to request multiple types from an [Error] at once.
908891
///
909892
/// Requesting a type from an [Error] is fairly fast - normally faster than formatting
@@ -946,33 +929,44 @@ where
946929
/// val_field: MyExitCode(3),
947930
/// };
948931
///
949-
/// let mut str_val = None;
950-
/// let mut exit_code_val = None;
951-
/// let mut string_val = None;
952-
/// let mut value = core::error::MultiRequestBuilder::new()
932+
/// let mut request = core::error::MultiRequestBuilder::new()
953933
/// // request by reference
954934
/// .with_ref::<str>()
955935
/// // and by value
956936
/// .with_value::<MyExitCode>()
957937
/// // and some type that isn't in the error
958938
/// .with_value::<String>()
959-
/// .request(&e)
960-
/// // The error has str by reference
961-
/// .retrieve_ref::<str>(|val| str_val = Some(val))
962-
/// // The error has MyExitCode by value
963-
/// .retrieve_value::<MyExitCode>(|val| exit_code_val = Some(val))
964-
/// // The error does not have a string field, consume will not be called
965-
/// .retrieve_value::<String>(|val| string_val = Some(val));
939+
/// .request(&e);
966940
///
967-
/// assert_eq!(exit_code_val, Some(MyExitCode(3)));
968-
/// assert_eq!(str_val, Some("hello"));
969-
/// assert_eq!(string_val, None);
941+
/// // The error has MyExitCode by value
942+
/// assert_eq!(request.retrieve_value::<MyExitCode>(), Some(MyExitCode(3)));
943+
/// // The error has str by reference
944+
/// assert_eq!(request.retrieve_ref::<str>(), Some("hello"));
945+
/// // The error does not have a string field
946+
/// assert_eq!(request.retrieve_value::<String>(), None);
970947
/// }
971948
/// ```
972949
pub struct MultiRequestBuilder<INNER: IntoMultiRequest> {
973950
inner: PhantomData<INNER>,
974951
}
975952

953+
#[unstable(feature = "error_generic_member_access", issue = "99301")]
954+
impl<INNER: IntoMultiRequest> Debug for MultiRequestBuilder<INNER> {
955+
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
956+
f.debug_tuple("MultiRequestBuilder").field(&crate::any::type_name::<INNER>()).finish()
957+
}
958+
}
959+
960+
#[unstable(feature = "error_generic_member_access", issue = "99301")]
961+
impl<INNER: IntoMultiRequest> Copy for MultiRequestBuilder<INNER> {}
962+
963+
#[unstable(feature = "error_generic_member_access", issue = "99301")]
964+
impl<INNER: IntoMultiRequest> Clone for MultiRequestBuilder<INNER> {
965+
fn clone(&self) -> Self {
966+
*self
967+
}
968+
}
969+
976970
impl MultiRequestBuilder<EmptyMultiRequestBuilder> {
977971
/// Create a new [MultiRequestBuilder]
978972
#[unstable(feature = "error_generic_member_access", issue = "99301")]
@@ -991,12 +985,10 @@ impl<INNER: IntoMultiRequest> MultiRequestBuilder<INNER> {
991985
/// use core::error::{Error, MultiRequestBuilder, MultiResponse};
992986
///
993987
/// fn get_string(e: &dyn Error) -> Option<String> {
994-
/// let mut result = None;
995988
/// MultiRequestBuilder::new()
996989
/// .with_value::<String>()
997990
/// .request(e)
998-
/// .retrieve_value(|res| result = Some(res));
999-
/// result
991+
/// .retrieve_value::<String>()
1000992
/// }
1001993
/// ```
1002994
#[unstable(feature = "error_generic_member_access", issue = "99301")]
@@ -1014,13 +1006,11 @@ impl<INNER: IntoMultiRequest> MultiRequestBuilder<INNER> {
10141006
/// #![feature(error_generic_member_access)]
10151007
/// use core::error::{Error, MultiRequestBuilder, MultiResponse};
10161008
///
1017-
/// fn get_string(e: &dyn Error) -> Option<String> {
1018-
/// let mut result = None;
1009+
/// fn get_str<'a>(e: &dyn Error) -> Option<&str> {
10191010
/// MultiRequestBuilder::new()
1020-
/// .with_value::<String>()
1011+
/// .with_ref::<str>()
10211012
/// .request(e)
1022-
/// .retrieve_value(|res| result = Some(res));
1023-
/// result
1013+
/// .retrieve_ref::<str>()
10241014
/// }
10251015
/// ```
10261016
#[unstable(feature = "error_generic_member_access", issue = "99301")]

library/coretests/tests/error.rs

Lines changed: 42 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use core::error::{Request, request_ref, request_value};
1+
use core::error::{Error, MultiRequestBuilder, MultiResponse, Request, request_ref, request_value};
22

33
// Test the `Request` API.
44
#[derive(Debug)]
@@ -84,51 +84,60 @@ fn test_error_generic_member_access_concrete() {
8484
fn test_error_combined_access_concrete() {
8585
let obj = SomeConcreteType { some_string: "hello".to_owned() };
8686

87-
let mut string_val = None;
88-
let mut string_ref = None;
89-
let mut u8_val = None;
90-
let mut valid_ref = None;
91-
92-
MultiRequestBuilder::new()
87+
let mut request = MultiRequestBuilder::new()
9388
.with_value::<String>()
9489
.with_ref::<String>()
9590
.with_value::<u8>()
9691
.with_ref::<Valid>()
97-
.request(&obj)
98-
.retrieve_value::<String>(|val| string_val = Some(val))
99-
.retrieve_ref::<String>(|val| string_ref = Some(val))
100-
.retrieve_value::<u8>(|val| u8_val = Some(val))
101-
.retrieve_ref::<Valid>(|val| valid_ref = Some(val));
102-
103-
assert_eq!(string_ref.unwrap(), "hello");
104-
assert_eq!(string_val.unwrap(), "bye");
105-
assert_eq!(u8_val, None);
106-
assert_eq!(valid_ref.unwrap(), Valid);
92+
.request(&obj);
93+
94+
assert_eq!(request.retrieve_ref::<String>().unwrap(), "hello");
95+
assert_eq!(request.retrieve_value::<String>().unwrap(), "bye");
96+
assert_eq!(request.retrieve_value::<u8>(), None);
97+
assert_eq!(request.retrieve_ref::<Valid>().unwrap(), &Valid);
98+
99+
// second retrieve of same value returns none
100+
assert_eq!(request.retrieve_ref::<Valid>(), None);
101+
assert_eq!(request.retrieve_value::<String>(), None);
102+
// retrieving an unknown type should return none
103+
assert_eq!(request.retrieve_value::<*const ()>(), None);
107104
}
108105

109106
#[test]
110107
fn test_error_combined_access_dyn() {
111108
let obj = SomeConcreteType { some_string: "hello".to_owned() };
112109
let obj: &dyn Error = &obj;
113110

114-
let mut string_val = None;
115-
let mut string_ref = None;
116-
let mut u8_val = None;
117-
let mut valid_ref = None;
118-
119-
MultiRequestBuilder::new()
111+
let mut request = MultiRequestBuilder::new()
120112
.with_value::<String>()
121113
.with_ref::<String>()
122114
.with_value::<u8>()
123115
.with_ref::<Valid>()
124-
.request(&obj)
125-
.retrieve_value::<String>(|val| string_val = Some(val))
126-
.retrieve_ref::<String>(|val| string_ref = Some(val))
127-
.retrieve_value::<u8>(|val| u8_val = Some(val))
128-
.retrieve_ref::<Valid>(|val| valid_ref = Some(val));
129-
130-
assert_eq!(string_ref.unwrap(), "hello");
131-
assert_eq!(string_val.unwrap(), "bye");
132-
assert_eq!(u8_val, None);
133-
assert_eq!(valid_ref.unwrap(), Valid);
116+
.request(&obj);
117+
118+
assert_eq!(request.retrieve_ref::<String>().unwrap(), "hello");
119+
assert_eq!(request.retrieve_value::<String>().unwrap(), "bye");
120+
assert_eq!(request.retrieve_value::<u8>(), None);
121+
assert_eq!(request.retrieve_ref::<Valid>().unwrap(), &Valid);
122+
123+
// second retrieve of same value returns none
124+
assert_eq!(request.retrieve_ref::<Valid>(), None);
125+
assert_eq!(request.retrieve_value::<String>(), None);
126+
// retrieving an unknown type should return none
127+
assert_eq!(request.retrieve_value::<*const ()>(), None);
128+
}
129+
130+
fn assert_copy<T: Copy>(_t: T) {}
131+
132+
#[test]
133+
fn test_builder_copy_and_debug() {
134+
// Check that MultiRequestBuilder implements Debug + Copy even if the contents doesn't (the exact contents don't matter)
135+
// (Chain*MultiRequest don't, but their values are not really user-visible so it doesn't matter)
136+
let builder = MultiRequestBuilder::new().with_value::<Valid>().with_ref::<Invalid>();
137+
assert_copy(builder);
138+
// check Debug
139+
assert_eq!(
140+
format!("{:?}", builder),
141+
"MultiRequestBuilder(\"core::error::provide::ChainRefMultiRequestBuilder<coretests::error::Invalid, core::error::provide::ChainValMultiRequestBuilder<coretests::error::Valid, core::error::provide::EmptyMultiRequestBuilder>>\")"
142+
);
134143
}

library/coretests/tests/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ mod clone;
175175
mod cmp;
176176
mod const_ptr;
177177
mod convert;
178+
mod error;
178179
mod ffi;
179180
mod floats;
180181
mod fmt;

0 commit comments

Comments
 (0)