]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_borrowck/src/type_check/canonical.rs
Rollup merge of #89876 - AlexApps99:const_ops, r=oli-obk
[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, category, op), level = "trace")]
28     pub(super) fn fully_perform_op<R, Op>(
29         &mut self,
30         locations: Locations,
31         category: ConstraintCategory,
32         op: Op,
33     ) -> Fallible<R>
34     where
35         Op: type_op::TypeOp<'tcx, Output = R>,
36         Canonical<'tcx, Op>: ToUniverseInfo<'tcx>,
37     {
38         let old_universe = self.infcx.universe();
39
40         let TypeOpOutput { output, constraints, canonicalized_query } =
41             op.fully_perform(self.infcx)?;
42
43         if let Some(data) = &constraints {
44             self.push_region_constraints(locations, category, data);
45         }
46
47         let universe = self.infcx.universe();
48
49         if old_universe != universe {
50             let universe_info = match canonicalized_query {
51                 Some(canonicalized_query) => canonicalized_query.to_universe_info(old_universe),
52                 None => UniverseInfo::other(),
53             };
54             for u in old_universe..universe {
55                 self.borrowck_context
56                     .constraints
57                     .universe_causes
58                     .insert(u + 1, universe_info.clone());
59             }
60         }
61
62         Ok(output)
63     }
64
65     pub(super) fn instantiate_canonical_with_fresh_inference_vars<T>(
66         &mut self,
67         span: Span,
68         canonical: &Canonical<'tcx, T>,
69     ) -> T
70     where
71         T: TypeFoldable<'tcx>,
72     {
73         let (instantiated, _) =
74             self.infcx.instantiate_canonical_with_fresh_inference_vars(span, canonical);
75
76         for u in 0..canonical.max_universe.as_u32() {
77             let info = UniverseInfo::other();
78             self.borrowck_context
79                 .constraints
80                 .universe_causes
81                 .insert(ty::UniverseIndex::from_u32(u), info);
82         }
83
84         instantiated
85     }
86
87     pub(super) fn prove_trait_ref(
88         &mut self,
89         trait_ref: ty::TraitRef<'tcx>,
90         locations: Locations,
91         category: ConstraintCategory,
92     ) {
93         self.prove_predicates(
94             Some(ty::Binder::dummy(ty::PredicateKind::Trait(ty::TraitPredicate {
95                 trait_ref,
96                 constness: ty::BoundConstness::NotConst,
97                 polarity: ty::ImplPolarity::Positive,
98             }))),
99             locations,
100             category,
101         );
102     }
103
104     pub(super) fn normalize_and_prove_instantiated_predicates(
105         &mut self,
106         // Keep this parameter for now, in case we start using
107         // it in `ConstraintCategory` at some point.
108         _def_id: DefId,
109         instantiated_predicates: ty::InstantiatedPredicates<'tcx>,
110         locations: Locations,
111     ) {
112         for (predicate, span) in instantiated_predicates
113             .predicates
114             .into_iter()
115             .zip(instantiated_predicates.spans.into_iter())
116         {
117             let predicate = self.normalize(predicate, locations);
118             self.prove_predicate(predicate, locations, ConstraintCategory::Predicate(span));
119         }
120     }
121
122     pub(super) fn prove_predicates(
123         &mut self,
124         predicates: impl IntoIterator<Item = impl ToPredicate<'tcx>>,
125         locations: Locations,
126         category: ConstraintCategory,
127     ) {
128         for predicate in predicates {
129             let predicate = predicate.to_predicate(self.tcx());
130             debug!("prove_predicates(predicate={:?}, locations={:?})", predicate, locations,);
131
132             self.prove_predicate(predicate, locations, category);
133         }
134     }
135
136     #[instrument(skip(self), level = "debug")]
137     pub(super) fn prove_predicate(
138         &mut self,
139         predicate: ty::Predicate<'tcx>,
140         locations: Locations,
141         category: ConstraintCategory,
142     ) {
143         let param_env = self.param_env;
144         self.fully_perform_op(
145             locations,
146             category,
147             param_env.and(type_op::prove_predicate::ProvePredicate::new(predicate)),
148         )
149         .unwrap_or_else(|NoSolution| {
150             span_mirbug!(self, NoSolution, "could not prove {:?}", predicate);
151         })
152     }
153
154     #[instrument(skip(self), level = "debug")]
155     pub(super) fn normalize<T>(&mut self, value: T, location: impl NormalizeLocation) -> T
156     where
157         T: type_op::normalize::Normalizable<'tcx> + fmt::Display + Copy + 'tcx,
158     {
159         let param_env = self.param_env;
160         self.fully_perform_op(
161             location.to_locations(),
162             ConstraintCategory::Boring,
163             param_env.and(type_op::normalize::Normalize::new(value)),
164         )
165         .unwrap_or_else(|NoSolution| {
166             span_mirbug!(self, NoSolution, "failed to normalize `{:?}`", value);
167             value
168         })
169     }
170 }