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