]> git.lizzy.rs Git - rust.git/blob - src/librustc/ty/wf.rs
Fixes issue #43205: ICE in Rvalue::Len evaluation.
[rust.git] / src / librustc / ty / wf.rs
1 // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use hir::def_id::DefId;
12 use infer::InferCtxt;
13 use ty::subst::Substs;
14 use traits;
15 use ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable};
16 use std::iter::once;
17 use syntax::ast;
18 use syntax_pos::Span;
19 use middle::lang_items;
20
21 /// Returns the set of obligations needed to make `ty` well-formed.
22 /// If `ty` contains unresolved inference variables, this may include
23 /// further WF obligations. However, if `ty` IS an unresolved
24 /// inference variable, returns `None`, because we are not able to
25 /// make any progress at all. This is to prevent "livelock" where we
26 /// say "$0 is WF if $0 is WF".
27 pub fn obligations<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
28                                    param_env: ty::ParamEnv<'tcx>,
29                                    body_id: ast::NodeId,
30                                    ty: Ty<'tcx>,
31                                    span: Span)
32                                    -> Option<Vec<traits::PredicateObligation<'tcx>>>
33 {
34     let mut wf = WfPredicates { infcx,
35                                 param_env,
36                                 body_id,
37                                 span,
38                                 out: vec![] };
39     if wf.compute(ty) {
40         debug!("wf::obligations({:?}, body_id={:?}) = {:?}", ty, body_id, wf.out);
41         let result = wf.normalize();
42         debug!("wf::obligations({:?}, body_id={:?}) ~~> {:?}", ty, body_id, result);
43         Some(result)
44     } else {
45         None // no progress made, return None
46     }
47 }
48
49 /// Returns the obligations that make this trait reference
50 /// well-formed.  For example, if there is a trait `Set` defined like
51 /// `trait Set<K:Eq>`, then the trait reference `Foo: Set<Bar>` is WF
52 /// if `Bar: Eq`.
53 pub fn trait_obligations<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
54                                          param_env: ty::ParamEnv<'tcx>,
55                                          body_id: ast::NodeId,
56                                          trait_ref: &ty::TraitRef<'tcx>,
57                                          span: Span)
58                                          -> Vec<traits::PredicateObligation<'tcx>>
59 {
60     let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![] };
61     wf.compute_trait_ref(trait_ref);
62     wf.normalize()
63 }
64
65 pub fn predicate_obligations<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
66                                              param_env: ty::ParamEnv<'tcx>,
67                                              body_id: ast::NodeId,
68                                              predicate: &ty::Predicate<'tcx>,
69                                              span: Span)
70                                              -> Vec<traits::PredicateObligation<'tcx>>
71 {
72     let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![] };
73
74     // (*) ok to skip binders, because wf code is prepared for it
75     match *predicate {
76         ty::Predicate::Trait(ref t) => {
77             wf.compute_trait_ref(&t.skip_binder().trait_ref); // (*)
78         }
79         ty::Predicate::Equate(ref t) => {
80             wf.compute(t.skip_binder().0);
81             wf.compute(t.skip_binder().1);
82         }
83         ty::Predicate::RegionOutlives(..) => {
84         }
85         ty::Predicate::TypeOutlives(ref t) => {
86             wf.compute(t.skip_binder().0);
87         }
88         ty::Predicate::Projection(ref t) => {
89             let t = t.skip_binder(); // (*)
90             wf.compute_projection(t.projection_ty);
91             wf.compute(t.ty);
92         }
93         ty::Predicate::WellFormed(t) => {
94             wf.compute(t);
95         }
96         ty::Predicate::ObjectSafe(_) => {
97         }
98         ty::Predicate::ClosureKind(..) => {
99         }
100         ty::Predicate::Subtype(ref data) => {
101             wf.compute(data.skip_binder().a); // (*)
102             wf.compute(data.skip_binder().b); // (*)
103         }
104     }
105
106     wf.normalize()
107 }
108
109 struct WfPredicates<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
110     infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
111     param_env: ty::ParamEnv<'tcx>,
112     body_id: ast::NodeId,
113     span: Span,
114     out: Vec<traits::PredicateObligation<'tcx>>,
115 }
116
117 impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
118     fn cause(&mut self, code: traits::ObligationCauseCode<'tcx>) -> traits::ObligationCause<'tcx> {
119         traits::ObligationCause::new(self.span, self.body_id, code)
120     }
121
122     fn normalize(&mut self) -> Vec<traits::PredicateObligation<'tcx>> {
123         let cause = self.cause(traits::MiscObligation);
124         let infcx = &mut self.infcx;
125         let param_env = self.param_env;
126         self.out.iter()
127                 .inspect(|pred| assert!(!pred.has_escaping_regions()))
128                 .flat_map(|pred| {
129                     let mut selcx = traits::SelectionContext::new(infcx);
130                     let pred = traits::normalize(&mut selcx, param_env, cause.clone(), pred);
131                     once(pred.value).chain(pred.obligations)
132                 })
133                 .collect()
134     }
135
136     /// Pushes the obligations required for `trait_ref` to be WF into
137     /// `self.out`.
138     fn compute_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>) {
139         let obligations = self.nominal_obligations(trait_ref.def_id, trait_ref.substs);
140         self.out.extend(obligations);
141
142         let cause = self.cause(traits::MiscObligation);
143         let param_env = self.param_env;
144         self.out.extend(
145             trait_ref.substs.types()
146                             .filter(|ty| !ty.has_escaping_regions())
147                             .map(|ty| traits::Obligation::new(cause.clone(),
148                                                               param_env,
149                                                               ty::Predicate::WellFormed(ty))));
150     }
151
152     /// Pushes the obligations required for `trait_ref::Item` to be WF
153     /// into `self.out`.
154     fn compute_projection(&mut self, data: ty::ProjectionTy<'tcx>) {
155         // A projection is well-formed if (a) the trait ref itself is
156         // WF and (b) the trait-ref holds.  (It may also be
157         // normalizable and be WF that way.)
158         let trait_ref = data.trait_ref(self.infcx.tcx);
159         self.compute_trait_ref(&trait_ref);
160
161         if !data.has_escaping_regions() {
162             let predicate = trait_ref.to_predicate();
163             let cause = self.cause(traits::ProjectionWf(data));
164             self.out.push(traits::Obligation::new(cause, self.param_env, predicate));
165         }
166     }
167
168     fn require_sized(&mut self, subty: Ty<'tcx>, cause: traits::ObligationCauseCode<'tcx>) {
169         if !subty.has_escaping_regions() {
170             let cause = self.cause(cause);
171             let trait_ref = ty::TraitRef {
172                 def_id: self.infcx.tcx.require_lang_item(lang_items::SizedTraitLangItem),
173                 substs: self.infcx.tcx.mk_substs_trait(subty, &[]),
174             };
175             self.out.push(traits::Obligation::new(cause, self.param_env, trait_ref.to_predicate()));
176         }
177     }
178
179     /// Push new obligations into `out`. Returns true if it was able
180     /// to generate all the predicates needed to validate that `ty0`
181     /// is WF. Returns false if `ty0` is an unresolved type variable,
182     /// in which case we are not able to simplify at all.
183     fn compute(&mut self, ty0: Ty<'tcx>) -> bool {
184         let mut subtys = ty0.walk();
185         let param_env = self.param_env;
186         while let Some(ty) = subtys.next() {
187             match ty.sty {
188                 ty::TyBool |
189                 ty::TyChar |
190                 ty::TyInt(..) |
191                 ty::TyUint(..) |
192                 ty::TyFloat(..) |
193                 ty::TyError |
194                 ty::TyStr |
195                 ty::TyNever |
196                 ty::TyParam(_) => {
197                     // WfScalar, WfParameter, etc
198                 }
199
200                 ty::TySlice(subty) |
201                 ty::TyArray(subty, _) => {
202                     self.require_sized(subty, traits::SliceOrArrayElem);
203                 }
204
205                 ty::TyTuple(ref tys, _) => {
206                     if let Some((_last, rest)) = tys.split_last() {
207                         for elem in rest {
208                             self.require_sized(elem, traits::TupleElem);
209                         }
210                     }
211                 }
212
213                 ty::TyRawPtr(_) => {
214                     // simple cases that are WF if their type args are WF
215                 }
216
217                 ty::TyProjection(data) => {
218                     subtys.skip_current_subtree(); // subtree handled by compute_projection
219                     self.compute_projection(data);
220                 }
221
222                 ty::TyAdt(def, substs) => {
223                     // WfNominalType
224                     let obligations = self.nominal_obligations(def.did, substs);
225                     self.out.extend(obligations);
226                 }
227
228                 ty::TyRef(r, mt) => {
229                     // WfReference
230                     if !r.has_escaping_regions() && !mt.ty.has_escaping_regions() {
231                         let cause = self.cause(traits::ReferenceOutlivesReferent(ty));
232                         self.out.push(
233                             traits::Obligation::new(
234                                 cause,
235                                 param_env,
236                                 ty::Predicate::TypeOutlives(
237                                     ty::Binder(
238                                         ty::OutlivesPredicate(mt.ty, r)))));
239                     }
240                 }
241
242                 ty::TyClosure(..) => {
243                     // the types in a closure are always the types of
244                     // local variables (or possibly references to local
245                     // variables), we'll walk those.
246                     //
247                     // (Though, local variables are probably not
248                     // needed, as they are separately checked w/r/t
249                     // WFedness.)
250                 }
251
252                 ty::TyFnDef(..) | ty::TyFnPtr(_) => {
253                     // let the loop iterate into the argument/return
254                     // types appearing in the fn signature
255                 }
256
257                 ty::TyAnon(..) => {
258                     // all of the requirements on type parameters
259                     // should've been checked by the instantiation
260                     // of whatever returned this exact `impl Trait`.
261                 }
262
263                 ty::TyDynamic(data, r) => {
264                     // WfObject
265                     //
266                     // Here, we defer WF checking due to higher-ranked
267                     // regions. This is perhaps not ideal.
268                     self.from_object_ty(ty, data, r);
269
270                     // FIXME(#27579) RFC also considers adding trait
271                     // obligations that don't refer to Self and
272                     // checking those
273
274                     let cause = self.cause(traits::MiscObligation);
275                     let component_traits =
276                         data.auto_traits().chain(data.principal().map(|p| p.def_id()));
277                     self.out.extend(
278                         component_traits.map(|did| traits::Obligation::new(
279                             cause.clone(),
280                             param_env,
281                             ty::Predicate::ObjectSafe(did)
282                         ))
283                     );
284                 }
285
286                 // Inference variables are the complicated case, since we don't
287                 // know what type they are. We do two things:
288                 //
289                 // 1. Check if they have been resolved, and if so proceed with
290                 //    THAT type.
291                 // 2. If not, check whether this is the type that we
292                 //    started with (ty0). In that case, we've made no
293                 //    progress at all, so return false. Otherwise,
294                 //    we've at least simplified things (i.e., we went
295                 //    from `Vec<$0>: WF` to `$0: WF`, so we can
296                 //    register a pending obligation and keep
297                 //    moving. (Goal is that an "inductive hypothesis"
298                 //    is satisfied to ensure termination.)
299                 ty::TyInfer(_) => {
300                     let ty = self.infcx.shallow_resolve(ty);
301                     if let ty::TyInfer(_) = ty.sty { // not yet resolved...
302                         if ty == ty0 { // ...this is the type we started from! no progress.
303                             return false;
304                         }
305
306                         let cause = self.cause(traits::MiscObligation);
307                         self.out.push( // ...not the type we started from, so we made progress.
308                             traits::Obligation::new(cause,
309                                                     self.param_env,
310                                                     ty::Predicate::WellFormed(ty)));
311                     } else {
312                         // Yes, resolved, proceed with the
313                         // result. Should never return false because
314                         // `ty` is not a TyInfer.
315                         assert!(self.compute(ty));
316                     }
317                 }
318             }
319         }
320
321         // if we made it through that loop above, we made progress!
322         return true;
323     }
324
325     fn nominal_obligations(&mut self,
326                            def_id: DefId,
327                            substs: &Substs<'tcx>)
328                            -> Vec<traits::PredicateObligation<'tcx>>
329     {
330         let predicates =
331             self.infcx.tcx.predicates_of(def_id)
332                           .instantiate(self.infcx.tcx, substs);
333         let cause = self.cause(traits::ItemObligation(def_id));
334         predicates.predicates
335                   .into_iter()
336                   .map(|pred| traits::Obligation::new(cause.clone(),
337                                                       self.param_env,
338                                                       pred))
339                   .filter(|pred| !pred.has_escaping_regions())
340                   .collect()
341     }
342
343     fn from_object_ty(&mut self, ty: Ty<'tcx>,
344                       data: ty::Binder<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>>,
345                       region: ty::Region<'tcx>) {
346         // Imagine a type like this:
347         //
348         //     trait Foo { }
349         //     trait Bar<'c> : 'c { }
350         //
351         //     &'b (Foo+'c+Bar<'d>)
352         //         ^
353         //
354         // In this case, the following relationships must hold:
355         //
356         //     'b <= 'c
357         //     'd <= 'c
358         //
359         // The first conditions is due to the normal region pointer
360         // rules, which say that a reference cannot outlive its
361         // referent.
362         //
363         // The final condition may be a bit surprising. In particular,
364         // you may expect that it would have been `'c <= 'd`, since
365         // usually lifetimes of outer things are conservative
366         // approximations for inner things. However, it works somewhat
367         // differently with trait objects: here the idea is that if the
368         // user specifies a region bound (`'c`, in this case) it is the
369         // "master bound" that *implies* that bounds from other traits are
370         // all met. (Remember that *all bounds* in a type like
371         // `Foo+Bar+Zed` must be met, not just one, hence if we write
372         // `Foo<'x>+Bar<'y>`, we know that the type outlives *both* 'x and
373         // 'y.)
374         //
375         // Note: in fact we only permit builtin traits, not `Bar<'d>`, I
376         // am looking forward to the future here.
377
378         if !data.has_escaping_regions() {
379             let implicit_bounds =
380                 object_region_bounds(self.infcx.tcx, data);
381
382             let explicit_bound = region;
383
384             for implicit_bound in implicit_bounds {
385                 let cause = self.cause(traits::ObjectTypeBound(ty, explicit_bound));
386                 let outlives = ty::Binder(ty::OutlivesPredicate(explicit_bound, implicit_bound));
387                 self.out.push(traits::Obligation::new(cause,
388                                                       self.param_env,
389                                                       outlives.to_predicate()));
390             }
391         }
392     }
393 }
394
395 /// Given an object type like `SomeTrait+Send`, computes the lifetime
396 /// bounds that must hold on the elided self type. These are derived
397 /// from the declarations of `SomeTrait`, `Send`, and friends -- if
398 /// they declare `trait SomeTrait : 'static`, for example, then
399 /// `'static` would appear in the list. The hard work is done by
400 /// `ty::required_region_bounds`, see that for more information.
401 pub fn object_region_bounds<'a, 'gcx, 'tcx>(
402     tcx: TyCtxt<'a, 'gcx, 'tcx>,
403     existential_predicates: ty::Binder<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>>)
404     -> Vec<ty::Region<'tcx>>
405 {
406     // Since we don't actually *know* the self type for an object,
407     // this "open(err)" serves as a kind of dummy standin -- basically
408     // a skolemized type.
409     let open_ty = tcx.mk_infer(ty::FreshTy(0));
410
411     let predicates = existential_predicates.iter().filter_map(|predicate| {
412         if let ty::ExistentialPredicate::Projection(_) = *predicate.skip_binder() {
413             None
414         } else {
415             Some(predicate.with_self_ty(tcx, open_ty))
416         }
417     }).collect();
418
419     tcx.required_region_bounds(open_ty, predicates)
420 }