1 //! Some helper functions for `AutoDeref`
2 use super::method
::MethodCallee
;
3 use super::{FnCtxt, PlaceOp}
;
5 use rustc_infer
::infer
::InferOk
;
6 use rustc_middle
::ty
::adjustment
::{Adjust, Adjustment, OverloadedDeref}
;
7 use rustc_middle
::ty
::{self, Ty}
;
9 use rustc_trait_selection
::autoderef
::{Autoderef, AutoderefKind}
;
13 impl<'a
, 'tcx
> FnCtxt
<'a
, 'tcx
> {
14 pub fn autoderef(&'a
self, span
: Span
, base_ty
: Ty
<'tcx
>) -> Autoderef
<'a
, 'tcx
> {
15 Autoderef
::new(self, self.param_env
, self.body_id
, span
, base_ty
)
18 pub fn try_overloaded_deref(
22 ) -> Option
<InferOk
<'tcx
, MethodCallee
<'tcx
>>> {
23 self.try_overloaded_place_op(span
, base_ty
, &[], PlaceOp
::Deref
)
26 /// Returns the adjustment steps.
27 pub fn adjust_steps(&self, autoderef
: &Autoderef
<'a
, 'tcx
>) -> Vec
<Adjustment
<'tcx
>> {
28 self.register_infer_ok_obligations(self.adjust_steps_as_infer_ok(autoderef
))
31 pub fn adjust_steps_as_infer_ok(
33 autoderef
: &Autoderef
<'a
, 'tcx
>,
34 ) -> InferOk
<'tcx
, Vec
<Adjustment
<'tcx
>>> {
35 let mut obligations
= vec
![];
36 let steps
= autoderef
.steps();
38 steps
.iter().skip(1).map(|&(ty
, _
)| ty
).chain(iter
::once(autoderef
.final_ty(false)));
39 let steps
: Vec
<_
> = steps
41 .map(|&(source
, kind
)| {
42 if let AutoderefKind
::Overloaded
= kind
{
43 self.try_overloaded_deref(autoderef
.span(), source
).and_then(
44 |InferOk { value: method, obligations: o }
| {
45 obligations
.extend(o
);
46 if let ty
::Ref(region
, _
, mutbl
) = *method
.sig
.output().kind() {
47 Some(OverloadedDeref { region, mutbl, span: autoderef.span() }
)
58 .map(|(autoderef
, target
)| Adjustment { kind: Adjust::Deref(autoderef), target }
)
61 InferOk { obligations, value: steps }