]> git.proxmox.com Git - rustc.git/blob - compiler/rustc_hir_typeck/src/autoderef.rs
New upstream version 1.67.1+dfsg1
[rustc.git] / compiler / rustc_hir_typeck / src / autoderef.rs
1 //! Some helper functions for `AutoDeref`
2 use super::method::MethodCallee;
3 use super::{FnCtxt, PlaceOp};
4
5 use rustc_infer::infer::InferOk;
6 use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref};
7 use rustc_middle::ty::{self, Ty};
8 use rustc_span::Span;
9 use rustc_trait_selection::autoderef::{Autoderef, AutoderefKind};
10
11 use std::iter;
12
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)
16 }
17
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.
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
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 }