]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_borrowck/src/type_check/canonical.rs
Rollup merge of #101779 - eholk:drop-tracking-test-output, r=jyn514
[rust.git] / compiler / rustc_borrowck / src / type_check / canonical.rs
1 use std::fmt;
2
3 use rustc_infer::infer::canonical::Canonical;
4 use rustc_infer::traits::query::NoSolution;
5 use rustc_middle::mir::ConstraintCategory;
6 use rustc_middle::ty::{self, ToPredicate, TypeFoldable};
7 use rustc_span::def_id::DefId;
8 use rustc_span::Span;
9 use rustc_trait_selection::traits::query::type_op::{self, TypeOpOutput};
10 use rustc_trait_selection::traits::query::Fallible;
11
12 use crate::diagnostics::{ToUniverseInfo, UniverseInfo};
13
14 use super::{Locations, NormalizeLocation, TypeChecker};
15
16 impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
17     /// Given some operation `op` that manipulates types, proves
18     /// predicates, or otherwise uses the inference context, executes
19     /// `op` and then executes all the further obligations that `op`
20     /// returns. This will yield a set of outlives constraints amongst
21     /// regions which are extracted and stored as having occurred at
22     /// `locations`.
23     ///
24     /// **Any `rustc_infer::infer` operations that might generate region
25     /// constraints should occur within this method so that those
26     /// constraints can be properly localized!**
27     #[instrument(skip(self, op), level = "trace")]
28     pub(super) fn fully_perform_op<R: fmt::Debug, Op>(
29         &mut self,
30         locations: Locations,
31         category: ConstraintCategory<'tcx>,
32         op: Op,
33     ) -> Fallible<R>
34     where
35         Op: type_op::TypeOp<'tcx, Output = R>,
36         Op::ErrorInfo: ToUniverseInfo<'tcx>,
37     {
38         let old_universe = self.infcx.universe();
39
40         let TypeOpOutput { output, constraints, error_info } = op.fully_perform(self.infcx)?;
41
42         debug!(?output, ?constraints);
43
44         if let Some(data) = constraints {
45             self.push_region_constraints(locations, category, data);
46         }
47
48         let universe = self.infcx.universe();
49
50         if old_universe != universe {
51             let universe_info = match error_info {
52                 Some(error_info) => error_info.to_universe_info(old_universe),
53                 None => UniverseInfo::other(),
54             };
55             for u in old_universe..universe {
56                 self.borrowck_context
57                     .constraints
58                     .universe_causes
59                     .insert(u + 1, universe_info.clone());
60             }
61         }
62
63         Ok(output)
64     }
65
66     pub(super) fn instantiate_canonical_with_fresh_inference_vars<T>(
67         &mut self,
68         span: Span,
69         canonical: &Canonical<'tcx, T>,
70     ) -> T
71     where
72         T: TypeFoldable<'tcx>,
73     {
74         let (instantiated, _) =
75             self.infcx.instantiate_canonical_with_fresh_inference_vars(span, canonical);
76
77         for u in 0..canonical.max_universe.as_u32() {
78             let info = UniverseInfo::other();
79             self.borrowck_context
80                 .constraints
81                 .universe_causes
82                 .insert(ty::UniverseIndex::from_u32(u), info);
83         }
84
85         instantiated
86     }
87
88     #[instrument(skip(self), level = "debug")]
89     pub(super) fn prove_trait_ref(
90         &mut self,
91         trait_ref: ty::TraitRef<'tcx>,
92         locations: Locations,
93         category: ConstraintCategory<'tcx>,
94     ) {
95         self.prove_predicate(
96             ty::Binder::dummy(ty::PredicateKind::Trait(ty::TraitPredicate {
97                 trait_ref,
98                 constness: ty::BoundConstness::NotConst,
99                 polarity: ty::ImplPolarity::Positive,
100             }))
101             .to_predicate(self.tcx()),
102             locations,
103             category,
104         );
105     }
106
107     #[instrument(level = "debug", skip(self))]
108     pub(super) fn normalize_and_prove_instantiated_predicates(
109         &mut self,
110         // Keep this parameter for now, in case we start using
111         // it in `ConstraintCategory` at some point.
112         _def_id: DefId,
113         instantiated_predicates: ty::InstantiatedPredicates<'tcx>,
114         locations: Locations,
115     ) {
116         for (predicate, span) in instantiated_predicates
117             .predicates
118             .into_iter()
119             .zip(instantiated_predicates.spans.into_iter())
120         {
121             debug!(?predicate);
122             let category = ConstraintCategory::Predicate(span);
123             let predicate = self.normalize_with_category(predicate, locations, category);
124             self.prove_predicate(predicate, locations, category);
125         }
126     }
127
128     pub(super) fn prove_predicates(
129         &mut self,
130         predicates: impl IntoIterator<Item = impl ToPredicate<'tcx>>,
131         locations: Locations,
132         category: ConstraintCategory<'tcx>,
133     ) {
134         for predicate in predicates {
135             let predicate = predicate.to_predicate(self.tcx());
136             debug!("prove_predicates(predicate={:?}, locations={:?})", predicate, locations,);
137
138             self.prove_predicate(predicate, locations, category);
139         }
140     }
141
142     #[instrument(skip(self), level = "debug")]
143     pub(super) fn prove_predicate(
144         &mut self,
145         predicate: ty::Predicate<'tcx>,
146         locations: Locations,
147         category: ConstraintCategory<'tcx>,
148     ) {
149         let param_env = self.param_env;
150         self.fully_perform_op(
151             locations,
152             category,
153             param_env.and(type_op::prove_predicate::ProvePredicate::new(predicate)),
154         )
155         .unwrap_or_else(|NoSolution| {
156             span_mirbug!(self, NoSolution, "could not prove {:?}", predicate);
157         })
158     }
159
160     pub(super) fn normalize<T>(&mut self, value: T, location: impl NormalizeLocation) -> T
161     where
162         T: type_op::normalize::Normalizable<'tcx> + fmt::Display + Copy + 'tcx,
163     {
164         self.normalize_with_category(value, location, ConstraintCategory::Boring)
165     }
166
167     #[instrument(skip(self), level = "debug")]
168     pub(super) fn normalize_with_category<T>(
169         &mut self,
170         value: T,
171         location: impl NormalizeLocation,
172         category: ConstraintCategory<'tcx>,
173     ) -> T
174     where
175         T: type_op::normalize::Normalizable<'tcx> + fmt::Display + Copy + 'tcx,
176     {
177         let param_env = self.param_env;
178         self.fully_perform_op(
179             location.to_locations(),
180             category,
181             param_env.and(type_op::normalize::Normalize::new(value)),
182         )
183         .unwrap_or_else(|NoSolution| {
184             span_mirbug!(self, NoSolution, "failed to normalize `{:?}`", value);
185             value
186         })
187     }
188 }