1 //! This module contains the "canonicalizer" itself.
3 //! For an overview of what canonicalization is and how it fits into
4 //! rustc, check out the [chapter in the rustc dev guide][c].
6 //! [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html
8 use crate::infer
::canonical
::{
9 Canonical
, CanonicalTyVarKind
, CanonicalVarInfo
, CanonicalVarKind
, OriginalQueryValues
,
11 use crate::infer
::InferCtxt
;
12 use rustc_middle
::ty
::flags
::FlagComputation
;
13 use rustc_middle
::ty
::fold
::{TypeFoldable, TypeFolder, TypeSuperFoldable}
;
14 use rustc_middle
::ty
::GenericArg
;
15 use rustc_middle
::ty
::{self, BoundVar, InferConst, List, Ty, TyCtxt, TypeFlags, TypeVisitableExt}
;
16 use std
::sync
::atomic
::Ordering
;
18 use rustc_data_structures
::fx
::FxHashMap
;
20 use smallvec
::SmallVec
;
22 impl<'tcx
> InferCtxt
<'tcx
> {
23 /// Canonicalizes a query value `V`. When we canonicalize a query,
24 /// we not only canonicalize unbound inference variables, but we
25 /// *also* replace all free regions whatsoever. So for example a
26 /// query like `T: Trait<'static>` would be canonicalized to
32 /// with a mapping M that maps `'?0` to `'static`.
34 /// To get a good understanding of what is happening here, check
35 /// out the [chapter in the rustc dev guide][c].
37 /// [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html#canonicalizing-the-query
38 pub fn canonicalize_query
<V
>(
41 query_state
: &mut OriginalQueryValues
<'tcx
>,
42 ) -> Canonical
<'tcx
, V
>
44 V
: TypeFoldable
<TyCtxt
<'tcx
>>,
46 self.tcx
.sess
.perf_stats
.queries_canonicalized
.fetch_add(1, Ordering
::Relaxed
);
48 Canonicalizer
::canonicalize(value
, self, self.tcx
, &CanonicalizeAllFreeRegions
, query_state
)
51 /// Like [Self::canonicalize_query], but preserves distinct universes. For
52 /// example, canonicalizing `&'?0: Trait<'?1>`, where `'?0` is in `U1` and
53 /// `'?1` is in `U3` would be canonicalized to have `?0` in `U1` and `'?1`
56 /// This is used for Chalk integration.
57 pub fn canonicalize_query_preserving_universes
<V
>(
60 query_state
: &mut OriginalQueryValues
<'tcx
>,
61 ) -> Canonical
<'tcx
, V
>
63 V
: TypeFoldable
<TyCtxt
<'tcx
>>,
65 self.tcx
.sess
.perf_stats
.queries_canonicalized
.fetch_add(1, Ordering
::Relaxed
);
67 Canonicalizer
::canonicalize(
71 &CanonicalizeAllFreeRegionsPreservingUniverses
,
76 /// Canonicalizes a query *response* `V`. When we canonicalize a
77 /// query response, we only canonicalize unbound inference
78 /// variables, and we leave other free regions alone. So,
79 /// continuing with the example from `canonicalize_query`, if
80 /// there was an input query `T: Trait<'static>`, it would have
81 /// been canonicalized to
87 /// with a mapping M that maps `'?0` to `'static`. But if we found that there
88 /// exists only one possible impl of `Trait`, and it looks like
89 /// ```ignore (illustrative)
90 /// impl<T> Trait<'static> for T { .. }
92 /// then we would prepare a query result R that (among other
93 /// things) includes a mapping to `'?0 := 'static`. When
94 /// canonicalizing this query result R, we would leave this
95 /// reference to `'static` alone.
97 /// To get a good understanding of what is happening here, check
98 /// out the [chapter in the rustc dev guide][c].
100 /// [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html#canonicalizing-the-query-result
101 pub fn canonicalize_response
<V
>(&self, value
: V
) -> Canonical
<'tcx
, V
>
103 V
: TypeFoldable
<TyCtxt
<'tcx
>>,
105 let mut query_state
= OriginalQueryValues
::default();
106 Canonicalizer
::canonicalize(
110 &CanonicalizeQueryResponse
,
115 pub fn canonicalize_user_type_annotation
<V
>(&self, value
: V
) -> Canonical
<'tcx
, V
>
117 V
: TypeFoldable
<TyCtxt
<'tcx
>>,
119 let mut query_state
= OriginalQueryValues
::default();
120 Canonicalizer
::canonicalize(
124 &CanonicalizeUserTypeAnnotation
,
129 /// A variant of `canonicalize_query` that does not
130 /// canonicalize `'static`. This is useful when
131 /// the query implementation can perform more efficient
132 /// handling of `'static` regions (e.g. trait evaluation).
133 pub fn canonicalize_query_keep_static
<V
>(
136 query_state
: &mut OriginalQueryValues
<'tcx
>,
137 ) -> Canonical
<'tcx
, V
>
139 V
: TypeFoldable
<TyCtxt
<'tcx
>>,
141 self.tcx
.sess
.perf_stats
.queries_canonicalized
.fetch_add(1, Ordering
::Relaxed
);
143 Canonicalizer
::canonicalize(
147 &CanonicalizeFreeRegionsOtherThanStatic
,
153 /// Controls how we canonicalize "free regions" that are not inference
154 /// variables. This depends on what we are canonicalizing *for* --
155 /// e.g., if we are canonicalizing to create a query, we want to
156 /// replace those with inference variables, since we want to make a
157 /// maximally general query. But if we are canonicalizing a *query
158 /// response*, then we don't typically replace free regions, as they
159 /// must have been introduced from other parts of the system.
160 trait CanonicalizeMode
{
161 fn canonicalize_free_region
<'tcx
>(
163 canonicalizer
: &mut Canonicalizer
<'_
, 'tcx
>,
165 ) -> ty
::Region
<'tcx
>;
167 fn any(&self) -> bool
;
169 // Do we preserve universe of variables.
170 fn preserve_universes(&self) -> bool
;
173 struct CanonicalizeQueryResponse
;
175 impl CanonicalizeMode
for CanonicalizeQueryResponse
{
176 fn canonicalize_free_region
<'tcx
>(
178 canonicalizer
: &mut Canonicalizer
<'_
, 'tcx
>,
180 ) -> ty
::Region
<'tcx
> {
182 ty
::ReFree(_
) | ty
::ReErased
| ty
::ReStatic
| ty
::ReEarlyBound(..) => r
,
184 ty
::RePlaceholder(placeholder
) => canonicalizer
.canonical_var_for_region(
185 CanonicalVarInfo { kind: CanonicalVarKind::PlaceholderRegion(placeholder) }
,
190 let universe
= canonicalizer
.region_var_universe(vid
);
191 canonicalizer
.canonical_var_for_region(
192 CanonicalVarInfo { kind: CanonicalVarKind::Region(universe) }
,
198 // Other than `'static` or `'empty`, the query
199 // response should be executing in a fully
200 // canonicalized environment, so there shouldn't be
201 // any other region names it can come up.
203 // rust-lang/rust#57464: `impl Trait` can leak local
204 // scopes (in manner violating typeck). Therefore, use
205 // `delay_span_bug` to allow type error over an ICE.
206 canonicalizer
.tcx
.sess
.delay_span_bug(
207 rustc_span
::DUMMY_SP
,
208 format
!("unexpected region in query response: `{r:?}`"),
215 fn any(&self) -> bool
{
219 fn preserve_universes(&self) -> bool
{
224 struct CanonicalizeUserTypeAnnotation
;
226 impl CanonicalizeMode
for CanonicalizeUserTypeAnnotation
{
227 fn canonicalize_free_region
<'tcx
>(
229 canonicalizer
: &mut Canonicalizer
<'_
, 'tcx
>,
231 ) -> ty
::Region
<'tcx
> {
233 ty
::ReEarlyBound(_
) | ty
::ReFree(_
) | ty
::ReErased
| ty
::ReStatic
| ty
::ReError(_
) => r
,
234 ty
::ReVar(_
) => canonicalizer
.canonical_var_for_region_in_root_universe(r
),
235 ty
::RePlaceholder(..) | ty
::ReLateBound(..) => {
236 // We only expect region names that the user can type.
237 bug
!("unexpected region in query response: `{:?}`", r
)
242 fn any(&self) -> bool
{
246 fn preserve_universes(&self) -> bool
{
251 struct CanonicalizeAllFreeRegions
;
253 impl CanonicalizeMode
for CanonicalizeAllFreeRegions
{
254 fn canonicalize_free_region
<'tcx
>(
256 canonicalizer
: &mut Canonicalizer
<'_
, 'tcx
>,
258 ) -> ty
::Region
<'tcx
> {
259 canonicalizer
.canonical_var_for_region_in_root_universe(r
)
262 fn any(&self) -> bool
{
266 fn preserve_universes(&self) -> bool
{
271 struct CanonicalizeAllFreeRegionsPreservingUniverses
;
273 impl CanonicalizeMode
for CanonicalizeAllFreeRegionsPreservingUniverses
{
274 fn canonicalize_free_region
<'tcx
>(
276 canonicalizer
: &mut Canonicalizer
<'_
, 'tcx
>,
278 ) -> ty
::Region
<'tcx
> {
279 let universe
= canonicalizer
.infcx
.universe_of_region(r
);
280 canonicalizer
.canonical_var_for_region(
281 CanonicalVarInfo { kind: CanonicalVarKind::Region(universe) }
,
286 fn any(&self) -> bool
{
290 fn preserve_universes(&self) -> bool
{
295 struct CanonicalizeFreeRegionsOtherThanStatic
;
297 impl CanonicalizeMode
for CanonicalizeFreeRegionsOtherThanStatic
{
298 fn canonicalize_free_region
<'tcx
>(
300 canonicalizer
: &mut Canonicalizer
<'_
, 'tcx
>,
302 ) -> ty
::Region
<'tcx
> {
303 if r
.is_static() { r }
else { canonicalizer.canonical_var_for_region_in_root_universe(r) }
306 fn any(&self) -> bool
{
310 fn preserve_universes(&self) -> bool
{
315 struct Canonicalizer
<'cx
, 'tcx
> {
316 infcx
: &'cx InferCtxt
<'tcx
>,
318 variables
: SmallVec
<[CanonicalVarInfo
<'tcx
>; 8]>,
319 query_state
: &'cx
mut OriginalQueryValues
<'tcx
>,
320 // Note that indices is only used once `var_values` is big enough to be
322 indices
: FxHashMap
<GenericArg
<'tcx
>, BoundVar
>,
323 canonicalize_mode
: &'cx
dyn CanonicalizeMode
,
324 needs_canonical_flags
: TypeFlags
,
326 binder_index
: ty
::DebruijnIndex
,
329 impl<'cx
, 'tcx
> TypeFolder
<TyCtxt
<'tcx
>> for Canonicalizer
<'cx
, 'tcx
> {
330 fn interner(&self) -> TyCtxt
<'tcx
> {
334 fn fold_binder
<T
>(&mut self, t
: ty
::Binder
<'tcx
, T
>) -> ty
::Binder
<'tcx
, T
>
336 T
: TypeFoldable
<TyCtxt
<'tcx
>>,
338 self.binder_index
.shift_in(1);
339 let t
= t
.super_fold_with(self);
340 self.binder_index
.shift_out(1);
344 fn fold_region(&mut self, r
: ty
::Region
<'tcx
>) -> ty
::Region
<'tcx
> {
346 ty
::ReLateBound(index
, ..) => {
347 if index
>= self.binder_index
{
348 bug
!("escaping late-bound region during canonicalization");
359 .unwrap_region_constraints()
360 .opportunistic_resolve_var(self.tcx
, vid
);
362 "canonical: region var found with vid {vid:?}, \
363 opportunistically resolved to {resolved:?}",
365 self.canonicalize_mode
.canonicalize_free_region(self, resolved
)
369 | ty
::ReEarlyBound(..)
372 | ty
::RePlaceholder(..)
373 | ty
::ReErased
=> self.canonicalize_mode
.canonicalize_free_region(self, r
),
377 fn fold_ty(&mut self, mut t
: Ty
<'tcx
>) -> Ty
<'tcx
> {
379 ty
::Infer(ty
::TyVar(mut vid
)) => {
380 // We need to canonicalize the *root* of our ty var.
381 // This is so that our canonical response correctly reflects
382 // any equated inference vars correctly!
383 let root_vid
= self.infcx
.root_var(vid
);
385 t
= Ty
::new_var(self.infcx
.tcx
, root_vid
);
389 debug
!("canonical: type var found with vid {:?}", vid
);
390 match self.infcx
.probe_ty_var(vid
) {
391 // `t` could be a float / int variable; canonicalize that instead.
393 debug
!("(resolved to {:?})", t
);
397 // `TyVar(vid)` is unresolved, track its universe index in the canonicalized
400 if !self.canonicalize_mode
.preserve_universes() {
401 // FIXME: perf problem described in #55921.
402 ui
= ty
::UniverseIndex
::ROOT
;
404 self.canonicalize_ty_var(
406 kind
: CanonicalVarKind
::Ty(CanonicalTyVarKind
::General(ui
)),
414 ty
::Infer(ty
::IntVar(vid
)) => {
415 let nt
= self.infcx
.opportunistic_resolve_int_var(vid
);
417 return self.fold_ty(nt
);
419 self.canonicalize_ty_var(
420 CanonicalVarInfo { kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Int) }
,
425 ty
::Infer(ty
::FloatVar(vid
)) => {
426 let nt
= self.infcx
.opportunistic_resolve_float_var(vid
);
428 return self.fold_ty(nt
);
430 self.canonicalize_ty_var(
431 CanonicalVarInfo { kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Float) }
,
437 ty
::Infer(ty
::FreshTy(_
) | ty
::FreshIntTy(_
) | ty
::FreshFloatTy(_
)) => {
438 bug
!("encountered a fresh type during canonicalization")
441 ty
::Placeholder(mut placeholder
) => {
442 if !self.canonicalize_mode
.preserve_universes() {
443 placeholder
.universe
= ty
::UniverseIndex
::ROOT
;
445 self.canonicalize_ty_var(
446 CanonicalVarInfo { kind: CanonicalVarKind::PlaceholderTy(placeholder) }
,
451 ty
::Bound(debruijn
, _
) => {
452 if debruijn
>= self.binder_index
{
453 bug
!("escaping bound type during canonicalization")
461 | ty
::GeneratorWitness(..)
482 if t
.flags().intersects(self.needs_canonical_flags
) {
483 t
.super_fold_with(self)
491 fn fold_const(&mut self, mut ct
: ty
::Const
<'tcx
>) -> ty
::Const
<'tcx
> {
493 ty
::ConstKind
::Infer(InferConst
::Var(mut vid
)) => {
494 // We need to canonicalize the *root* of our const var.
495 // This is so that our canonical response correctly reflects
496 // any equated inference vars correctly!
497 let root_vid
= self.infcx
.root_const_var(vid
);
499 ct
= ty
::Const
::new_var(self.infcx
.tcx
, root_vid
, ct
.ty());
503 debug
!("canonical: const var found with vid {:?}", vid
);
504 match self.infcx
.probe_const_var(vid
) {
506 debug
!("(resolved to {:?})", c
);
507 return self.fold_const(c
);
510 // `ConstVar(vid)` is unresolved, track its universe index in the
511 // canonicalized result
513 if !self.canonicalize_mode
.preserve_universes() {
514 // FIXME: perf problem described in #55921.
515 ui
= ty
::UniverseIndex
::ROOT
;
517 return self.canonicalize_const_var(
518 CanonicalVarInfo { kind: CanonicalVarKind::Const(ui, ct.ty()) }
,
524 ty
::ConstKind
::Infer(InferConst
::EffectVar(vid
)) => {
525 match self.infcx
.probe_effect_var(vid
) {
526 Some(value
) => return self.fold_const(value
.as_const(self.infcx
.tcx
)),
528 return self.canonicalize_const_var(
529 CanonicalVarInfo { kind: CanonicalVarKind::Effect }
,
535 ty
::ConstKind
::Infer(InferConst
::Fresh(_
)) => {
536 bug
!("encountered a fresh const during canonicalization")
538 ty
::ConstKind
::Bound(debruijn
, _
) => {
539 if debruijn
>= self.binder_index
{
540 bug
!("escaping bound const during canonicalization")
545 ty
::ConstKind
::Placeholder(placeholder
) => {
546 return self.canonicalize_const_var(
548 kind
: CanonicalVarKind
::PlaceholderConst(placeholder
, ct
.ty()),
556 let flags
= FlagComputation
::for_const(ct
);
557 if flags
.intersects(self.needs_canonical_flags
) { ct.super_fold_with(self) }
else { ct }
561 impl<'cx
, 'tcx
> Canonicalizer
<'cx
, 'tcx
> {
562 /// The main `canonicalize` method, shared impl of
563 /// `canonicalize_query` and `canonicalize_response`.
566 infcx
: &InferCtxt
<'tcx
>,
568 canonicalize_region_mode
: &dyn CanonicalizeMode
,
569 query_state
: &mut OriginalQueryValues
<'tcx
>,
570 ) -> Canonical
<'tcx
, V
>
572 V
: TypeFoldable
<TyCtxt
<'tcx
>>,
574 let needs_canonical_flags
= if canonicalize_region_mode
.any() {
575 TypeFlags
::HAS_INFER
| TypeFlags
::HAS_PLACEHOLDER
| TypeFlags
::HAS_FREE_REGIONS
577 TypeFlags
::HAS_INFER
| TypeFlags
::HAS_PLACEHOLDER
580 // Fast path: nothing that needs to be canonicalized.
581 if !value
.has_type_flags(needs_canonical_flags
) {
582 let canon_value
= Canonical
{
583 max_universe
: ty
::UniverseIndex
::ROOT
,
584 variables
: List
::empty(),
590 let mut canonicalizer
= Canonicalizer
{
593 canonicalize_mode
: canonicalize_region_mode
,
594 needs_canonical_flags
,
595 variables
: SmallVec
::new(),
597 indices
: FxHashMap
::default(),
598 binder_index
: ty
::INNERMOST
,
600 let out_value
= value
.fold_with(&mut canonicalizer
);
602 // Once we have canonicalized `out_value`, it should not
603 // contain anything that ties it to this inference context
605 debug_assert
!(!out_value
.has_infer() && !out_value
.has_placeholders());
607 let canonical_variables
=
608 tcx
.mk_canonical_var_infos(&canonicalizer
.universe_canonicalized_variables());
610 let max_universe
= canonical_variables
612 .map(|cvar
| cvar
.universe())
614 .unwrap_or(ty
::UniverseIndex
::ROOT
);
616 Canonical { max_universe, variables: canonical_variables, value: out_value }
619 /// Creates a canonical variable replacing `kind` from the input,
620 /// or returns an existing variable if `kind` has already been
621 /// seen. `kind` is expected to be an unbound variable (or
622 /// potentially a free region).
623 fn canonical_var(&mut self, info
: CanonicalVarInfo
<'tcx
>, kind
: GenericArg
<'tcx
>) -> BoundVar
{
624 let Canonicalizer { variables, query_state, indices, .. }
= self;
626 let var_values
= &mut query_state
.var_values
;
628 let universe
= info
.universe();
629 if universe
!= ty
::UniverseIndex
::ROOT
{
630 assert
!(self.canonicalize_mode
.preserve_universes());
632 // Insert universe into the universe map. To preserve the order of the
633 // universes in the value being canonicalized, we don't update the
634 // universe in `info` until we have finished canonicalizing.
635 match query_state
.universe_map
.binary_search(&universe
) {
636 Err(idx
) => query_state
.universe_map
.insert(idx
, universe
),
641 // This code is hot. `variables` and `var_values` are usually small
642 // (fewer than 8 elements ~95% of the time). They are SmallVec's to
643 // avoid allocations in those cases. We also don't use `indices` to
644 // determine if a kind has been seen before until the limit of 8 has
645 // been exceeded, to also avoid allocations for `indices`.
646 if !var_values
.spilled() {
647 // `var_values` is stack-allocated. `indices` isn't used yet. Do a
648 // direct linear search of `var_values`.
649 if let Some(idx
) = var_values
.iter().position(|&k
| k
== kind
) {
650 // `kind` is already present in `var_values`.
653 // `kind` isn't present in `var_values`. Append it. Likewise
654 // for `info` and `variables`.
655 variables
.push(info
);
656 var_values
.push(kind
);
657 assert_eq
!(variables
.len(), var_values
.len());
659 // If `var_values` has become big enough to be heap-allocated,
660 // fill up `indices` to facilitate subsequent lookups.
661 if var_values
.spilled() {
662 assert
!(indices
.is_empty());
663 *indices
= var_values
666 .map(|(i
, &kind
)| (kind
, BoundVar
::new(i
)))
669 // The cv is the index of the appended element.
670 BoundVar
::new(var_values
.len() - 1)
673 // `var_values` is large. Do a hashmap search via `indices`.
674 *indices
.entry(kind
).or_insert_with(|| {
675 variables
.push(info
);
676 var_values
.push(kind
);
677 assert_eq
!(variables
.len(), var_values
.len());
678 BoundVar
::new(variables
.len() - 1)
683 /// Replaces the universe indexes used in `var_values` with their index in
684 /// `query_state.universe_map`. This minimizes the maximum universe used in
685 /// the canonicalized value.
686 fn universe_canonicalized_variables(self) -> SmallVec
<[CanonicalVarInfo
<'tcx
>; 8]> {
687 if self.query_state
.universe_map
.len() == 1 {
688 return self.variables
;
691 let reverse_universe_map
: FxHashMap
<ty
::UniverseIndex
, ty
::UniverseIndex
> = self
696 .map(|(idx
, universe
)| (*universe
, ty
::UniverseIndex
::from_usize(idx
)))
701 .map(|v
| CanonicalVarInfo
{
703 CanonicalVarKind
::Ty(CanonicalTyVarKind
::Int
| CanonicalTyVarKind
::Float
)
704 | CanonicalVarKind
::Effect
=> {
707 CanonicalVarKind
::Ty(CanonicalTyVarKind
::General(u
)) => {
708 CanonicalVarKind
::Ty(CanonicalTyVarKind
::General(reverse_universe_map
[&u
]))
710 CanonicalVarKind
::Region(u
) => {
711 CanonicalVarKind
::Region(reverse_universe_map
[&u
])
713 CanonicalVarKind
::Const(u
, t
) => {
714 CanonicalVarKind
::Const(reverse_universe_map
[&u
], t
)
716 CanonicalVarKind
::PlaceholderTy(placeholder
) => {
717 CanonicalVarKind
::PlaceholderTy(ty
::Placeholder
{
718 universe
: reverse_universe_map
[&placeholder
.universe
],
722 CanonicalVarKind
::PlaceholderRegion(placeholder
) => {
723 CanonicalVarKind
::PlaceholderRegion(ty
::Placeholder
{
724 universe
: reverse_universe_map
[&placeholder
.universe
],
728 CanonicalVarKind
::PlaceholderConst(placeholder
, t
) => {
729 CanonicalVarKind
::PlaceholderConst(
731 universe
: reverse_universe_map
[&placeholder
.universe
],
742 /// Shorthand helper that creates a canonical region variable for
743 /// `r` (always in the root universe). The reason that we always
744 /// put these variables into the root universe is because this
745 /// method is used during **query construction:** in that case, we
746 /// are taking all the regions and just putting them into the most
747 /// generic context we can. This may generate solutions that don't
748 /// fit (e.g., that equate some region variable with a placeholder
749 /// it can't name) on the caller side, but that's ok, the caller
750 /// can figure that out. In the meantime, it maximizes our
753 /// (This works because unification never fails -- and hence trait
754 /// selection is never affected -- due to a universe mismatch.)
755 fn canonical_var_for_region_in_root_universe(
758 ) -> ty
::Region
<'tcx
> {
759 self.canonical_var_for_region(
760 CanonicalVarInfo { kind: CanonicalVarKind::Region(ty::UniverseIndex::ROOT) }
,
765 /// Returns the universe in which `vid` is defined.
766 fn region_var_universe(&self, vid
: ty
::RegionVid
) -> ty
::UniverseIndex
{
767 self.infcx
.inner
.borrow_mut().unwrap_region_constraints().var_universe(vid
)
770 /// Creates a canonical variable (with the given `info`)
771 /// representing the region `r`; return a region referencing it.
772 fn canonical_var_for_region(
774 info
: CanonicalVarInfo
<'tcx
>,
776 ) -> ty
::Region
<'tcx
> {
777 let var
= self.canonical_var(info
, r
.into());
778 let br
= ty
::BoundRegion { var, kind: ty::BrAnon }
;
779 ty
::Region
::new_late_bound(self.interner(), self.binder_index
, br
)
782 /// Given a type variable `ty_var` of the given kind, first check
783 /// if `ty_var` is bound to anything; if so, canonicalize
784 /// *that*. Otherwise, create a new canonical variable for
786 fn canonicalize_ty_var(&mut self, info
: CanonicalVarInfo
<'tcx
>, ty_var
: Ty
<'tcx
>) -> Ty
<'tcx
> {
787 let infcx
= self.infcx
;
788 let bound_to
= infcx
.shallow_resolve(ty_var
);
789 if bound_to
!= ty_var
{
790 self.fold_ty(bound_to
)
792 let var
= self.canonical_var(info
, ty_var
.into());
793 Ty
::new_bound(self.tcx
, self.binder_index
, var
.into())
797 /// Given a type variable `const_var` of the given kind, first check
798 /// if `const_var` is bound to anything; if so, canonicalize
799 /// *that*. Otherwise, create a new canonical variable for
801 fn canonicalize_const_var(
803 info
: CanonicalVarInfo
<'tcx
>,
804 const_var
: ty
::Const
<'tcx
>,
805 ) -> ty
::Const
<'tcx
> {
806 let infcx
= self.infcx
;
807 let bound_to
= infcx
.shallow_resolve(const_var
);
808 if bound_to
!= const_var
{
809 self.fold_const(bound_to
)
811 let var
= self.canonical_var(info
, const_var
.into());
812 ty
::Const
::new_bound(self.tcx
, self.binder_index
, var
, self.fold_ty(const_var
.ty()))