]>
Commit | Line | Data |
---|---|---|
9c376795 | 1 | use crate::infer::canonical::{Canonical, CanonicalQueryResponse}; |
49aad941 FG |
2 | use crate::traits::ObligationCtxt; |
3 | use rustc_hir::def_id::{DefId, CRATE_DEF_ID}; | |
4 | use rustc_infer::traits::Obligation; | |
5 | use rustc_middle::traits::query::NoSolution; | |
6 | use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; | |
7 | use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, UserSelfTy, UserSubsts, UserType}; | |
0bf4aa26 | 8 | |
ba9703b0 | 9 | pub use rustc_middle::traits::query::type_op::AscribeUserType; |
49aad941 | 10 | use rustc_span::{Span, DUMMY_SP}; |
0bf4aa26 | 11 | |
dc9dc135 | 12 | impl<'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. | |
40 | pub 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))] | |
58 | fn 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))] | |
76 | fn 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 | } |