1 //! Some helper functions for `AutoDeref` 2 use super::method::MethodCallee; 3 use super::{FnCtxt, PlaceOp}; 4 5 use rustc_hir_analysis::autoderef::{Autoderef, AutoderefKind}; 6 use rustc_infer::infer::InferOk; 7 use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref}; 8 use rustc_middle::ty::{self, Ty}; 9 use rustc_span::Span; 10 11 use std::iter; 12 13 impl<'a, 'tcx> FnCtxt<'a, 'tcx> { autoderef(&'a self, span: Span, base_ty: Ty<'tcx>) -> Autoderef<'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) 16 } 17 try_overloaded_deref( &self, span: Span, base_ty: Ty<'tcx>, ) -> Option<InferOk<'tcx, MethodCallee<'tcx>>>18 pub fn try_overloaded_deref( 19 &self, 20 span: Span, 21 base_ty: Ty<'tcx>, 22 ) -> Option<InferOk<'tcx, MethodCallee<'tcx>>> { 23 self.try_overloaded_place_op(span, base_ty, &[], PlaceOp::Deref) 24 } 25 26 /// Returns the adjustment steps. adjust_steps(&self, autoderef: &Autoderef<'a, 'tcx>) -> Vec<Adjustment<'tcx>>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)) 29 } 30 adjust_steps_as_infer_ok( &self, autoderef: &Autoderef<'a, 'tcx>, ) -> InferOk<'tcx, Vec<Adjustment<'tcx>>>31 pub fn adjust_steps_as_infer_ok( 32 &self, 33 autoderef: &Autoderef<'a, 'tcx>, 34 ) -> InferOk<'tcx, Vec<Adjustment<'tcx>>> { 35 let mut obligations = vec![]; 36 let steps = autoderef.steps(); 37 let targets = 38 steps.iter().skip(1).map(|&(ty, _)| ty).chain(iter::once(autoderef.final_ty(false))); 39 let steps: Vec<_> = steps 40 .iter() 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() }) 48 } else { 49 None 50 } 51 }, 52 ) 53 } else { 54 None 55 } 56 }) 57 .zip(targets) 58 .map(|(autoderef, target)| Adjustment { kind: Adjust::Deref(autoderef), target }) 59 .collect(); 60 61 InferOk { obligations, value: steps } 62 } 63 } 64