Skip to main content

rustc_traits/
type_op.rs

1use std::fmt;
2
3use rustc_infer::infer::TyCtxtInferExt;
4use rustc_infer::infer::canonical::{Canonical, CanonicalQueryInput, QueryResponse};
5use rustc_middle::query::Providers;
6use rustc_middle::traits::query::NoSolution;
7use rustc_middle::ty::{Clause, FnSig, ParamEnvAnd, PolyFnSig, Ty, TyCtxt, TypeFoldable};
8use rustc_span::DUMMY_SP;
9use rustc_trait_selection::infer::InferCtxtBuilderExt;
10use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt;
11use rustc_trait_selection::traits::query::type_op::ascribe_user_type::{
12    AscribeUserType, type_op_ascribe_user_type_with_span,
13};
14use rustc_trait_selection::traits::query::type_op::normalize::Normalize;
15use rustc_trait_selection::traits::query::type_op::prove_predicate::ProvePredicate;
16use rustc_trait_selection::traits::{Normalized, Obligation, ObligationCause, ObligationCtxt};
17
18pub(crate) fn provide(p: &mut Providers) {
19    *p = Providers {
20        type_op_ascribe_user_type,
21        type_op_prove_predicate,
22        type_op_normalize_ty,
23        type_op_normalize_clause,
24        type_op_normalize_fn_sig,
25        type_op_normalize_poly_fn_sig,
26        ..*p
27    };
28}
29
30fn type_op_ascribe_user_type<'tcx>(
31    tcx: TyCtxt<'tcx>,
32    canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, AscribeUserType<'tcx>>>,
33) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, ()>>, NoSolution> {
34    tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, |ocx, key| {
35        type_op_ascribe_user_type_with_span(ocx, key, DUMMY_SP)
36    })
37}
38
39fn type_op_normalize<'tcx, T>(
40    ocx: &ObligationCtxt<'_, 'tcx>,
41    key: ParamEnvAnd<'tcx, Normalize<'tcx, T>>,
42) -> Result<T, NoSolution>
43where
44    T: fmt::Debug + TypeFoldable<TyCtxt<'tcx>>,
45{
46    let ParamEnvAnd { param_env, value: Normalize { value } } = key;
47    let Normalized { value, obligations } = ocx
48        .infcx
49        .at(&ObligationCause::dummy(), param_env)
50        .query_normalize(value.skip_normalization())?;
51    ocx.register_obligations(obligations);
52    Ok(value)
53}
54
55fn type_op_normalize_ty<'tcx>(
56    tcx: TyCtxt<'tcx>,
57    canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Normalize<'tcx, Ty<'tcx>>>>,
58) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>, NoSolution> {
59    tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, type_op_normalize)
60}
61
62fn type_op_normalize_clause<'tcx>(
63    tcx: TyCtxt<'tcx>,
64    canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Normalize<'tcx, Clause<'tcx>>>>,
65) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, Clause<'tcx>>>, NoSolution> {
66    tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, type_op_normalize)
67}
68
69fn type_op_normalize_fn_sig<'tcx>(
70    tcx: TyCtxt<'tcx>,
71    canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Normalize<'tcx, FnSig<'tcx>>>>,
72) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, FnSig<'tcx>>>, NoSolution> {
73    tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, type_op_normalize)
74}
75
76fn type_op_normalize_poly_fn_sig<'tcx>(
77    tcx: TyCtxt<'tcx>,
78    canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Normalize<'tcx, PolyFnSig<'tcx>>>>,
79) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, PolyFnSig<'tcx>>>, NoSolution> {
80    tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, type_op_normalize)
81}
82
83fn type_op_prove_predicate<'tcx>(
84    tcx: TyCtxt<'tcx>,
85    canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, ProvePredicate<'tcx>>>,
86) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, ()>>, NoSolution> {
87    tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, |ocx, key| {
88        type_op_prove_predicate_with_cause(ocx, key, ObligationCause::dummy());
89        Ok(())
90    })
91}
92
93/// The core of the `type_op_prove_predicate` query: for diagnostics purposes in NLL HRTB errors,
94/// this query can be re-run to better track the span of the obligation cause, and improve the error
95/// message. Do not call directly unless you're in that very specific context.
96pub fn type_op_prove_predicate_with_cause<'tcx>(
97    ocx: &ObligationCtxt<'_, 'tcx>,
98    key: ParamEnvAnd<'tcx, ProvePredicate<'tcx>>,
99    cause: ObligationCause<'tcx>,
100) {
101    let ParamEnvAnd { param_env, value: ProvePredicate { predicate } } = key;
102    ocx.register_obligation(Obligation::new(ocx.infcx.tcx, cause, param_env, predicate));
103}