]>
Commit | Line | Data |
---|---|---|
dfeec247 XL |
1 | use rustc_hir as hir; |
2 | use rustc_hir::def_id::DefId; | |
74b04a01 XL |
3 | use rustc_infer::infer::at::ToTrace; |
4 | use rustc_infer::infer::canonical::{Canonical, QueryResponse}; | |
064997fb | 5 | use rustc_infer::infer::{DefiningAnchor, InferCtxt, TyCtxtInferExt}; |
f2b60f7d | 6 | use rustc_infer::traits::{ObligationCauseCode, TraitEngineExt as _}; |
ba9703b0 XL |
7 | use rustc_middle::ty::query::Providers; |
8 | use rustc_middle::ty::subst::{GenericArg, Subst, UserSelfTy, UserSubsts}; | |
04454e1e FG |
9 | use rustc_middle::ty::{ |
10 | self, EarlyBinder, FnSig, Lift, PolyFnSig, Ty, TyCtxt, TypeFoldable, Variance, | |
11 | }; | |
f9f354fc | 12 | use rustc_middle::ty::{ParamEnv, ParamEnvAnd, Predicate, ToPredicate}; |
94222f64 | 13 | use rustc_span::{Span, DUMMY_SP}; |
ba9703b0 XL |
14 | use rustc_trait_selection::infer::InferCtxtBuilderExt; |
15 | use rustc_trait_selection::infer::InferCtxtExt; | |
16 | use rustc_trait_selection::traits::query::normalize::AtExt; | |
17 | use rustc_trait_selection::traits::query::type_op::ascribe_user_type::AscribeUserType; | |
18 | use rustc_trait_selection::traits::query::type_op::eq::Eq; | |
19 | use rustc_trait_selection::traits::query::type_op::normalize::Normalize; | |
20 | use rustc_trait_selection::traits::query::type_op::prove_predicate::ProvePredicate; | |
21 | use rustc_trait_selection::traits::query::type_op::subtype::Subtype; | |
22 | use rustc_trait_selection::traits::query::{Fallible, NoSolution}; | |
23 | use rustc_trait_selection::traits::{Normalized, Obligation, ObligationCause, TraitEngine}; | |
8faf50e0 | 24 | use std::fmt; |
f2b60f7d | 25 | use std::iter::zip; |
8faf50e0 | 26 | |
923072b8 | 27 | pub(crate) fn provide(p: &mut Providers) { |
8faf50e0 | 28 | *p = Providers { |
0bf4aa26 | 29 | type_op_ascribe_user_type, |
8faf50e0 XL |
30 | type_op_eq, |
31 | type_op_prove_predicate, | |
32 | type_op_subtype, | |
33 | type_op_normalize_ty, | |
34 | type_op_normalize_predicate, | |
35 | type_op_normalize_fn_sig, | |
36 | type_op_normalize_poly_fn_sig, | |
37 | ..*p | |
38 | }; | |
39 | } | |
40 | ||
0bf4aa26 | 41 | fn type_op_ascribe_user_type<'tcx>( |
dc9dc135 | 42 | tcx: TyCtxt<'tcx>, |
0bf4aa26 | 43 | canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, AscribeUserType<'tcx>>>, |
48663c56 | 44 | ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, ()>>, NoSolution> { |
dfeec247 | 45 | tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, |infcx, fulfill_cx, key| { |
94222f64 XL |
46 | type_op_ascribe_user_type_with_span(infcx, fulfill_cx, key, None) |
47 | }) | |
48 | } | |
0bf4aa26 | 49 | |
94222f64 XL |
50 | /// The core of the `type_op_ascribe_user_type` query: for diagnostics purposes in NLL HRTB errors, |
51 | /// this query can be re-run to better track the span of the obligation cause, and improve the error | |
52 | /// message. Do not call directly unless you're in that very specific context. | |
53 | pub fn type_op_ascribe_user_type_with_span<'a, 'tcx: 'a>( | |
54 | infcx: &'a InferCtxt<'a, 'tcx>, | |
55 | fulfill_cx: &'a mut dyn TraitEngine<'tcx>, | |
56 | key: ParamEnvAnd<'tcx, AscribeUserType<'tcx>>, | |
57 | span: Option<Span>, | |
58 | ) -> Result<(), NoSolution> { | |
59 | let (param_env, AscribeUserType { mir_ty, def_id, user_substs }) = key.into_parts(); | |
60 | debug!( | |
61 | "type_op_ascribe_user_type: mir_ty={:?} def_id={:?} user_substs={:?}", | |
62 | mir_ty, def_id, user_substs | |
63 | ); | |
0bf4aa26 | 64 | |
f2b60f7d FG |
65 | let mut cx = AscribeUserTypeCx { infcx, param_env, span: span.unwrap_or(DUMMY_SP), fulfill_cx }; |
66 | cx.relate_mir_and_user_ty(mir_ty, def_id, user_substs)?; | |
94222f64 | 67 | Ok(()) |
0bf4aa26 XL |
68 | } |
69 | ||
dc9dc135 XL |
70 | struct AscribeUserTypeCx<'me, 'tcx> { |
71 | infcx: &'me InferCtxt<'me, 'tcx>, | |
0bf4aa26 | 72 | param_env: ParamEnv<'tcx>, |
f2b60f7d | 73 | span: Span, |
0731742a | 74 | fulfill_cx: &'me mut dyn TraitEngine<'tcx>, |
0bf4aa26 XL |
75 | } |
76 | ||
a2a8927a | 77 | impl<'me, 'tcx> AscribeUserTypeCx<'me, 'tcx> { |
0bf4aa26 | 78 | fn normalize<T>(&mut self, value: T) -> T |
f2b60f7d FG |
79 | where |
80 | T: TypeFoldable<'tcx>, | |
81 | { | |
82 | self.normalize_with_cause(value, ObligationCause::misc(self.span, hir::CRATE_HIR_ID)) | |
83 | } | |
84 | ||
85 | fn normalize_with_cause<T>(&mut self, value: T, cause: ObligationCause<'tcx>) -> T | |
0bf4aa26 XL |
86 | where |
87 | T: TypeFoldable<'tcx>, | |
88 | { | |
89 | self.infcx | |
f2b60f7d | 90 | .partially_normalize_associated_types_in(cause, self.param_env, value) |
0bf4aa26 XL |
91 | .into_value_registering_obligations(self.infcx, self.fulfill_cx) |
92 | } | |
93 | ||
94 | fn relate<T>(&mut self, a: T, variance: Variance, b: T) -> Result<(), NoSolution> | |
95 | where | |
96 | T: ToTrace<'tcx>, | |
97 | { | |
ba9703b0 | 98 | self.infcx |
f2b60f7d | 99 | .at(&ObligationCause::dummy_with_span(self.span), self.param_env) |
dfeec247 | 100 | .relate(a, variance, b)? |
ba9703b0 XL |
101 | .into_value_registering_obligations(self.infcx, self.fulfill_cx); |
102 | Ok(()) | |
0bf4aa26 XL |
103 | } |
104 | ||
f2b60f7d | 105 | fn prove_predicate(&mut self, predicate: Predicate<'tcx>, cause: ObligationCause<'tcx>) { |
0bf4aa26 XL |
106 | self.fulfill_cx.register_predicate_obligation( |
107 | self.infcx, | |
94222f64 | 108 | Obligation::new(cause, self.param_env, predicate), |
0bf4aa26 XL |
109 | ); |
110 | } | |
111 | ||
dc9dc135 | 112 | fn tcx(&self) -> TyCtxt<'tcx> { |
0bf4aa26 XL |
113 | self.infcx.tcx |
114 | } | |
115 | ||
e74abb32 | 116 | fn subst<T>(&self, value: T, substs: &[GenericArg<'tcx>]) -> T |
0bf4aa26 XL |
117 | where |
118 | T: TypeFoldable<'tcx>, | |
119 | { | |
04454e1e | 120 | EarlyBinder(value).subst(self.tcx(), substs) |
0bf4aa26 XL |
121 | } |
122 | ||
f2b60f7d | 123 | #[instrument(level = "debug", skip(self))] |
0bf4aa26 XL |
124 | fn relate_mir_and_user_ty( |
125 | &mut self, | |
126 | mir_ty: Ty<'tcx>, | |
0bf4aa26 XL |
127 | def_id: DefId, |
128 | user_substs: UserSubsts<'tcx>, | |
0bf4aa26 | 129 | ) -> Result<(), NoSolution> { |
dfeec247 | 130 | let UserSubsts { user_self_ty, substs } = user_substs; |
0bf4aa26 XL |
131 | let tcx = self.tcx(); |
132 | ||
133 | let ty = tcx.type_of(def_id); | |
134 | let ty = self.subst(ty, substs); | |
0bf4aa26 | 135 | let ty = self.normalize(ty); |
f2b60f7d | 136 | debug!("relate_type_and_user_type: ty of def-id is {:?}", ty); |
0bf4aa26 | 137 | |
9fa01778 | 138 | self.relate(mir_ty, Variance::Invariant, ty)?; |
0bf4aa26 | 139 | |
0bf4aa26 XL |
140 | // Prove the predicates coming along with `def_id`. |
141 | // | |
142 | // Also, normalize the `instantiated_predicates` | |
143 | // because otherwise we wind up with duplicate "type | |
144 | // outlives" error messages. | |
dfeec247 XL |
145 | let instantiated_predicates = |
146 | self.tcx().predicates_of(def_id).instantiate(self.tcx(), substs); | |
f2b60f7d FG |
147 | |
148 | let cause = ObligationCause::dummy_with_span(self.span); | |
149 | ||
150 | debug!(?instantiated_predicates); | |
151 | for (instantiated_predicate, predicate_span) in | |
152 | zip(instantiated_predicates.predicates, instantiated_predicates.spans) | |
153 | { | |
154 | let span = if self.span == DUMMY_SP { predicate_span } else { self.span }; | |
155 | let cause = ObligationCause::new( | |
156 | span, | |
157 | hir::CRATE_HIR_ID, | |
158 | ObligationCauseCode::AscribeUserTypeProvePredicate(predicate_span), | |
159 | ); | |
160 | let instantiated_predicate = | |
161 | self.normalize_with_cause(instantiated_predicate, cause.clone()); | |
162 | self.prove_predicate(instantiated_predicate, cause); | |
0bf4aa26 XL |
163 | } |
164 | ||
dfeec247 | 165 | if let Some(UserSelfTy { impl_def_id, self_ty }) = user_self_ty { |
0731742a XL |
166 | let impl_self_ty = self.tcx().type_of(impl_def_id); |
167 | let impl_self_ty = self.subst(impl_self_ty, &substs); | |
168 | let impl_self_ty = self.normalize(impl_self_ty); | |
169 | ||
170 | self.relate(self_ty, Variance::Invariant, impl_self_ty)?; | |
171 | ||
f9f354fc | 172 | self.prove_predicate( |
c295e0f8 XL |
173 | ty::Binder::dummy(ty::PredicateKind::WellFormed(impl_self_ty.into())) |
174 | .to_predicate(self.tcx()), | |
f2b60f7d | 175 | cause.clone(), |
f9f354fc | 176 | ); |
0731742a XL |
177 | } |
178 | ||
0bf4aa26 XL |
179 | // In addition to proving the predicates, we have to |
180 | // prove that `ty` is well-formed -- this is because | |
181 | // the WF of `ty` is predicated on the substs being | |
182 | // well-formed, and we haven't proven *that*. We don't | |
183 | // want to prove the WF of types from `substs` directly because they | |
184 | // haven't been normalized. | |
185 | // | |
186 | // FIXME(nmatsakis): Well, perhaps we should normalize | |
187 | // them? This would only be relevant if some input | |
188 | // type were ill-formed but did not appear in `ty`, | |
189 | // which...could happen with normalization... | |
94222f64 | 190 | self.prove_predicate( |
c295e0f8 | 191 | ty::Binder::dummy(ty::PredicateKind::WellFormed(ty.into())).to_predicate(self.tcx()), |
f2b60f7d | 192 | cause, |
94222f64 | 193 | ); |
0bf4aa26 XL |
194 | Ok(()) |
195 | } | |
196 | } | |
197 | ||
8faf50e0 | 198 | fn type_op_eq<'tcx>( |
dc9dc135 | 199 | tcx: TyCtxt<'tcx>, |
8faf50e0 | 200 | canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Eq<'tcx>>>, |
48663c56 | 201 | ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, ()>>, NoSolution> { |
dfeec247 XL |
202 | tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, |infcx, fulfill_cx, key| { |
203 | let (param_env, Eq { a, b }) = key.into_parts(); | |
ba9703b0 | 204 | infcx |
dfeec247 XL |
205 | .at(&ObligationCause::dummy(), param_env) |
206 | .eq(a, b)? | |
ba9703b0 XL |
207 | .into_value_registering_obligations(infcx, fulfill_cx); |
208 | Ok(()) | |
dfeec247 | 209 | }) |
8faf50e0 XL |
210 | } |
211 | ||
a2a8927a | 212 | fn type_op_normalize<'tcx, T>( |
dc9dc135 | 213 | infcx: &InferCtxt<'_, 'tcx>, |
0731742a | 214 | fulfill_cx: &mut dyn TraitEngine<'tcx>, |
8faf50e0 XL |
215 | key: ParamEnvAnd<'tcx, Normalize<T>>, |
216 | ) -> Fallible<T> | |
217 | where | |
dc9dc135 | 218 | T: fmt::Debug + TypeFoldable<'tcx> + Lift<'tcx>, |
8faf50e0 XL |
219 | { |
220 | let (param_env, Normalize { value }) = key.into_parts(); | |
dfeec247 | 221 | let Normalized { value, obligations } = |
fc512014 | 222 | infcx.at(&ObligationCause::dummy(), param_env).normalize(value)?; |
8faf50e0 XL |
223 | fulfill_cx.register_predicate_obligations(infcx, obligations); |
224 | Ok(value) | |
225 | } | |
226 | ||
a2a8927a | 227 | fn type_op_normalize_ty<'tcx>( |
dc9dc135 | 228 | tcx: TyCtxt<'tcx>, |
8faf50e0 | 229 | canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<Ty<'tcx>>>>, |
48663c56 | 230 | ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>, NoSolution> { |
dfeec247 | 231 | tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, type_op_normalize) |
8faf50e0 XL |
232 | } |
233 | ||
a2a8927a | 234 | fn type_op_normalize_predicate<'tcx>( |
dc9dc135 | 235 | tcx: TyCtxt<'tcx>, |
8faf50e0 | 236 | canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<Predicate<'tcx>>>>, |
48663c56 | 237 | ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, Predicate<'tcx>>>, NoSolution> { |
dfeec247 | 238 | tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, type_op_normalize) |
8faf50e0 XL |
239 | } |
240 | ||
a2a8927a | 241 | fn type_op_normalize_fn_sig<'tcx>( |
dc9dc135 | 242 | tcx: TyCtxt<'tcx>, |
8faf50e0 | 243 | canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<FnSig<'tcx>>>>, |
48663c56 | 244 | ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, FnSig<'tcx>>>, NoSolution> { |
dfeec247 | 245 | tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, type_op_normalize) |
8faf50e0 XL |
246 | } |
247 | ||
a2a8927a | 248 | fn type_op_normalize_poly_fn_sig<'tcx>( |
dc9dc135 | 249 | tcx: TyCtxt<'tcx>, |
8faf50e0 | 250 | canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<PolyFnSig<'tcx>>>>, |
48663c56 | 251 | ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, PolyFnSig<'tcx>>>, NoSolution> { |
dfeec247 | 252 | tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, type_op_normalize) |
8faf50e0 XL |
253 | } |
254 | ||
255 | fn type_op_subtype<'tcx>( | |
dc9dc135 | 256 | tcx: TyCtxt<'tcx>, |
8faf50e0 | 257 | canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Subtype<'tcx>>>, |
48663c56 | 258 | ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, ()>>, NoSolution> { |
dfeec247 XL |
259 | tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, |infcx, fulfill_cx, key| { |
260 | let (param_env, Subtype { sub, sup }) = key.into_parts(); | |
ba9703b0 | 261 | infcx |
dfeec247 XL |
262 | .at(&ObligationCause::dummy(), param_env) |
263 | .sup(sup, sub)? | |
ba9703b0 XL |
264 | .into_value_registering_obligations(infcx, fulfill_cx); |
265 | Ok(()) | |
dfeec247 | 266 | }) |
8faf50e0 XL |
267 | } |
268 | ||
269 | fn type_op_prove_predicate<'tcx>( | |
dc9dc135 | 270 | tcx: TyCtxt<'tcx>, |
8faf50e0 | 271 | canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, ProvePredicate<'tcx>>>, |
48663c56 | 272 | ) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, ()>>, NoSolution> { |
064997fb FG |
273 | // HACK This bubble is required for this test to pass: |
274 | // impl-trait/issue-99642.rs | |
275 | tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).enter_canonical_trait_query( | |
276 | &canonicalized, | |
277 | |infcx, fulfill_cx, key| { | |
278 | type_op_prove_predicate_with_cause(infcx, fulfill_cx, key, ObligationCause::dummy()); | |
279 | Ok(()) | |
280 | }, | |
281 | ) | |
8faf50e0 | 282 | } |
94222f64 XL |
283 | |
284 | /// The core of the `type_op_prove_predicate` query: for diagnostics purposes in NLL HRTB errors, | |
285 | /// this query can be re-run to better track the span of the obligation cause, and improve the error | |
286 | /// message. Do not call directly unless you're in that very specific context. | |
c295e0f8 | 287 | pub fn type_op_prove_predicate_with_cause<'a, 'tcx: 'a>( |
94222f64 XL |
288 | infcx: &'a InferCtxt<'a, 'tcx>, |
289 | fulfill_cx: &'a mut dyn TraitEngine<'tcx>, | |
290 | key: ParamEnvAnd<'tcx, ProvePredicate<'tcx>>, | |
c295e0f8 | 291 | cause: ObligationCause<'tcx>, |
94222f64 | 292 | ) { |
94222f64 XL |
293 | let (param_env, ProvePredicate { predicate }) = key.into_parts(); |
294 | fulfill_cx.register_predicate_obligation(infcx, Obligation::new(cause, param_env, predicate)); | |
295 | } |