1use rustc_hash::{FxHashMap as HashMap, FxHashSet as HashSet};
2
3use rustc_hir::def::DefKind as RDefKind;
4use rustc_middle::infer::canonical::QueryRegionConstraints;
5use rustc_middle::ty::relate::{
6 Relate, RelateResult, TypeRelation, relate_args_with_variances, structurally_relate_consts,
7 structurally_relate_tys,
8};
9use rustc_middle::{mir, ty};
10use rustc_span::kw;
11
12use crate::hax::prelude::*;
13
14pub type UserAnnotation<'tcx> = ty::Binder<'tcx, UserAnnotationData<'tcx>>;
16pub type UserAnnotationData<'tcx> = (Vec<ty::Ty<'tcx>>, Vec<ty::Clause<'tcx>>);
20pub type UserAnnotationProj = Vec<mir::ProjectionKind>;
23
24pub fn translate_user_annotation<'tcx>(
27 tcx: ty::TyCtxt<'tcx>,
28 typing_env: ty::TypingEnv<'tcx>,
29 owner: RDefId,
30 annotation: &ty::CanonicalUserTypeAnnotation<'tcx>,
31 projections: &[UserAnnotationProj],
32) -> Result<UserAnnotation<'tcx>, String> {
33 use rustc_trait_selection::infer::{RegionVariableOrigin, TyCtxtInferExt};
34 use rustc_trait_selection::traits::query::type_op::{AscribeUserType, Normalize, TypeOp};
35 use ty::{TypeVisitableExt, Upcast};
36
37 let span = annotation.span;
38 let owner = tcx.typeck_root_def_id(owner).as_local().unwrap();
39 let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env);
40
41 let (user_ty, _) = infcx.instantiate_canonical(span, &annotation.user_ty);
42 let user_ty = ty::fold_regions(tcx, user_ty, |r, _| {
43 if r.is_erased() {
44 infcx.next_region_var(RegionVariableOrigin::Misc(span))
45 } else {
46 r
47 }
48 });
49 let inferred_ty = ty::fold_regions(tcx, annotation.inferred_ty, |_, _| {
50 infcx.next_region_var(RegionVariableOrigin::Misc(span))
51 });
52
53 let (projected_tys, constraints): (Vec<ty::Ty<'tcx>>, QueryRegionConstraints<'tcx>) = {
56 let mut all_constraints: Vec<Option<&'tcx QueryRegionConstraints<'tcx>>> = Vec::new();
57
58 let normalized = param_env
60 .and(Normalize {
61 value: ty::set_opaques_to_non_rigid(tcx, inferred_ty),
62 })
63 .fully_perform(&infcx, owner, span)
64 .map_err(|_| "could not normalize inferred annotation type".to_owned())?;
65 let inferred_ty = normalized.output;
66 all_constraints.push(normalized.constraints);
67
68 let ascribe_result = param_env
69 .and(AscribeUserType {
70 mir_ty: inferred_ty,
71 user_ty,
72 })
73 .fully_perform(&infcx, owner, span)
74 .map_err(|_| "could not recover user type ascription".to_owned())?;
75 all_constraints.push(ascribe_result.constraints);
76
77 let mut projected_tys = Vec::new();
78 for projections in projections {
79 let mut projected_ty = mir::PlaceTy::from_ty(inferred_ty);
80 let mut iter = projections.iter();
81 loop {
82 let resolved = param_env
83 .and(Normalize {
84 value: ty::Unnormalized::new_wip(projected_ty.ty),
85 })
86 .fully_perform(&infcx, owner, span)
87 .map_err(|_| "could not normalize user type projection".to_owned())?;
88 projected_ty.ty = resolved.output;
89 all_constraints.push(resolved.constraints);
90 let Some(projection) = iter.next() else { break };
91 if matches!(
92 projection,
93 mir::ProjectionElem::OpaqueCast(())
94 | mir::ProjectionElem::UnwrapUnsafeBinder(())
95 ) {
96 return Err("unsupported cast in user type projection".into());
97 }
98 projected_ty = projected_ty.projection_ty_core(
99 tcx,
100 projection,
101 |ty, variant, field, ()| {
102 mir::PlaceTy::field_ty(tcx, ty, variant, field).skip_normalization()
103 },
104 |()| unreachable!(),
105 );
106 }
107 projected_tys.push(projected_ty.ty);
108 }
109
110 let mut constraints: QueryRegionConstraints<'tcx> = Default::default();
112 for c in all_constraints.into_iter().flatten() {
113 constraints
114 .constraints
115 .extend(c.constraints.iter().copied());
116 constraints
117 .assumptions
118 .extend(c.assumptions.iter().copied());
119 }
120
121 (projected_tys, constraints)
122 };
123
124 let (projected_tys, constraints) = {
126 let cause = rustc_middle::traits::ObligationCause::dummy_with_span(span);
127 for constraint in &constraints.constraints {
128 if let ty::RegionConstraint::Eq(eq @ ty::RegionEqPredicate(lhs, rhs)) =
129 constraint.constraint
130 && [lhs, rhs]
131 .into_iter()
132 .all(|r| infcx.universe_of_region(r) == ty::UniverseIndex::ROOT)
133 {
134 infcx.register_region_eq_constraint(eq, constraint.visible_for_leak_check, &cause);
135 }
136 }
137 infcx.deeply_resolve_via_unification_table((projected_tys, constraints))
138 };
139
140 let clauses: Vec<ty::Clause<'tcx>> = {
142 if !constraints.assumptions.is_empty() {
143 return Err("unsupported assumptions in user type ascription constraints".into());
144 }
145 let mut clauses = Vec::new();
146 let mut push_clause = |kind| clauses.push(ty::Binder::dummy(kind).upcast(tcx));
147 for constraint in constraints.constraints {
148 match constraint.constraint {
149 ty::RegionConstraint::Outlives(ty::OutlivesClause(lhs, rhs)) => {
150 let clause = match lhs.kind() {
151 ty::GenericArgKind::Lifetime(lhs) => {
152 ty::ClauseKind::RegionOutlives(ty::OutlivesClause(lhs, rhs))
153 }
154 ty::GenericArgKind::Type(lhs) => {
155 ty::ClauseKind::TypeOutlives(ty::OutlivesClause(lhs, rhs))
156 }
157 ty::GenericArgKind::Const(_) => {
158 return Err("const outlives constraint in user type ascription".into());
159 }
160 };
161 push_clause(clause);
162 }
163 ty::RegionConstraint::Eq(ty::RegionEqPredicate(lhs, rhs)) => {
164 if lhs != rhs {
165 for (lhs, rhs) in [(lhs, rhs), (rhs, lhs)] {
167 push_clause(ty::ClauseKind::RegionOutlives(ty::OutlivesClause(
168 lhs, rhs,
169 )));
170 }
171 }
172 }
173 }
174 }
175 clauses
176 };
177
178 let bound = {
180 let value = (projected_tys, clauses);
181 if value.has_non_region_infer() || value.has_non_region_placeholders() {
182 return Err("unresolved type or const in user type ascription".into());
183 }
184 let mut regions = HashMap::default();
185 let mut bound_vars = Vec::new();
186 let mut unsupported_region = false;
187 let value = ty::fold_regions(tcx, value, |region, depth| match region.kind() {
188 ty::ReVar(_) if infcx.universe_of_region(region) == ty::UniverseIndex::ROOT => {
189 let var = *regions.entry(region).or_insert_with(|| {
190 let var = ty::BoundVar::from_usize(bound_vars.len());
191 bound_vars.push(ty::BoundVariableKind::Region(ty::BoundRegionKind::Anon));
192 var
193 });
194 ty::Region::new_bound(
195 tcx,
196 depth,
197 ty::BoundRegion {
198 var,
199 kind: ty::BoundRegionKind::Anon,
200 },
201 )
202 }
203 ty::ReVar(_) | ty::RePlaceholder(_) | ty::ReErased => {
204 unsupported_region = true;
205 region
206 }
207 _ => region,
208 });
209 if unsupported_region {
210 return Err("unsupported region in user type ascription constraints".into());
211 }
212 ty::Binder::bind_with_vars(value, tcx.mk_bound_variable_kinds(&bound_vars))
213 };
214
215 Ok(bound)
216}
217
218pub fn fn_sig_bound_region_variances<'tcx>(
222 tcx: ty::TyCtxt<'tcx>,
223 sig: ty::PolyFnSig<'tcx>,
224) -> HashMap<ty::BoundVar, ty::Variance> {
225 struct FunctionalVariances<'tcx> {
226 tcx: ty::TyCtxt<'tcx>,
227 variances: HashMap<ty::BoundVar, ty::Variance>,
228 ambient_variance: ty::Variance,
229 target_binder: ty::DebruijnIndex,
230 }
231
232 impl<'tcx> TypeRelation<ty::TyCtxt<'tcx>> for FunctionalVariances<'tcx> {
233 fn cx(&self) -> ty::TyCtxt<'tcx> {
234 self.tcx
235 }
236
237 fn relate_ty_args(
238 &mut self,
239 a_ty: ty::Ty<'tcx>,
240 _: ty::Ty<'tcx>,
241 def_id: rustc_hir::def_id::DefId,
242 a_args: ty::GenericArgsRef<'tcx>,
243 b_args: ty::GenericArgsRef<'tcx>,
244 _: impl FnOnce(ty::GenericArgsRef<'tcx>) -> ty::Ty<'tcx>,
245 ) -> RelateResult<'tcx, ty::Ty<'tcx>> {
246 relate_args_with_variances(self, self.tcx.variances_of(def_id), a_args, b_args)?;
247 Ok(a_ty)
248 }
249
250 fn relate_with_variance<T: Relate<ty::TyCtxt<'tcx>>>(
251 &mut self,
252 variance: ty::Variance,
253 _: ty::VarianceDiagInfo<ty::TyCtxt<'tcx>>,
254 a: T,
255 b: T,
256 ) -> RelateResult<'tcx, T> {
257 let old_variance = self.ambient_variance;
258 self.ambient_variance = self.ambient_variance.xform(variance);
259 let result = self.relate(a, b);
260 self.ambient_variance = old_variance;
261 result
262 }
263
264 fn tys(&mut self, a: ty::Ty<'tcx>, b: ty::Ty<'tcx>) -> RelateResult<'tcx, ty::Ty<'tcx>> {
265 structurally_relate_tys(self, a, b)
266 }
267
268 fn regions(
269 &mut self,
270 a: ty::Region<'tcx>,
271 _: ty::Region<'tcx>,
272 ) -> RelateResult<'tcx, ty::Region<'tcx>> {
273 if let ty::ReBound(ty::BoundVarIndexKind::Bound(binder), ty::BoundRegion { var, .. }) =
274 a.kind()
275 && binder == self.target_binder
276 {
277 self.variances
278 .entry(var)
279 .and_modify(|old| *old = unify_variances(*old, self.ambient_variance))
280 .or_insert(self.ambient_variance);
281 }
282 Ok(a)
283 }
284
285 fn consts(
286 &mut self,
287 a: ty::Const<'tcx>,
288 b: ty::Const<'tcx>,
289 ) -> RelateResult<'tcx, ty::Const<'tcx>> {
290 structurally_relate_consts(self, a, b)
291 }
292
293 fn binders<T>(
294 &mut self,
295 a: ty::Binder<'tcx, T>,
296 b: ty::Binder<'tcx, T>,
297 ) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
298 where
299 T: Relate<ty::TyCtxt<'tcx>>,
300 {
301 let old_target_binder = self.target_binder;
302 self.target_binder = self.target_binder.shifted_in(1);
303 let result = self.relate(a.skip_binder(), b.skip_binder());
304 self.target_binder = old_target_binder;
305 result?;
306 Ok(a)
307 }
308 }
309
310 fn unify_variances(a: ty::Variance, b: ty::Variance) -> ty::Variance {
311 match (a, b) {
312 (ty::Bivariant, other) | (other, ty::Bivariant) => other,
313 (ty::Invariant, _) | (_, ty::Invariant) => ty::Invariant,
314 (ty::Contravariant, ty::Covariant) | (ty::Covariant, ty::Contravariant) => {
315 ty::Invariant
316 }
317 (ty::Contravariant, ty::Contravariant) => ty::Contravariant,
318 (ty::Covariant, ty::Covariant) => ty::Covariant,
319 }
320 }
321
322 let mut relation = FunctionalVariances {
323 tcx,
324 variances: HashMap::default(),
325 ambient_variance: ty::Contravariant,
329 target_binder: ty::INNERMOST,
330 };
331 relation
332 .relate(sig.skip_binder(), sig.skip_binder())
333 .expect("a signature must relate to itself");
334
335 for (index, var) in sig.bound_vars().iter().enumerate() {
337 if matches!(var, ty::BoundVariableKind::Region(_)) {
338 relation
339 .variances
340 .entry(ty::BoundVar::from_usize(index))
341 .or_insert(ty::Bivariant);
342 }
343 }
344 relation.variances
345}
346
347pub fn inst_binder<'tcx, T>(
350 tcx: ty::TyCtxt<'tcx>,
351 typing_env: ty::TypingEnv<'tcx>,
352 args: Option<ty::GenericArgsRef<'tcx>>,
353 x: ty::EarlyBinder<'tcx, T>,
354) -> T
355where
356 T: ty::TypeFoldable<ty::TyCtxt<'tcx>> + Clone,
357{
358 match args {
359 None => x.instantiate_identity().skip_normalization(),
360 Some(args) => normalize(tcx, typing_env, x.instantiate(tcx, args)),
361 }
362}
363
364pub fn substitute<'tcx, T>(
367 tcx: ty::TyCtxt<'tcx>,
368 typing_env: ty::TypingEnv<'tcx>,
369 args: Option<ty::GenericArgsRef<'tcx>>,
370 x: T,
371) -> T
372where
373 T: ty::TypeFoldable<ty::TyCtxt<'tcx>>,
374{
375 inst_binder(tcx, typing_env, args, ty::EarlyBinder::bind(tcx, x))
376}
377
378pub fn identity_args_with_inferred<'tcx>(
382 tcx: ty::TyCtxt<'tcx>,
383 def_id: RDefId,
384) -> ty::GenericArgsRef<'tcx> {
385 match tcx.def_kind(def_id) {
386 RDefKind::Closure | RDefKind::SyntheticCoroutineBody => {
387 let type_of = tcx
388 .type_of(def_id)
389 .instantiate_identity()
390 .skip_normalization();
391 match *type_of.kind() {
392 ty::Closure(_, args) | ty::Coroutine(_, args) => args,
393 _ => unreachable!(),
394 }
395 }
396 RDefKind::AnonConst
397 if tcx.anon_const_kind(def_id) == ty::AnonConstKind::NonTypeSystemInline =>
398 {
399 let get_ret_ty = |body: &mir::Body<'tcx>| body.local_decls[mir::Local::ZERO].ty;
402 let ret_ty = mir_kinds::CTFE::get_mir(tcx, def_id, get_ret_ty)
403 .or_else(|| mir_kinds::Optimized::get_mir(tcx, def_id, get_ret_ty))
404 .expect("could not compute the type of this inline const: {def_id:?}");
405 let mut args = ty::GenericArgs::identity_for_item(tcx, def_id).to_vec();
406 *args
407 .last_mut()
408 .expect("inline const has a return type parameter") = ret_ty.into();
409 tcx.mk_args_from_iter(args.into_iter())
410 }
411 _ => ty::GenericArgs::identity_for_item(tcx, def_id),
412 }
413}
414
415pub fn unerase_lifetimes<'tcx, T>(
417 s: &impl UnderOwnerState<'tcx>,
418 val: T,
419 new_region_name: Symbol,
420) -> (T, Vec<ty::PlaceholderRegion<'tcx>>)
421where
422 T: ty::TypeFoldable<ty::TyCtxt<'tcx>>,
423{
424 let tcx = s.base().tcx;
425 let mut extra_regions = Vec::new();
426 let val = ty::fold_regions(tcx, val, |region, _| {
427 if region.is_erased() {
428 let placeholder = ty::PlaceholderRegion::new(
429 ty::UniverseIndex::ROOT,
430 ty::BoundRegion {
431 var: ty::BoundVar::from_usize(extra_regions.len()),
432 kind: ty::BoundRegionKind::NamedForPrinting(new_region_name),
433 },
434 );
435 extra_regions.push(placeholder);
436 ty::Region::new_placeholder(tcx, placeholder)
437 } else {
438 region
439 }
440 });
441 (val, extra_regions)
442}
443
444#[extension_traits::extension(pub trait SubstBinder)]
445impl<'tcx, T: ty::TypeFoldable<ty::TyCtxt<'tcx>>> ty::Binder<'tcx, T> {
446 fn subst(
447 self,
448 tcx: ty::TyCtxt<'tcx>,
449 generics: &[ty::GenericArg<'tcx>],
450 ) -> ty::Binder<'tcx, T> {
451 ty::EarlyBinder::bind(tcx, self)
452 .instantiate(tcx, generics)
453 .skip_normalization()
454 }
455}
456
457pub(crate) fn can_have_generics<'tcx>(tcx: ty::TyCtxt<'tcx>, def_id: RDefId) -> bool {
459 use RDefKind::*;
460 !matches!(
461 get_def_kind(tcx, def_id),
462 ConstParam
463 | ExternCrate
464 | ForeignMod
465 | GlobalAsm
466 | LifetimeParam
467 | Macro(..)
468 | Mod
469 | TyParam
470 | Use
471 )
472}
473
474pub(crate) fn get_variant_kind<'s, S: UnderOwnerState<'s>>(
475 adt_def: &ty::AdtDef<'s>,
476 variant_index: rustc_abi::VariantIdx,
477 _s: &S,
478) -> VariantKind {
479 if adt_def.is_struct() {
480 VariantKind::Struct
481 } else if adt_def.is_union() {
482 VariantKind::Union
483 } else {
484 let index = variant_index;
485 VariantKind::Enum { index }
486 }
487}
488
489pub fn get_mod_children<'tcx>(
491 tcx: ty::TyCtxt<'tcx>,
492 def_id: RDefId,
493) -> Vec<(Option<rustc_span::Ident>, RDefId)> {
494 match def_id.as_local() {
495 Some(ldid) => match tcx.hir_node_by_def_id(ldid) {
496 rustc_hir::Node::Crate(m)
497 | rustc_hir::Node::Item(&rustc_hir::Item {
498 kind: rustc_hir::ItemKind::Mod(_, m),
499 ..
500 }) => m
501 .item_ids
502 .iter()
503 .map(|&item_id| {
504 let opt_ident = tcx.hir_item(item_id).kind.ident();
505 let def_id = item_id.owner_id.to_def_id();
506 (opt_ident, def_id)
507 })
508 .collect(),
509 node => panic!("DefKind::Module is an unexpected node: {node:?}"),
510 },
511 None => tcx
512 .module_children(def_id)
513 .iter()
514 .filter_map(|child| Some((Some(child.ident), child.res.opt_def_id()?)))
515 .collect(),
516 }
517}
518
519pub fn get_foreign_mod_children<'tcx>(tcx: ty::TyCtxt<'tcx>, def_id: RDefId) -> Vec<RDefId> {
521 match def_id.as_local() {
522 Some(ldid) => tcx
523 .hir_node_by_def_id(ldid)
524 .expect_item()
525 .expect_foreign_mod()
526 .1
527 .iter()
528 .map(|foreign_item_ref| foreign_item_ref.owner_id.to_def_id())
529 .collect(),
530 None => vec![],
531 }
532}
533
534pub fn get_method_sig<'tcx>(
556 tcx: ty::TyCtxt<'tcx>,
557 typing_env: ty::TypingEnv<'tcx>,
558 def_id: RDefId,
559 method_args: Option<ty::GenericArgsRef<'tcx>>,
560) -> ty::PolyFnSig<'tcx> {
561 let real_sig = inst_binder(tcx, typing_env, method_args, tcx.fn_sig(def_id));
562 let item = tcx.associated_item(def_id);
563 let ty::AssocContainer::TraitImpl(Ok(decl_method_id)) = item.container else {
564 return real_sig;
565 };
566 let declared_sig = tcx.fn_sig(decl_method_id);
567
568 let impl_def_id = item.container_id(tcx);
569 let method_args =
570 method_args.unwrap_or_else(|| ty::GenericArgs::identity_for_item(tcx, def_id));
571 let implemented_trait_ref = tcx
573 .impl_trait_ref(impl_def_id)
574 .instantiate(tcx, method_args);
575 let implemented_trait_ref = normalize(tcx, typing_env, implemented_trait_ref);
576 let decl_args = method_args.rebase_onto(tcx, impl_def_id, implemented_trait_ref.args);
579 let sig = declared_sig.instantiate(tcx, decl_args);
580 let sig = normalize(tcx, typing_env, sig);
581
582 if let container_named_lts = tcx
583 .generics_of(impl_def_id)
584 .own_params
585 .iter()
586 .filter(|p| matches!(p.kind, ty::GenericParamDefKind::Lifetime))
587 .filter(|p| p.name != kw::UnderscoreLifetime)
588 .map(|p| p.name)
589 .collect::<HashSet<_>>()
590 && sig
591 .bound_vars()
592 .iter()
593 .map(|v| v.expect_region())
594 .filter_map(|v| v.get_name(tcx))
595 .any(|lt| container_named_lts.contains(<))
596 {
597 tcx.anonymize_bound_vars(sig)
600 } else {
601 sig
602 }
603}
604
605pub fn assoc_tys_for_trait<'tcx>(
608 tcx: ty::TyCtxt<'tcx>,
609 typing_env: ty::TypingEnv<'tcx>,
610 tref: ty::TraitRef<'tcx>,
611) -> Vec<ty::AliasTy<'tcx>> {
612 fn gather_assoc_tys<'tcx>(
613 tcx: ty::TyCtxt<'tcx>,
614 typing_env: ty::TypingEnv<'tcx>,
615 assoc_tys: &mut Vec<ty::AliasTy<'tcx>>,
616 tref: ty::TraitRef<'tcx>,
617 ) {
618 assoc_tys.extend(
619 tcx.associated_items(tref.def_id)
620 .in_definition_order()
621 .filter(|assoc| matches!(assoc.kind, ty::AssocKind::Type { .. }))
622 .filter(|assoc| {
623 tcx.generics_of(assoc.def_id).own_params.is_empty()
624 && tcx.clauses_of(assoc.def_id).clauses.is_empty()
625 })
626 .map(|assoc| {
627 let alias_ty = ty::AliasTyKind::Projection {
628 def_id: assoc.def_id,
629 };
630 ty::AliasTy::new(tcx, alias_ty, tref.args)
631 }),
632 );
633 for clause in tcx
634 .explicit_super_clauses_of(tref.def_id)
635 .map_bound(|clauses| clauses.iter().map(|(clause, _span)| *clause))
636 .iter_instantiated(tcx, tref.args)
637 {
638 if let Some(pred) = clause.as_trait_clause() {
639 let tref = erase_and_norm(tcx, typing_env, pred.map(|b| b.skip_binder().trait_ref));
640 gather_assoc_tys(tcx, typing_env, assoc_tys, tref);
641 }
642 }
643 }
644 let mut ret = vec![];
645 gather_assoc_tys(tcx, typing_env, &mut ret, tref);
646 ret
647}
648
649pub fn dyn_self_ty<'tcx>(
651 tcx: ty::TyCtxt<'tcx>,
652 typing_env: ty::TypingEnv<'tcx>,
653 tref: ty::TraitRef<'tcx>,
654) -> Option<ty::Ty<'tcx>> {
655 let re_erased = tcx.lifetimes.re_erased;
656 if !tcx.is_dyn_compatible(tref.def_id) {
657 return None;
658 }
659
660 let main_pred = ty::Binder::dummy(ty::ExistentialPredicate::Trait(
662 ty::ExistentialTraitRef::erase_self_ty(tcx, tref),
663 ));
664
665 let ty_constraints = assoc_tys_for_trait(tcx, typing_env, tref)
666 .into_iter()
667 .map(|alias_ty| {
668 let proj = ty::ProjectionClause {
669 projection_term: alias_ty.into(),
670 term: ty::Ty::new_alias(tcx, ty::IsRigid::No, alias_ty).into(),
671 };
672 let proj = ty::ExistentialProjection::erase_self_ty(tcx, proj);
673 ty::Binder::dummy(ty::ExistentialPredicate::Projection(proj))
674 });
675
676 let preds = {
677 let mut preds: Vec<_> = [main_pred].into_iter().chain(ty_constraints).collect();
679 preds.sort_by(|a, b| {
680 use rustc_middle::ty::ExistentialPredicateStableCmpExt;
681 a.skip_binder().stable_cmp(tcx, &b.skip_binder())
682 });
683 tcx.mk_poly_existential_predicates(&preds)
684 };
685 let ty = tcx.mk_ty_from_kind(ty::Dynamic(preds, re_erased));
686 let ty = normalize(tcx, typing_env, ty::Unnormalized::new_wip(ty));
687 Some(ty)
688}
689
690pub fn closure_once_shim<'tcx>(
691 tcx: ty::TyCtxt<'tcx>,
692 closure_ty: ty::Ty<'tcx>,
693) -> Option<mir::Body<'tcx>> {
694 let ty::Closure(def_id, args) = closure_ty.kind() else {
695 unreachable!()
696 };
697 let instance = match args.as_closure().kind() {
698 ty::ClosureKind::Fn | ty::ClosureKind::FnMut => {
699 ty::Instance::fn_once_adapter_instance(tcx, *def_id, args)
700 }
701 ty::ClosureKind::FnOnce => return None,
702 };
703 let mir = tcx.instance_mir(instance.def).clone();
704 let mir = ty::EarlyBinder::bind(tcx, mir)
705 .instantiate(tcx, instance.args)
706 .skip_normalization();
707 Some(mir)
708}
709
710pub fn drop_glue_shim<'tcx>(
711 s: &impl UnderOwnerState<'tcx>,
712 def_id: &DefId,
713 instantiate: Option<ty::GenericArgsRef<'tcx>>,
714) -> mir::Body<'tcx> {
715 let tcx = s.base().tcx;
716 let drop_glue =
717 tcx.require_lang_item(rustc_hir::attrs::LangItem::DropGlue, rustc_span::DUMMY_SP);
718 let ty = inst_binder(tcx, s.typing_env(), instantiate, def_id.type_of(s));
719 let mut body = rustc_mir_transform::build_drop_shim(tcx, drop_glue, Some(ty), s.typing_env());
720 body.phase = mir::MirPhase::Runtime(mir::RuntimePhase::Optimized);
722 body
723}