Auto merge of #133570 - adetaylor:receiver_trait_with_target_for_real… · rust-lang/rust@2277c63 (original) (raw)
`@@ -18,7 +18,6 @@ pub enum AutoderefKind {
`
18
18
`` /// A type which must dispatch to a Deref
implementation.
``
19
19
`Overloaded,
`
20
20
`}
`
21
``
-
22
21
`struct AutoderefSnapshot<'tcx> {
`
23
22
`at_start: bool,
`
24
23
`reached_recursion_limit: bool,
`
`@@ -27,6 +26,10 @@ struct AutoderefSnapshot<'tcx> {
`
27
26
`obligations: PredicateObligations<'tcx>,
`
28
27
`}
`
29
28
``
``
29
`+
/// Recursively dereference a type, considering both built-in
`
``
30
`` +
/// dereferences (*
) and the Deref
trait.
``
``
31
`` +
/// Although called Autoderef
it can be configured to use the
``
``
32
`` +
/// Receiver
trait instead of the Deref
trait.
``
30
33
`pub struct Autoderef<'a, 'tcx> {
`
31
34
`// Meta infos:
`
32
35
`infcx: &'a InferCtxt<'tcx>,
`
`@@ -39,6 +42,7 @@ pub struct Autoderef<'a, 'tcx> {
`
39
42
``
40
43
`// Configurations:
`
41
44
`include_raw_pointers: bool,
`
``
45
`+
use_receiver_trait: bool,
`
42
46
`silence_errors: bool,
`
43
47
`}
`
44
48
``
`@@ -69,6 +73,10 @@ impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> {
`
69
73
`}
`
70
74
``
71
75
`// Otherwise, deref if type is derefable:
`
``
76
`+
// NOTE: in the case of self.use_receiver_trait = true, you might think it would
`
``
77
`+
// be better to skip this clause and use the Overloaded case only, since &T
`
``
78
`+
// and &mut T implement Receiver. But built-in derefs apply equally to Receiver
`
``
79
`+
// and Deref, and this has benefits for const and the emitted MIR.
`
72
80
`let (kind, new_ty) =
`
73
81
`if let Some(ty) = self.state.cur_ty.builtin_deref(self.include_raw_pointers) {
`
74
82
`debug_assert_eq!(ty, self.infcx.resolve_vars_if_possible(ty));
`
`@@ -111,7 +119,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
`
111
119
`body_def_id: LocalDefId,
`
112
120
`span: Span,
`
113
121
`base_ty: Ty<'tcx>,
`
114
``
`-
) -> Autoderef<'a, 'tcx> {
`
``
122
`+
) -> Self {
`
115
123
`Autoderef {
`
116
124
` infcx,
`
117
125
` span,
`
`@@ -125,6 +133,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
`
125
133
`reached_recursion_limit: false,
`
126
134
`},
`
127
135
`include_raw_pointers: false,
`
``
136
`+
use_receiver_trait: false,
`
128
137
`silence_errors: false,
`
129
138
`}
`
130
139
`}
`
`@@ -137,8 +146,13 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
`
137
146
`return None;
`
138
147
`}
`
139
148
``
140
``
`-
//
`
141
``
`-
let trait_ref = ty::TraitRef::new(tcx, tcx.lang_items().deref_trait()?, [ty]);
`
``
149
`+
// , or whatever the equivalent trait is that we've been asked to walk.
`
``
150
`+
let (trait_def_id, trait_target_def_id) = if self.use_receiver_trait {
`
``
151
`+
(tcx.lang_items().receiver_trait()?, tcx.lang_items().receiver_target()?)
`
``
152
`+
} else {
`
``
153
`+
(tcx.lang_items().deref_trait()?, tcx.lang_items().deref_target()?)
`
``
154
`+
};
`
``
155
`+
let trait_ref = ty::TraitRef::new(tcx, trait_def_id, [ty]);
`
142
156
`let cause = traits::ObligationCause::misc(self.span, self.body_id);
`
143
157
`let obligation = traits::Obligation::new(
`
144
158
` tcx,
`
`@@ -151,11 +165,8 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
`
151
165
`return None;
`
152
166
`}
`
153
167
``
154
``
`-
let (normalized_ty, obligations) = self.structurally_normalize(Ty::new_projection(
`
155
``
`-
tcx,
`
156
``
`-
tcx.lang_items().deref_target()?,
`
157
``
`-
[ty],
`
158
``
`-
))?;
`
``
168
`+
let (normalized_ty, obligations) =
`
``
169
`+
self.structurally_normalize(Ty::new_projection(tcx, trait_target_def_id, [ty]))?;
`
159
170
`debug!("overloaded_deref_ty({:?}) = ({:?}, {:?})", ty, normalized_ty, obligations);
`
160
171
`self.state.obligations.extend(obligations);
`
161
172
``
`@@ -234,6 +245,14 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
`
234
245
`self
`
235
246
`}
`
236
247
``
``
248
`` +
/// Use core::ops::Receiver
and core::ops::Receiver::Target
as
``
``
249
`+
/// the trait and associated type to iterate, instead of
`
``
250
`` +
/// core::ops::Deref
and core::ops::Deref::Target
``
``
251
`+
pub fn use_receiver_trait(mut self) -> Self {
`
``
252
`+
self.use_receiver_trait = true;
`
``
253
`+
self
`
``
254
`+
}
`
``
255
+
237
256
`pub fn silence_errors(mut self) -> Self {
`
238
257
`self.silence_errors = true;
`
239
258
`self
`