2 use rustc_infer
::infer
::canonical
::{Canonical, QueryResponse}
;
3 use rustc_infer
::infer
::{DefiningAnchor, TyCtxtInferExt}
;
4 use rustc_infer
::traits
::ObligationCauseCode
;
5 use rustc_middle
::ty
::query
::Providers
;
6 use rustc_middle
::ty
::{self, FnSig, Lift, PolyFnSig, Ty, TyCtxt, TypeFoldable}
;
7 use rustc_middle
::ty
::{ParamEnvAnd, Predicate, ToPredicate}
;
8 use rustc_middle
::ty
::{UserSelfTy, UserSubsts}
;
9 use rustc_span
::{Span, DUMMY_SP}
;
10 use rustc_trait_selection
::infer
::InferCtxtBuilderExt
;
11 use rustc_trait_selection
::traits
::query
::normalize
::QueryNormalizeExt
;
12 use rustc_trait_selection
::traits
::query
::type_op
::ascribe_user_type
::AscribeUserType
;
13 use rustc_trait_selection
::traits
::query
::type_op
::eq
::Eq
;
14 use rustc_trait_selection
::traits
::query
::type_op
::normalize
::Normalize
;
15 use rustc_trait_selection
::traits
::query
::type_op
::prove_predicate
::ProvePredicate
;
16 use rustc_trait_selection
::traits
::query
::type_op
::subtype
::Subtype
;
17 use rustc_trait_selection
::traits
::query
::{Fallible, NoSolution}
;
18 use rustc_trait_selection
::traits
::{Normalized, Obligation, ObligationCause, ObligationCtxt}
;
22 pub(crate) fn provide(p
: &mut Providers
) {
24 type_op_ascribe_user_type
,
26 type_op_prove_predicate
,
29 type_op_normalize_predicate
,
30 type_op_normalize_fn_sig
,
31 type_op_normalize_poly_fn_sig
,
36 fn type_op_ascribe_user_type
<'tcx
>(
38 canonicalized
: Canonical
<'tcx
, ParamEnvAnd
<'tcx
, AscribeUserType
<'tcx
>>>,
39 ) -> Result
<&'tcx Canonical
<'tcx
, QueryResponse
<'tcx
, ()>>, NoSolution
> {
40 tcx
.infer_ctxt().enter_canonical_trait_query(&canonicalized
, |ocx
, key
| {
41 type_op_ascribe_user_type_with_span(ocx
, key
, None
)
45 /// The core of the `type_op_ascribe_user_type` query: for diagnostics purposes in NLL HRTB errors,
46 /// this query can be re-run to better track the span of the obligation cause, and improve the error
47 /// message. Do not call directly unless you're in that very specific context.
48 pub fn type_op_ascribe_user_type_with_span
<'tcx
>(
49 ocx
: &ObligationCtxt
<'_
, 'tcx
>,
50 key
: ParamEnvAnd
<'tcx
, AscribeUserType
<'tcx
>>,
52 ) -> Result
<(), NoSolution
> {
53 let (param_env
, AscribeUserType { mir_ty, def_id, user_substs }
) = key
.into_parts();
55 "type_op_ascribe_user_type: mir_ty={:?} def_id={:?} user_substs={:?}",
56 mir_ty
, def_id
, user_substs
58 let span
= span
.unwrap_or(DUMMY_SP
);
60 let UserSubsts { user_self_ty, substs }
= user_substs
;
61 let tcx
= ocx
.infcx
.tcx
;
62 let cause
= ObligationCause
::dummy_with_span(span
);
64 let ty
= tcx
.bound_type_of(def_id
).subst(tcx
, substs
);
65 let ty
= ocx
.normalize(&cause
, param_env
, ty
);
66 debug
!("relate_type_and_user_type: ty of def-id is {:?}", ty
);
68 ocx
.eq(&cause
, param_env
, mir_ty
, ty
)?
;
70 // Prove the predicates coming along with `def_id`.
72 // Also, normalize the `instantiated_predicates`
73 // because otherwise we wind up with duplicate "type
74 // outlives" error messages.
75 let instantiated_predicates
= tcx
.predicates_of(def_id
).instantiate(tcx
, substs
);
77 debug
!(?instantiated_predicates
);
78 for (instantiated_predicate
, predicate_span
) in
79 zip(instantiated_predicates
.predicates
, instantiated_predicates
.spans
)
81 let span
= if span
== DUMMY_SP { predicate_span }
else { span }
;
82 let cause
= ObligationCause
::new(
85 ObligationCauseCode
::AscribeUserTypeProvePredicate(predicate_span
),
87 let instantiated_predicate
=
88 ocx
.normalize(&cause
.clone(), param_env
, instantiated_predicate
);
90 ocx
.register_obligation(Obligation
::new(tcx
, cause
, param_env
, instantiated_predicate
));
93 if let Some(UserSelfTy { impl_def_id, self_ty }
) = user_self_ty
{
94 let impl_self_ty
= tcx
.bound_type_of(impl_def_id
).subst(tcx
, substs
);
95 let impl_self_ty
= ocx
.normalize(&cause
, param_env
, impl_self_ty
);
97 ocx
.eq(&cause
, param_env
, self_ty
, impl_self_ty
)?
;
99 let predicate
: Predicate
<'tcx
> =
100 ty
::Binder
::dummy(ty
::PredicateKind
::WellFormed(impl_self_ty
.into())).to_predicate(tcx
);
101 ocx
.register_obligation(Obligation
::new(tcx
, cause
.clone(), param_env
, predicate
));
104 // In addition to proving the predicates, we have to
105 // prove that `ty` is well-formed -- this is because
106 // the WF of `ty` is predicated on the substs being
107 // well-formed, and we haven't proven *that*. We don't
108 // want to prove the WF of types from `substs` directly because they
109 // haven't been normalized.
111 // FIXME(nmatsakis): Well, perhaps we should normalize
112 // them? This would only be relevant if some input
113 // type were ill-formed but did not appear in `ty`,
114 // which...could happen with normalization...
115 let predicate
: Predicate
<'tcx
> =
116 ty
::Binder
::dummy(ty
::PredicateKind
::WellFormed(ty
.into())).to_predicate(tcx
);
117 ocx
.register_obligation(Obligation
::new(tcx
, cause
, param_env
, predicate
));
123 canonicalized
: Canonical
<'tcx
, ParamEnvAnd
<'tcx
, Eq
<'tcx
>>>,
124 ) -> Result
<&'tcx Canonical
<'tcx
, QueryResponse
<'tcx
, ()>>, NoSolution
> {
125 tcx
.infer_ctxt().enter_canonical_trait_query(&canonicalized
, |ocx
, key
| {
126 let (param_env
, Eq { a, b }
) = key
.into_parts();
127 Ok(ocx
.eq(&ObligationCause
::dummy(), param_env
, a
, b
)?
)
131 fn type_op_normalize
<'tcx
, T
>(
132 ocx
: &ObligationCtxt
<'_
, 'tcx
>,
133 key
: ParamEnvAnd
<'tcx
, Normalize
<T
>>,
136 T
: fmt
::Debug
+ TypeFoldable
<'tcx
> + Lift
<'tcx
>,
138 let (param_env
, Normalize { value }
) = key
.into_parts();
139 let Normalized { value, obligations }
=
140 ocx
.infcx
.at(&ObligationCause
::dummy(), param_env
).query_normalize(value
)?
;
141 ocx
.register_obligations(obligations
);
145 fn type_op_normalize_ty
<'tcx
>(
147 canonicalized
: Canonical
<'tcx
, ParamEnvAnd
<'tcx
, Normalize
<Ty
<'tcx
>>>>,
148 ) -> Result
<&'tcx Canonical
<'tcx
, QueryResponse
<'tcx
, Ty
<'tcx
>>>, NoSolution
> {
149 tcx
.infer_ctxt().enter_canonical_trait_query(&canonicalized
, type_op_normalize
)
152 fn type_op_normalize_predicate
<'tcx
>(
154 canonicalized
: Canonical
<'tcx
, ParamEnvAnd
<'tcx
, Normalize
<Predicate
<'tcx
>>>>,
155 ) -> Result
<&'tcx Canonical
<'tcx
, QueryResponse
<'tcx
, Predicate
<'tcx
>>>, NoSolution
> {
156 tcx
.infer_ctxt().enter_canonical_trait_query(&canonicalized
, type_op_normalize
)
159 fn type_op_normalize_fn_sig
<'tcx
>(
161 canonicalized
: Canonical
<'tcx
, ParamEnvAnd
<'tcx
, Normalize
<FnSig
<'tcx
>>>>,
162 ) -> Result
<&'tcx Canonical
<'tcx
, QueryResponse
<'tcx
, FnSig
<'tcx
>>>, NoSolution
> {
163 tcx
.infer_ctxt().enter_canonical_trait_query(&canonicalized
, type_op_normalize
)
166 fn type_op_normalize_poly_fn_sig
<'tcx
>(
168 canonicalized
: Canonical
<'tcx
, ParamEnvAnd
<'tcx
, Normalize
<PolyFnSig
<'tcx
>>>>,
169 ) -> Result
<&'tcx Canonical
<'tcx
, QueryResponse
<'tcx
, PolyFnSig
<'tcx
>>>, NoSolution
> {
170 tcx
.infer_ctxt().enter_canonical_trait_query(&canonicalized
, type_op_normalize
)
173 fn type_op_subtype
<'tcx
>(
175 canonicalized
: Canonical
<'tcx
, ParamEnvAnd
<'tcx
, Subtype
<'tcx
>>>,
176 ) -> Result
<&'tcx Canonical
<'tcx
, QueryResponse
<'tcx
, ()>>, NoSolution
> {
177 tcx
.infer_ctxt().enter_canonical_trait_query(&canonicalized
, |ocx
, key
| {
178 let (param_env
, Subtype { sub, sup }
) = key
.into_parts();
179 Ok(ocx
.sup(&ObligationCause
::dummy(), param_env
, sup
, sub
)?
)
183 fn type_op_prove_predicate
<'tcx
>(
185 canonicalized
: Canonical
<'tcx
, ParamEnvAnd
<'tcx
, ProvePredicate
<'tcx
>>>,
186 ) -> Result
<&'tcx Canonical
<'tcx
, QueryResponse
<'tcx
, ()>>, NoSolution
> {
187 // HACK This bubble is required for this test to pass:
188 // impl-trait/issue-99642.rs
189 tcx
.infer_ctxt().with_opaque_type_inference(DefiningAnchor
::Bubble
).enter_canonical_trait_query(
192 type_op_prove_predicate_with_cause(ocx
, key
, ObligationCause
::dummy());
198 /// The core of the `type_op_prove_predicate` query: for diagnostics purposes in NLL HRTB errors,
199 /// this query can be re-run to better track the span of the obligation cause, and improve the error
200 /// message. Do not call directly unless you're in that very specific context.
201 pub fn type_op_prove_predicate_with_cause
<'tcx
>(
202 ocx
: &ObligationCtxt
<'_
, 'tcx
>,
203 key
: ParamEnvAnd
<'tcx
, ProvePredicate
<'tcx
>>,
204 cause
: ObligationCause
<'tcx
>,
206 let (param_env
, ProvePredicate { predicate }
) = key
.into_parts();
207 ocx
.register_obligation(Obligation
::new(ocx
.infcx
.tcx
, cause
, param_env
, predicate
));