1 // Copyright 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.
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.
14 use rustc::hir::def::{CtorKind, Def};
15 use rustc::hir::def_id::{self, CrateNum, DefId, LOCAL_CRATE};
16 use rustc::hir::itemlikevisit::ItemLikeVisitor;
17 use rustc::hir::map as hir_map;
19 use rustc::ty::maps::Providers;
20 use rustc::ty::outlives::Component;
21 use rustc::ty::subst::{Kind, Subst, UnpackedKind};
22 use rustc::ty::{self, AdtKind, CratePredicatesMap, Region, RegionKind, ReprOptions,
23 ToPolyTraitRef, ToPredicate, Ty, TyCtxt};
24 use rustc::util::nodemap::{FxHashMap, FxHashSet};
25 use rustc_data_structures::sync::Lrc;
26 use rustc_target::spec::abi;
28 use syntax_pos::{Span, DUMMY_SP};
30 /// Infer predicates for the items in the crate.
32 /// global_inferred_outlives: this is initially the empty map that
33 /// was generated by walking the items in the crate. This will
34 /// now be filled with inferred predicates.
35 pub fn infer_predicates<'tcx>(
36 tcx: TyCtxt<'_, 'tcx, 'tcx>,
37 explicit_map: &FxHashMap<DefId, Lrc<Vec<ty::Predicate<'tcx>>>>,
38 ) -> FxHashMap<DefId, RequiredPredicates<'tcx>> {
39 debug!("infer_predicates");
41 let mut predicates_added = true;
43 let mut global_inferred_outlives = FxHashMap::default();
45 // If new predicates were added then we need to re-calculate
46 // all crates since there could be new implied predicates.
47 while predicates_added {
48 predicates_added = false;
50 let mut visitor = InferVisitor {
52 global_inferred_outlives: &mut global_inferred_outlives,
53 predicates_added: &mut predicates_added,
54 explicit_map: explicit_map,
57 // Visit all the crates and infer predicates
58 tcx.hir.krate().visit_all_item_likes(&mut visitor);
61 global_inferred_outlives
64 pub struct InferVisitor<'cx, 'tcx: 'cx> {
65 tcx: TyCtxt<'cx, 'tcx, 'tcx>,
66 global_inferred_outlives: &'cx mut FxHashMap<DefId, RequiredPredicates<'tcx>>,
67 predicates_added: &'cx mut bool,
68 explicit_map: &'cx FxHashMap<DefId, Lrc<Vec<ty::Predicate<'tcx>>>>,
71 /// Tracks the `T: 'a` or `'a: 'a` predicates that we have inferred
72 /// must be added to the struct header.
73 type RequiredPredicates<'tcx> = FxHashSet<ty::OutlivesPredicate<Kind<'tcx>, ty::Region<'tcx>>>;
75 impl<'cx, 'tcx> ItemLikeVisitor<'tcx> for InferVisitor<'cx, 'tcx> {
76 fn visit_item(&mut self, item: &hir::Item) {
77 let item_did = self.tcx.hir.local_def_id(item.id);
79 debug!("InferVisitor::visit_item(item={:?})", item_did);
81 let node_id = self.tcx
83 .as_local_node_id(item_did)
84 .expect("expected local def-id");
85 let item = match self.tcx.hir.get(node_id) {
86 hir::map::NodeItem(item) => item,
90 let mut item_required_predicates = RequiredPredicates::default();
92 hir::ItemUnion(..) | hir::ItemEnum(..) | hir::ItemStruct(..) => {
93 let adt_def = self.tcx.adt_def(item_did);
95 // Iterate over all fields in item_did
96 for field_def in adt_def.all_fields() {
97 // Calculating the predicate requirements necessary
100 // For field of type &'a T (reference) or TyAdt
101 // (struct/enum/union) there will be outlive
102 // requirements for adt_def.
103 let field_ty = self.tcx.type_of(field_def.did);
104 insert_required_predicates_to_be_wf(
107 self.global_inferred_outlives,
108 &mut item_required_predicates,
117 // If new predicates were added (`local_predicate_map` has more
118 // predicates than the `global_inferred_outlives`), the new predicates
119 // might result in implied predicates for their parent types.
120 // Therefore mark `predicates_added` as true and which will ensure
121 // we walk the crates again and re-calculate predicates for all
123 let item_predicates_len: usize = self.global_inferred_outlives
127 if item_required_predicates.len() > item_predicates_len {
128 *self.predicates_added = true;
129 self.global_inferred_outlives
130 .insert(item_did, item_required_predicates);
134 fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {}
136 fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {}
139 fn insert_required_predicates_to_be_wf<'tcx>(
140 tcx: TyCtxt<'_, 'tcx, 'tcx>,
142 global_inferred_outlives: &FxHashMap<DefId, RequiredPredicates<'tcx>>,
143 required_predicates: &mut RequiredPredicates<'tcx>,
144 explicit_map: &FxHashMap<DefId, Lrc<Vec<ty::Predicate<'tcx>>>>,
146 for ty in field_ty.walk() {
148 // The field is of type &'a T which means that we will have
149 // a predicate requirement of T: 'a (T outlives 'a).
151 // We also want to calculate potential predicates for the T
152 ty::TyRef(region, rty, _) => {
153 insert_outlives_predicate(tcx, rty.into(), region, required_predicates);
156 // For each TyAdt (struct/enum/union) type `Foo<'a, T>`, we
157 // can load the current set of inferred and explicit
158 // predicates from `global_inferred_outlives` and filter the
159 // ones that are TypeOutlives.
161 ty::TyAdt(def, substs) => {
162 // First check the inferred predicates
166 // struct Foo<'a, T> {
167 // field1: Bar<'a, T>
170 // struct Bar<'b, U> {
174 // Here, when processing the type of `field1`, we would
175 // request the set of implicit predicates computed for `Bar`
176 // thus far. This will initially come back empty, but in next
177 // round we will get `U: 'b`. We then apply the substitution
178 // `['b => 'a, U => T]` and thus get the requirement that `T:
179 // 'a` holds for `Foo`.
180 if let Some(unsubstituted_predicates) = global_inferred_outlives.get(&def.did) {
181 for unsubstituted_predicate in unsubstituted_predicates {
182 // `unsubstituted_predicate` is `U: 'b` in the
183 // example above. So apply the substitution to
184 // get `T: 'a` (or `predicate`):
185 let predicate = unsubstituted_predicate.subst(tcx, substs);
186 insert_outlives_predicate(
195 // Check if the type has any explicit predicates that need
196 // to be added to `required_predicates`
197 // let _: () = substs.region_at(0);
198 check_explicit_predicates(tcx, &def.did, substs, required_predicates, explicit_map);
201 ty::TyDynamic(obj, region) => {
202 // FIXME This corresponds to `dyn Trait<..>`. In this
203 // case, we should use the explicit predicates as
205 if let Some(p) = obj.principal() {
206 check_explicit_predicates(
208 &p.skip_binder().def_id,
216 ty::TyProjection(obj) => {
217 // FIXME This corresponds to `<T as Foo<'a>>::Bar`. In this case, we should use the
218 // explicit predicates as well.
219 check_explicit_predicates(
233 /// We also have to check the explicit predicates
234 /// declared on the type.
236 /// struct Foo<'a, T> {
240 /// struct Bar<U> where U: 'static, U: Foo {
244 /// Here, we should fetch the explicit predicates, which
245 /// will give us `U: 'static` and `U: Foo`. The latter we
246 /// can ignore, but we will want to process `U: 'static`,
247 /// applying the substitution as above.
248 fn check_explicit_predicates<'tcx>(
249 tcx: TyCtxt<'_, 'tcx, 'tcx>,
251 substs: &[Kind<'tcx>],
252 required_predicates: &mut RequiredPredicates<'tcx>,
253 explicit_map: &FxHashMap<DefId, Lrc<Vec<ty::Predicate<'tcx>>>>,
255 if let Some(general_predicates) = explicit_map.get(def_id) {
256 for general_predicate in general_predicates.iter() {
257 match general_predicate {
258 // `poly` is `PolyTypeOutlivesPredicate<OutlivesPredicate<Ty>>`
259 // where OutlivesPredicate<type1, region1> is the predicate
261 ty::Predicate::TypeOutlives(poly) => {
262 let predicate = poly.skip_binder().subst(tcx, substs);
263 insert_outlives_predicate(
271 // `poly` is `PolyRegionOutlivesPredicate<OutlivesPredicate<Ty>>`
272 // where OutlivesPredicate<region1, region2> is the predicate
274 ty::Predicate::RegionOutlives(poly) => {
275 let predicate = poly.skip_binder().subst(tcx, substs);
276 insert_outlives_predicate(
284 ty::Predicate::Trait(..)
285 | ty::Predicate::Projection(..)
286 | ty::Predicate::WellFormed(..)
287 | ty::Predicate::ObjectSafe(..)
288 | ty::Predicate::ClosureKind(..)
289 | ty::Predicate::Subtype(..)
290 | ty::Predicate::ConstEvaluatable(..) => (),
296 /// Given a requirement `T: 'a` or `'b: 'a`, deduce the
297 /// outlives_component and add it to `required_predicates`
298 fn insert_outlives_predicate<'tcx>(
299 tcx: TyCtxt<'_, 'tcx, 'tcx>,
301 outlived_region: Region<'tcx>,
302 required_predicates: &mut RequiredPredicates<'tcx>,
304 // If the `'a` region is bound within the field type itself, we
305 // don't want to propagate this constraint to the header.
306 if !is_free_region(outlived_region) {
310 match kind.unpack() {
311 UnpackedKind::Type(ty) => {
312 // `T: 'outlived_region` for some type `T`
313 // But T could be a lot of things:
314 // e.g., if `T = &'b u32`, then `'b: 'outlived_region` is
315 // what we want to add.
317 // Or if within `struct Foo<U>` you had `T = Vec<U>`, then
318 // we would want to add `U: 'outlived_region`
319 for component in tcx.outlives_components(ty) {
321 Component::Region(r) => {
322 // This would arise from something like:
325 // struct Foo<'a, 'b> {
330 // Here `outlived_region = 'a` and `kind = &'b
331 // u32`. Decomposing `&'b u32` into
332 // components would yield `'b`, and we add the
333 // where clause that `'b: 'a`.
334 insert_outlives_predicate(
342 Component::Param(param_ty) => {
343 // param_ty: ty::ParamTy
344 // This would arise from something like:
347 // struct Foo<'a, U> {
352 // Here `outlived_region = 'a` and `kind =
353 // Vec<U>`. Decomposing `Vec<U>` into
354 // components would yield `U`, and we add the
355 // where clause that `U: 'a`.
356 let ty: Ty<'tcx> = tcx.mk_ty_param(param_ty.idx, param_ty.name);
358 .insert(ty::OutlivesPredicate(ty.into(), outlived_region));
361 Component::Projection(proj_ty) => {
362 // This would arise from something like:
365 // struct Foo<'a, T: Iterator> {
366 // x: &'a <T as Iterator>::Item
370 // Here we want to add an explicit `where <T as Iterator>::Item: 'a`.
371 let ty: Ty<'tcx> = tcx.mk_projection(proj_ty.item_def_id, proj_ty.substs);
373 .insert(ty::OutlivesPredicate(ty.into(), outlived_region));
376 Component::EscapingProjection(_) => {
377 // As above, but the projection involves
378 // late-bound regions. Therefore, the WF
379 // requirement is not checked in type definition
380 // but at fn call site, so ignore it.
383 // struct Foo<'a, T: Iterator> {
384 // x: for<'b> fn(<&'b T as Iterator>::Item)
385 // // ^^^^^^^^^^^^^^^^^^^^^^^^^
389 // Since `'b` is not in scope on `Foo`, can't
390 // do anything here, ignore it.
393 Component::UnresolvedInferenceVariable(_) => bug!("not using infcx"),
398 UnpackedKind::Lifetime(r) => {
399 if !is_free_region(r) {
402 required_predicates.insert(ty::OutlivesPredicate(kind, outlived_region));
407 fn is_free_region(region: Region<'_>) -> bool {
408 // First, screen for regions that might appear in a type header.
410 // *These* correspond to `T: 'a` relationships where `'a` is
411 // either declared on the type or `'static`:
413 // struct Foo<'a, T> {
414 // field: &'a T, // this would generate a ReEarlyBound referencing `'a`
415 // field2: &'static T, // this would generate a ReStatic
418 // We care about these, so fall through.
419 RegionKind::ReStatic | RegionKind::ReEarlyBound(_) => true,
421 // Late-bound regions can appear in `fn` types:
424 // field: for<'b> fn(&'b T) // e.g., 'b here
427 // The type above might generate a `T: 'b` bound, but we can
428 // ignore it. We can't put it on the struct header anyway.
429 RegionKind::ReLateBound(..) => false,
431 // These regions don't appear in types from type declarations:
433 | RegionKind::ReErased
434 | RegionKind::ReClosureBound(..)
435 | RegionKind::ReCanonical(..)
436 | RegionKind::ReScope(..)
437 | RegionKind::ReVar(..)
438 | RegionKind::ReSkolemized(..)
439 | RegionKind::ReFree(..) => {
440 bug!("unexpected region in outlives inference: {:?}", region);