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<T>>,
42) -> Result<T, NoSolution>
43where
44 T: fmt::Debug + TypeFoldable<TyCtxt<'tcx>>,
45{
46 let (param_env, Normalize { value }) = key.into_parts();
47 let Normalized { value, obligations } =
48 ocx.infcx.at(&ObligationCause::dummy(), param_env).query_normalize(value)?;
49 ocx.register_obligations(obligations);
50 Ok(value)
51}
52
53fn type_op_normalize_ty<'tcx>(
54 tcx: TyCtxt<'tcx>,
55 canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Normalize<Ty<'tcx>>>>,
56) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>, NoSolution> {
57 tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, type_op_normalize)
58}
59
60fn type_op_normalize_clause<'tcx>(
61 tcx: TyCtxt<'tcx>,
62 canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Normalize<Clause<'tcx>>>>,
63) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, Clause<'tcx>>>, NoSolution> {
64 tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, type_op_normalize)
65}
66
67fn type_op_normalize_fn_sig<'tcx>(
68 tcx: TyCtxt<'tcx>,
69 canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Normalize<FnSig<'tcx>>>>,
70) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, FnSig<'tcx>>>, NoSolution> {
71 tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, type_op_normalize)
72}
73
74fn type_op_normalize_poly_fn_sig<'tcx>(
75 tcx: TyCtxt<'tcx>,
76 canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Normalize<PolyFnSig<'tcx>>>>,
77) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, PolyFnSig<'tcx>>>, NoSolution> {
78 tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, type_op_normalize)
79}
80
81fn type_op_prove_predicate<'tcx>(
82 tcx: TyCtxt<'tcx>,
83 canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, ProvePredicate<'tcx>>>,
84) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, ()>>, NoSolution> {
85 tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, |ocx, key| {
86 type_op_prove_predicate_with_cause(ocx, key, ObligationCause::dummy());
87 Ok(())
88 })
89}
90
91pub fn type_op_prove_predicate_with_cause<'tcx>(
95 ocx: &ObligationCtxt<'_, 'tcx>,
96 key: ParamEnvAnd<'tcx, ProvePredicate<'tcx>>,
97 cause: ObligationCause<'tcx>,
98) {
99 let (param_env, ProvePredicate { predicate }) = key.into_parts();
100 ocx.register_obligation(Obligation::new(ocx.infcx.tcx, cause, param_env, predicate));
101}