Skip to main content

hir_ty/infer/
autoderef.rs

1//! Autoderef helpers for inference.
2
3use std::iter;
4
5use rustc_ast_ir::Mutability;
6
7use crate::{
8    Adjust, Adjustment, OverloadedDeref, Span,
9    autoderef::{Autoderef, AutoderefCtx, AutoderefKind, GeneralAutoderef},
10    infer::unify::InferenceTable,
11    next_solver::{
12        Ty,
13        infer::{InferOk, traits::PredicateObligations},
14    },
15};
16
17impl<'db> InferenceTable<'db> {
18    pub(crate) fn autoderef(&self, base_ty: Ty<'db>, span: Span) -> Autoderef<'_, 'db, usize> {
19        Autoderef::new(&self.infer_ctxt, self.param_env, base_ty, span)
20    }
21
22    pub(crate) fn autoderef_with_tracking(
23        &self,
24        base_ty: Ty<'db>,
25        span: Span,
26    ) -> Autoderef<'_, 'db> {
27        Autoderef::new_with_tracking(&self.infer_ctxt, self.param_env, base_ty, span)
28    }
29}
30
31impl<'db, Ctx: AutoderefCtx<'db>> GeneralAutoderef<'db, Ctx> {
32    pub(crate) fn adjust_steps_as_infer_ok(&mut self) -> InferOk<'db, Vec<Adjustment>> {
33        let steps = self.steps();
34        if steps.is_empty() {
35            return InferOk { obligations: PredicateObligations::new(), value: vec![] };
36        }
37
38        let targets = steps.iter().skip(1).map(|&(ty, _)| ty).chain(iter::once(self.final_ty()));
39        let steps: Vec<_> = steps
40            .iter()
41            .map(|&(_source, kind)| {
42                if let AutoderefKind::Overloaded = kind {
43                    Some(OverloadedDeref(Mutability::Not))
44                } else {
45                    None
46                }
47            })
48            .zip(targets)
49            .map(|(autoderef, target)| Adjustment {
50                kind: Adjust::Deref(autoderef),
51                target: target.store(),
52            })
53            .collect();
54
55        InferOk { obligations: self.take_obligations(), value: steps }
56    }
57}