Unnamed repository; edit this file 'description' to name the repository.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
//! Autoderef helpers for inference.

use std::iter;

use rustc_ast_ir::Mutability;

use crate::{
    Adjust, Adjustment, OverloadedDeref,
    autoderef::{Autoderef, AutoderefCtx, AutoderefKind, GeneralAutoderef},
    infer::unify::InferenceTable,
    next_solver::{
        Ty,
        infer::{InferOk, traits::PredicateObligations},
    },
};

impl<'db> InferenceTable<'db> {
    pub(crate) fn autoderef(&self, base_ty: Ty<'db>) -> Autoderef<'_, 'db, usize> {
        Autoderef::new(&self.infer_ctxt, self.param_env, base_ty)
    }

    pub(crate) fn autoderef_with_tracking(&self, base_ty: Ty<'db>) -> Autoderef<'_, 'db> {
        Autoderef::new_with_tracking(&self.infer_ctxt, self.param_env, base_ty)
    }
}

impl<'db, Ctx: AutoderefCtx<'db>> GeneralAutoderef<'db, Ctx> {
    pub(crate) fn adjust_steps_as_infer_ok(&mut self) -> InferOk<'db, Vec<Adjustment>> {
        let steps = self.steps();
        if steps.is_empty() {
            return InferOk { obligations: PredicateObligations::new(), value: vec![] };
        }

        let targets = steps.iter().skip(1).map(|&(ty, _)| ty).chain(iter::once(self.final_ty()));
        let steps: Vec<_> = steps
            .iter()
            .map(|&(_source, kind)| {
                if let AutoderefKind::Overloaded = kind {
                    Some(OverloadedDeref(Some(Mutability::Not)))
                } else {
                    None
                }
            })
            .zip(targets)
            .map(|(autoderef, target)| Adjustment {
                kind: Adjust::Deref(autoderef),
                target: target.store(),
            })
            .collect();

        InferOk { obligations: self.take_obligations(), value: steps }
    }
}