]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_hir_typeck/src/autoderef.rs
New upstream version 1.66.0+dfsg1
[rustc.git] / compiler / rustc_hir_typeck / src / autoderef.rs
CommitLineData
f035d41b 1//! Some helper functions for `AutoDeref`
7cac9316 2use super::method::MethodCallee;
f035d41b 3use super::{FnCtxt, PlaceOp};
3157f602 4
f035d41b 5use rustc_infer::infer::InferOk;
ba9703b0 6use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref};
f035d41b 7use rustc_middle::ty::{self, Ty};
dfeec247 8use rustc_span::Span;
f035d41b 9use rustc_trait_selection::autoderef::{Autoderef, AutoderefKind};
3157f602 10
7cac9316
XL
11use std::iter;
12
f035d41b
XL
13impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14 pub fn autoderef(&'a self, span: Span, base_ty: Ty<'tcx>) -> Autoderef<'a, 'tcx> {
1b1a35ee
XL
15 Autoderef::new(self, self.param_env, self.body_id, span, base_ty, span)
16 }
17
18 /// Like `autoderef`, but provides a custom `Span` to use for calls to
19 /// an overloaded `Deref` operator
20 pub fn autoderef_overloaded_span(
21 &'a self,
22 span: Span,
23 base_ty: Ty<'tcx>,
24 overloaded_span: Span,
25 ) -> Autoderef<'a, 'tcx> {
26 Autoderef::new(self, self.param_env, self.body_id, span, base_ty, overloaded_span)
3157f602 27 }
3157f602 28
f035d41b
XL
29 pub fn try_overloaded_deref(
30 &self,
dc9dc135
XL
31 span: Span,
32 base_ty: Ty<'tcx>,
f035d41b
XL
33 ) -> Option<InferOk<'tcx, MethodCallee<'tcx>>> {
34 self.try_overloaded_place_op(span, base_ty, &[], PlaceOp::Deref)
7cac9316
XL
35 }
36
37 /// Returns the adjustment steps.
f035d41b
XL
38 pub fn adjust_steps(&self, autoderef: &Autoderef<'a, 'tcx>) -> Vec<Adjustment<'tcx>> {
39 self.register_infer_ok_obligations(self.adjust_steps_as_infer_ok(autoderef))
8bb4bdeb
XL
40 }
41
dc9dc135
XL
42 pub fn adjust_steps_as_infer_ok(
43 &self,
f035d41b 44 autoderef: &Autoderef<'a, 'tcx>,
dc9dc135 45 ) -> InferOk<'tcx, Vec<Adjustment<'tcx>>> {
7cac9316 46 let mut obligations = vec![];
f035d41b
XL
47 let steps = autoderef.steps();
48 let targets =
49 steps.iter().skip(1).map(|&(ty, _)| ty).chain(iter::once(autoderef.final_ty(false)));
50 let steps: Vec<_> = steps
dfeec247
XL
51 .iter()
52 .map(|&(source, kind)| {
53 if let AutoderefKind::Overloaded = kind {
f035d41b 54 self.try_overloaded_deref(autoderef.span(), source).and_then(
dfeec247
XL
55 |InferOk { value: method, obligations: o }| {
56 obligations.extend(o);
1b1a35ee
XL
57 if let ty::Ref(region, _, mutbl) = *method.sig.output().kind() {
58 Some(OverloadedDeref {
59 region,
60 mutbl,
61 span: autoderef.overloaded_span(),
62 })
dfeec247
XL
63 } else {
64 None
65 }
66 },
67 )
68 } else {
69 None
70 }
71 })
72 .zip(targets)
73 .map(|(autoderef, target)| Adjustment { kind: Adjust::Deref(autoderef), target })
74 .collect();
75
76 InferOk { obligations, value: steps }
3157f602 77 }
3157f602 78}