]>
Commit | Line | Data |
---|---|---|
74b04a01 | 1 | pub use self::freshen::TypeFreshener; |
94222f64 | 2 | pub use self::lexical_region_resolve::RegionResolutionError; |
74b04a01 XL |
3 | pub use self::LateBoundRegionConversionTime::*; |
4 | pub use self::RegionVariableOrigin::*; | |
5 | pub use self::SubregionOrigin::*; | |
6 | pub use self::ValuePairs::*; | |
74b04a01 | 7 | |
5e7ed085 | 8 | use self::opaque_types::OpaqueTypeStorage; |
f9f354fc XL |
9 | pub(crate) use self::undo_log::{InferCtxtUndoLogs, Snapshot, UndoLog}; |
10 | ||
064997fb | 11 | use crate::traits::{self, ObligationCause, PredicateObligations, TraitEngine, TraitEngineExt}; |
74b04a01 | 12 | |
74b04a01 XL |
13 | use rustc_data_structures::fx::{FxHashMap, FxHashSet}; |
14 | use rustc_data_structures::sync::Lrc; | |
f9f354fc | 15 | use rustc_data_structures::undo_log::Rollback; |
74b04a01 | 16 | use rustc_data_structures::unify as ut; |
5e7ed085 | 17 | use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed}; |
ba9703b0 XL |
18 | use rustc_hir::def_id::{DefId, LocalDefId}; |
19 | use rustc_middle::infer::canonical::{Canonical, CanonicalVarValues}; | |
20 | use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue}; | |
21 | use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType}; | |
923072b8 | 22 | use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult}; |
f2b60f7d | 23 | use rustc_middle::mir::ConstraintCategory; |
ba9703b0 | 24 | use rustc_middle::traits::select; |
064997fb | 25 | use rustc_middle::ty::abstract_const::{AbstractConst, FailureKind}; |
94222f64 | 26 | use rustc_middle::ty::error::{ExpectedFound, TypeError}; |
064997fb | 27 | use rustc_middle::ty::fold::BoundVarReplacerDelegate; |
923072b8 | 28 | use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; |
ba9703b0 XL |
29 | use rustc_middle::ty::relate::RelateResult; |
30 | use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef}; | |
064997fb | 31 | use rustc_middle::ty::visit::TypeVisitable; |
ba9703b0 XL |
32 | pub use rustc_middle::ty::IntVarValue; |
33 | use rustc_middle::ty::{self, GenericParamDefKind, InferConst, Ty, TyCtxt}; | |
34 | use rustc_middle::ty::{ConstVid, FloatVid, IntVid, TyVid}; | |
74b04a01 | 35 | use rustc_span::symbol::Symbol; |
f2b60f7d | 36 | use rustc_span::{Span, DUMMY_SP}; |
ba9703b0 | 37 | |
2b03887a | 38 | use std::cell::{Cell, RefCell}; |
74b04a01 XL |
39 | use std::fmt; |
40 | ||
41 | use self::combine::CombineFields; | |
2b03887a | 42 | use self::error_reporting::TypeErrCtxt; |
f9f354fc | 43 | use self::free_regions::RegionRelations; |
74b04a01 XL |
44 | use self::lexical_region_resolve::LexicalRegionResolutions; |
45 | use self::outlives::env::OutlivesEnvironment; | |
46 | use self::region_constraints::{GenericKind, RegionConstraintData, VarInfos, VerifyBound}; | |
f9f354fc XL |
47 | use self::region_constraints::{ |
48 | RegionConstraintCollector, RegionConstraintStorage, RegionSnapshot, | |
49 | }; | |
c295e0f8 | 50 | use self::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; |
74b04a01 XL |
51 | |
52 | pub mod at; | |
53 | pub mod canonical; | |
54 | mod combine; | |
55 | mod equate; | |
56 | pub mod error_reporting; | |
f9f354fc | 57 | pub mod free_regions; |
74b04a01 XL |
58 | mod freshen; |
59 | mod fudge; | |
60 | mod glb; | |
61 | mod higher_ranked; | |
62 | pub mod lattice; | |
63 | mod lexical_region_resolve; | |
64 | mod lub; | |
65 | pub mod nll_relate; | |
94222f64 | 66 | pub mod opaque_types; |
74b04a01 | 67 | pub mod outlives; |
c295e0f8 | 68 | mod projection; |
74b04a01 XL |
69 | pub mod region_constraints; |
70 | pub mod resolve; | |
71 | mod sub; | |
72 | pub mod type_variable; | |
f9f354fc | 73 | mod undo_log; |
74b04a01 | 74 | |
74b04a01 XL |
75 | #[must_use] |
76 | #[derive(Debug)] | |
77 | pub struct InferOk<'tcx, T> { | |
78 | pub value: T, | |
79 | pub obligations: PredicateObligations<'tcx>, | |
80 | } | |
81 | pub type InferResult<'tcx, T> = Result<InferOk<'tcx, T>, TypeError<'tcx>>; | |
82 | ||
83 | pub type Bound<T> = Option<T>; | |
84 | pub type UnitResult<'tcx> = RelateResult<'tcx, ()>; // "unify result" | |
85 | pub type FixupResult<'tcx, T> = Result<T, FixupError<'tcx>>; // "fixup result" | |
86 | ||
f9f354fc XL |
87 | pub(crate) type UnificationTable<'a, 'tcx, T> = ut::UnificationTable< |
88 | ut::InPlace<T, &'a mut ut::UnificationStorage<T>, &'a mut InferCtxtUndoLogs<'tcx>>, | |
89 | >; | |
90 | ||
74b04a01 XL |
91 | /// This type contains all the things within `InferCtxt` that sit within a |
92 | /// `RefCell` and are involved with taking/rolling back snapshots. Snapshot | |
93 | /// operations are hot enough that we want only one call to `borrow_mut` per | |
94 | /// call to `start_snapshot` and `rollback_to`. | |
5099ac24 | 95 | #[derive(Clone)] |
74b04a01 XL |
96 | pub struct InferCtxtInner<'tcx> { |
97 | /// Cache for projections. This cache is snapshotted along with the infcx. | |
98 | /// | |
99 | /// Public so that `traits::project` can use it. | |
f9f354fc | 100 | pub projection_cache: traits::ProjectionCacheStorage<'tcx>, |
74b04a01 XL |
101 | |
102 | /// We instantiate `UnificationTable` with `bounds<Ty>` because the types | |
103 | /// that might instantiate a general type variable have an order, | |
104 | /// represented by its upper and lower bounds. | |
f9f354fc | 105 | type_variable_storage: type_variable::TypeVariableStorage<'tcx>, |
74b04a01 XL |
106 | |
107 | /// Map from const parameter variable to the kind of const it represents. | |
f9f354fc | 108 | const_unification_storage: ut::UnificationTableStorage<ty::ConstVid<'tcx>>, |
74b04a01 XL |
109 | |
110 | /// Map from integral variable to the kind of integer it represents. | |
f9f354fc | 111 | int_unification_storage: ut::UnificationTableStorage<ty::IntVid>, |
74b04a01 XL |
112 | |
113 | /// Map from floating variable to the kind of float it represents. | |
f9f354fc | 114 | float_unification_storage: ut::UnificationTableStorage<ty::FloatVid>, |
74b04a01 XL |
115 | |
116 | /// Tracks the set of region variables and the constraints between them. | |
117 | /// This is initially `Some(_)` but when | |
118 | /// `resolve_regions_and_report_errors` is invoked, this gets set to `None` | |
119 | /// -- further attempts to perform unification, etc., may fail if new | |
120 | /// region constraints would've been added. | |
f9f354fc | 121 | region_constraint_storage: Option<RegionConstraintStorage<'tcx>>, |
74b04a01 XL |
122 | |
123 | /// A set of constraints that regionck must validate. Each | |
124 | /// constraint has the form `T:'a`, meaning "some type `T` must | |
125 | /// outlive the lifetime 'a". These constraints derive from | |
126 | /// instantiated type parameters. So if you had a struct defined | |
127 | /// like | |
04454e1e | 128 | /// ```ignore (illustrative) |
74b04a01 | 129 | /// struct Foo<T:'static> { ... } |
04454e1e | 130 | /// ``` |
74b04a01 XL |
131 | /// then in some expression `let x = Foo { ... }` it will |
132 | /// instantiate the type parameter `T` with a fresh type `$0`. At | |
133 | /// the same time, it will record a region obligation of | |
134 | /// `$0:'static`. This will get checked later by regionck. (We | |
135 | /// can't generally check these things right away because we have | |
136 | /// to wait until types are resolved.) | |
137 | /// | |
138 | /// These are stored in a map keyed to the id of the innermost | |
139 | /// enclosing fn body / static initializer expression. This is | |
140 | /// because the location where the obligation was incurred can be | |
141 | /// relevant with respect to which sublifetime assumptions are in | |
142 | /// place. The reason that we store under the fn-id, and not | |
143 | /// something more fine-grained, is so that it is easier for | |
144 | /// regionck to be sure that it has found *all* the region | |
145 | /// obligations (otherwise, it's easy to fail to walk to a | |
146 | /// particular node-id). | |
147 | /// | |
148 | /// Before running `resolve_regions_and_report_errors`, the creator | |
149 | /// of the inference context is expected to invoke | |
923072b8 | 150 | /// [`InferCtxt::process_registered_region_obligations`] |
74b04a01 XL |
151 | /// for each body-id in this map, which will process the |
152 | /// obligations within. This is expected to be done 'late enough' | |
153 | /// that all type inference variables have been bound and so forth. | |
064997fb | 154 | region_obligations: Vec<RegionObligation<'tcx>>, |
f9f354fc XL |
155 | |
156 | undo_log: InferCtxtUndoLogs<'tcx>, | |
94222f64 | 157 | |
5e7ed085 FG |
158 | /// Caches for opaque type inference. |
159 | pub opaque_type_storage: OpaqueTypeStorage<'tcx>, | |
74b04a01 XL |
160 | } |
161 | ||
162 | impl<'tcx> InferCtxtInner<'tcx> { | |
163 | fn new() -> InferCtxtInner<'tcx> { | |
164 | InferCtxtInner { | |
165 | projection_cache: Default::default(), | |
f9f354fc XL |
166 | type_variable_storage: type_variable::TypeVariableStorage::new(), |
167 | undo_log: InferCtxtUndoLogs::default(), | |
168 | const_unification_storage: ut::UnificationTableStorage::new(), | |
169 | int_unification_storage: ut::UnificationTableStorage::new(), | |
170 | float_unification_storage: ut::UnificationTableStorage::new(), | |
171 | region_constraint_storage: Some(RegionConstraintStorage::new()), | |
74b04a01 | 172 | region_obligations: vec![], |
5e7ed085 | 173 | opaque_type_storage: Default::default(), |
74b04a01 XL |
174 | } |
175 | } | |
176 | ||
f9f354fc | 177 | #[inline] |
064997fb | 178 | pub fn region_obligations(&self) -> &[RegionObligation<'tcx>] { |
f9f354fc XL |
179 | &self.region_obligations |
180 | } | |
181 | ||
182 | #[inline] | |
183 | pub fn projection_cache(&mut self) -> traits::ProjectionCache<'_, 'tcx> { | |
184 | self.projection_cache.with_log(&mut self.undo_log) | |
185 | } | |
186 | ||
187 | #[inline] | |
188 | fn type_variables(&mut self) -> type_variable::TypeVariableTable<'_, 'tcx> { | |
189 | self.type_variable_storage.with_log(&mut self.undo_log) | |
190 | } | |
191 | ||
5e7ed085 FG |
192 | #[inline] |
193 | pub fn opaque_types(&mut self) -> opaque_types::OpaqueTypeTable<'_, 'tcx> { | |
194 | self.opaque_type_storage.with_log(&mut self.undo_log) | |
195 | } | |
196 | ||
f9f354fc XL |
197 | #[inline] |
198 | fn int_unification_table( | |
199 | &mut self, | |
200 | ) -> ut::UnificationTable< | |
201 | ut::InPlace< | |
202 | ty::IntVid, | |
203 | &mut ut::UnificationStorage<ty::IntVid>, | |
204 | &mut InferCtxtUndoLogs<'tcx>, | |
205 | >, | |
206 | > { | |
207 | self.int_unification_storage.with_log(&mut self.undo_log) | |
208 | } | |
209 | ||
210 | #[inline] | |
211 | fn float_unification_table( | |
212 | &mut self, | |
213 | ) -> ut::UnificationTable< | |
214 | ut::InPlace< | |
215 | ty::FloatVid, | |
216 | &mut ut::UnificationStorage<ty::FloatVid>, | |
217 | &mut InferCtxtUndoLogs<'tcx>, | |
218 | >, | |
219 | > { | |
220 | self.float_unification_storage.with_log(&mut self.undo_log) | |
221 | } | |
222 | ||
223 | #[inline] | |
224 | fn const_unification_table( | |
225 | &mut self, | |
226 | ) -> ut::UnificationTable< | |
227 | ut::InPlace< | |
228 | ty::ConstVid<'tcx>, | |
229 | &mut ut::UnificationStorage<ty::ConstVid<'tcx>>, | |
230 | &mut InferCtxtUndoLogs<'tcx>, | |
231 | >, | |
232 | > { | |
233 | self.const_unification_storage.with_log(&mut self.undo_log) | |
234 | } | |
235 | ||
236 | #[inline] | |
237 | pub fn unwrap_region_constraints(&mut self) -> RegionConstraintCollector<'_, 'tcx> { | |
238 | self.region_constraint_storage | |
239 | .as_mut() | |
240 | .expect("region constraints already solved") | |
241 | .with_log(&mut self.undo_log) | |
74b04a01 XL |
242 | } |
243 | } | |
244 | ||
064997fb FG |
245 | #[derive(Clone, Copy, Debug, PartialEq, Eq)] |
246 | pub enum DefiningAnchor { | |
247 | /// `DefId` of the item. | |
248 | Bind(LocalDefId), | |
249 | /// When opaque types are not resolved, we `Bubble` up, meaning | |
250 | /// return the opaque/hidden type pair from query, for caller of query to handle it. | |
251 | Bubble, | |
252 | /// Used to catch type mismatch errors when handling opaque types. | |
253 | Error, | |
254 | } | |
255 | ||
2b03887a | 256 | pub struct InferCtxt<'tcx> { |
74b04a01 XL |
257 | pub tcx: TyCtxt<'tcx>, |
258 | ||
94222f64 XL |
259 | /// The `DefId` of the item in whose context we are performing inference or typeck. |
260 | /// It is used to check whether an opaque type use is a defining use. | |
5099ac24 | 261 | /// |
064997fb | 262 | /// If it is `DefiningAnchor::Bubble`, we can't resolve opaque types here and need to bubble up |
5099ac24 FG |
263 | /// the obligation. This frequently happens for |
264 | /// short lived InferCtxt within queries. The opaque type obligations are forwarded | |
265 | /// to the outside until the end up in an `InferCtxt` for typeck or borrowck. | |
064997fb FG |
266 | /// |
267 | /// It is default value is `DefiningAnchor::Error`, this way it is easier to catch errors that | |
268 | /// might come up during inference or typeck. | |
269 | pub defining_use_anchor: DefiningAnchor, | |
270 | ||
271 | /// Whether this inference context should care about region obligations in | |
272 | /// the root universe. Most notably, this is used during hir typeck as region | |
273 | /// solving is left to borrowck instead. | |
274 | pub considering_regions: bool, | |
94222f64 | 275 | |
74b04a01 XL |
276 | pub inner: RefCell<InferCtxtInner<'tcx>>, |
277 | ||
278 | /// If set, this flag causes us to skip the 'leak check' during | |
279 | /// higher-ranked subtyping operations. This flag is a temporary one used | |
280 | /// to manage the removal of the leak-check: for the time being, we still run the | |
281 | /// leak-check, but we issue warnings. This flag can only be set to true | |
282 | /// when entering a snapshot. | |
283 | skip_leak_check: Cell<bool>, | |
284 | ||
285 | /// Once region inference is done, the values for each variable. | |
286 | lexical_region_resolutions: RefCell<Option<LexicalRegionResolutions<'tcx>>>, | |
287 | ||
288 | /// Caches the results of trait selection. This cache is used | |
289 | /// for things that have to do with the parameters in scope. | |
ba9703b0 | 290 | pub selection_cache: select::SelectionCache<'tcx>, |
74b04a01 XL |
291 | |
292 | /// Caches the results of trait evaluation. | |
ba9703b0 | 293 | pub evaluation_cache: select::EvaluationCache<'tcx>, |
74b04a01 XL |
294 | |
295 | /// the set of predicates on which errors have been reported, to | |
296 | /// avoid reporting the same error twice. | |
297 | pub reported_trait_errors: RefCell<FxHashMap<Span, Vec<ty::Predicate<'tcx>>>>, | |
298 | ||
299 | pub reported_closure_mismatch: RefCell<FxHashSet<(Span, Option<Span>)>>, | |
300 | ||
301 | /// When an error occurs, we want to avoid reporting "derived" | |
302 | /// errors that are due to this original failure. Normally, we | |
303 | /// handle this with the `err_count_on_creation` count, which | |
304 | /// basically just tracks how many errors were reported when we | |
305 | /// started type-checking a fn and checks to see if any new errors | |
306 | /// have been reported since then. Not great, but it works. | |
307 | /// | |
308 | /// However, when errors originated in other passes -- notably | |
309 | /// resolve -- this heuristic breaks down. Therefore, we have this | |
310 | /// auxiliary flag that one can set whenever one creates a | |
311 | /// type-error that is due to an error in a prior pass. | |
312 | /// | |
313 | /// Don't read this flag directly, call `is_tainted_by_errors()` | |
314 | /// and `set_tainted_by_errors()`. | |
f2b60f7d | 315 | tainted_by_errors: Cell<Option<ErrorGuaranteed>>, |
74b04a01 XL |
316 | |
317 | /// Track how many errors were reported when this infcx is created. | |
318 | /// If the number of errors increases, that's also a sign (line | |
5e7ed085 | 319 | /// `tainted_by_errors`) to avoid reporting certain kinds of errors. |
f2b60f7d | 320 | // FIXME(matthewjasper) Merge into `tainted_by_errors` |
74b04a01 XL |
321 | err_count_on_creation: usize, |
322 | ||
323 | /// This flag is true while there is an active snapshot. | |
324 | in_snapshot: Cell<bool>, | |
325 | ||
326 | /// What is the innermost universe we have created? Starts out as | |
327 | /// `UniverseIndex::root()` but grows from there as we enter | |
328 | /// universal quantifiers. | |
329 | /// | |
330 | /// N.B., at present, we exclude the universal quantifiers on the | |
331 | /// item we are type-checking, and just consider those names as | |
332 | /// part of the root universe. So this would only get incremented | |
333 | /// when we enter into a higher-ranked (`for<..>`) type or trait | |
334 | /// bound. | |
335 | universe: Cell<ty::UniverseIndex>, | |
f2b60f7d FG |
336 | |
337 | normalize_fn_sig_for_diagnostic: | |
2b03887a | 338 | Option<Lrc<dyn Fn(&InferCtxt<'tcx>, ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx>>>, |
74b04a01 XL |
339 | } |
340 | ||
74b04a01 | 341 | /// See the `error_reporting` module for more details. |
064997fb | 342 | #[derive(Clone, Copy, Debug, PartialEq, Eq, TypeFoldable, TypeVisitable)] |
74b04a01 | 343 | pub enum ValuePairs<'tcx> { |
74b04a01 | 344 | Regions(ExpectedFound<ty::Region<'tcx>>), |
5099ac24 | 345 | Terms(ExpectedFound<ty::Term<'tcx>>), |
74b04a01 XL |
346 | TraitRefs(ExpectedFound<ty::TraitRef<'tcx>>), |
347 | PolyTraitRefs(ExpectedFound<ty::PolyTraitRef<'tcx>>), | |
348 | } | |
349 | ||
5099ac24 FG |
350 | impl<'tcx> ValuePairs<'tcx> { |
351 | pub fn ty(&self) -> Option<(Ty<'tcx>, Ty<'tcx>)> { | |
f2b60f7d FG |
352 | if let ValuePairs::Terms(ExpectedFound { expected, found }) = self |
353 | && let Some(expected) = expected.ty() | |
354 | && let Some(found) = found.ty() | |
5099ac24 | 355 | { |
f2b60f7d | 356 | Some((expected, found)) |
5099ac24 FG |
357 | } else { |
358 | None | |
359 | } | |
360 | } | |
361 | } | |
362 | ||
74b04a01 XL |
363 | /// The trace designates the path through inference that we took to |
364 | /// encounter an error or subtyping constraint. | |
365 | /// | |
366 | /// See the `error_reporting` module for more details. | |
367 | #[derive(Clone, Debug)] | |
368 | pub struct TypeTrace<'tcx> { | |
04454e1e FG |
369 | pub cause: ObligationCause<'tcx>, |
370 | pub values: ValuePairs<'tcx>, | |
74b04a01 XL |
371 | } |
372 | ||
373 | /// The origin of a `r1 <= r2` constraint. | |
374 | /// | |
375 | /// See `error_reporting` module for more details | |
376 | #[derive(Clone, Debug)] | |
377 | pub enum SubregionOrigin<'tcx> { | |
378 | /// Arose from a subtyping relation | |
379 | Subtype(Box<TypeTrace<'tcx>>), | |
380 | ||
74b04a01 XL |
381 | /// When casting `&'a T` to an `&'b Trait` object, |
382 | /// relating `'a` to `'b` | |
383 | RelateObjectBound(Span), | |
384 | ||
385 | /// Some type parameter was instantiated with the given type, | |
386 | /// and that type must outlive some region. | |
94222f64 | 387 | RelateParamBound(Span, Ty<'tcx>, Option<Span>), |
74b04a01 XL |
388 | |
389 | /// The given region parameter was instantiated with a region | |
390 | /// that must outlive some other region. | |
391 | RelateRegionParamBound(Span), | |
392 | ||
74b04a01 XL |
393 | /// Creating a pointer `b` to contents of another reference |
394 | Reborrow(Span), | |
395 | ||
396 | /// Creating a pointer `b` to contents of an upvar | |
397 | ReborrowUpvar(Span, ty::UpvarId), | |
398 | ||
399 | /// Data with type `Ty<'tcx>` was borrowed | |
400 | DataBorrowed(Ty<'tcx>, Span), | |
401 | ||
402 | /// (&'a &'b T) where a >= b | |
403 | ReferenceOutlivesReferent(Ty<'tcx>, Span), | |
404 | ||
74b04a01 XL |
405 | /// Comparing the signature and requirements of an impl method against |
406 | /// the containing trait. | |
f2b60f7d FG |
407 | CompareImplItemObligation { |
408 | span: Span, | |
409 | impl_item_def_id: LocalDefId, | |
410 | trait_item_def_id: DefId, | |
411 | }, | |
5099ac24 FG |
412 | |
413 | /// Checking that the bounds of a trait's associated type hold for a given impl | |
414 | CheckAssociatedTypeBounds { | |
415 | parent: Box<SubregionOrigin<'tcx>>, | |
5e7ed085 | 416 | impl_item_def_id: LocalDefId, |
5099ac24 FG |
417 | trait_item_def_id: DefId, |
418 | }, | |
f2b60f7d FG |
419 | |
420 | AscribeUserTypeProvePredicate(Span), | |
74b04a01 XL |
421 | } |
422 | ||
423 | // `SubregionOrigin` is used a lot. Make sure it doesn't unintentionally get bigger. | |
6a06907d | 424 | #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] |
74b04a01 XL |
425 | static_assert_size!(SubregionOrigin<'_>, 32); |
426 | ||
f2b60f7d FG |
427 | impl<'tcx> SubregionOrigin<'tcx> { |
428 | pub fn to_constraint_category(&self) -> ConstraintCategory<'tcx> { | |
429 | match self { | |
430 | Self::Subtype(type_trace) => type_trace.cause.to_constraint_category(), | |
431 | Self::AscribeUserTypeProvePredicate(span) => ConstraintCategory::Predicate(*span), | |
432 | _ => ConstraintCategory::BoringNoLocation, | |
433 | } | |
434 | } | |
435 | } | |
436 | ||
74b04a01 XL |
437 | /// Times when we replace late-bound regions with variables: |
438 | #[derive(Clone, Copy, Debug)] | |
439 | pub enum LateBoundRegionConversionTime { | |
440 | /// when a fn is called | |
441 | FnCall, | |
442 | ||
443 | /// when two higher-ranked types are compared | |
444 | HigherRankedType, | |
445 | ||
446 | /// when projecting an associated type | |
447 | AssocTypeProjection(DefId), | |
448 | } | |
449 | ||
450 | /// Reasons to create a region inference variable | |
451 | /// | |
452 | /// See `error_reporting` module for more details | |
453 | #[derive(Copy, Clone, Debug)] | |
454 | pub enum RegionVariableOrigin { | |
455 | /// Region variables created for ill-categorized reasons, | |
456 | /// mostly indicates places in need of refactoring | |
457 | MiscVariable(Span), | |
458 | ||
459 | /// Regions created by a `&P` or `[...]` pattern | |
460 | PatternRegion(Span), | |
461 | ||
462 | /// Regions created by `&` operator | |
463 | AddrOfRegion(Span), | |
464 | ||
465 | /// Regions created as part of an autoref of a method receiver | |
3c0e092e | 466 | Autoref(Span), |
74b04a01 XL |
467 | |
468 | /// Regions created as part of an automatic coercion | |
469 | Coercion(Span), | |
470 | ||
471 | /// Region variables created as the values for early-bound regions | |
472 | EarlyBoundRegion(Span, Symbol), | |
473 | ||
474 | /// Region variables created for bound regions | |
475 | /// in a function or method that is called | |
fc512014 | 476 | LateBoundRegion(Span, ty::BoundRegionKind, LateBoundRegionConversionTime), |
74b04a01 XL |
477 | |
478 | UpvarRegion(ty::UpvarId, Span), | |
479 | ||
74b04a01 XL |
480 | /// This origin is used for the inference variables that we create |
481 | /// during NLL region processing. | |
5869c6ff | 482 | Nll(NllRegionVariableOrigin), |
74b04a01 XL |
483 | } |
484 | ||
485 | #[derive(Copy, Clone, Debug)] | |
5869c6ff | 486 | pub enum NllRegionVariableOrigin { |
74b04a01 XL |
487 | /// During NLL region processing, we create variables for free |
488 | /// regions that we encounter in the function signature and | |
489 | /// elsewhere. This origin indices we've got one of those. | |
490 | FreeRegion, | |
491 | ||
492 | /// "Universal" instantiation of a higher-ranked region (e.g., | |
493 | /// from a `for<'a> T` binder). Meant to represent "any region". | |
494 | Placeholder(ty::PlaceholderRegion), | |
495 | ||
496 | Existential { | |
497 | /// If this is true, then this variable was created to represent a lifetime | |
498 | /// bound in a `for` binder. For example, it might have been created to | |
499 | /// represent the lifetime `'a` in a type like `for<'a> fn(&'a u32)`. | |
500 | /// Such variables are created when we are trying to figure out if there | |
501 | /// is any valid instantiation of `'a` that could fit into some scenario. | |
502 | /// | |
503 | /// This is used to inform error reporting: in the case that we are trying to | |
504 | /// determine whether there is any valid instantiation of a `'a` variable that meets | |
505 | /// some constraint C, we want to blame the "source" of that `for` type, | |
506 | /// rather than blaming the source of the constraint C. | |
507 | from_forall: bool, | |
508 | }, | |
509 | } | |
510 | ||
ba9703b0 | 511 | // FIXME(eddyb) investigate overlap between this and `TyOrConstInferVar`. |
74b04a01 XL |
512 | #[derive(Copy, Clone, Debug)] |
513 | pub enum FixupError<'tcx> { | |
514 | UnresolvedIntTy(IntVid), | |
515 | UnresolvedFloatTy(FloatVid), | |
516 | UnresolvedTy(TyVid), | |
517 | UnresolvedConst(ConstVid<'tcx>), | |
518 | } | |
519 | ||
520 | /// See the `region_obligations` field for more information. | |
f2b60f7d | 521 | #[derive(Clone, Debug)] |
74b04a01 XL |
522 | pub struct RegionObligation<'tcx> { |
523 | pub sub_region: ty::Region<'tcx>, | |
524 | pub sup_type: Ty<'tcx>, | |
525 | pub origin: SubregionOrigin<'tcx>, | |
526 | } | |
527 | ||
528 | impl<'tcx> fmt::Display for FixupError<'tcx> { | |
529 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
530 | use self::FixupError::*; | |
531 | ||
532 | match *self { | |
533 | UnresolvedIntTy(_) => write!( | |
534 | f, | |
535 | "cannot determine the type of this integer; \ | |
536 | add a suffix to specify the type explicitly" | |
537 | ), | |
538 | UnresolvedFloatTy(_) => write!( | |
539 | f, | |
540 | "cannot determine the type of this number; \ | |
541 | add a suffix to specify the type explicitly" | |
542 | ), | |
543 | UnresolvedTy(_) => write!(f, "unconstrained type"), | |
544 | UnresolvedConst(_) => write!(f, "unconstrained const value"), | |
545 | } | |
546 | } | |
547 | } | |
548 | ||
2b03887a | 549 | /// Used to configure inference contexts before their creation |
74b04a01 | 550 | pub struct InferCtxtBuilder<'tcx> { |
f035d41b | 551 | tcx: TyCtxt<'tcx>, |
064997fb FG |
552 | defining_use_anchor: DefiningAnchor, |
553 | considering_regions: bool, | |
f2b60f7d | 554 | normalize_fn_sig_for_diagnostic: |
2b03887a | 555 | Option<Lrc<dyn Fn(&InferCtxt<'tcx>, ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx>>>, |
74b04a01 XL |
556 | } |
557 | ||
558 | pub trait TyCtxtInferExt<'tcx> { | |
559 | fn infer_ctxt(self) -> InferCtxtBuilder<'tcx>; | |
560 | } | |
561 | ||
a2a8927a | 562 | impl<'tcx> TyCtxtInferExt<'tcx> for TyCtxt<'tcx> { |
74b04a01 | 563 | fn infer_ctxt(self) -> InferCtxtBuilder<'tcx> { |
064997fb FG |
564 | InferCtxtBuilder { |
565 | tcx: self, | |
566 | defining_use_anchor: DefiningAnchor::Error, | |
567 | considering_regions: true, | |
f2b60f7d | 568 | normalize_fn_sig_for_diagnostic: None, |
064997fb | 569 | } |
74b04a01 XL |
570 | } |
571 | } | |
572 | ||
573 | impl<'tcx> InferCtxtBuilder<'tcx> { | |
94222f64 XL |
574 | /// Whenever the `InferCtxt` should be able to handle defining uses of opaque types, |
575 | /// you need to call this function. Otherwise the opaque type will be treated opaquely. | |
576 | /// | |
577 | /// It is only meant to be called in two places, for typeck | |
2b03887a | 578 | /// (via `Inherited::build`) and for the inference context used |
94222f64 | 579 | /// in mir borrowck. |
064997fb FG |
580 | pub fn with_opaque_type_inference(mut self, defining_use_anchor: DefiningAnchor) -> Self { |
581 | self.defining_use_anchor = defining_use_anchor; | |
582 | self | |
583 | } | |
584 | ||
585 | pub fn ignoring_regions(mut self) -> Self { | |
586 | self.considering_regions = false; | |
74b04a01 XL |
587 | self |
588 | } | |
589 | ||
f2b60f7d FG |
590 | pub fn with_normalize_fn_sig_for_diagnostic( |
591 | mut self, | |
2b03887a | 592 | fun: Lrc<dyn Fn(&InferCtxt<'tcx>, ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx>>, |
f2b60f7d FG |
593 | ) -> Self { |
594 | self.normalize_fn_sig_for_diagnostic = Some(fun); | |
595 | self | |
596 | } | |
597 | ||
74b04a01 XL |
598 | /// Given a canonical value `C` as a starting point, create an |
599 | /// inference context that contains each of the bound values | |
600 | /// within instantiated as a fresh variable. The `f` closure is | |
601 | /// invoked with the new infcx, along with the instantiated value | |
602 | /// `V` and a substitution `S`. This substitution `S` maps from | |
603 | /// the bound values in `C` to their instantiated values in `V` | |
604 | /// (in other words, `S(C) = V`). | |
2b03887a | 605 | pub fn build_with_canonical<T>( |
74b04a01 XL |
606 | &mut self, |
607 | span: Span, | |
608 | canonical: &Canonical<'tcx, T>, | |
2b03887a | 609 | ) -> (InferCtxt<'tcx>, T, CanonicalVarValues<'tcx>) |
74b04a01 XL |
610 | where |
611 | T: TypeFoldable<'tcx>, | |
612 | { | |
2b03887a FG |
613 | let infcx = self.build(); |
614 | let (value, subst) = infcx.instantiate_canonical_with_fresh_inference_vars(span, canonical); | |
615 | (infcx, value, subst) | |
74b04a01 XL |
616 | } |
617 | ||
2b03887a | 618 | pub fn build(&mut self) -> InferCtxt<'tcx> { |
064997fb FG |
619 | let InferCtxtBuilder { |
620 | tcx, | |
621 | defining_use_anchor, | |
622 | considering_regions, | |
f2b60f7d | 623 | ref normalize_fn_sig_for_diagnostic, |
064997fb | 624 | } = *self; |
2b03887a | 625 | InferCtxt { |
f035d41b | 626 | tcx, |
94222f64 | 627 | defining_use_anchor, |
064997fb | 628 | considering_regions, |
f035d41b XL |
629 | inner: RefCell::new(InferCtxtInner::new()), |
630 | lexical_region_resolutions: RefCell::new(None), | |
631 | selection_cache: Default::default(), | |
632 | evaluation_cache: Default::default(), | |
633 | reported_trait_errors: Default::default(), | |
634 | reported_closure_mismatch: Default::default(), | |
f2b60f7d | 635 | tainted_by_errors: Cell::new(None), |
f035d41b XL |
636 | err_count_on_creation: tcx.sess.err_count(), |
637 | in_snapshot: Cell::new(false), | |
638 | skip_leak_check: Cell::new(false), | |
639 | universe: Cell::new(ty::UniverseIndex::ROOT), | |
f2b60f7d FG |
640 | normalize_fn_sig_for_diagnostic: normalize_fn_sig_for_diagnostic |
641 | .as_ref() | |
642 | .map(|f| f.clone()), | |
2b03887a | 643 | } |
74b04a01 XL |
644 | } |
645 | } | |
646 | ||
647 | impl<'tcx, T> InferOk<'tcx, T> { | |
648 | pub fn unit(self) -> InferOk<'tcx, ()> { | |
649 | InferOk { value: (), obligations: self.obligations } | |
650 | } | |
651 | ||
652 | /// Extracts `value`, registering any obligations into `fulfill_cx`. | |
653 | pub fn into_value_registering_obligations( | |
654 | self, | |
2b03887a | 655 | infcx: &InferCtxt<'tcx>, |
74b04a01 XL |
656 | fulfill_cx: &mut dyn TraitEngine<'tcx>, |
657 | ) -> T { | |
658 | let InferOk { value, obligations } = self; | |
064997fb | 659 | fulfill_cx.register_predicate_obligations(infcx, obligations); |
74b04a01 XL |
660 | value |
661 | } | |
662 | } | |
663 | ||
664 | impl<'tcx> InferOk<'tcx, ()> { | |
665 | pub fn into_obligations(self) -> PredicateObligations<'tcx> { | |
666 | self.obligations | |
667 | } | |
668 | } | |
669 | ||
670 | #[must_use = "once you start a snapshot, you should always consume it"] | |
2b03887a | 671 | pub struct CombinedSnapshot<'tcx> { |
f9f354fc | 672 | undo_snapshot: Snapshot<'tcx>, |
74b04a01 | 673 | region_constraints_snapshot: RegionSnapshot, |
74b04a01 XL |
674 | universe: ty::UniverseIndex, |
675 | was_in_snapshot: bool, | |
74b04a01 XL |
676 | } |
677 | ||
2b03887a FG |
678 | impl<'tcx> InferCtxt<'tcx> { |
679 | /// Creates a `TypeErrCtxt` for emitting various inference errors. | |
680 | /// During typeck, use `FnCtxt::infer_err` instead. | |
681 | pub fn err_ctxt(&self) -> TypeErrCtxt<'_, 'tcx> { | |
682 | TypeErrCtxt { infcx: self, typeck_results: None } | |
683 | } | |
684 | ||
94222f64 XL |
685 | /// calls `tcx.try_unify_abstract_consts` after |
686 | /// canonicalizing the consts. | |
5e7ed085 | 687 | #[instrument(skip(self), level = "debug")] |
94222f64 XL |
688 | pub fn try_unify_abstract_consts( |
689 | &self, | |
2b03887a FG |
690 | a: ty::UnevaluatedConst<'tcx>, |
691 | b: ty::UnevaluatedConst<'tcx>, | |
5e7ed085 | 692 | param_env: ty::ParamEnv<'tcx>, |
94222f64 | 693 | ) -> bool { |
5e7ed085 FG |
694 | // Reject any attempt to unify two unevaluated constants that contain inference |
695 | // variables, since inference variables in queries lead to ICEs. | |
2b03887a FG |
696 | if a.substs.has_non_region_infer() |
697 | || b.substs.has_non_region_infer() | |
698 | || param_env.has_non_region_infer() | |
5e7ed085 FG |
699 | { |
700 | debug!("a or b or param_env contain infer vars in its substs -> cannot unify"); | |
701 | return false; | |
702 | } | |
703 | ||
704 | let param_env_and = param_env.and((a, b)); | |
705 | let erased = self.tcx.erase_regions(param_env_and); | |
706 | debug!("after erase_regions: {:?}", erased); | |
94222f64 | 707 | |
5e7ed085 | 708 | self.tcx.try_unify_abstract_consts(erased) |
94222f64 XL |
709 | } |
710 | ||
74b04a01 XL |
711 | pub fn is_in_snapshot(&self) -> bool { |
712 | self.in_snapshot.get() | |
713 | } | |
714 | ||
715 | pub fn freshen<T: TypeFoldable<'tcx>>(&self, t: T) -> T { | |
716 | t.fold_with(&mut self.freshener()) | |
717 | } | |
718 | ||
94222f64 XL |
719 | /// Returns the origin of the type variable identified by `vid`, or `None` |
720 | /// if this is not a type variable. | |
721 | /// | |
722 | /// No attempt is made to resolve `ty`. | |
2b03887a | 723 | pub fn type_var_origin(&self, ty: Ty<'tcx>) -> Option<TypeVariableOrigin> { |
94222f64 XL |
724 | match *ty.kind() { |
725 | ty::Infer(ty::TyVar(vid)) => { | |
726 | Some(*self.inner.borrow_mut().type_variables().var_origin(vid)) | |
727 | } | |
728 | _ => None, | |
74b04a01 XL |
729 | } |
730 | } | |
731 | ||
732 | pub fn freshener<'b>(&'b self) -> TypeFreshener<'b, 'tcx> { | |
136023e0 XL |
733 | freshen::TypeFreshener::new(self, false) |
734 | } | |
735 | ||
736 | /// Like `freshener`, but does not replace `'static` regions. | |
737 | pub fn freshener_keep_static<'b>(&'b self) -> TypeFreshener<'b, 'tcx> { | |
738 | freshen::TypeFreshener::new(self, true) | |
74b04a01 XL |
739 | } |
740 | ||
74b04a01 XL |
741 | pub fn unsolved_variables(&self) -> Vec<Ty<'tcx>> { |
742 | let mut inner = self.inner.borrow_mut(); | |
74b04a01 | 743 | let mut vars: Vec<Ty<'_>> = inner |
f9f354fc | 744 | .type_variables() |
74b04a01 XL |
745 | .unsolved_variables() |
746 | .into_iter() | |
747 | .map(|t| self.tcx.mk_ty_var(t)) | |
748 | .collect(); | |
749 | vars.extend( | |
f9f354fc | 750 | (0..inner.int_unification_table().len()) |
74b04a01 | 751 | .map(|i| ty::IntVid { index: i as u32 }) |
f9f354fc | 752 | .filter(|&vid| inner.int_unification_table().probe_value(vid).is_none()) |
74b04a01 XL |
753 | .map(|v| self.tcx.mk_int_var(v)), |
754 | ); | |
755 | vars.extend( | |
f9f354fc | 756 | (0..inner.float_unification_table().len()) |
74b04a01 | 757 | .map(|i| ty::FloatVid { index: i as u32 }) |
f9f354fc | 758 | .filter(|&vid| inner.float_unification_table().probe_value(vid).is_none()) |
74b04a01 XL |
759 | .map(|v| self.tcx.mk_float_var(v)), |
760 | ); | |
761 | vars | |
762 | } | |
763 | ||
2b03887a | 764 | fn combine_fields<'a>( |
74b04a01 XL |
765 | &'a self, |
766 | trace: TypeTrace<'tcx>, | |
767 | param_env: ty::ParamEnv<'tcx>, | |
5e7ed085 | 768 | define_opaque_types: bool, |
74b04a01 XL |
769 | ) -> CombineFields<'a, 'tcx> { |
770 | CombineFields { | |
771 | infcx: self, | |
772 | trace, | |
773 | cause: None, | |
774 | param_env, | |
775 | obligations: PredicateObligations::new(), | |
5e7ed085 | 776 | define_opaque_types, |
74b04a01 XL |
777 | } |
778 | } | |
779 | ||
780 | /// Clear the "currently in a snapshot" flag, invoke the closure, | |
781 | /// then restore the flag to its original value. This flag is a | |
782 | /// debugging measure designed to detect cases where we start a | |
783 | /// snapshot, create type variables, and register obligations | |
784 | /// which may involve those type variables in the fulfillment cx, | |
785 | /// potentially leaving "dangling type variables" behind. | |
786 | /// In such cases, an assertion will fail when attempting to | |
787 | /// register obligations, within a snapshot. Very useful, much | |
788 | /// better than grovelling through megabytes of `RUSTC_LOG` output. | |
789 | /// | |
790 | /// HOWEVER, in some cases the flag is unhelpful. In particular, we | |
791 | /// sometimes create a "mini-fulfilment-cx" in which we enroll | |
792 | /// obligations. As long as this fulfillment cx is fully drained | |
793 | /// before we return, this is not a problem, as there won't be any | |
794 | /// escaping obligations in the main cx. In those cases, you can | |
795 | /// use this function. | |
796 | pub fn save_and_restore_in_snapshot_flag<F, R>(&self, func: F) -> R | |
797 | where | |
798 | F: FnOnce(&Self) -> R, | |
799 | { | |
800 | let flag = self.in_snapshot.replace(false); | |
801 | let result = func(self); | |
802 | self.in_snapshot.set(flag); | |
803 | result | |
804 | } | |
805 | ||
2b03887a | 806 | fn start_snapshot(&self) -> CombinedSnapshot<'tcx> { |
74b04a01 XL |
807 | debug!("start_snapshot()"); |
808 | ||
809 | let in_snapshot = self.in_snapshot.replace(true); | |
810 | ||
811 | let mut inner = self.inner.borrow_mut(); | |
f9f354fc | 812 | |
74b04a01 | 813 | CombinedSnapshot { |
f9f354fc | 814 | undo_snapshot: inner.undo_log.start_snapshot(), |
74b04a01 | 815 | region_constraints_snapshot: inner.unwrap_region_constraints().start_snapshot(), |
74b04a01 XL |
816 | universe: self.universe(), |
817 | was_in_snapshot: in_snapshot, | |
74b04a01 XL |
818 | } |
819 | } | |
820 | ||
c295e0f8 | 821 | #[instrument(skip(self, snapshot), level = "debug")] |
2b03887a | 822 | fn rollback_to(&self, cause: &str, snapshot: CombinedSnapshot<'tcx>) { |
74b04a01 | 823 | let CombinedSnapshot { |
f9f354fc | 824 | undo_snapshot, |
74b04a01 | 825 | region_constraints_snapshot, |
74b04a01 XL |
826 | universe, |
827 | was_in_snapshot, | |
74b04a01 XL |
828 | } = snapshot; |
829 | ||
830 | self.in_snapshot.set(was_in_snapshot); | |
831 | self.universe.set(universe); | |
74b04a01 XL |
832 | |
833 | let mut inner = self.inner.borrow_mut(); | |
f9f354fc | 834 | inner.rollback_to(undo_snapshot); |
74b04a01 | 835 | inner.unwrap_region_constraints().rollback_to(region_constraints_snapshot); |
74b04a01 XL |
836 | } |
837 | ||
c295e0f8 | 838 | #[instrument(skip(self, snapshot), level = "debug")] |
2b03887a | 839 | fn commit_from(&self, snapshot: CombinedSnapshot<'tcx>) { |
74b04a01 | 840 | let CombinedSnapshot { |
f9f354fc XL |
841 | undo_snapshot, |
842 | region_constraints_snapshot: _, | |
74b04a01 XL |
843 | universe: _, |
844 | was_in_snapshot, | |
74b04a01 XL |
845 | } = snapshot; |
846 | ||
847 | self.in_snapshot.set(was_in_snapshot); | |
74b04a01 | 848 | |
f9f354fc | 849 | self.inner.borrow_mut().commit(undo_snapshot); |
74b04a01 XL |
850 | } |
851 | ||
74b04a01 | 852 | /// Execute `f` and commit the bindings if closure `f` returns `Ok(_)`. |
c295e0f8 | 853 | #[instrument(skip(self, f), level = "debug")] |
74b04a01 XL |
854 | pub fn commit_if_ok<T, E, F>(&self, f: F) -> Result<T, E> |
855 | where | |
2b03887a | 856 | F: FnOnce(&CombinedSnapshot<'tcx>) -> Result<T, E>, |
74b04a01 | 857 | { |
74b04a01 XL |
858 | let snapshot = self.start_snapshot(); |
859 | let r = f(&snapshot); | |
860 | debug!("commit_if_ok() -- r.is_ok() = {}", r.is_ok()); | |
861 | match r { | |
862 | Ok(_) => { | |
863 | self.commit_from(snapshot); | |
864 | } | |
865 | Err(_) => { | |
866 | self.rollback_to("commit_if_ok -- error", snapshot); | |
867 | } | |
868 | } | |
869 | r | |
870 | } | |
871 | ||
872 | /// Execute `f` then unroll any bindings it creates. | |
c295e0f8 | 873 | #[instrument(skip(self, f), level = "debug")] |
74b04a01 XL |
874 | pub fn probe<R, F>(&self, f: F) -> R |
875 | where | |
2b03887a | 876 | F: FnOnce(&CombinedSnapshot<'tcx>) -> R, |
74b04a01 | 877 | { |
74b04a01 XL |
878 | let snapshot = self.start_snapshot(); |
879 | let r = f(&snapshot); | |
880 | self.rollback_to("probe", snapshot); | |
881 | r | |
882 | } | |
883 | ||
884 | /// If `should_skip` is true, then execute `f` then unroll any bindings it creates. | |
c295e0f8 | 885 | #[instrument(skip(self, f), level = "debug")] |
74b04a01 XL |
886 | pub fn probe_maybe_skip_leak_check<R, F>(&self, should_skip: bool, f: F) -> R |
887 | where | |
2b03887a | 888 | F: FnOnce(&CombinedSnapshot<'tcx>) -> R, |
74b04a01 | 889 | { |
74b04a01 | 890 | let snapshot = self.start_snapshot(); |
f9f354fc XL |
891 | let was_skip_leak_check = self.skip_leak_check.get(); |
892 | if should_skip { | |
893 | self.skip_leak_check.set(true); | |
894 | } | |
74b04a01 XL |
895 | let r = f(&snapshot); |
896 | self.rollback_to("probe", snapshot); | |
f9f354fc | 897 | self.skip_leak_check.set(was_skip_leak_check); |
74b04a01 XL |
898 | r |
899 | } | |
900 | ||
901 | /// Scan the constraints produced since `snapshot` began and returns: | |
902 | /// | |
903 | /// - `None` -- if none of them involve "region outlives" constraints | |
904 | /// - `Some(true)` -- if there are `'a: 'b` constraints where `'a` or `'b` is a placeholder | |
905 | /// - `Some(false)` -- if there are `'a: 'b` constraints but none involve placeholders | |
906 | pub fn region_constraints_added_in_snapshot( | |
907 | &self, | |
2b03887a | 908 | snapshot: &CombinedSnapshot<'tcx>, |
74b04a01 XL |
909 | ) -> Option<bool> { |
910 | self.inner | |
911 | .borrow_mut() | |
912 | .unwrap_region_constraints() | |
f9f354fc | 913 | .region_constraints_added_in_snapshot(&snapshot.undo_snapshot) |
74b04a01 XL |
914 | } |
915 | ||
2b03887a | 916 | pub fn opaque_types_added_in_snapshot(&self, snapshot: &CombinedSnapshot<'tcx>) -> bool { |
04454e1e FG |
917 | self.inner.borrow().undo_log.opaque_types_in_snapshot(&snapshot.undo_snapshot) |
918 | } | |
919 | ||
74b04a01 XL |
920 | pub fn add_given(&self, sub: ty::Region<'tcx>, sup: ty::RegionVid) { |
921 | self.inner.borrow_mut().unwrap_region_constraints().add_given(sub, sup); | |
922 | } | |
923 | ||
924 | pub fn can_sub<T>(&self, param_env: ty::ParamEnv<'tcx>, a: T, b: T) -> UnitResult<'tcx> | |
925 | where | |
926 | T: at::ToTrace<'tcx>, | |
927 | { | |
928 | let origin = &ObligationCause::dummy(); | |
929 | self.probe(|_| { | |
930 | self.at(origin, param_env).sub(a, b).map(|InferOk { obligations: _, .. }| { | |
931 | // Ignore obligations, since we are unrolling | |
932 | // everything anyway. | |
933 | }) | |
934 | }) | |
935 | } | |
936 | ||
937 | pub fn can_eq<T>(&self, param_env: ty::ParamEnv<'tcx>, a: T, b: T) -> UnitResult<'tcx> | |
938 | where | |
939 | T: at::ToTrace<'tcx>, | |
940 | { | |
941 | let origin = &ObligationCause::dummy(); | |
942 | self.probe(|_| { | |
943 | self.at(origin, param_env).eq(a, b).map(|InferOk { obligations: _, .. }| { | |
944 | // Ignore obligations, since we are unrolling | |
945 | // everything anyway. | |
946 | }) | |
947 | }) | |
948 | } | |
949 | ||
c295e0f8 | 950 | #[instrument(skip(self), level = "debug")] |
74b04a01 XL |
951 | pub fn sub_regions( |
952 | &self, | |
953 | origin: SubregionOrigin<'tcx>, | |
954 | a: ty::Region<'tcx>, | |
955 | b: ty::Region<'tcx>, | |
956 | ) { | |
74b04a01 XL |
957 | self.inner.borrow_mut().unwrap_region_constraints().make_subregion(origin, a, b); |
958 | } | |
959 | ||
960 | /// Require that the region `r` be equal to one of the regions in | |
961 | /// the set `regions`. | |
c295e0f8 | 962 | #[instrument(skip(self), level = "debug")] |
74b04a01 XL |
963 | pub fn member_constraint( |
964 | &self, | |
064997fb | 965 | key: ty::OpaqueTypeKey<'tcx>, |
74b04a01 XL |
966 | definition_span: Span, |
967 | hidden_ty: Ty<'tcx>, | |
968 | region: ty::Region<'tcx>, | |
969 | in_regions: &Lrc<Vec<ty::Region<'tcx>>>, | |
970 | ) { | |
74b04a01 | 971 | self.inner.borrow_mut().unwrap_region_constraints().member_constraint( |
064997fb | 972 | key, |
74b04a01 XL |
973 | definition_span, |
974 | hidden_ty, | |
975 | region, | |
976 | in_regions, | |
977 | ); | |
978 | } | |
979 | ||
94222f64 XL |
980 | /// Processes a `Coerce` predicate from the fulfillment context. |
981 | /// This is NOT the preferred way to handle coercion, which is to | |
982 | /// invoke `FnCtxt::coerce` or a similar method (see `coercion.rs`). | |
983 | /// | |
984 | /// This method here is actually a fallback that winds up being | |
985 | /// invoked when `FnCtxt::coerce` encounters unresolved type variables | |
986 | /// and records a coercion predicate. Presently, this method is equivalent | |
987 | /// to `subtype_predicate` -- that is, "coercing" `a` to `b` winds up | |
988 | /// actually requiring `a <: b`. This is of course a valid coercion, | |
989 | /// but it's not as flexible as `FnCtxt::coerce` would be. | |
990 | /// | |
991 | /// (We may refactor this in the future, but there are a number of | |
992 | /// practical obstacles. Among other things, `FnCtxt::coerce` presently | |
993 | /// records adjustments that are required on the HIR in order to perform | |
994 | /// the coercion, and we don't currently have a way to manage that.) | |
995 | pub fn coerce_predicate( | |
996 | &self, | |
997 | cause: &ObligationCause<'tcx>, | |
998 | param_env: ty::ParamEnv<'tcx>, | |
999 | predicate: ty::PolyCoercePredicate<'tcx>, | |
f2b60f7d | 1000 | ) -> Result<InferResult<'tcx, ()>, (TyVid, TyVid)> { |
94222f64 XL |
1001 | let subtype_predicate = predicate.map_bound(|p| ty::SubtypePredicate { |
1002 | a_is_expected: false, // when coercing from `a` to `b`, `b` is expected | |
1003 | a: p.a, | |
1004 | b: p.b, | |
1005 | }); | |
1006 | self.subtype_predicate(cause, param_env, subtype_predicate) | |
1007 | } | |
1008 | ||
74b04a01 XL |
1009 | pub fn subtype_predicate( |
1010 | &self, | |
1011 | cause: &ObligationCause<'tcx>, | |
1012 | param_env: ty::ParamEnv<'tcx>, | |
f9f354fc | 1013 | predicate: ty::PolySubtypePredicate<'tcx>, |
f2b60f7d | 1014 | ) -> Result<InferResult<'tcx, ()>, (TyVid, TyVid)> { |
94222f64 XL |
1015 | // Check for two unresolved inference variables, in which case we can |
1016 | // make no progress. This is partly a micro-optimization, but it's | |
1017 | // also an opportunity to "sub-unify" the variables. This isn't | |
1018 | // *necessary* to prevent cycles, because they would eventually be sub-unified | |
1019 | // anyhow during generalization, but it helps with diagnostics (we can detect | |
1020 | // earlier that they are sub-unified). | |
1021 | // | |
1022 | // Note that we can just skip the binders here because | |
1023 | // type variables can't (at present, at | |
74b04a01 XL |
1024 | // least) capture any of the things bound by this binder. |
1025 | // | |
94222f64 XL |
1026 | // Note that this sub here is not just for diagnostics - it has semantic |
1027 | // effects as well. | |
1028 | let r_a = self.shallow_resolve(predicate.skip_binder().a); | |
1029 | let r_b = self.shallow_resolve(predicate.skip_binder().b); | |
1030 | match (r_a.kind(), r_b.kind()) { | |
1031 | (&ty::Infer(ty::TyVar(a_vid)), &ty::Infer(ty::TyVar(b_vid))) => { | |
1032 | self.inner.borrow_mut().type_variables().sub(a_vid, b_vid); | |
f2b60f7d | 1033 | return Err((a_vid, b_vid)); |
94222f64 XL |
1034 | } |
1035 | _ => {} | |
74b04a01 XL |
1036 | } |
1037 | ||
f2b60f7d | 1038 | Ok(self.commit_if_ok(|_snapshot| { |
29967ef6 | 1039 | let ty::SubtypePredicate { a_is_expected, a, b } = |
fc512014 | 1040 | self.replace_bound_vars_with_placeholders(predicate); |
74b04a01 XL |
1041 | |
1042 | let ok = self.at(cause, param_env).sub_exp(a_is_expected, a, b)?; | |
1043 | ||
74b04a01 XL |
1044 | Ok(ok.unit()) |
1045 | })) | |
1046 | } | |
1047 | ||
1048 | pub fn region_outlives_predicate( | |
1049 | &self, | |
1050 | cause: &traits::ObligationCause<'tcx>, | |
f9f354fc | 1051 | predicate: ty::PolyRegionOutlivesPredicate<'tcx>, |
064997fb FG |
1052 | ) { |
1053 | let ty::OutlivesPredicate(r_a, r_b) = self.replace_bound_vars_with_placeholders(predicate); | |
1054 | let origin = | |
1055 | SubregionOrigin::from_obligation_cause(cause, || RelateRegionParamBound(cause.span)); | |
1056 | self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b` | |
74b04a01 XL |
1057 | } |
1058 | ||
c295e0f8 XL |
1059 | /// Number of type variables created so far. |
1060 | pub fn num_ty_vars(&self) -> usize { | |
1061 | self.inner.borrow_mut().type_variables().num_vars() | |
1062 | } | |
1063 | ||
1064 | pub fn next_ty_var_id(&self, origin: TypeVariableOrigin) -> TyVid { | |
1065 | self.inner.borrow_mut().type_variables().new_var(self.universe(), origin) | |
74b04a01 XL |
1066 | } |
1067 | ||
1068 | pub fn next_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> { | |
c295e0f8 | 1069 | self.tcx.mk_ty_var(self.next_ty_var_id(origin)) |
74b04a01 XL |
1070 | } |
1071 | ||
5e7ed085 FG |
1072 | pub fn next_ty_var_id_in_universe( |
1073 | &self, | |
1074 | origin: TypeVariableOrigin, | |
1075 | universe: ty::UniverseIndex, | |
1076 | ) -> TyVid { | |
1077 | self.inner.borrow_mut().type_variables().new_var(universe, origin) | |
1078 | } | |
1079 | ||
74b04a01 XL |
1080 | pub fn next_ty_var_in_universe( |
1081 | &self, | |
1082 | origin: TypeVariableOrigin, | |
1083 | universe: ty::UniverseIndex, | |
1084 | ) -> Ty<'tcx> { | |
5e7ed085 | 1085 | let vid = self.next_ty_var_id_in_universe(origin, universe); |
74b04a01 XL |
1086 | self.tcx.mk_ty_var(vid) |
1087 | } | |
1088 | ||
5099ac24 | 1089 | pub fn next_const_var(&self, ty: Ty<'tcx>, origin: ConstVariableOrigin) -> ty::Const<'tcx> { |
74b04a01 XL |
1090 | self.tcx.mk_const_var(self.next_const_var_id(origin), ty) |
1091 | } | |
1092 | ||
1093 | pub fn next_const_var_in_universe( | |
1094 | &self, | |
1095 | ty: Ty<'tcx>, | |
1096 | origin: ConstVariableOrigin, | |
1097 | universe: ty::UniverseIndex, | |
5099ac24 | 1098 | ) -> ty::Const<'tcx> { |
74b04a01 XL |
1099 | let vid = self |
1100 | .inner | |
1101 | .borrow_mut() | |
f9f354fc | 1102 | .const_unification_table() |
74b04a01 XL |
1103 | .new_key(ConstVarValue { origin, val: ConstVariableValue::Unknown { universe } }); |
1104 | self.tcx.mk_const_var(vid, ty) | |
1105 | } | |
1106 | ||
1107 | pub fn next_const_var_id(&self, origin: ConstVariableOrigin) -> ConstVid<'tcx> { | |
f9f354fc | 1108 | self.inner.borrow_mut().const_unification_table().new_key(ConstVarValue { |
74b04a01 XL |
1109 | origin, |
1110 | val: ConstVariableValue::Unknown { universe: self.universe() }, | |
1111 | }) | |
1112 | } | |
1113 | ||
1114 | fn next_int_var_id(&self) -> IntVid { | |
f9f354fc | 1115 | self.inner.borrow_mut().int_unification_table().new_key(None) |
74b04a01 XL |
1116 | } |
1117 | ||
1118 | pub fn next_int_var(&self) -> Ty<'tcx> { | |
1119 | self.tcx.mk_int_var(self.next_int_var_id()) | |
1120 | } | |
1121 | ||
1122 | fn next_float_var_id(&self) -> FloatVid { | |
f9f354fc | 1123 | self.inner.borrow_mut().float_unification_table().new_key(None) |
74b04a01 XL |
1124 | } |
1125 | ||
1126 | pub fn next_float_var(&self) -> Ty<'tcx> { | |
1127 | self.tcx.mk_float_var(self.next_float_var_id()) | |
1128 | } | |
1129 | ||
1130 | /// Creates a fresh region variable with the next available index. | |
1131 | /// The variable will be created in the maximum universe created | |
1132 | /// thus far, allowing it to name any region created thus far. | |
1133 | pub fn next_region_var(&self, origin: RegionVariableOrigin) -> ty::Region<'tcx> { | |
1134 | self.next_region_var_in_universe(origin, self.universe()) | |
1135 | } | |
1136 | ||
1137 | /// Creates a fresh region variable with the next available index | |
1138 | /// in the given universe; typically, you can use | |
1139 | /// `next_region_var` and just use the maximal universe. | |
1140 | pub fn next_region_var_in_universe( | |
1141 | &self, | |
1142 | origin: RegionVariableOrigin, | |
1143 | universe: ty::UniverseIndex, | |
1144 | ) -> ty::Region<'tcx> { | |
1145 | let region_var = | |
1146 | self.inner.borrow_mut().unwrap_region_constraints().new_region_var(universe, origin); | |
1147 | self.tcx.mk_region(ty::ReVar(region_var)) | |
1148 | } | |
1149 | ||
1150 | /// Return the universe that the region `r` was created in. For | |
1151 | /// most regions (e.g., `'static`, named regions from the user, | |
1152 | /// etc) this is the root universe U0. For inference variables or | |
2b03887a FG |
1153 | /// placeholders, however, it will return the universe which they |
1154 | /// are associated. | |
94222f64 | 1155 | pub fn universe_of_region(&self, r: ty::Region<'tcx>) -> ty::UniverseIndex { |
74b04a01 XL |
1156 | self.inner.borrow_mut().unwrap_region_constraints().universe(r) |
1157 | } | |
1158 | ||
1159 | /// Number of region variables created so far. | |
1160 | pub fn num_region_vars(&self) -> usize { | |
1161 | self.inner.borrow_mut().unwrap_region_constraints().num_region_vars() | |
1162 | } | |
1163 | ||
1164 | /// Just a convenient wrapper of `next_region_var` for using during NLL. | |
5869c6ff XL |
1165 | pub fn next_nll_region_var(&self, origin: NllRegionVariableOrigin) -> ty::Region<'tcx> { |
1166 | self.next_region_var(RegionVariableOrigin::Nll(origin)) | |
74b04a01 XL |
1167 | } |
1168 | ||
1169 | /// Just a convenient wrapper of `next_region_var` for using during NLL. | |
1170 | pub fn next_nll_region_var_in_universe( | |
1171 | &self, | |
5869c6ff | 1172 | origin: NllRegionVariableOrigin, |
74b04a01 XL |
1173 | universe: ty::UniverseIndex, |
1174 | ) -> ty::Region<'tcx> { | |
5869c6ff | 1175 | self.next_region_var_in_universe(RegionVariableOrigin::Nll(origin), universe) |
74b04a01 XL |
1176 | } |
1177 | ||
1178 | pub fn var_for_def(&self, span: Span, param: &ty::GenericParamDef) -> GenericArg<'tcx> { | |
1179 | match param.kind { | |
1180 | GenericParamDefKind::Lifetime => { | |
1181 | // Create a region inference variable for the given | |
1182 | // region parameter definition. | |
1183 | self.next_region_var(EarlyBoundRegion(span, param.name)).into() | |
1184 | } | |
1185 | GenericParamDefKind::Type { .. } => { | |
1186 | // Create a type inference variable for the given | |
1187 | // type parameter definition. The substitutions are | |
1188 | // for actual parameters that may be referred to by | |
1189 | // the default of this type parameter, if it exists. | |
1190 | // e.g., `struct Foo<A, B, C = (A, B)>(...);` when | |
1191 | // used in a path such as `Foo::<T, U>::new()` will | |
1192 | // use an inference variable for `C` with `[T, U]` | |
1193 | // as the substitutions for the default, `(T, U)`. | |
f9f354fc | 1194 | let ty_var_id = self.inner.borrow_mut().type_variables().new_var( |
74b04a01 | 1195 | self.universe(), |
74b04a01 XL |
1196 | TypeVariableOrigin { |
1197 | kind: TypeVariableOriginKind::TypeParameterDefinition( | |
1198 | param.name, | |
1199 | Some(param.def_id), | |
1200 | ), | |
1201 | span, | |
1202 | }, | |
1203 | ); | |
1204 | ||
1205 | self.tcx.mk_ty_var(ty_var_id).into() | |
1206 | } | |
1207 | GenericParamDefKind::Const { .. } => { | |
1208 | let origin = ConstVariableOrigin { | |
1b1a35ee XL |
1209 | kind: ConstVariableOriginKind::ConstParameterDefinition( |
1210 | param.name, | |
1211 | param.def_id, | |
1212 | ), | |
74b04a01 XL |
1213 | span, |
1214 | }; | |
1215 | let const_var_id = | |
f9f354fc | 1216 | self.inner.borrow_mut().const_unification_table().new_key(ConstVarValue { |
74b04a01 XL |
1217 | origin, |
1218 | val: ConstVariableValue::Unknown { universe: self.universe() }, | |
1219 | }); | |
1220 | self.tcx.mk_const_var(const_var_id, self.tcx.type_of(param.def_id)).into() | |
1221 | } | |
1222 | } | |
1223 | } | |
1224 | ||
1225 | /// Given a set of generics defined on a type or impl, returns a substitution mapping each | |
1226 | /// type/region parameter to a fresh inference variable. | |
1227 | pub fn fresh_substs_for_item(&self, span: Span, def_id: DefId) -> SubstsRef<'tcx> { | |
1228 | InternalSubsts::for_item(self.tcx, def_id, |param, _| self.var_for_def(span, param)) | |
1229 | } | |
1230 | ||
1231 | /// Returns `true` if errors have been reported since this infcx was | |
1232 | /// created. This is sometimes used as a heuristic to skip | |
1233 | /// reporting errors that often occur as a result of earlier | |
1234 | /// errors, but where it's hard to be 100% sure (e.g., unresolved | |
1235 | /// inference variables, regionck errors). | |
1236 | pub fn is_tainted_by_errors(&self) -> bool { | |
1237 | debug!( | |
1238 | "is_tainted_by_errors(err_count={}, err_count_on_creation={}, \ | |
f2b60f7d | 1239 | tainted_by_errors={})", |
74b04a01 XL |
1240 | self.tcx.sess.err_count(), |
1241 | self.err_count_on_creation, | |
f2b60f7d | 1242 | self.tainted_by_errors.get().is_some() |
74b04a01 XL |
1243 | ); |
1244 | ||
1245 | if self.tcx.sess.err_count() > self.err_count_on_creation { | |
1246 | return true; // errors reported since this infcx was made | |
1247 | } | |
f2b60f7d | 1248 | self.tainted_by_errors.get().is_some() |
74b04a01 XL |
1249 | } |
1250 | ||
1251 | /// Set the "tainted by errors" flag to true. We call this when we | |
1252 | /// observe an error from a prior pass. | |
1253 | pub fn set_tainted_by_errors(&self) { | |
1254 | debug!("set_tainted_by_errors()"); | |
f2b60f7d FG |
1255 | self.tainted_by_errors.set(Some( |
1256 | self.tcx.sess.delay_span_bug(DUMMY_SP, "`InferCtxt` incorrectly tainted by errors"), | |
1257 | )); | |
74b04a01 XL |
1258 | } |
1259 | ||
923072b8 FG |
1260 | pub fn skip_region_resolution(&self) { |
1261 | let (var_infos, _) = { | |
1262 | let mut inner = self.inner.borrow_mut(); | |
1263 | let inner = &mut *inner; | |
1264 | // Note: `inner.region_obligations` may not be empty, because we | |
1265 | // didn't necessarily call `process_registered_region_obligations`. | |
1266 | // This is okay, because that doesn't introduce new vars. | |
1267 | inner | |
1268 | .region_constraint_storage | |
1269 | .take() | |
1270 | .expect("regions already resolved") | |
1271 | .with_log(&mut inner.undo_log) | |
1272 | .into_infos_and_data() | |
1273 | }; | |
1274 | ||
1275 | let lexical_region_resolutions = LexicalRegionResolutions { | |
923072b8 FG |
1276 | values: rustc_index::vec::IndexVec::from_elem_n( |
1277 | crate::infer::lexical_region_resolve::VarValue::Value(self.tcx.lifetimes.re_erased), | |
1278 | var_infos.len(), | |
1279 | ), | |
1280 | }; | |
1281 | ||
1282 | let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions)); | |
1283 | assert!(old_value.is_none()); | |
1284 | } | |
1285 | ||
2b03887a | 1286 | /// Process the region constraints and return any errors that |
74b04a01 XL |
1287 | /// result. After this, no more unification operations should be |
1288 | /// done -- or the compiler will panic -- but it is legal to use | |
1289 | /// `resolve_vars_if_possible` as well as `fully_resolve`. | |
3c0e092e | 1290 | pub fn resolve_regions( |
74b04a01 | 1291 | &self, |
74b04a01 | 1292 | outlives_env: &OutlivesEnvironment<'tcx>, |
3c0e092e | 1293 | ) -> Vec<RegionResolutionError<'tcx>> { |
f9f354fc XL |
1294 | let (var_infos, data) = { |
1295 | let mut inner = self.inner.borrow_mut(); | |
1296 | let inner = &mut *inner; | |
1297 | assert!( | |
1298 | self.is_tainted_by_errors() || inner.region_obligations.is_empty(), | |
1299 | "region_obligations not empty: {:#?}", | |
1300 | inner.region_obligations | |
1301 | ); | |
1302 | inner | |
1303 | .region_constraint_storage | |
1304 | .take() | |
1305 | .expect("regions already resolved") | |
1306 | .with_log(&mut inner.undo_log) | |
1307 | .into_infos_and_data() | |
1308 | }; | |
ba9703b0 | 1309 | |
064997fb | 1310 | let region_rels = &RegionRelations::new(self.tcx, outlives_env.free_region_map()); |
ba9703b0 | 1311 | |
74b04a01 | 1312 | let (lexical_region_resolutions, errors) = |
923072b8 | 1313 | lexical_region_resolve::resolve(outlives_env.param_env, region_rels, var_infos, data); |
74b04a01 XL |
1314 | |
1315 | let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions)); | |
1316 | assert!(old_value.is_none()); | |
1317 | ||
3c0e092e XL |
1318 | errors |
1319 | } | |
74b04a01 XL |
1320 | /// Obtains (and clears) the current set of region |
1321 | /// constraints. The inference context is still usable: further | |
1322 | /// unifications will simply add new constraints. | |
1323 | /// | |
1324 | /// This method is not meant to be used with normal lexical region | |
1325 | /// resolution. Rather, it is used in the NLL mode as a kind of | |
1326 | /// interim hack: basically we run normal type-check and generate | |
1327 | /// region constraints as normal, but then we take them and | |
1328 | /// translate them into the form that the NLL solver | |
1329 | /// understands. See the NLL module for mode details. | |
1330 | pub fn take_and_reset_region_constraints(&self) -> RegionConstraintData<'tcx> { | |
1331 | assert!( | |
1332 | self.inner.borrow().region_obligations.is_empty(), | |
1333 | "region_obligations not empty: {:#?}", | |
1334 | self.inner.borrow().region_obligations | |
1335 | ); | |
1336 | ||
1337 | self.inner.borrow_mut().unwrap_region_constraints().take_and_reset_data() | |
1338 | } | |
1339 | ||
1340 | /// Gives temporary access to the region constraint data. | |
74b04a01 XL |
1341 | pub fn with_region_constraints<R>( |
1342 | &self, | |
1343 | op: impl FnOnce(&RegionConstraintData<'tcx>) -> R, | |
1344 | ) -> R { | |
1345 | let mut inner = self.inner.borrow_mut(); | |
1346 | op(inner.unwrap_region_constraints().data()) | |
1347 | } | |
1348 | ||
94222f64 XL |
1349 | pub fn region_var_origin(&self, vid: ty::RegionVid) -> RegionVariableOrigin { |
1350 | let mut inner = self.inner.borrow_mut(); | |
1351 | let inner = &mut *inner; | |
1352 | inner | |
1353 | .region_constraint_storage | |
1354 | .as_mut() | |
1355 | .expect("regions already resolved") | |
1356 | .with_log(&mut inner.undo_log) | |
1357 | .var_origin(vid) | |
1358 | } | |
1359 | ||
74b04a01 XL |
1360 | /// Takes ownership of the list of variable regions. This implies |
1361 | /// that all the region constraints have already been taken, and | |
1362 | /// hence that `resolve_regions_and_report_errors` can never be | |
1363 | /// called. This is used only during NLL processing to "hand off" ownership | |
1364 | /// of the set of region variables into the NLL region context. | |
1365 | pub fn take_region_var_origins(&self) -> VarInfos { | |
f9f354fc XL |
1366 | let mut inner = self.inner.borrow_mut(); |
1367 | let (var_infos, data) = inner | |
1368 | .region_constraint_storage | |
74b04a01 XL |
1369 | .take() |
1370 | .expect("regions already resolved") | |
f9f354fc | 1371 | .with_log(&mut inner.undo_log) |
74b04a01 XL |
1372 | .into_infos_and_data(); |
1373 | assert!(data.is_empty()); | |
1374 | var_infos | |
1375 | } | |
1376 | ||
1377 | pub fn ty_to_string(&self, t: Ty<'tcx>) -> String { | |
fc512014 | 1378 | self.resolve_vars_if_possible(t).to_string() |
74b04a01 XL |
1379 | } |
1380 | ||
74b04a01 XL |
1381 | /// If `TyVar(vid)` resolves to a type, return that type. Else, return the |
1382 | /// universe index of `TyVar(vid)`. | |
1383 | pub fn probe_ty_var(&self, vid: TyVid) -> Result<Ty<'tcx>, ty::UniverseIndex> { | |
1384 | use self::type_variable::TypeVariableValue; | |
1385 | ||
f9f354fc | 1386 | match self.inner.borrow_mut().type_variables().probe(vid) { |
74b04a01 XL |
1387 | TypeVariableValue::Known { value } => Ok(value), |
1388 | TypeVariableValue::Unknown { universe } => Err(universe), | |
1389 | } | |
1390 | } | |
1391 | ||
1392 | /// Resolve any type variables found in `value` -- but only one | |
1393 | /// level. So, if the variable `?X` is bound to some type | |
1394 | /// `Foo<?Y>`, then this would return `Foo<?Y>` (but `?Y` may | |
1395 | /// itself be bound to a type). | |
1396 | /// | |
1397 | /// Useful when you only need to inspect the outermost level of | |
1398 | /// the type and don't care about nested types (or perhaps you | |
1399 | /// will be resolving them as well, e.g. in a loop). | |
1400 | pub fn shallow_resolve<T>(&self, value: T) -> T | |
1401 | where | |
1402 | T: TypeFoldable<'tcx>, | |
1403 | { | |
ba9703b0 | 1404 | value.fold_with(&mut ShallowResolver { infcx: self }) |
74b04a01 XL |
1405 | } |
1406 | ||
1407 | pub fn root_var(&self, var: ty::TyVid) -> ty::TyVid { | |
f9f354fc | 1408 | self.inner.borrow_mut().type_variables().root_var(var) |
74b04a01 XL |
1409 | } |
1410 | ||
1411 | /// Where possible, replaces type/const variables in | |
1412 | /// `value` with their final value. Note that region variables | |
1413 | /// are unaffected. If a type/const variable has not been unified, it | |
1414 | /// is left as is. This is an idempotent operation that does | |
1415 | /// not affect inference state in any way and so you can do it | |
1416 | /// at will. | |
fc512014 | 1417 | pub fn resolve_vars_if_possible<T>(&self, value: T) -> T |
74b04a01 XL |
1418 | where |
1419 | T: TypeFoldable<'tcx>, | |
1420 | { | |
1421 | if !value.needs_infer() { | |
5869c6ff | 1422 | return value; // Avoid duplicated subst-folding. |
74b04a01 XL |
1423 | } |
1424 | let mut r = resolve::OpportunisticVarResolver::new(self); | |
1425 | value.fold_with(&mut r) | |
1426 | } | |
1427 | ||
5e7ed085 FG |
1428 | pub fn resolve_numeric_literals_with_default<T>(&self, value: T) -> T |
1429 | where | |
1430 | T: TypeFoldable<'tcx>, | |
1431 | { | |
1432 | if !value.needs_infer() { | |
1433 | return value; // Avoid duplicated subst-folding. | |
1434 | } | |
1435 | let mut r = InferenceLiteralEraser { tcx: self.tcx }; | |
1436 | value.fold_with(&mut r) | |
1437 | } | |
1438 | ||
74b04a01 XL |
1439 | /// Returns the first unresolved variable contained in `T`. In the |
1440 | /// process of visiting `T`, this will resolve (where possible) | |
1441 | /// type variables in `T`, but it never constructs the final, | |
1442 | /// resolved type, so it's more efficient than | |
1443 | /// `resolve_vars_if_possible()`. | |
1444 | pub fn unresolved_type_vars<T>(&self, value: &T) -> Option<(Ty<'tcx>, Option<Span>)> | |
1445 | where | |
064997fb | 1446 | T: TypeVisitable<'tcx>, |
74b04a01 | 1447 | { |
fc512014 | 1448 | value.visit_with(&mut resolve::UnresolvedTypeFinder::new(self)).break_value() |
74b04a01 XL |
1449 | } |
1450 | ||
1451 | pub fn probe_const_var( | |
1452 | &self, | |
1453 | vid: ty::ConstVid<'tcx>, | |
5099ac24 | 1454 | ) -> Result<ty::Const<'tcx>, ty::UniverseIndex> { |
f9f354fc | 1455 | match self.inner.borrow_mut().const_unification_table().probe_value(vid).val { |
74b04a01 XL |
1456 | ConstVariableValue::Known { value } => Ok(value), |
1457 | ConstVariableValue::Unknown { universe } => Err(universe), | |
1458 | } | |
1459 | } | |
1460 | ||
fc512014 | 1461 | pub fn fully_resolve<T: TypeFoldable<'tcx>>(&self, value: T) -> FixupResult<'tcx, T> { |
74b04a01 XL |
1462 | /*! |
1463 | * Attempts to resolve all type/region/const variables in | |
1464 | * `value`. Region inference must have been run already (e.g., | |
1465 | * by calling `resolve_regions_and_report_errors`). If some | |
1466 | * variable was never unified, an `Err` results. | |
1467 | * | |
1468 | * This method is idempotent, but it not typically not invoked | |
1469 | * except during the writeback phase. | |
1470 | */ | |
1471 | ||
2b03887a FG |
1472 | let value = resolve::fully_resolve(self, value); |
1473 | assert!( | |
1474 | value.as_ref().map_or(true, |value| !value.needs_infer()), | |
1475 | "`{value:?}` is not fully resolved" | |
1476 | ); | |
1477 | value | |
f9f354fc XL |
1478 | } |
1479 | ||
74b04a01 XL |
1480 | pub fn replace_bound_vars_with_fresh_vars<T>( |
1481 | &self, | |
1482 | span: Span, | |
1483 | lbrct: LateBoundRegionConversionTime, | |
cdc7bbd5 | 1484 | value: ty::Binder<'tcx, T>, |
923072b8 | 1485 | ) -> T |
74b04a01 | 1486 | where |
923072b8 | 1487 | T: TypeFoldable<'tcx> + Copy, |
74b04a01 | 1488 | { |
923072b8 FG |
1489 | if let Some(inner) = value.no_bound_vars() { |
1490 | return inner; | |
1491 | } | |
1492 | ||
064997fb | 1493 | struct ToFreshVars<'a, 'tcx> { |
2b03887a | 1494 | infcx: &'a InferCtxt<'tcx>, |
064997fb FG |
1495 | span: Span, |
1496 | lbrct: LateBoundRegionConversionTime, | |
1497 | map: FxHashMap<ty::BoundVar, ty::GenericArg<'tcx>>, | |
1498 | } | |
923072b8 | 1499 | |
064997fb FG |
1500 | impl<'tcx> BoundVarReplacerDelegate<'tcx> for ToFreshVars<'_, 'tcx> { |
1501 | fn replace_region(&mut self, br: ty::BoundRegion) -> ty::Region<'tcx> { | |
1502 | self.map | |
1503 | .entry(br.var) | |
1504 | .or_insert_with(|| { | |
1505 | self.infcx | |
1506 | .next_region_var(LateBoundRegion(self.span, br.kind, self.lbrct)) | |
1507 | .into() | |
1508 | }) | |
1509 | .expect_region() | |
1510 | } | |
1511 | fn replace_ty(&mut self, bt: ty::BoundTy) -> Ty<'tcx> { | |
1512 | self.map | |
1513 | .entry(bt.var) | |
1514 | .or_insert_with(|| { | |
1515 | self.infcx | |
1516 | .next_ty_var(TypeVariableOrigin { | |
1517 | kind: TypeVariableOriginKind::MiscVariable, | |
1518 | span: self.span, | |
1519 | }) | |
1520 | .into() | |
1521 | }) | |
1522 | .expect_ty() | |
1523 | } | |
1524 | fn replace_const(&mut self, bv: ty::BoundVar, ty: Ty<'tcx>) -> ty::Const<'tcx> { | |
1525 | self.map | |
1526 | .entry(bv) | |
1527 | .or_insert_with(|| { | |
1528 | self.infcx | |
1529 | .next_const_var( | |
1530 | ty, | |
1531 | ConstVariableOrigin { | |
1532 | kind: ConstVariableOriginKind::MiscVariable, | |
1533 | span: self.span, | |
1534 | }, | |
1535 | ) | |
1536 | .into() | |
1537 | }) | |
1538 | .expect_const() | |
1539 | } | |
1540 | } | |
1541 | let delegate = ToFreshVars { infcx: self, span, lbrct, map: Default::default() }; | |
1542 | self.tcx.replace_bound_vars_uncached(value, delegate) | |
74b04a01 XL |
1543 | } |
1544 | ||
f9f354fc | 1545 | /// See the [`region_constraints::RegionConstraintCollector::verify_generic_bound`] method. |
74b04a01 XL |
1546 | pub fn verify_generic_bound( |
1547 | &self, | |
1548 | origin: SubregionOrigin<'tcx>, | |
1549 | kind: GenericKind<'tcx>, | |
1550 | a: ty::Region<'tcx>, | |
1551 | bound: VerifyBound<'tcx>, | |
1552 | ) { | |
1553 | debug!("verify_generic_bound({:?}, {:?} <: {:?})", kind, a, bound); | |
1554 | ||
1555 | self.inner | |
1556 | .borrow_mut() | |
1557 | .unwrap_region_constraints() | |
1558 | .verify_generic_bound(origin, kind, a, bound); | |
1559 | } | |
1560 | ||
74b04a01 XL |
1561 | /// Obtains the latest type of the given closure; this may be a |
1562 | /// closure in the current function, in which case its | |
1563 | /// `ClosureKind` may not yet be known. | |
ba9703b0 XL |
1564 | pub fn closure_kind(&self, closure_substs: SubstsRef<'tcx>) -> Option<ty::ClosureKind> { |
1565 | let closure_kind_ty = closure_substs.as_closure().kind_ty(); | |
74b04a01 XL |
1566 | let closure_kind_ty = self.shallow_resolve(closure_kind_ty); |
1567 | closure_kind_ty.to_opt_closure_kind() | |
1568 | } | |
1569 | ||
74b04a01 XL |
1570 | /// Clears the selection, evaluation, and projection caches. This is useful when |
1571 | /// repeatedly attempting to select an `Obligation` while changing only | |
1572 | /// its `ParamEnv`, since `FulfillmentContext` doesn't use probing. | |
1573 | pub fn clear_caches(&self) { | |
1574 | self.selection_cache.clear(); | |
1575 | self.evaluation_cache.clear(); | |
f9f354fc | 1576 | self.inner.borrow_mut().projection_cache().clear(); |
74b04a01 XL |
1577 | } |
1578 | ||
94222f64 | 1579 | pub fn universe(&self) -> ty::UniverseIndex { |
74b04a01 XL |
1580 | self.universe.get() |
1581 | } | |
1582 | ||
1583 | /// Creates and return a fresh universe that extends all previous | |
1584 | /// universes. Updates `self.universe` to that new universe. | |
1585 | pub fn create_next_universe(&self) -> ty::UniverseIndex { | |
1586 | let u = self.universe.get().next_universe(); | |
1587 | self.universe.set(u); | |
1588 | u | |
1589 | } | |
1590 | ||
923072b8 FG |
1591 | pub fn try_const_eval_resolve( |
1592 | &self, | |
1593 | param_env: ty::ParamEnv<'tcx>, | |
2b03887a | 1594 | unevaluated: ty::UnevaluatedConst<'tcx>, |
923072b8 FG |
1595 | ty: Ty<'tcx>, |
1596 | span: Option<Span>, | |
1597 | ) -> Result<ty::Const<'tcx>, ErrorHandled> { | |
1598 | match self.const_eval_resolve(param_env, unevaluated, span) { | |
1599 | Ok(Some(val)) => Ok(ty::Const::from_value(self.tcx, val, ty)), | |
1600 | Ok(None) => { | |
1601 | let tcx = self.tcx; | |
1602 | let def_id = unevaluated.def.did; | |
1603 | span_bug!( | |
1604 | tcx.def_span(def_id), | |
1605 | "unable to construct a constant value for the unevaluated constant {:?}", | |
1606 | unevaluated | |
1607 | ); | |
1608 | } | |
1609 | Err(err) => Err(err), | |
1610 | } | |
1611 | } | |
1612 | ||
74b04a01 XL |
1613 | /// Resolves and evaluates a constant. |
1614 | /// | |
1615 | /// The constant can be located on a trait like `<A as B>::C`, in which case the given | |
1616 | /// substitutions and environment are used to resolve the constant. Alternatively if the | |
1617 | /// constant has generic parameters in scope the substitutions are used to evaluate the value of | |
1618 | /// the constant. For example in `fn foo<T>() { let _ = [0; bar::<T>()]; }` the repeat count | |
1619 | /// constant `bar::<T>()` requires a substitution for `T`, if the substitution for `T` is still | |
1620 | /// too generic for the constant to be evaluated then `Err(ErrorHandled::TooGeneric)` is | |
1621 | /// returned. | |
1622 | /// | |
1623 | /// This handles inferences variables within both `param_env` and `substs` by | |
1624 | /// performing the operation on their respective canonical forms. | |
5e7ed085 | 1625 | #[instrument(skip(self), level = "debug")] |
74b04a01 XL |
1626 | pub fn const_eval_resolve( |
1627 | &self, | |
064997fb | 1628 | mut param_env: ty::ParamEnv<'tcx>, |
2b03887a | 1629 | unevaluated: ty::UnevaluatedConst<'tcx>, |
74b04a01 | 1630 | span: Option<Span>, |
923072b8 | 1631 | ) -> EvalToValTreeResult<'tcx> { |
064997fb | 1632 | let mut substs = self.resolve_vars_if_possible(unevaluated.substs); |
5e7ed085 | 1633 | debug!(?substs); |
a2a8927a XL |
1634 | |
1635 | // Postpone the evaluation of constants whose substs depend on inference | |
1636 | // variables | |
2b03887a | 1637 | if substs.has_non_region_infer() { |
f2b60f7d | 1638 | let ac = AbstractConst::new(self.tcx, unevaluated); |
064997fb FG |
1639 | match ac { |
1640 | Ok(None) => { | |
1641 | substs = InternalSubsts::identity_for_item(self.tcx, unevaluated.def.did); | |
1642 | param_env = self.tcx.param_env(unevaluated.def.did); | |
1643 | } | |
1644 | Ok(Some(ct)) => { | |
1645 | if ct.unify_failure_kind(self.tcx) == FailureKind::Concrete { | |
1646 | substs = replace_param_and_infer_substs_with_placeholder(self.tcx, substs); | |
1647 | } else { | |
1648 | return Err(ErrorHandled::TooGeneric); | |
1649 | } | |
1650 | } | |
1651 | Err(guar) => return Err(ErrorHandled::Reported(guar)), | |
1652 | } | |
a2a8927a XL |
1653 | } |
1654 | ||
1655 | let param_env_erased = self.tcx.erase_regions(param_env); | |
1656 | let substs_erased = self.tcx.erase_regions(substs); | |
5e7ed085 FG |
1657 | debug!(?param_env_erased); |
1658 | debug!(?substs_erased); | |
a2a8927a | 1659 | |
2b03887a | 1660 | let unevaluated = ty::UnevaluatedConst { def: unevaluated.def, substs: substs_erased }; |
74b04a01 | 1661 | |
74b04a01 XL |
1662 | // The return value is the evaluated value which doesn't contain any reference to inference |
1663 | // variables, thus we don't need to substitute back the original values. | |
923072b8 | 1664 | self.tcx.const_eval_resolve_for_typeck(param_env_erased, unevaluated, span) |
74b04a01 | 1665 | } |
74b04a01 | 1666 | |
ba9703b0 XL |
1667 | /// `ty_or_const_infer_var_changed` is equivalent to one of these two: |
1668 | /// * `shallow_resolve(ty) != ty` (where `ty.kind = ty::Infer(_)`) | |
1669 | /// * `shallow_resolve(ct) != ct` (where `ct.kind = ty::ConstKind::Infer(_)`) | |
1670 | /// | |
1671 | /// However, `ty_or_const_infer_var_changed` is more efficient. It's always | |
1672 | /// inlined, despite being large, because it has only two call sites that | |
1673 | /// are extremely hot (both in `traits::fulfill`'s checking of `stalled_on` | |
1674 | /// inference variables), and it handles both `Ty` and `ty::Const` without | |
1675 | /// having to resort to storing full `GenericArg`s in `stalled_on`. | |
74b04a01 | 1676 | #[inline(always)] |
ba9703b0 XL |
1677 | pub fn ty_or_const_infer_var_changed(&self, infer_var: TyOrConstInferVar<'tcx>) -> bool { |
1678 | match infer_var { | |
1679 | TyOrConstInferVar::Ty(v) => { | |
74b04a01 XL |
1680 | use self::type_variable::TypeVariableValue; |
1681 | ||
ba9703b0 XL |
1682 | // If `inlined_probe` returns a `Known` value, it never equals |
1683 | // `ty::Infer(ty::TyVar(v))`. | |
f9f354fc | 1684 | match self.inner.borrow_mut().type_variables().inlined_probe(v) { |
74b04a01 XL |
1685 | TypeVariableValue::Unknown { .. } => false, |
1686 | TypeVariableValue::Known { .. } => true, | |
1687 | } | |
1688 | } | |
1689 | ||
ba9703b0 XL |
1690 | TyOrConstInferVar::TyInt(v) => { |
1691 | // If `inlined_probe_value` returns a value it's always a | |
74b04a01 XL |
1692 | // `ty::Int(_)` or `ty::UInt(_)`, which never matches a |
1693 | // `ty::Infer(_)`. | |
f9f354fc | 1694 | self.inner.borrow_mut().int_unification_table().inlined_probe_value(v).is_some() |
74b04a01 XL |
1695 | } |
1696 | ||
ba9703b0 XL |
1697 | TyOrConstInferVar::TyFloat(v) => { |
1698 | // If `probe_value` returns a value it's always a | |
74b04a01 XL |
1699 | // `ty::Float(_)`, which never matches a `ty::Infer(_)`. |
1700 | // | |
1701 | // Not `inlined_probe_value(v)` because this call site is colder. | |
f9f354fc | 1702 | self.inner.borrow_mut().float_unification_table().probe_value(v).is_some() |
74b04a01 XL |
1703 | } |
1704 | ||
ba9703b0 XL |
1705 | TyOrConstInferVar::Const(v) => { |
1706 | // If `probe_value` returns a `Known` value, it never equals | |
1707 | // `ty::ConstKind::Infer(ty::InferConst::Var(v))`. | |
1708 | // | |
1709 | // Not `inlined_probe_value(v)` because this call site is colder. | |
f9f354fc | 1710 | match self.inner.borrow_mut().const_unification_table().probe_value(v).val { |
ba9703b0 XL |
1711 | ConstVariableValue::Unknown { .. } => false, |
1712 | ConstVariableValue::Known { .. } => true, | |
1713 | } | |
1714 | } | |
1715 | } | |
1716 | } | |
1717 | } | |
1718 | ||
2b03887a FG |
1719 | impl<'tcx> TypeErrCtxt<'_, 'tcx> { |
1720 | /// Process the region constraints and report any errors that | |
1721 | /// result. After this, no more unification operations should be | |
1722 | /// done -- or the compiler will panic -- but it is legal to use | |
1723 | /// `resolve_vars_if_possible` as well as `fully_resolve`. | |
1724 | /// | |
1725 | /// Make sure to call [`InferCtxt::process_registered_region_obligations`] | |
1726 | /// first, or preferably use [`InferCtxt::check_region_obligations_and_report_errors`] | |
1727 | /// to do both of these operations together. | |
1728 | pub fn resolve_regions_and_report_errors( | |
1729 | &self, | |
1730 | generic_param_scope: LocalDefId, | |
1731 | outlives_env: &OutlivesEnvironment<'tcx>, | |
1732 | ) { | |
1733 | let errors = self.resolve_regions(outlives_env); | |
1734 | ||
1735 | if !self.is_tainted_by_errors() { | |
1736 | // As a heuristic, just skip reporting region errors | |
1737 | // altogether if other errors have been reported while | |
1738 | // this infcx was in use. This is totally hokey but | |
1739 | // otherwise we have a hard time separating legit region | |
1740 | // errors from silly ones. | |
1741 | self.report_region_errors(generic_param_scope, &errors); | |
1742 | } | |
1743 | } | |
1744 | ||
1745 | // [Note-Type-error-reporting] | |
1746 | // An invariant is that anytime the expected or actual type is Error (the special | |
1747 | // error type, meaning that an error occurred when typechecking this expression), | |
1748 | // this is a derived error. The error cascaded from another error (that was already | |
1749 | // reported), so it's not useful to display it to the user. | |
1750 | // The following methods implement this logic. | |
1751 | // They check if either the actual or expected type is Error, and don't print the error | |
1752 | // in this case. The typechecker should only ever report type errors involving mismatched | |
1753 | // types using one of these methods, and should not call span_err directly for such | |
1754 | // errors. | |
1755 | ||
1756 | pub fn type_error_struct_with_diag<M>( | |
1757 | &self, | |
1758 | sp: Span, | |
1759 | mk_diag: M, | |
1760 | actual_ty: Ty<'tcx>, | |
1761 | ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> | |
1762 | where | |
1763 | M: FnOnce(String) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>, | |
1764 | { | |
1765 | let actual_ty = self.resolve_vars_if_possible(actual_ty); | |
1766 | debug!("type_error_struct_with_diag({:?}, {:?})", sp, actual_ty); | |
1767 | ||
1768 | let mut err = mk_diag(self.ty_to_string(actual_ty)); | |
1769 | ||
1770 | // Don't report an error if actual type is `Error`. | |
1771 | if actual_ty.references_error() { | |
1772 | err.downgrade_to_delayed_bug(); | |
1773 | } | |
1774 | ||
1775 | err | |
1776 | } | |
1777 | ||
1778 | pub fn report_mismatched_types( | |
1779 | &self, | |
1780 | cause: &ObligationCause<'tcx>, | |
1781 | expected: Ty<'tcx>, | |
1782 | actual: Ty<'tcx>, | |
1783 | err: TypeError<'tcx>, | |
1784 | ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { | |
1785 | self.report_and_explain_type_error(TypeTrace::types(cause, true, expected, actual), err) | |
1786 | } | |
1787 | ||
1788 | pub fn report_mismatched_consts( | |
1789 | &self, | |
1790 | cause: &ObligationCause<'tcx>, | |
1791 | expected: ty::Const<'tcx>, | |
1792 | actual: ty::Const<'tcx>, | |
1793 | err: TypeError<'tcx>, | |
1794 | ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { | |
1795 | self.report_and_explain_type_error(TypeTrace::consts(cause, true, expected, actual), err) | |
1796 | } | |
1797 | } | |
1798 | ||
ba9703b0 XL |
1799 | /// Helper for `ty_or_const_infer_var_changed` (see comment on that), currently |
1800 | /// used only for `traits::fulfill`'s list of `stalled_on` inference variables. | |
1801 | #[derive(Copy, Clone, Debug)] | |
1802 | pub enum TyOrConstInferVar<'tcx> { | |
1803 | /// Equivalent to `ty::Infer(ty::TyVar(_))`. | |
1804 | Ty(TyVid), | |
1805 | /// Equivalent to `ty::Infer(ty::IntVar(_))`. | |
1806 | TyInt(IntVid), | |
1807 | /// Equivalent to `ty::Infer(ty::FloatVar(_))`. | |
1808 | TyFloat(FloatVid), | |
1809 | ||
1810 | /// Equivalent to `ty::ConstKind::Infer(ty::InferConst::Var(_))`. | |
1811 | Const(ConstVid<'tcx>), | |
1812 | } | |
1813 | ||
a2a8927a | 1814 | impl<'tcx> TyOrConstInferVar<'tcx> { |
ba9703b0 XL |
1815 | /// Tries to extract an inference variable from a type or a constant, returns `None` |
1816 | /// for types other than `ty::Infer(_)` (or `InferTy::Fresh*`) and | |
1817 | /// for constants other than `ty::ConstKind::Infer(_)` (or `InferConst::Fresh`). | |
1818 | pub fn maybe_from_generic_arg(arg: GenericArg<'tcx>) -> Option<Self> { | |
1819 | match arg.unpack() { | |
1820 | GenericArgKind::Type(ty) => Self::maybe_from_ty(ty), | |
1821 | GenericArgKind::Const(ct) => Self::maybe_from_const(ct), | |
1822 | GenericArgKind::Lifetime(_) => None, | |
74b04a01 XL |
1823 | } |
1824 | } | |
ba9703b0 XL |
1825 | |
1826 | /// Tries to extract an inference variable from a type, returns `None` | |
1827 | /// for types other than `ty::Infer(_)` (or `InferTy::Fresh*`). | |
f2b60f7d | 1828 | fn maybe_from_ty(ty: Ty<'tcx>) -> Option<Self> { |
1b1a35ee | 1829 | match *ty.kind() { |
ba9703b0 XL |
1830 | ty::Infer(ty::TyVar(v)) => Some(TyOrConstInferVar::Ty(v)), |
1831 | ty::Infer(ty::IntVar(v)) => Some(TyOrConstInferVar::TyInt(v)), | |
1832 | ty::Infer(ty::FloatVar(v)) => Some(TyOrConstInferVar::TyFloat(v)), | |
1833 | _ => None, | |
1834 | } | |
1835 | } | |
1836 | ||
1837 | /// Tries to extract an inference variable from a constant, returns `None` | |
1838 | /// for constants other than `ty::ConstKind::Infer(_)` (or `InferConst::Fresh`). | |
f2b60f7d | 1839 | fn maybe_from_const(ct: ty::Const<'tcx>) -> Option<Self> { |
923072b8 | 1840 | match ct.kind() { |
ba9703b0 XL |
1841 | ty::ConstKind::Infer(InferConst::Var(v)) => Some(TyOrConstInferVar::Const(v)), |
1842 | _ => None, | |
1843 | } | |
1844 | } | |
1845 | } | |
1846 | ||
5e7ed085 FG |
1847 | /// Replace `{integer}` with `i32` and `{float}` with `f64`. |
1848 | /// Used only for diagnostics. | |
1849 | struct InferenceLiteralEraser<'tcx> { | |
1850 | tcx: TyCtxt<'tcx>, | |
1851 | } | |
1852 | ||
1853 | impl<'tcx> TypeFolder<'tcx> for InferenceLiteralEraser<'tcx> { | |
1854 | fn tcx(&self) -> TyCtxt<'tcx> { | |
1855 | self.tcx | |
1856 | } | |
1857 | ||
1858 | fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { | |
1859 | match ty.kind() { | |
1860 | ty::Infer(ty::IntVar(_) | ty::FreshIntTy(_)) => self.tcx.types.i32, | |
1861 | ty::Infer(ty::FloatVar(_) | ty::FreshFloatTy(_)) => self.tcx.types.f64, | |
1862 | _ => ty.super_fold_with(self), | |
1863 | } | |
1864 | } | |
1865 | } | |
1866 | ||
ba9703b0 | 1867 | struct ShallowResolver<'a, 'tcx> { |
2b03887a | 1868 | infcx: &'a InferCtxt<'tcx>, |
74b04a01 XL |
1869 | } |
1870 | ||
1871 | impl<'a, 'tcx> TypeFolder<'tcx> for ShallowResolver<'a, 'tcx> { | |
1872 | fn tcx<'b>(&'b self) -> TyCtxt<'tcx> { | |
1873 | self.infcx.tcx | |
1874 | } | |
1875 | ||
04454e1e FG |
1876 | /// If `ty` is a type variable of some kind, resolve it one level |
1877 | /// (but do not resolve types found in the result). If `typ` is | |
1878 | /// not a type variable, just return it unmodified. | |
74b04a01 | 1879 | fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { |
04454e1e FG |
1880 | match *ty.kind() { |
1881 | ty::Infer(ty::TyVar(v)) => { | |
1882 | // Not entirely obvious: if `typ` is a type variable, | |
1883 | // it can be resolved to an int/float variable, which | |
1884 | // can then be recursively resolved, hence the | |
1885 | // recursion. Note though that we prevent type | |
1886 | // variables from unifying to other type variables | |
1887 | // directly (though they may be embedded | |
1888 | // structurally), and we prevent cycles in any case, | |
1889 | // so this recursion should always be of very limited | |
1890 | // depth. | |
1891 | // | |
1892 | // Note: if these two lines are combined into one we get | |
1893 | // dynamic borrow errors on `self.inner`. | |
1894 | let known = self.infcx.inner.borrow_mut().type_variables().probe(v).known(); | |
1895 | known.map_or(ty, |t| self.fold_ty(t)) | |
1896 | } | |
1897 | ||
1898 | ty::Infer(ty::IntVar(v)) => self | |
1899 | .infcx | |
1900 | .inner | |
1901 | .borrow_mut() | |
1902 | .int_unification_table() | |
1903 | .probe_value(v) | |
1904 | .map_or(ty, |v| v.to_type(self.infcx.tcx)), | |
1905 | ||
1906 | ty::Infer(ty::FloatVar(v)) => self | |
1907 | .infcx | |
1908 | .inner | |
1909 | .borrow_mut() | |
1910 | .float_unification_table() | |
1911 | .probe_value(v) | |
1912 | .map_or(ty, |v| v.to_type(self.infcx.tcx)), | |
1913 | ||
1914 | _ => ty, | |
1915 | } | |
74b04a01 XL |
1916 | } |
1917 | ||
5099ac24 | 1918 | fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { |
923072b8 | 1919 | if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.kind() { |
74b04a01 XL |
1920 | self.infcx |
1921 | .inner | |
1922 | .borrow_mut() | |
f9f354fc | 1923 | .const_unification_table() |
5099ac24 | 1924 | .probe_value(vid) |
74b04a01 XL |
1925 | .val |
1926 | .known() | |
1927 | .unwrap_or(ct) | |
1928 | } else { | |
1929 | ct | |
1930 | } | |
1931 | } | |
1932 | } | |
1933 | ||
1934 | impl<'tcx> TypeTrace<'tcx> { | |
1935 | pub fn span(&self) -> Span { | |
1936 | self.cause.span | |
1937 | } | |
1938 | ||
1939 | pub fn types( | |
1940 | cause: &ObligationCause<'tcx>, | |
1941 | a_is_expected: bool, | |
1942 | a: Ty<'tcx>, | |
1943 | b: Ty<'tcx>, | |
1944 | ) -> TypeTrace<'tcx> { | |
5099ac24 FG |
1945 | TypeTrace { |
1946 | cause: cause.clone(), | |
1947 | values: Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())), | |
1948 | } | |
74b04a01 XL |
1949 | } |
1950 | ||
f2b60f7d FG |
1951 | pub fn poly_trait_refs( |
1952 | cause: &ObligationCause<'tcx>, | |
1953 | a_is_expected: bool, | |
1954 | a: ty::PolyTraitRef<'tcx>, | |
1955 | b: ty::PolyTraitRef<'tcx>, | |
1956 | ) -> TypeTrace<'tcx> { | |
1957 | TypeTrace { | |
1958 | cause: cause.clone(), | |
1959 | values: PolyTraitRefs(ExpectedFound::new(a_is_expected, a.into(), b.into())), | |
1960 | } | |
1961 | } | |
1962 | ||
f9f354fc XL |
1963 | pub fn consts( |
1964 | cause: &ObligationCause<'tcx>, | |
1965 | a_is_expected: bool, | |
5099ac24 FG |
1966 | a: ty::Const<'tcx>, |
1967 | b: ty::Const<'tcx>, | |
f9f354fc | 1968 | ) -> TypeTrace<'tcx> { |
5099ac24 FG |
1969 | TypeTrace { |
1970 | cause: cause.clone(), | |
1971 | values: Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())), | |
1972 | } | |
f9f354fc | 1973 | } |
74b04a01 XL |
1974 | } |
1975 | ||
1976 | impl<'tcx> SubregionOrigin<'tcx> { | |
1977 | pub fn span(&self) -> Span { | |
1978 | match *self { | |
1979 | Subtype(ref a) => a.span(), | |
74b04a01 | 1980 | RelateObjectBound(a) => a, |
94222f64 | 1981 | RelateParamBound(a, ..) => a, |
74b04a01 | 1982 | RelateRegionParamBound(a) => a, |
74b04a01 XL |
1983 | Reborrow(a) => a, |
1984 | ReborrowUpvar(a, _) => a, | |
1985 | DataBorrowed(_, a) => a, | |
1986 | ReferenceOutlivesReferent(_, a) => a, | |
064997fb | 1987 | CompareImplItemObligation { span, .. } => span, |
f2b60f7d | 1988 | AscribeUserTypeProvePredicate(span) => span, |
5099ac24 | 1989 | CheckAssociatedTypeBounds { ref parent, .. } => parent.span(), |
74b04a01 XL |
1990 | } |
1991 | } | |
1992 | ||
1993 | pub fn from_obligation_cause<F>(cause: &traits::ObligationCause<'tcx>, default: F) -> Self | |
1994 | where | |
1995 | F: FnOnce() -> Self, | |
1996 | { | |
a2a8927a | 1997 | match *cause.code() { |
74b04a01 XL |
1998 | traits::ObligationCauseCode::ReferenceOutlivesReferent(ref_type) => { |
1999 | SubregionOrigin::ReferenceOutlivesReferent(ref_type, cause.span) | |
2000 | } | |
2001 | ||
064997fb | 2002 | traits::ObligationCauseCode::CompareImplItemObligation { |
c295e0f8 XL |
2003 | impl_item_def_id, |
2004 | trait_item_def_id, | |
064997fb FG |
2005 | kind: _, |
2006 | } => SubregionOrigin::CompareImplItemObligation { | |
c295e0f8 | 2007 | span: cause.span, |
c295e0f8 XL |
2008 | impl_item_def_id, |
2009 | trait_item_def_id, | |
2010 | }, | |
2011 | ||
5099ac24 FG |
2012 | traits::ObligationCauseCode::CheckAssociatedTypeBounds { |
2013 | impl_item_def_id, | |
2014 | trait_item_def_id, | |
2015 | } => SubregionOrigin::CheckAssociatedTypeBounds { | |
2016 | impl_item_def_id, | |
2017 | trait_item_def_id, | |
2018 | parent: Box::new(default()), | |
2019 | }, | |
2020 | ||
f2b60f7d FG |
2021 | traits::ObligationCauseCode::AscribeUserTypeProvePredicate(span) => { |
2022 | SubregionOrigin::AscribeUserTypeProvePredicate(span) | |
2023 | } | |
2024 | ||
74b04a01 XL |
2025 | _ => default(), |
2026 | } | |
2027 | } | |
2028 | } | |
2029 | ||
2030 | impl RegionVariableOrigin { | |
2031 | pub fn span(&self) -> Span { | |
2032 | match *self { | |
3dfed10e XL |
2033 | MiscVariable(a) |
2034 | | PatternRegion(a) | |
2035 | | AddrOfRegion(a) | |
3c0e092e | 2036 | | Autoref(a) |
3dfed10e XL |
2037 | | Coercion(a) |
2038 | | EarlyBoundRegion(a, ..) | |
2039 | | LateBoundRegion(a, ..) | |
2040 | | UpvarRegion(_, a) => a, | |
5869c6ff | 2041 | Nll(..) => bug!("NLL variable used with `span`"), |
74b04a01 XL |
2042 | } |
2043 | } | |
2044 | } | |
2045 | ||
064997fb FG |
2046 | /// Replaces substs that reference param or infer variables with suitable |
2047 | /// placeholders. This function is meant to remove these param and infer | |
2048 | /// substs when they're not actually needed to evaluate a constant. | |
2049 | fn replace_param_and_infer_substs_with_placeholder<'tcx>( | |
2050 | tcx: TyCtxt<'tcx>, | |
2051 | substs: SubstsRef<'tcx>, | |
2052 | ) -> SubstsRef<'tcx> { | |
2053 | tcx.mk_substs(substs.iter().enumerate().map(|(idx, arg)| { | |
2054 | match arg.unpack() { | |
2b03887a | 2055 | GenericArgKind::Type(_) if arg.has_non_region_param() || arg.has_non_region_infer() => { |
064997fb FG |
2056 | tcx.mk_ty(ty::Placeholder(ty::PlaceholderType { |
2057 | universe: ty::UniverseIndex::ROOT, | |
2058 | name: ty::BoundVar::from_usize(idx), | |
2059 | })) | |
2060 | .into() | |
2061 | } | |
2b03887a | 2062 | GenericArgKind::Const(ct) if ct.has_non_region_infer() || ct.has_non_region_param() => { |
064997fb FG |
2063 | let ty = ct.ty(); |
2064 | // If the type references param or infer, replace that too... | |
2b03887a | 2065 | if ty.has_non_region_param() || ty.has_non_region_infer() { |
064997fb FG |
2066 | bug!("const `{ct}`'s type should not reference params or types"); |
2067 | } | |
2068 | tcx.mk_const(ty::ConstS { | |
2069 | ty, | |
2070 | kind: ty::ConstKind::Placeholder(ty::PlaceholderConst { | |
2071 | universe: ty::UniverseIndex::ROOT, | |
2072 | name: ty::BoundVar::from_usize(idx), | |
2073 | }), | |
2074 | }) | |
2075 | .into() | |
2076 | } | |
2077 | _ => arg, | |
2078 | } | |
2079 | })) | |
2080 | } |