]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_borrowck/src/type_check/canonical.rs
New upstream version 1.57.0+dfsg1
[rustc.git] / compiler / rustc_borrowck / src / type_check / canonical.rs
CommitLineData
94222f64
XL
1use std::fmt;
2
3use rustc_infer::infer::canonical::Canonical;
4use rustc_infer::traits::query::NoSolution;
5use rustc_middle::mir::ConstraintCategory;
6use rustc_middle::ty::{self, ToPredicate, TypeFoldable};
c295e0f8 7use rustc_span::def_id::DefId;
94222f64
XL
8use rustc_span::Span;
9use rustc_trait_selection::traits::query::type_op::{self, TypeOpOutput};
10use rustc_trait_selection::traits::query::Fallible;
11
c295e0f8 12use crate::diagnostics::{ToUniverseInfo, UniverseInfo};
94222f64
XL
13
14use super::{Locations, NormalizeLocation, TypeChecker};
15
16impl<'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!**
c295e0f8 27 #[instrument(skip(self, category, op), level = "trace")]
94222f64
XL
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 {
c295e0f8
XL
55 self.borrowck_context
56 .constraints
57 .universe_causes
58 .insert(u + 1, universe_info.clone());
94222f64
XL
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
c295e0f8 76 for u in 0..canonical.max_universe.as_u32() {
94222f64 77 let info = UniverseInfo::other();
c295e0f8
XL
78 self.borrowck_context
79 .constraints
80 .universe_causes
81 .insert(ty::UniverseIndex::from_u32(u), info);
94222f64
XL
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(
c295e0f8 94 Some(ty::Binder::dummy(ty::PredicateKind::Trait(ty::TraitPredicate {
94222f64
XL
95 trait_ref,
96 constness: ty::BoundConstness::NotConst,
c295e0f8 97 }))),
94222f64
XL
98 locations,
99 category,
100 );
101 }
102
103 pub(super) fn normalize_and_prove_instantiated_predicates(
104 &mut self,
c295e0f8
XL
105 // Keep this parameter for now, in case we start using
106 // it in `ConstraintCategory` at some point.
107 _def_id: DefId,
94222f64
XL
108 instantiated_predicates: ty::InstantiatedPredicates<'tcx>,
109 locations: Locations,
110 ) {
c295e0f8
XL
111 for (predicate, span) in instantiated_predicates
112 .predicates
113 .into_iter()
114 .zip(instantiated_predicates.spans.into_iter())
115 {
94222f64 116 let predicate = self.normalize(predicate, locations);
c295e0f8 117 self.prove_predicate(predicate, locations, ConstraintCategory::Predicate(span));
94222f64
XL
118 }
119 }
120
121 pub(super) fn prove_predicates(
122 &mut self,
123 predicates: impl IntoIterator<Item = impl ToPredicate<'tcx>>,
124 locations: Locations,
125 category: ConstraintCategory,
126 ) {
127 for predicate in predicates {
128 let predicate = predicate.to_predicate(self.tcx());
129 debug!("prove_predicates(predicate={:?}, locations={:?})", predicate, locations,);
130
131 self.prove_predicate(predicate, locations, category);
132 }
133 }
134
c295e0f8 135 #[instrument(skip(self), level = "debug")]
94222f64
XL
136 pub(super) fn prove_predicate(
137 &mut self,
138 predicate: ty::Predicate<'tcx>,
139 locations: Locations,
140 category: ConstraintCategory,
141 ) {
94222f64
XL
142 let param_env = self.param_env;
143 self.fully_perform_op(
144 locations,
145 category,
146 param_env.and(type_op::prove_predicate::ProvePredicate::new(predicate)),
147 )
148 .unwrap_or_else(|NoSolution| {
149 span_mirbug!(self, NoSolution, "could not prove {:?}", predicate);
150 })
151 }
152
c295e0f8 153 #[instrument(skip(self), level = "debug")]
94222f64
XL
154 pub(super) fn normalize<T>(&mut self, value: T, location: impl NormalizeLocation) -> T
155 where
156 T: type_op::normalize::Normalizable<'tcx> + fmt::Display + Copy + 'tcx,
157 {
94222f64
XL
158 let param_env = self.param_env;
159 self.fully_perform_op(
160 location.to_locations(),
161 ConstraintCategory::Boring,
162 param_env.and(type_op::normalize::Normalize::new(value)),
163 )
164 .unwrap_or_else(|NoSolution| {
165 span_mirbug!(self, NoSolution, "failed to normalize `{:?}`", value);
166 value
167 })
168 }
169}