2 use rustc_hir
::def_id
::DefId
;
3 use rustc_infer
::infer
::at
::ToTrace
;
4 use rustc_infer
::infer
::canonical
::{Canonical, QueryResponse}
;
5 use rustc_infer
::infer
::{InferCtxt, TyCtxtInferExt}
;
6 use rustc_infer
::traits
::TraitEngineExt
as _
;
7 use rustc_middle
::ty
::query
::Providers
;
8 use rustc_middle
::ty
::subst
::{GenericArg, Subst, UserSelfTy, UserSubsts}
;
9 use rustc_middle
::ty
::{
10 self, EarlyBinder
, FnSig
, Lift
, PolyFnSig
, Ty
, TyCtxt
, TypeFoldable
, Variance
,
12 use rustc_middle
::ty
::{ParamEnv, ParamEnvAnd, Predicate, ToPredicate}
;
13 use rustc_span
::{Span, DUMMY_SP}
;
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}
;
26 pub(crate) fn provide(p
: &mut Providers
) {
28 type_op_ascribe_user_type
,
30 type_op_prove_predicate
,
33 type_op_normalize_predicate
,
34 type_op_normalize_fn_sig
,
35 type_op_normalize_poly_fn_sig
,
40 fn type_op_ascribe_user_type
<'tcx
>(
42 canonicalized
: Canonical
<'tcx
, ParamEnvAnd
<'tcx
, AscribeUserType
<'tcx
>>>,
43 ) -> Result
<&'tcx Canonical
<'tcx
, QueryResponse
<'tcx
, ()>>, NoSolution
> {
44 tcx
.infer_ctxt().enter_canonical_trait_query(&canonicalized
, |infcx
, fulfill_cx
, key
| {
45 type_op_ascribe_user_type_with_span(infcx
, fulfill_cx
, key
, None
)
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
>>,
57 ) -> Result
<(), NoSolution
> {
58 let (param_env
, AscribeUserType { mir_ty, def_id, user_substs }
) = key
.into_parts();
60 "type_op_ascribe_user_type: mir_ty={:?} def_id={:?} user_substs={:?}",
61 mir_ty
, def_id
, user_substs
64 let mut cx
= AscribeUserTypeCx { infcx, param_env, fulfill_cx }
;
65 cx
.relate_mir_and_user_ty(mir_ty
, def_id
, user_substs
, span
)?
;
69 struct AscribeUserTypeCx
<'me
, 'tcx
> {
70 infcx
: &'me InferCtxt
<'me
, 'tcx
>,
71 param_env
: ParamEnv
<'tcx
>,
72 fulfill_cx
: &'me
mut dyn TraitEngine
<'tcx
>,
75 impl<'me
, 'tcx
> AscribeUserTypeCx
<'me
, 'tcx
> {
76 fn normalize
<T
>(&mut self, value
: T
) -> T
78 T
: TypeFoldable
<'tcx
>,
81 .partially_normalize_associated_types_in(
82 ObligationCause
::misc(DUMMY_SP
, hir
::CRATE_HIR_ID
),
86 .into_value_registering_obligations(self.infcx
, self.fulfill_cx
)
89 fn relate
<T
>(&mut self, a
: T
, variance
: Variance
, b
: T
) -> Result
<(), NoSolution
>
94 .at(&ObligationCause
::dummy(), self.param_env
)
95 .relate(a
, variance
, b
)?
96 .into_value_registering_obligations(self.infcx
, self.fulfill_cx
);
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
)
104 ObligationCause
::dummy()
106 self.fulfill_cx
.register_predicate_obligation(
108 Obligation
::new(cause
, self.param_env
, predicate
),
112 fn tcx(&self) -> TyCtxt
<'tcx
> {
116 fn subst
<T
>(&self, value
: T
, substs
: &[GenericArg
<'tcx
>]) -> T
118 T
: TypeFoldable
<'tcx
>,
120 EarlyBinder(value
).subst(self.tcx(), substs
)
123 fn relate_mir_and_user_ty(
127 user_substs
: UserSubsts
<'tcx
>,
129 ) -> Result
<(), NoSolution
> {
130 let UserSubsts { user_self_ty, substs }
= user_substs
;
131 let tcx
= self.tcx();
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
);
138 self.relate(mir_ty
, Variance
::Invariant
, ty
)?
;
140 // Prove the predicates coming along with `def_id`.
142 // Also, normalize the `instantiated_predicates`
143 // because otherwise we wind up with duplicate "type
144 // outlives" error messages.
145 let instantiated_predicates
=
146 self.tcx().predicates_of(def_id
).instantiate(self.tcx(), substs
);
147 debug
!(?instantiated_predicates
.predicates
);
148 for instantiated_predicate
in instantiated_predicates
.predicates
{
149 let instantiated_predicate
= self.normalize(instantiated_predicate
);
150 self.prove_predicate(instantiated_predicate
, span
);
153 if let Some(UserSelfTy { impl_def_id, self_ty }
) = user_self_ty
{
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
);
158 self.relate(self_ty
, Variance
::Invariant
, impl_self_ty
)?
;
160 self.prove_predicate(
161 ty
::Binder
::dummy(ty
::PredicateKind
::WellFormed(impl_self_ty
.into()))
162 .to_predicate(self.tcx()),
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.
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...
178 self.prove_predicate(
179 ty
::Binder
::dummy(ty
::PredicateKind
::WellFormed(ty
.into())).to_predicate(self.tcx()),
188 canonicalized
: Canonical
<'tcx
, ParamEnvAnd
<'tcx
, Eq
<'tcx
>>>,
189 ) -> Result
<&'tcx Canonical
<'tcx
, QueryResponse
<'tcx
, ()>>, NoSolution
> {
190 tcx
.infer_ctxt().enter_canonical_trait_query(&canonicalized
, |infcx
, fulfill_cx
, key
| {
191 let (param_env
, Eq { a, b }
) = key
.into_parts();
193 .at(&ObligationCause
::dummy(), param_env
)
195 .into_value_registering_obligations(infcx
, fulfill_cx
);
200 fn type_op_normalize
<'tcx
, T
>(
201 infcx
: &InferCtxt
<'_
, 'tcx
>,
202 fulfill_cx
: &mut dyn TraitEngine
<'tcx
>,
203 key
: ParamEnvAnd
<'tcx
, Normalize
<T
>>,
206 T
: fmt
::Debug
+ TypeFoldable
<'tcx
> + Lift
<'tcx
>,
208 let (param_env
, Normalize { value }
) = key
.into_parts();
209 let Normalized { value, obligations }
=
210 infcx
.at(&ObligationCause
::dummy(), param_env
).normalize(value
)?
;
211 fulfill_cx
.register_predicate_obligations(infcx
, obligations
);
215 fn type_op_normalize_ty
<'tcx
>(
217 canonicalized
: Canonical
<'tcx
, ParamEnvAnd
<'tcx
, Normalize
<Ty
<'tcx
>>>>,
218 ) -> Result
<&'tcx Canonical
<'tcx
, QueryResponse
<'tcx
, Ty
<'tcx
>>>, NoSolution
> {
219 tcx
.infer_ctxt().enter_canonical_trait_query(&canonicalized
, type_op_normalize
)
222 fn type_op_normalize_predicate
<'tcx
>(
224 canonicalized
: Canonical
<'tcx
, ParamEnvAnd
<'tcx
, Normalize
<Predicate
<'tcx
>>>>,
225 ) -> Result
<&'tcx Canonical
<'tcx
, QueryResponse
<'tcx
, Predicate
<'tcx
>>>, NoSolution
> {
226 tcx
.infer_ctxt().enter_canonical_trait_query(&canonicalized
, type_op_normalize
)
229 fn type_op_normalize_fn_sig
<'tcx
>(
231 canonicalized
: Canonical
<'tcx
, ParamEnvAnd
<'tcx
, Normalize
<FnSig
<'tcx
>>>>,
232 ) -> Result
<&'tcx Canonical
<'tcx
, QueryResponse
<'tcx
, FnSig
<'tcx
>>>, NoSolution
> {
233 tcx
.infer_ctxt().enter_canonical_trait_query(&canonicalized
, type_op_normalize
)
236 fn type_op_normalize_poly_fn_sig
<'tcx
>(
238 canonicalized
: Canonical
<'tcx
, ParamEnvAnd
<'tcx
, Normalize
<PolyFnSig
<'tcx
>>>>,
239 ) -> Result
<&'tcx Canonical
<'tcx
, QueryResponse
<'tcx
, PolyFnSig
<'tcx
>>>, NoSolution
> {
240 tcx
.infer_ctxt().enter_canonical_trait_query(&canonicalized
, type_op_normalize
)
243 fn type_op_subtype
<'tcx
>(
245 canonicalized
: Canonical
<'tcx
, ParamEnvAnd
<'tcx
, Subtype
<'tcx
>>>,
246 ) -> Result
<&'tcx Canonical
<'tcx
, QueryResponse
<'tcx
, ()>>, NoSolution
> {
247 tcx
.infer_ctxt().enter_canonical_trait_query(&canonicalized
, |infcx
, fulfill_cx
, key
| {
248 let (param_env
, Subtype { sub, sup }
) = key
.into_parts();
250 .at(&ObligationCause
::dummy(), param_env
)
252 .into_value_registering_obligations(infcx
, fulfill_cx
);
257 fn type_op_prove_predicate
<'tcx
>(
259 canonicalized
: Canonical
<'tcx
, ParamEnvAnd
<'tcx
, ProvePredicate
<'tcx
>>>,
260 ) -> Result
<&'tcx Canonical
<'tcx
, QueryResponse
<'tcx
, ()>>, NoSolution
> {
261 tcx
.infer_ctxt().enter_canonical_trait_query(&canonicalized
, |infcx
, fulfill_cx
, key
| {
262 type_op_prove_predicate_with_cause(infcx
, fulfill_cx
, key
, ObligationCause
::dummy());
267 /// The core of the `type_op_prove_predicate` query: for diagnostics purposes in NLL HRTB errors,
268 /// this query can be re-run to better track the span of the obligation cause, and improve the error
269 /// message. Do not call directly unless you're in that very specific context.
270 pub fn type_op_prove_predicate_with_cause
<'a
, 'tcx
: 'a
>(
271 infcx
: &'a InferCtxt
<'a
, 'tcx
>,
272 fulfill_cx
: &'a
mut dyn TraitEngine
<'tcx
>,
273 key
: ParamEnvAnd
<'tcx
, ProvePredicate
<'tcx
>>,
274 cause
: ObligationCause
<'tcx
>,
276 let (param_env
, ProvePredicate { predicate }
) = key
.into_parts();
277 fulfill_cx
.register_predicate_obligation(infcx
, Obligation
::new(cause
, param_env
, predicate
));