summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_infer/src/infer/projection.rs
blob: f795047709e4033088ed6c65df34a12fe622e24f (plain)
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
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::{self, Ty};

use crate::traits::{Obligation, PredicateObligation};

use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use super::InferCtxt;

impl<'tcx> InferCtxt<'tcx> {
    /// Instead of normalizing an associated type projection,
    /// this function generates an inference variable and registers
    /// an obligation that this inference variable must be the result
    /// of the given projection. This allows us to proceed with projections
    /// while they cannot be resolved yet due to missing information or
    /// simply due to the lack of access to the trait resolution machinery.
    pub fn infer_projection(
        &self,
        param_env: ty::ParamEnv<'tcx>,
        projection_ty: ty::AliasTy<'tcx>,
        cause: ObligationCause<'tcx>,
        recursion_depth: usize,
        obligations: &mut Vec<PredicateObligation<'tcx>>,
    ) -> Ty<'tcx> {
        if self.tcx.trait_solver_next() {
            // FIXME(-Ztrait-solver=next): Instead of branching here,
            // completely change the normalization routine with the new solver.
            //
            // The new solver correctly handles projection equality so this hack
            // is not necessary. if re-enabled it should emit `PredicateKind::AliasEq`
            // not `PredicateKind::Clause(Clause::Projection(..))` as in the new solver
            // `Projection` is used as `normalizes-to` which will fail for `<T as Trait>::Assoc eq ?0`.
            return projection_ty.to_ty(self.tcx);
        } else {
            let def_id = projection_ty.def_id;
            let ty_var = self.next_ty_var(TypeVariableOrigin {
                kind: TypeVariableOriginKind::NormalizeProjectionType,
                span: self.tcx.def_span(def_id),
            });
            let projection = ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::Projection(
                ty::ProjectionPredicate { projection_ty, term: ty_var.into() },
            )));
            let obligation =
                Obligation::with_depth(self.tcx, cause, recursion_depth, param_env, projection);
            obligations.push(obligation);
            ty_var
        }
    }
}