1use std::collections::{HashMap, HashSet};
2use std::fmt::Debug;
3use std::mem;
4
5use crate::hax;
6use crate::hax::{BaseState, Symbol};
7use rustc_middle::ty;
8
9use super::translate_ctx::{ItemTransCtx, TransImplSource, TransItemSourceKind};
10use charon_lib::ast::*;
11use charon_lib::ids::IndexVec;
12use charon_lib::utils::CycleDetector;
13
14#[derive(Debug, Default)]
26pub(crate) struct BindingLevel {
27 pub def_id: Option<hax::DefId>,
29 pub params: GenericParams,
31 pub early_region_vars: HashMap<hax::EarlyParamRegion, RegionId>,
38 pub region_vars_by_def_id: HashMap<hax::DefId, RegionId>,
40 pub bound_region_vars: Vec<RegionId>,
42 pub closure_call_method_region: Option<RegionId>,
44 pub drop_glue_region: Option<RegionId>,
46 pub type_vars_map: HashMap<u32, TypeVarId>,
48 pub const_generic_vars_map: HashMap<u32, ConstGenericVarId>,
50 pub trait_preds: HashMap<hax::GenericPredicateId, TraitClauseId>,
52 pub closure_upvar_tys: Option<IndexVec<FieldId, Ty>>,
56 pub closure_upvar_regions: Vec<RegionId>,
58 pub used_region_names: HashSet<Symbol>,
61 pub type_trans_cache: HashMap<hax::Ty, Ty>,
65}
66
67fn translate_region_name(s: hax::Symbol) -> Option<String> {
69 let s = s.to_string();
70 if s == "'_" { None } else { Some(s) }
71}
72
73fn translate_variance(variance: Option<&hax::Variance>) -> Variance {
74 match variance {
75 Some(hax::Variance::Covariant) => Variance::Covariant,
76 Some(hax::Variance::Invariant) => Variance::Invariant,
77 Some(hax::Variance::Contravariant) => Variance::Contravariant,
78 Some(hax::Variance::Bivariant) => Variance::Bivariant,
79 None => Variance::Unknown,
80 }
81}
82
83impl BindingLevel {
84 pub(crate) fn new(def_id: Option<hax::DefId>) -> Self {
85 Self {
86 def_id,
87 ..Default::default()
88 }
89 }
90
91 pub(crate) fn push_early_region(
93 &mut self,
94 region: hax::EarlyParamRegion,
95 def_id: hax::DefId,
96 variance: Variance,
97 mutability: LifetimeMutability,
98 ) -> RegionId {
99 let name = if self.used_region_names.insert(region.name) {
100 translate_region_name(region.name)
101 } else {
102 None
103 };
104 assert!(
106 self.bound_region_vars.is_empty(),
107 "Early regions must be translated before late ones"
108 );
109 let rid = self.params.regions.push_with(|index| RegionParam {
110 index,
111 name,
112 variance,
113 mutability,
114 });
115 self.early_region_vars.insert(region, rid);
116 self.region_vars_by_def_id.insert(def_id, rid);
117 rid
118 }
119
120 pub(crate) fn push_bound_region(
122 &mut self,
123 region: hax::BoundRegionKind,
124 variance: Variance,
125 ) -> RegionId {
126 use crate::hax::BoundRegionKind::*;
127 let (name, def_id) = match region {
128 Anon => (None, None),
129 NamedForPrinting(symbol) => (translate_region_name(symbol), None),
130 Named(def_id, symbol) => (translate_region_name(symbol), Some(def_id)),
131 ClosureEnv => (Some("@env".to_owned()), None),
132 };
133 let rid = self
134 .params
135 .regions
136 .push_with(|index| RegionParam::new(index, name, variance));
137 self.bound_region_vars.push(rid);
138 if let Some(def_id) = def_id {
139 self.region_vars_by_def_id.insert(def_id, rid);
140 }
141 rid
142 }
143
144 pub fn push_upvar_region(&mut self) -> RegionId {
146 let region_id = self
149 .params
150 .regions
151 .push_with(|index| RegionParam::new(index, None, Variance::Unknown));
152 self.closure_upvar_regions.push(region_id);
153 region_id
154 }
155
156 pub fn push_drop_glue_region(&mut self) -> RegionId {
157 let region_id = self
158 .params
159 .regions
160 .push_with(|index| RegionParam::new(index, None, Variance::Covariant));
161 self.drop_glue_region = Some(region_id);
162 region_id
163 }
164
165 pub(crate) fn push_type_var(
166 &mut self,
167 rid: u32,
168 name: hax::Symbol,
169 variance: Variance,
170 ) -> TypeVarId {
171 let mut name = name.to_string();
174 if name
175 .chars()
176 .any(|c| !(c.is_ascii_alphanumeric() || c == '_'))
177 {
178 name = format!("T{rid}")
179 }
180 let var_id = self.params.types.push_with(|index| TypeParam {
181 index,
182 name,
183 variance,
184 });
185 self.type_vars_map.insert(rid, var_id);
186 var_id
187 }
188
189 pub(crate) fn push_const_generic_var(&mut self, rid: u32, ty: Ty, name: hax::Symbol) {
190 let var_id = self
191 .params
192 .const_generics
193 .push_with(|index| ConstGenericParam {
194 index,
195 name: name.to_string(),
196 ty,
197 });
198 self.const_generic_vars_map.insert(rid, var_id);
199 }
200
201 pub(crate) fn push_params_from_binder(&mut self, binder: hax::Binder<()>) -> Result<(), Error> {
203 assert!(
204 self.bound_region_vars.is_empty(),
205 "Trying to use two binders at the same binding level"
206 );
207 use crate::hax::BoundVariableKind::*;
208 for p in binder.bound_vars {
209 match p {
210 Region(region, variance) => {
211 let variance = translate_variance(variance.as_ref());
212 self.push_bound_region(region, variance);
213 }
214 Ty(_) => {
215 panic!("Unexpected locally bound type variable");
216 }
217 Const => {
218 panic!("Unexpected locally bound const generic variable");
219 }
220 }
221 }
222 Ok(())
223 }
224}
225
226impl<'tcx, 'ctx> ItemTransCtx<'tcx, 'ctx> {
227 pub(crate) fn the_only_binder(&self) -> &BindingLevel {
229 assert_eq!(self.binding_levels.len(), 1);
230 self.innermost_binder()
231 }
232 pub(crate) fn the_only_binder_mut(&mut self) -> &mut BindingLevel {
234 assert_eq!(self.binding_levels.len(), 1);
235 self.innermost_binder_mut()
236 }
237
238 pub(crate) fn outermost_binder(&self) -> &BindingLevel {
239 self.binding_levels.outermost()
240 }
241 pub(crate) fn outermost_binder_mut(&mut self) -> &mut BindingLevel {
242 self.binding_levels.outermost_mut()
243 }
244 pub(crate) fn innermost_binder(&self) -> &BindingLevel {
245 self.binding_levels.innermost()
246 }
247 pub(crate) fn innermost_binder_mut(&mut self) -> &mut BindingLevel {
248 self.binding_levels.innermost_mut()
249 }
250
251 pub(crate) fn outermost_generics(&self) -> &GenericParams {
252 &self.outermost_binder().params
253 }
254 #[expect(dead_code)]
255 pub(crate) fn outermost_generics_mut(&mut self) -> &mut GenericParams {
256 &mut self.outermost_binder_mut().params
257 }
258 #[expect(dead_code)]
259 pub(crate) fn innermost_generics(&self) -> &GenericParams {
260 &self.innermost_binder().params
261 }
262 pub(crate) fn innermost_generics_mut(&mut self) -> &mut GenericParams {
263 &mut self.innermost_binder_mut().params
264 }
265
266 pub(crate) fn lookup_bound_region(
267 &mut self,
268 span: Span,
269 dbid: hax::DebruijnIndex,
270 var: hax::BoundVar,
271 ) -> Result<RegionDbVar, Error> {
272 let dbid = DeBruijnId::new(dbid);
273 if let Some(rid) = self
274 .binding_levels
275 .get(dbid)
276 .and_then(|bl| bl.bound_region_vars.get(var))
277 {
278 Ok(DeBruijnVar::bound(dbid, *rid))
279 } else {
280 raise_error!(
281 self,
282 span,
283 "Unexpected error: could not find region '{dbid}_{var}"
284 )
285 }
286 }
287
288 pub(crate) fn lookup_param<Id: Copy>(
289 &mut self,
290 span: Span,
291 f: impl for<'a> Fn(&'a BindingLevel) -> Option<Id>,
292 mk_err: impl FnOnce() -> String,
293 ) -> Result<DeBruijnVar<Id>, Error> {
294 for (dbid, bl) in self.binding_levels.iter_enumerated() {
295 if let Some(id) = f(bl) {
296 return Ok(DeBruijnVar::bound(dbid, id));
297 }
298 }
299 let err = mk_err();
300 raise_error!(self, span, "Unexpected error: could not find {}", err)
301 }
302
303 pub(crate) fn lookup_early_region(
304 &mut self,
305 span: Span,
306 region: &hax::EarlyParamRegion,
307 ) -> Result<RegionDbVar, Error> {
308 self.lookup_param(
309 span,
310 |bl| bl.early_region_vars.get(region).copied(),
311 || format!("the region variable {region:?}"),
312 )
313 }
314
315 pub(crate) fn lookup_late_param_region(
316 &mut self,
317 span: Span,
318 region: &hax::LateParamRegion,
319 ) -> Result<RegionDbVar, Error> {
320 use hax::LateParamRegionKind::*;
321 match ®ion.kind {
322 Anon(index) | NamedAnon(index, _) => {
323 let Some((dbid, binder)) = self
324 .binding_levels
325 .iter_enumerated()
326 .find(|(_, binder)| binder.def_id.as_ref() == Some(®ion.scope))
327 else {
328 raise_error!(
329 self,
330 span,
331 "Unexpected error: could not find the binder for late-bound region {region:?}"
332 )
333 };
334 let Some(region_id) = binder.bound_region_vars.get(*index as usize).copied() else {
335 raise_error!(
336 self,
337 span,
338 "Unexpected error: could not find the late-bound region variable {region:?}"
339 )
340 };
341 Ok(DeBruijnVar::bound(dbid, region_id))
342 }
343 Named(def_id, _) => self.lookup_param(
344 span,
345 |bl| bl.region_vars_by_def_id.get(def_id).copied(),
346 || format!("the late-bound region variable {region:?}"),
347 ),
348 ClosureEnv => {
349 raise_error!(self, span, "Unexpected late-bound region: {region:?}")
350 }
351 }
352 }
353
354 pub(crate) fn lookup_type_var(
355 &mut self,
356 span: Span,
357 param: &hax::ParamTy,
358 ) -> Result<TypeDbVar, Error> {
359 self.lookup_param(
360 span,
361 |bl| bl.type_vars_map.get(¶m.index).copied(),
362 || format!("the type variable {}", param.name),
363 )
364 }
365
366 pub(crate) fn lookup_const_generic_var(
367 &mut self,
368 span: Span,
369 param: &hax::ParamConst,
370 ) -> Result<ConstGenericDbVar, Error> {
371 self.lookup_param(
372 span,
373 |bl| bl.const_generic_vars_map.get(¶m.index).copied(),
374 || format!("the const generic variable {}", param.name),
375 )
376 }
377
378 pub(crate) fn lookup_clause_var(
379 &mut self,
380 span: Span,
381 id: &hax::GenericPredicateId,
382 ) -> Result<ClauseDbVar, Error> {
383 self.lookup_param(
384 span,
385 |bl| bl.trait_preds.get(id).copied(),
386 || format!("the trait clause variable {id:?}"),
387 )
388 }
389
390 pub(crate) fn push_generic_params(&mut self, generics: &hax::TyGenerics) -> Result<(), Error> {
391 for param in &generics.params {
392 self.push_generic_param(param)?;
393 }
394 Ok(())
395 }
396
397 pub(crate) fn push_generic_param(&mut self, param: &hax::GenericParamDef) -> Result<(), Error> {
398 let variance = translate_variance(param.variance.as_ref());
399 match ¶m.kind {
400 hax::GenericParamDefKind::Lifetime => {
401 let region = hax::EarlyParamRegion {
402 index: param.index,
403 name: param.name,
404 };
405 let mutability = self
406 .t_ctx
407 .lt_mutability_computer
408 .compute_lifetime_mutability(
409 &self.hax_state,
410 self.item_src.def_id(),
411 param.index,
412 );
413 let _ = self.innermost_binder_mut().push_early_region(
414 region,
415 param.def_id.clone(),
416 variance,
417 mutability,
418 );
419 }
420 hax::GenericParamDefKind::Type { .. } => {
421 let _ =
422 self.innermost_binder_mut()
423 .push_type_var(param.index, param.name, variance);
424 }
425 hax::GenericParamDefKind::Const { ty, .. } => {
426 let span = self.def_span(¶m.def_id);
427 let ty = self.translate_ty(span, ty)?;
430 self.innermost_binder_mut()
431 .push_const_generic_var(param.index, ty, param.name);
432 }
433 }
434
435 Ok(())
436 }
437
438 fn push_late_bound_generics_for_def(
447 &mut self,
448 _span: Span,
449 def: &hax::FullDef<'tcx>,
450 ) -> Result<(), Error> {
451 if let hax::FullDefKind::Fn { sig, .. }
452 | hax::FullDefKind::AssocFn { sig, .. }
453 | hax::FullDefKind::Ctor { sig, .. } = def.kind()
454 {
455 let innermost_binder = self.innermost_binder_mut();
456 assert!(innermost_binder.bound_region_vars.is_empty());
457 innermost_binder.push_params_from_binder(sig.rebind(()))?;
458 }
459 Ok(())
460 }
461
462 #[tracing::instrument(skip(self, span, def))]
464 fn push_generics_for_def(&mut self, span: Span, def: &hax::FullDef<'tcx>) -> Result<(), Error> {
465 trace!("{:?}", def.param_env());
466 if let Some(parent_item) = def.typing_parent(self.hax_state()) {
469 let parent_def = self.hax_def(&parent_item)?;
470 self.push_generics_for_def(span, &parent_def)?;
471 }
472 self.push_generics_for_def_without_parents(span, def)?;
473 Ok(())
474 }
475
476 fn push_generics_for_def_without_parents(
479 &mut self,
480 _span: Span,
481 def: &hax::FullDef<'tcx>,
482 ) -> Result<(), Error> {
483 if let Some(param_env) = def.param_env() {
484 let origin = Self::predicate_origin_for_def(def);
485 self.push_param_env_without_parents(param_env, origin)?;
486 }
487
488 Ok(())
489 }
490
491 fn predicate_origin_for_def(def: &hax::FullDef<'tcx>) -> PredicateOrigin {
492 use crate::hax::FullDefKind;
493 match &def.kind {
494 FullDefKind::Adt { .. } | FullDefKind::TyAlias { .. } | FullDefKind::AssocTy { .. } => {
495 PredicateOrigin::WhereClauseOnType
496 }
497 FullDefKind::Fn { .. }
498 | FullDefKind::AssocFn { .. }
499 | FullDefKind::Closure { .. }
500 | FullDefKind::Const { .. }
501 | FullDefKind::AssocConst { .. }
502 | FullDefKind::Static { .. } => PredicateOrigin::WhereClauseOnFn,
503 FullDefKind::TraitImpl { .. } | FullDefKind::InherentImpl { .. } => {
504 PredicateOrigin::WhereClauseOnImpl
505 }
506 FullDefKind::Trait { .. } | FullDefKind::TraitAlias { .. } => {
507 PredicateOrigin::WhereClauseOnTrait
508 }
509 _ => panic!("Unexpected def: {:?}", def.def_id().kind),
510 }
511 }
512
513 fn push_param_env_without_parents(
514 &mut self,
515 param_env: &hax::ParamEnv,
516 origin: PredicateOrigin,
517 ) -> Result<(), Error> {
518 self.push_generic_params(¶m_env.generics)?;
519 self.register_predicates(¶m_env.predicates, origin)?;
520 Ok(())
521 }
522
523 pub fn translate_item_generics(
531 &mut self,
532 span: Span,
533 def: &hax::FullDef<'tcx>,
534 kind: &TransItemSourceKind,
535 ) -> Result<(), Error> {
536 assert!(self.binding_levels.is_empty());
537 self.binding_levels
538 .push(BindingLevel::new(Some(def.def_id().clone())));
539 self.push_generics_for_def(span, def)?;
540 self.push_late_bound_generics_for_def(span, def)?;
541
542 if let hax::FullDefKind::Closure { args, .. } = def.kind() {
543 let upvar_tys = self.translate_closure_upvar_tys(span, args)?;
546 let upvar_tys = upvar_tys.replace_erased_regions(|| {
548 let region_id = self.the_only_binder_mut().push_upvar_region();
549 Region::Var(DeBruijnVar::new_at_zero(region_id))
550 });
551 self.the_only_binder_mut().closure_upvar_tys = Some(upvar_tys);
552
553 if let TransItemSourceKind::TraitImpl(TransImplSource::Callable(..))
555 | TransItemSourceKind::VTableInstance(TransImplSource::Callable(..))
556 | TransItemSourceKind::VTableInstanceInitializer(TransImplSource::Callable(..))
557 | TransItemSourceKind::VTableDropShim(TransImplSource::Callable(..))
558 | TransItemSourceKind::CallableMethod(..)
559 | TransItemSourceKind::VTableMethod(TransImplSource::Callable(..))
560 | TransItemSourceKind::ClosureAsFnCast = kind
561 {
562 self.the_only_binder_mut()
563 .push_params_from_binder(args.fn_sig.rebind(()))?;
564 }
565 }
566
567 if let hax::FullDefKind::Fn { .. }
568 | hax::FullDefKind::AssocFn { .. }
569 | hax::FullDefKind::Closure { .. }
570 | hax::FullDefKind::Ctor { .. } = def.kind()
571 && let TransItemSourceKind::CallableMethod(ClosureKind::Fn | ClosureKind::FnMut)
572 | TransItemSourceKind::VTableMethod(TransImplSource::Callable(
573 ClosureKind::Fn | ClosureKind::FnMut,
574 )) = kind
575 {
576 let rid = self
578 .the_only_binder_mut()
579 .params
580 .regions
581 .push_with(|index| RegionParam::new(index, None, Variance::Covariant));
582 self.the_only_binder_mut().closure_call_method_region = Some(rid);
583 }
584
585 if matches!(
586 kind,
587 TransItemSourceKind::DropGlueMethod(..) | TransItemSourceKind::VTableDropShim(..)
588 ) {
589 self.the_only_binder_mut().push_drop_glue_region();
590 }
591
592 self.innermost_binder_mut().params.check_consistency();
593 Ok(())
594 }
595
596 pub(crate) fn inside_binder<F, U>(
598 &mut self,
599 kind: BinderKind,
600 def_id: Option<hax::DefId>,
601 f: F,
602 ) -> Result<Binder<U>, Error>
603 where
604 F: FnOnce(&mut Self) -> Result<U, Error>,
605 {
606 self.binding_levels.push(BindingLevel::new(def_id));
607
608 let res = f(self);
610
611 let params = self.binding_levels.pop().unwrap().params;
613
614 res.map(|skip_binder| Binder {
616 kind,
617 params,
618 skip_binder,
619 })
620 }
621
622 pub(crate) fn translate_binder_for_def<F, U>(
625 &mut self,
626 span: Span,
627 kind: BinderKind,
628 def: &hax::FullDef<'tcx>,
629 f: F,
630 ) -> Result<Binder<U>, Error>
631 where
632 F: FnOnce(&mut Self) -> Result<U, Error>,
633 {
634 let inner_hax_state = self.t_ctx.hax_state.clone().with_hax_owner(def.def_id());
635 let outer_hax_state = mem::replace(&mut self.hax_state, inner_hax_state);
636 let ret = self.inside_binder(kind, Some(def.def_id().clone()), |this| {
637 this.push_generics_for_def_without_parents(span, def)?;
638 this.push_late_bound_generics_for_def(span, def)?;
639 this.innermost_binder().params.check_consistency();
640 f(this)
641 });
642 self.hax_state = outer_hax_state;
643 ret
644 }
645
646 pub(crate) fn translate_item_binder<F, T, U>(
649 &mut self,
650 _span: Span,
651 kind: BinderKind,
652 binder: &hax::TraitItemBinder<T>,
653 predicate_origin: PredicateOrigin,
654 f: F,
655 ) -> Result<Binder<U>, Error>
656 where
657 F: FnOnce(&mut Self, &T) -> Result<U, Error>,
658 {
659 let inner_hax_state = self.t_ctx.hax_state.clone().with_hax_owner(&binder.def_id);
660 let outer_hax_state = mem::replace(&mut self.hax_state, inner_hax_state);
661 let ret = self.inside_binder(kind, Some(binder.def_id.clone()), |this| {
662 this.push_param_env_without_parents(&binder.param_env, predicate_origin)?;
663 this.innermost_binder_mut()
664 .push_params_from_binder(binder.late_bound.clone())?;
665 this.innermost_binder().params.check_consistency();
666 f(this, &binder.skip_binder)
667 });
668 self.hax_state = outer_hax_state;
669 ret
670 }
671
672 pub(crate) fn translate_region_binder<F, T, U>(
676 &mut self,
677 _span: Span,
678 binder: &hax::Binder<T>,
679 f: F,
680 ) -> Result<RegionBinder<U>, Error>
681 where
682 F: FnOnce(&mut Self, &T) -> Result<U, Error>,
683 {
684 let binder = self.inside_binder(BinderKind::Other, None, |this| {
685 this.innermost_binder_mut()
686 .push_params_from_binder(binder.rebind(()))?;
687 f(this, binder.hax_skip_binder_ref())
688 })?;
689 Ok(RegionBinder {
691 regions: binder.params.regions,
692 skip_binder: binder.skip_binder,
693 })
694 }
695
696 pub(crate) fn into_generics(mut self) -> GenericParams {
697 assert!(self.binding_levels.len() == 1);
698 self.binding_levels.pop().unwrap().params
699 }
700}
701
702#[derive(Default)]
704pub struct LifetimeMutabilityComputer {
705 lt_mutability: HashMap<hax::DefId, CycleDetector<HashSet<u32>>>,
706}
707
708impl LifetimeMutabilityComputer {
709 pub(crate) fn compute_lifetime_mutability<'tcx>(
711 &mut self,
712 s: &impl BaseState<'tcx>,
713 item: &hax::DefId,
714 index: u32,
715 ) -> LifetimeMutability {
716 match self.compute_lifetime_mutabilities(s, item) {
717 Some(set) => {
718 if set.contains(&index) {
719 LifetimeMutability::Mutable
720 } else {
721 LifetimeMutability::Shared
722 }
723 }
724 None => LifetimeMutability::Unknown,
725 }
726 }
727
728 fn compute_lifetime_mutabilities<'tcx>(
731 &mut self,
732 s: &impl BaseState<'tcx>,
733 item: &hax::DefId,
734 ) -> Option<&HashSet<u32>> {
735 if !matches!(
736 item.kind,
737 hax::DefKind::Struct | hax::DefKind::Enum | hax::DefKind::Union
738 ) {
739 return None;
740 }
741 if self
742 .lt_mutability
743 .entry(item.clone())
744 .or_default()
745 .start_processing()
746 {
747 use crate::hax::SInto;
748 use ty::{TypeSuperVisitable, TypeVisitable};
749
750 struct LtMutabilityVisitor<'a, S> {
751 s: &'a S,
752 computer: &'a mut LifetimeMutabilityComputer,
753 set: HashSet<u32>,
754 }
755 impl<'tcx, S: BaseState<'tcx>> ty::TypeVisitor<ty::TyCtxt<'tcx>> for LtMutabilityVisitor<'_, S> {
756 fn visit_ty(&mut self, ty: ty::Ty<'tcx>) {
757 match ty.kind() {
758 ty::Ref(r, _, ty::Mutability::Mut)
759 if let ty::RegionKind::ReEarlyParam(r) = r.kind() =>
760 {
761 self.set.insert(r.index);
762 }
763 ty::Adt(adt, args) => {
764 let item = adt.did().sinto(self.s);
765 if let Some(mutabilities) =
766 self.computer.compute_lifetime_mutabilities(self.s, &item)
767 {
768 for arg in args.iter() {
769 if let Some(r) = arg.as_region()
770 && let ty::RegionKind::ReEarlyParam(r) = r.kind()
771 && mutabilities.contains(&r.index)
772 {
773 self.set.insert(r.index);
774 }
775 }
776 }
777 }
778 _ => {}
779 }
780 ty.super_visit_with(self)
781 }
782 }
783 let mut visitor = LtMutabilityVisitor {
784 s,
785 computer: self,
786 set: HashSet::new(),
787 };
788
789 let tcx = s.base().tcx;
790 let def_id = item.real_rust_def_id();
791 let adt_def = tcx.adt_def(def_id);
792 let generics = item.identity_args(s);
793 for variant in adt_def.variants() {
794 for field in &variant.fields {
795 field.ty(tcx, generics).visit_with(&mut visitor);
796 }
797 }
798 let set = visitor.set;
799
800 self.lt_mutability
801 .get_mut(item)
802 .unwrap()
803 .done_processing(set);
804 }
805 self.lt_mutability.get(item)?.as_processed()
806 }
807}