]> git.proxmox.com Git - rustc.git/blame - src/librustc_traits/type_op.rs
New upstream version 1.35.0+dfsg1
[rustc.git] / src / librustc_traits / type_op.rs
CommitLineData
0bf4aa26
XL
1use rustc::infer::at::ToTrace;
2use rustc::infer::canonical::{Canonical, QueryResponse};
8faf50e0 3use rustc::infer::InferCtxt;
9fa01778 4use rustc::hir;
0bf4aa26 5use rustc::hir::def_id::DefId;
0bf4aa26 6use rustc::traits::query::type_op::ascribe_user_type::AscribeUserType;
8faf50e0
XL
7use rustc::traits::query::type_op::eq::Eq;
8use rustc::traits::query::type_op::normalize::Normalize;
9use rustc::traits::query::type_op::prove_predicate::ProvePredicate;
10use rustc::traits::query::type_op::subtype::Subtype;
11use rustc::traits::query::{Fallible, NoSolution};
0bf4aa26 12use rustc::traits::{
0731742a 13 Normalized, Obligation, ObligationCause, TraitEngine, TraitEngineExt,
0bf4aa26 14};
8faf50e0 15use rustc::ty::query::Providers;
0731742a 16use rustc::ty::subst::{Kind, Subst, UserSubsts, UserSelfTy};
0bf4aa26
XL
17use rustc::ty::{
18 FnSig, Lift, ParamEnv, ParamEnvAnd, PolyFnSig, Predicate, Ty, TyCtxt, TypeFoldable, Variance,
19};
8faf50e0
XL
20use rustc_data_structures::sync::Lrc;
21use std::fmt;
0bf4aa26 22use syntax_pos::DUMMY_SP;
8faf50e0 23
9fa01778 24crate fn provide(p: &mut Providers<'_>) {
8faf50e0 25 *p = Providers {
0bf4aa26 26 type_op_ascribe_user_type,
8faf50e0
XL
27 type_op_eq,
28 type_op_prove_predicate,
29 type_op_subtype,
30 type_op_normalize_ty,
31 type_op_normalize_predicate,
32 type_op_normalize_fn_sig,
33 type_op_normalize_poly_fn_sig,
34 ..*p
35 };
36}
37
0bf4aa26
XL
38fn type_op_ascribe_user_type<'tcx>(
39 tcx: TyCtxt<'_, 'tcx, 'tcx>,
40 canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, AscribeUserType<'tcx>>>,
41) -> Result<Lrc<Canonical<'tcx, QueryResponse<'tcx, ()>>>, NoSolution> {
42 tcx.infer_ctxt()
43 .enter_canonical_trait_query(&canonicalized, |infcx, fulfill_cx, key| {
44 let (
9fa01778 45 param_env, AscribeUserType { mir_ty, def_id, user_substs }
0bf4aa26
XL
46 ) = key.into_parts();
47
48 debug!(
9fa01778
XL
49 "type_op_ascribe_user_type: mir_ty={:?} def_id={:?} user_substs={:?}",
50 mir_ty, def_id, user_substs
0bf4aa26
XL
51 );
52
0731742a 53 let mut cx = AscribeUserTypeCx { infcx, param_env, fulfill_cx };
9fa01778 54 cx.relate_mir_and_user_ty(mir_ty, def_id, user_substs)?;
0bf4aa26
XL
55
56 Ok(())
57 })
58}
59
60struct AscribeUserTypeCx<'me, 'gcx: 'tcx, 'tcx: 'me> {
61 infcx: &'me InferCtxt<'me, 'gcx, 'tcx>,
62 param_env: ParamEnv<'tcx>,
0731742a 63 fulfill_cx: &'me mut dyn TraitEngine<'tcx>,
0bf4aa26
XL
64}
65
66impl AscribeUserTypeCx<'me, 'gcx, 'tcx> {
67 fn normalize<T>(&mut self, value: T) -> T
68 where
69 T: TypeFoldable<'tcx>,
70 {
71 self.infcx
72 .partially_normalize_associated_types_in(
73 DUMMY_SP,
9fa01778 74 hir::CRATE_HIR_ID,
0bf4aa26
XL
75 self.param_env,
76 &value,
77 )
78 .into_value_registering_obligations(self.infcx, self.fulfill_cx)
79 }
80
81 fn relate<T>(&mut self, a: T, variance: Variance, b: T) -> Result<(), NoSolution>
82 where
83 T: ToTrace<'tcx>,
84 {
85 Ok(self.infcx
86 .at(&ObligationCause::dummy(), self.param_env)
87 .relate(a, variance, b)?
88 .into_value_registering_obligations(self.infcx, self.fulfill_cx))
89 }
90
91 fn prove_predicate(&mut self, predicate: Predicate<'tcx>) {
92 self.fulfill_cx.register_predicate_obligation(
93 self.infcx,
94 Obligation::new(ObligationCause::dummy(), self.param_env, predicate),
95 );
96 }
97
98 fn tcx(&self) -> TyCtxt<'me, 'gcx, 'tcx> {
99 self.infcx.tcx
100 }
101
102 fn subst<T>(&self, value: T, substs: &[Kind<'tcx>]) -> T
103 where
104 T: TypeFoldable<'tcx>,
105 {
106 value.subst(self.tcx(), substs)
107 }
108
109 fn relate_mir_and_user_ty(
110 &mut self,
111 mir_ty: Ty<'tcx>,
0bf4aa26
XL
112 def_id: DefId,
113 user_substs: UserSubsts<'tcx>,
0bf4aa26
XL
114 ) -> Result<(), NoSolution> {
115 let UserSubsts {
0bf4aa26 116 user_self_ty,
0731742a 117 substs,
0bf4aa26 118 } = user_substs;
0bf4aa26
XL
119 let tcx = self.tcx();
120
121 let ty = tcx.type_of(def_id);
122 let ty = self.subst(ty, substs);
123 debug!("relate_type_and_user_type: ty of def-id is {:?}", ty);
124 let ty = self.normalize(ty);
125
9fa01778 126 self.relate(mir_ty, Variance::Invariant, ty)?;
0bf4aa26 127
0bf4aa26
XL
128 // Prove the predicates coming along with `def_id`.
129 //
130 // Also, normalize the `instantiated_predicates`
131 // because otherwise we wind up with duplicate "type
132 // outlives" error messages.
133 let instantiated_predicates = self.tcx()
134 .predicates_of(def_id)
135 .instantiate(self.tcx(), substs);
136 for instantiated_predicate in instantiated_predicates.predicates {
137 let instantiated_predicate = self.normalize(instantiated_predicate);
138 self.prove_predicate(instantiated_predicate);
139 }
140
0731742a
XL
141 if let Some(UserSelfTy {
142 impl_def_id,
143 self_ty,
144 }) = user_self_ty {
145 let impl_self_ty = self.tcx().type_of(impl_def_id);
146 let impl_self_ty = self.subst(impl_self_ty, &substs);
147 let impl_self_ty = self.normalize(impl_self_ty);
148
149 self.relate(self_ty, Variance::Invariant, impl_self_ty)?;
150
151 self.prove_predicate(Predicate::WellFormed(impl_self_ty));
152 }
153
0bf4aa26
XL
154 // In addition to proving the predicates, we have to
155 // prove that `ty` is well-formed -- this is because
156 // the WF of `ty` is predicated on the substs being
157 // well-formed, and we haven't proven *that*. We don't
158 // want to prove the WF of types from `substs` directly because they
159 // haven't been normalized.
160 //
161 // FIXME(nmatsakis): Well, perhaps we should normalize
162 // them? This would only be relevant if some input
163 // type were ill-formed but did not appear in `ty`,
164 // which...could happen with normalization...
165 self.prove_predicate(Predicate::WellFormed(ty));
0bf4aa26
XL
166 Ok(())
167 }
168}
169
8faf50e0
XL
170fn type_op_eq<'tcx>(
171 tcx: TyCtxt<'_, 'tcx, 'tcx>,
172 canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Eq<'tcx>>>,
0bf4aa26 173) -> Result<Lrc<Canonical<'tcx, QueryResponse<'tcx, ()>>>, NoSolution> {
8faf50e0
XL
174 tcx.infer_ctxt()
175 .enter_canonical_trait_query(&canonicalized, |infcx, fulfill_cx, key| {
176 let (param_env, Eq { a, b }) = key.into_parts();
177 Ok(infcx
178 .at(&ObligationCause::dummy(), param_env)
179 .eq(a, b)?
180 .into_value_registering_obligations(infcx, fulfill_cx))
181 })
182}
183
184fn type_op_normalize<T>(
185 infcx: &InferCtxt<'_, 'gcx, 'tcx>,
0731742a 186 fulfill_cx: &mut dyn TraitEngine<'tcx>,
8faf50e0
XL
187 key: ParamEnvAnd<'tcx, Normalize<T>>,
188) -> Fallible<T>
189where
190 T: fmt::Debug + TypeFoldable<'tcx> + Lift<'gcx>,
191{
192 let (param_env, Normalize { value }) = key.into_parts();
193 let Normalized { value, obligations } = infcx
194 .at(&ObligationCause::dummy(), param_env)
195 .normalize(&value)?;
196 fulfill_cx.register_predicate_obligations(infcx, obligations);
197 Ok(value)
198}
199
200fn type_op_normalize_ty(
201 tcx: TyCtxt<'_, 'tcx, 'tcx>,
202 canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<Ty<'tcx>>>>,
0bf4aa26 203) -> Result<Lrc<Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>>, NoSolution> {
8faf50e0
XL
204 tcx.infer_ctxt()
205 .enter_canonical_trait_query(&canonicalized, type_op_normalize)
206}
207
208fn type_op_normalize_predicate(
209 tcx: TyCtxt<'_, 'tcx, 'tcx>,
210 canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<Predicate<'tcx>>>>,
0bf4aa26 211) -> Result<Lrc<Canonical<'tcx, QueryResponse<'tcx, Predicate<'tcx>>>>, NoSolution> {
8faf50e0
XL
212 tcx.infer_ctxt()
213 .enter_canonical_trait_query(&canonicalized, type_op_normalize)
214}
215
216fn type_op_normalize_fn_sig(
217 tcx: TyCtxt<'_, 'tcx, 'tcx>,
218 canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<FnSig<'tcx>>>>,
0bf4aa26 219) -> Result<Lrc<Canonical<'tcx, QueryResponse<'tcx, FnSig<'tcx>>>>, NoSolution> {
8faf50e0
XL
220 tcx.infer_ctxt()
221 .enter_canonical_trait_query(&canonicalized, type_op_normalize)
222}
223
224fn type_op_normalize_poly_fn_sig(
225 tcx: TyCtxt<'_, 'tcx, 'tcx>,
226 canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<PolyFnSig<'tcx>>>>,
0bf4aa26 227) -> Result<Lrc<Canonical<'tcx, QueryResponse<'tcx, PolyFnSig<'tcx>>>>, NoSolution> {
8faf50e0
XL
228 tcx.infer_ctxt()
229 .enter_canonical_trait_query(&canonicalized, type_op_normalize)
230}
231
232fn type_op_subtype<'tcx>(
233 tcx: TyCtxt<'_, 'tcx, 'tcx>,
234 canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Subtype<'tcx>>>,
0bf4aa26 235) -> Result<Lrc<Canonical<'tcx, QueryResponse<'tcx, ()>>>, NoSolution> {
8faf50e0
XL
236 tcx.infer_ctxt()
237 .enter_canonical_trait_query(&canonicalized, |infcx, fulfill_cx, key| {
238 let (param_env, Subtype { sub, sup }) = key.into_parts();
239 Ok(infcx
240 .at(&ObligationCause::dummy(), param_env)
241 .sup(sup, sub)?
242 .into_value_registering_obligations(infcx, fulfill_cx))
243 })
244}
245
246fn type_op_prove_predicate<'tcx>(
247 tcx: TyCtxt<'_, 'tcx, 'tcx>,
248 canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, ProvePredicate<'tcx>>>,
0bf4aa26 249) -> Result<Lrc<Canonical<'tcx, QueryResponse<'tcx, ()>>>, NoSolution> {
8faf50e0
XL
250 tcx.infer_ctxt()
251 .enter_canonical_trait_query(&canonicalized, |infcx, fulfill_cx, key| {
252 let (param_env, ProvePredicate { predicate }) = key.into_parts();
253 fulfill_cx.register_predicate_obligation(
254 infcx,
255 Obligation::new(ObligationCause::dummy(), param_env, predicate),
256 );
257 Ok(())
258 })
259}