]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs
New upstream version 1.71.1+dfsg1
[rustc.git] / compiler / rustc_trait_selection / src / traits / query / type_op / ascribe_user_type.rs
CommitLineData
9c376795 1use crate::infer::canonical::{Canonical, CanonicalQueryResponse};
49aad941
FG
2use crate::traits::ObligationCtxt;
3use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
4use rustc_infer::traits::Obligation;
5use rustc_middle::traits::query::NoSolution;
6use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
7use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, UserSelfTy, UserSubsts, UserType};
0bf4aa26 8
ba9703b0 9pub use rustc_middle::traits::query::type_op::AscribeUserType;
49aad941 10use rustc_span::{Span, DUMMY_SP};
0bf4aa26 11
dc9dc135 12impl<'tcx> super::QueryTypeOp<'tcx> for AscribeUserType<'tcx> {
0bf4aa26
XL
13 type QueryResponse = ();
14
15 fn try_fast_path(
dc9dc135 16 _tcx: TyCtxt<'tcx>,
0bf4aa26
XL
17 _key: &ParamEnvAnd<'tcx, Self>,
18 ) -> Option<Self::QueryResponse> {
19 None
20 }
21
22 fn perform_query(
dc9dc135 23 tcx: TyCtxt<'tcx>,
9c376795 24 canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>,
49aad941 25 ) -> Result<CanonicalQueryResponse<'tcx, ()>, NoSolution> {
0bf4aa26
XL
26 tcx.type_op_ascribe_user_type(canonicalized)
27 }
49aad941
FG
28
29 fn perform_locally_in_new_solver(
30 ocx: &ObligationCtxt<'_, 'tcx>,
31 key: ParamEnvAnd<'tcx, Self>,
32 ) -> Result<Self::QueryResponse, NoSolution> {
33 type_op_ascribe_user_type_with_span(ocx, key, None)
34 }
35}
36
37/// The core of the `type_op_ascribe_user_type` query: for diagnostics purposes in NLL HRTB errors,
38/// this query can be re-run to better track the span of the obligation cause, and improve the error
39/// message. Do not call directly unless you're in that very specific context.
40pub fn type_op_ascribe_user_type_with_span<'tcx>(
41 ocx: &ObligationCtxt<'_, 'tcx>,
42 key: ParamEnvAnd<'tcx, AscribeUserType<'tcx>>,
43 span: Option<Span>,
44) -> Result<(), NoSolution> {
45 let (param_env, AscribeUserType { mir_ty, user_ty }) = key.into_parts();
46 debug!("type_op_ascribe_user_type: mir_ty={:?} user_ty={:?}", mir_ty, user_ty);
47 let span = span.unwrap_or(DUMMY_SP);
48 match user_ty {
49 UserType::Ty(user_ty) => relate_mir_and_user_ty(ocx, param_env, span, mir_ty, user_ty)?,
50 UserType::TypeOf(def_id, user_substs) => {
51 relate_mir_and_user_substs(ocx, param_env, span, mir_ty, def_id, user_substs)?
52 }
53 };
54 Ok(())
55}
56
57#[instrument(level = "debug", skip(ocx, param_env, span))]
58fn relate_mir_and_user_ty<'tcx>(
59 ocx: &ObligationCtxt<'_, 'tcx>,
60 param_env: ty::ParamEnv<'tcx>,
61 span: Span,
62 mir_ty: Ty<'tcx>,
63 user_ty: Ty<'tcx>,
64) -> Result<(), NoSolution> {
65 let cause = ObligationCause::dummy_with_span(span);
66 let user_ty = ocx.normalize(&cause, param_env, user_ty);
67 ocx.eq(&cause, param_env, mir_ty, user_ty)?;
68
69 // FIXME(#104764): We should check well-formedness before normalization.
70 let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(user_ty.into()));
71 ocx.register_obligation(Obligation::new(ocx.infcx.tcx, cause, param_env, predicate));
72 Ok(())
73}
74
75#[instrument(level = "debug", skip(ocx, param_env, span))]
76fn relate_mir_and_user_substs<'tcx>(
77 ocx: &ObligationCtxt<'_, 'tcx>,
78 param_env: ty::ParamEnv<'tcx>,
79 span: Span,
80 mir_ty: Ty<'tcx>,
81 def_id: DefId,
82 user_substs: UserSubsts<'tcx>,
83) -> Result<(), NoSolution> {
84 let param_env = param_env.without_const();
85 let UserSubsts { user_self_ty, substs } = user_substs;
86 let tcx = ocx.infcx.tcx;
87 let cause = ObligationCause::dummy_with_span(span);
88
89 let ty = tcx.type_of(def_id).subst(tcx, substs);
90 let ty = ocx.normalize(&cause, param_env, ty);
91 debug!("relate_type_and_user_type: ty of def-id is {:?}", ty);
92
93 ocx.eq(&cause, param_env, mir_ty, ty)?;
94
95 // Prove the predicates coming along with `def_id`.
96 //
97 // Also, normalize the `instantiated_predicates`
98 // because otherwise we wind up with duplicate "type
99 // outlives" error messages.
100 let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, substs);
101
102 debug!(?instantiated_predicates);
103 for (instantiated_predicate, predicate_span) in instantiated_predicates {
104 let span = if span == DUMMY_SP { predicate_span } else { span };
105 let cause = ObligationCause::new(
106 span,
107 CRATE_DEF_ID,
108 ObligationCauseCode::AscribeUserTypeProvePredicate(predicate_span),
109 );
110 let instantiated_predicate =
111 ocx.normalize(&cause.clone(), param_env, instantiated_predicate);
112
113 ocx.register_obligation(Obligation::new(tcx, cause, param_env, instantiated_predicate));
114 }
115
116 if let Some(UserSelfTy { impl_def_id, self_ty }) = user_self_ty {
117 let self_ty = ocx.normalize(&cause, param_env, self_ty);
118 let impl_self_ty = tcx.type_of(impl_def_id).subst(tcx, substs);
119 let impl_self_ty = ocx.normalize(&cause, param_env, impl_self_ty);
120
121 ocx.eq(&cause, param_env, self_ty, impl_self_ty)?;
122 let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(impl_self_ty.into()));
123 ocx.register_obligation(Obligation::new(tcx, cause.clone(), param_env, predicate));
124 }
125
126 // In addition to proving the predicates, we have to
127 // prove that `ty` is well-formed -- this is because
128 // the WF of `ty` is predicated on the substs being
129 // well-formed, and we haven't proven *that*. We don't
130 // want to prove the WF of types from `substs` directly because they
131 // haven't been normalized.
132 //
133 // FIXME(nmatsakis): Well, perhaps we should normalize
134 // them? This would only be relevant if some input
135 // type were ill-formed but did not appear in `ty`,
136 // which...could happen with normalization...
137 let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(ty.into()));
138 ocx.register_obligation(Obligation::new(tcx, cause, param_env, predicate));
139 Ok(())
0bf4aa26 140}