1use std::collections::hash_map::Entry;
2use std::hash::Hash;
3use std::iter;
4
5use rustc_abi::{FieldIdx, VariantIdx};
6use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
7use rustc_data_structures::unord::{ExtendUnord, UnordItems, UnordSet};
8use rustc_errors::ErrorGuaranteed;
9use rustc_hir::def::{DefKind, Res};
10use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdMap};
11use rustc_hir::hir_id::OwnerId;
12use rustc_hir::{
13 self as hir, BindingMode, ByRef, HirId, ItemLocalId, ItemLocalMap, ItemLocalSet, Mutability,
14};
15use rustc_index::IndexVec;
16use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
17use rustc_session::Session;
18use rustc_span::Span;
19
20use super::RvalueScopes;
21use crate::hir::place::Place as HirPlace;
22use crate::infer::canonical::Canonical;
23use crate::mir::FakeReadCause;
24use crate::traits::ObligationCause;
25use crate::ty::{
26 self, BoundVar, CanonicalPolyFnSig, ClosureSizeProfileData, GenericArgKind, GenericArgs,
27 GenericArgsRef, Ty, UserArgs, tls,
28};
29
30#[derive(TyEncodable, TyDecodable, Debug, HashStable)]
31pub struct TypeckResults<'tcx> {
32 pub hir_owner: OwnerId,
34
35 type_dependent_defs: ItemLocalMap<Result<(DefKind, DefId), ErrorGuaranteed>>,
38
39 field_indices: ItemLocalMap<FieldIdx>,
44
45 node_types: ItemLocalMap<Ty<'tcx>>,
49
50 node_args: ItemLocalMap<GenericArgsRef<'tcx>>,
55
56 user_provided_types: ItemLocalMap<CanonicalUserType<'tcx>>,
66
67 pub user_provided_sigs: LocalDefIdMap<CanonicalPolyFnSig<'tcx>>,
70
71 adjustments: ItemLocalMap<Vec<ty::adjustment::Adjustment<'tcx>>>,
72
73 pat_binding_modes: ItemLocalMap<BindingMode>,
75
76 rust_2024_migration_desugared_pats: ItemLocalMap<Rust2024IncompatiblePatInfo>,
79
80 pat_adjustments: ItemLocalMap<Vec<ty::adjustment::PatAdjustment<'tcx>>>,
103
104 skipped_ref_pats: ItemLocalSet,
107
108 closure_kind_origins: ItemLocalMap<(Span, HirPlace<'tcx>)>,
111
112 liberated_fn_sigs: ItemLocalMap<ty::FnSig<'tcx>>,
147
148 fru_field_types: ItemLocalMap<Vec<Ty<'tcx>>>,
153
154 coercion_casts: ItemLocalSet,
157
158 pub used_trait_imports: UnordSet<LocalDefId>,
161
162 pub tainted_by_errors: Option<ErrorGuaranteed>,
165
166 pub concrete_opaque_types: FxIndexMap<LocalDefId, ty::OpaqueHiddenType<'tcx>>,
171
172 pub closure_min_captures: ty::MinCaptureInformationMap<'tcx>,
175
176 pub closure_fake_reads: LocalDefIdMap<Vec<(HirPlace<'tcx>, FakeReadCause, HirId)>>,
199
200 pub rvalue_scopes: RvalueScopes,
204
205 pub coroutine_stalled_predicates: FxIndexSet<(ty::Predicate<'tcx>, ObligationCause<'tcx>)>,
208
209 pub closure_size_eval: LocalDefIdMap<ClosureSizeProfileData<'tcx>>,
212
213 offset_of_data: ItemLocalMap<(Ty<'tcx>, Vec<(VariantIdx, FieldIdx)>)>,
215}
216
217impl<'tcx> TypeckResults<'tcx> {
218 pub fn new(hir_owner: OwnerId) -> TypeckResults<'tcx> {
219 TypeckResults {
220 hir_owner,
221 type_dependent_defs: Default::default(),
222 field_indices: Default::default(),
223 user_provided_types: Default::default(),
224 user_provided_sigs: Default::default(),
225 node_types: Default::default(),
226 node_args: Default::default(),
227 adjustments: Default::default(),
228 pat_binding_modes: Default::default(),
229 pat_adjustments: Default::default(),
230 rust_2024_migration_desugared_pats: Default::default(),
231 skipped_ref_pats: Default::default(),
232 closure_kind_origins: Default::default(),
233 liberated_fn_sigs: Default::default(),
234 fru_field_types: Default::default(),
235 coercion_casts: Default::default(),
236 used_trait_imports: Default::default(),
237 tainted_by_errors: None,
238 concrete_opaque_types: Default::default(),
239 closure_min_captures: Default::default(),
240 closure_fake_reads: Default::default(),
241 rvalue_scopes: Default::default(),
242 coroutine_stalled_predicates: Default::default(),
243 closure_size_eval: Default::default(),
244 offset_of_data: Default::default(),
245 }
246 }
247
248 pub fn qpath_res(&self, qpath: &hir::QPath<'_>, id: HirId) -> Res {
250 match *qpath {
251 hir::QPath::Resolved(_, path) => path.res,
252 hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => self
253 .type_dependent_def(id)
254 .map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)),
255 }
256 }
257
258 pub fn type_dependent_defs(
259 &self,
260 ) -> LocalTableInContext<'_, Result<(DefKind, DefId), ErrorGuaranteed>> {
261 LocalTableInContext { hir_owner: self.hir_owner, data: &self.type_dependent_defs }
262 }
263
264 pub fn type_dependent_def(&self, id: HirId) -> Option<(DefKind, DefId)> {
265 validate_hir_id_for_typeck_results(self.hir_owner, id);
266 self.type_dependent_defs.get(&id.local_id).cloned().and_then(|r| r.ok())
267 }
268
269 pub fn type_dependent_def_id(&self, id: HirId) -> Option<DefId> {
270 self.type_dependent_def(id).map(|(_, def_id)| def_id)
271 }
272
273 pub fn type_dependent_defs_mut(
274 &mut self,
275 ) -> LocalTableInContextMut<'_, Result<(DefKind, DefId), ErrorGuaranteed>> {
276 LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.type_dependent_defs }
277 }
278
279 pub fn field_indices(&self) -> LocalTableInContext<'_, FieldIdx> {
280 LocalTableInContext { hir_owner: self.hir_owner, data: &self.field_indices }
281 }
282
283 pub fn field_indices_mut(&mut self) -> LocalTableInContextMut<'_, FieldIdx> {
284 LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.field_indices }
285 }
286
287 pub fn field_index(&self, id: HirId) -> FieldIdx {
288 self.field_indices().get(id).cloned().expect("no index for a field")
289 }
290
291 pub fn opt_field_index(&self, id: HirId) -> Option<FieldIdx> {
292 self.field_indices().get(id).cloned()
293 }
294
295 pub fn user_provided_types(&self) -> LocalTableInContext<'_, CanonicalUserType<'tcx>> {
296 LocalTableInContext { hir_owner: self.hir_owner, data: &self.user_provided_types }
297 }
298
299 pub fn user_provided_types_mut(
300 &mut self,
301 ) -> LocalTableInContextMut<'_, CanonicalUserType<'tcx>> {
302 LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.user_provided_types }
303 }
304
305 pub fn node_types(&self) -> LocalTableInContext<'_, Ty<'tcx>> {
306 LocalTableInContext { hir_owner: self.hir_owner, data: &self.node_types }
307 }
308
309 pub fn node_types_mut(&mut self) -> LocalTableInContextMut<'_, Ty<'tcx>> {
310 LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.node_types }
311 }
312
313 pub fn node_type(&self, id: HirId) -> Ty<'tcx> {
314 self.node_type_opt(id).unwrap_or_else(|| {
315 bug!("node_type: no type for node {}", tls::with(|tcx| tcx.hir_id_to_string(id)))
316 })
317 }
318
319 pub fn node_type_opt(&self, id: HirId) -> Option<Ty<'tcx>> {
320 validate_hir_id_for_typeck_results(self.hir_owner, id);
321 self.node_types.get(&id.local_id).cloned()
322 }
323
324 pub fn node_args_mut(&mut self) -> LocalTableInContextMut<'_, GenericArgsRef<'tcx>> {
325 LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.node_args }
326 }
327
328 pub fn node_args(&self, id: HirId) -> GenericArgsRef<'tcx> {
329 validate_hir_id_for_typeck_results(self.hir_owner, id);
330 self.node_args.get(&id.local_id).cloned().unwrap_or_else(|| GenericArgs::empty())
331 }
332
333 pub fn node_args_opt(&self, id: HirId) -> Option<GenericArgsRef<'tcx>> {
334 validate_hir_id_for_typeck_results(self.hir_owner, id);
335 self.node_args.get(&id.local_id).cloned()
336 }
337
338 pub fn pat_ty(&self, pat: &hir::Pat<'_>) -> Ty<'tcx> {
343 self.node_type(pat.hir_id)
344 }
345
346 pub fn expr_ty(&self, expr: &hir::Expr<'_>) -> Ty<'tcx> {
357 self.node_type(expr.hir_id)
358 }
359
360 pub fn expr_ty_opt(&self, expr: &hir::Expr<'_>) -> Option<Ty<'tcx>> {
361 self.node_type_opt(expr.hir_id)
362 }
363
364 pub fn adjustments(&self) -> LocalTableInContext<'_, Vec<ty::adjustment::Adjustment<'tcx>>> {
365 LocalTableInContext { hir_owner: self.hir_owner, data: &self.adjustments }
366 }
367
368 pub fn adjustments_mut(
369 &mut self,
370 ) -> LocalTableInContextMut<'_, Vec<ty::adjustment::Adjustment<'tcx>>> {
371 LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.adjustments }
372 }
373
374 pub fn expr_adjustments(&self, expr: &hir::Expr<'_>) -> &[ty::adjustment::Adjustment<'tcx>] {
375 validate_hir_id_for_typeck_results(self.hir_owner, expr.hir_id);
376 self.adjustments.get(&expr.hir_id.local_id).map_or(&[], |a| &a[..])
377 }
378
379 pub fn expr_ty_adjusted(&self, expr: &hir::Expr<'_>) -> Ty<'tcx> {
382 self.expr_adjustments(expr).last().map_or_else(|| self.expr_ty(expr), |adj| adj.target)
383 }
384
385 pub fn expr_ty_adjusted_opt(&self, expr: &hir::Expr<'_>) -> Option<Ty<'tcx>> {
386 self.expr_adjustments(expr).last().map(|adj| adj.target).or_else(|| self.expr_ty_opt(expr))
387 }
388
389 pub fn is_method_call(&self, expr: &hir::Expr<'_>) -> bool {
390 if let hir::ExprKind::Path(_) = expr.kind {
393 return false;
394 }
395
396 matches!(self.type_dependent_defs().get(expr.hir_id), Some(Ok((DefKind::AssocFn, _))))
397 }
398
399 pub fn extract_binding_mode(&self, s: &Session, id: HirId, sp: Span) -> BindingMode {
402 self.pat_binding_modes().get(id).copied().unwrap_or_else(|| {
403 s.dcx().span_bug(sp, "missing binding mode");
404 })
405 }
406
407 pub fn pat_binding_modes(&self) -> LocalTableInContext<'_, BindingMode> {
408 LocalTableInContext { hir_owner: self.hir_owner, data: &self.pat_binding_modes }
409 }
410
411 pub fn pat_binding_modes_mut(&mut self) -> LocalTableInContextMut<'_, BindingMode> {
412 LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_binding_modes }
413 }
414
415 pub fn pat_adjustments(
416 &self,
417 ) -> LocalTableInContext<'_, Vec<ty::adjustment::PatAdjustment<'tcx>>> {
418 LocalTableInContext { hir_owner: self.hir_owner, data: &self.pat_adjustments }
419 }
420
421 pub fn pat_adjustments_mut(
422 &mut self,
423 ) -> LocalTableInContextMut<'_, Vec<ty::adjustment::PatAdjustment<'tcx>>> {
424 LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_adjustments }
425 }
426
427 pub fn rust_2024_migration_desugared_pats(
428 &self,
429 ) -> LocalTableInContext<'_, Rust2024IncompatiblePatInfo> {
430 LocalTableInContext {
431 hir_owner: self.hir_owner,
432 data: &self.rust_2024_migration_desugared_pats,
433 }
434 }
435
436 pub fn rust_2024_migration_desugared_pats_mut(
437 &mut self,
438 ) -> LocalTableInContextMut<'_, Rust2024IncompatiblePatInfo> {
439 LocalTableInContextMut {
440 hir_owner: self.hir_owner,
441 data: &mut self.rust_2024_migration_desugared_pats,
442 }
443 }
444
445 pub fn skipped_ref_pats(&self) -> LocalSetInContext<'_> {
446 LocalSetInContext { hir_owner: self.hir_owner, data: &self.skipped_ref_pats }
447 }
448
449 pub fn skipped_ref_pats_mut(&mut self) -> LocalSetInContextMut<'_> {
450 LocalSetInContextMut { hir_owner: self.hir_owner, data: &mut self.skipped_ref_pats }
451 }
452
453 pub fn pat_has_ref_mut_binding(&self, pat: &hir::Pat<'_>) -> bool {
462 let mut has_ref_mut = false;
463 pat.walk(|pat| {
464 if let hir::PatKind::Binding(_, id, _, _) = pat.kind
465 && let Some(BindingMode(ByRef::Yes(Mutability::Mut), _)) =
466 self.pat_binding_modes().get(id)
467 {
468 has_ref_mut = true;
469 false
471 } else {
472 true
473 }
474 });
475 has_ref_mut
476 }
477
478 pub fn deref_pat_borrow_mode(&self, pointer_ty: Ty<'_>, inner: &hir::Pat<'_>) -> ByRef {
485 if pointer_ty.is_box() {
486 ByRef::No
487 } else {
488 let mutable = self.pat_has_ref_mut_binding(inner);
489 ByRef::Yes(if mutable { Mutability::Mut } else { Mutability::Not })
490 }
491 }
492
493 pub fn closure_min_captures_flattened(
496 &self,
497 closure_def_id: LocalDefId,
498 ) -> impl Iterator<Item = &ty::CapturedPlace<'tcx>> {
499 self.closure_min_captures
500 .get(&closure_def_id)
501 .map(|closure_min_captures| closure_min_captures.values().flat_map(|v| v.iter()))
502 .into_iter()
503 .flatten()
504 }
505
506 pub fn closure_kind_origins(&self) -> LocalTableInContext<'_, (Span, HirPlace<'tcx>)> {
507 LocalTableInContext { hir_owner: self.hir_owner, data: &self.closure_kind_origins }
508 }
509
510 pub fn closure_kind_origins_mut(
511 &mut self,
512 ) -> LocalTableInContextMut<'_, (Span, HirPlace<'tcx>)> {
513 LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.closure_kind_origins }
514 }
515
516 pub fn liberated_fn_sigs(&self) -> LocalTableInContext<'_, ty::FnSig<'tcx>> {
517 LocalTableInContext { hir_owner: self.hir_owner, data: &self.liberated_fn_sigs }
518 }
519
520 pub fn liberated_fn_sigs_mut(&mut self) -> LocalTableInContextMut<'_, ty::FnSig<'tcx>> {
521 LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.liberated_fn_sigs }
522 }
523
524 pub fn fru_field_types(&self) -> LocalTableInContext<'_, Vec<Ty<'tcx>>> {
525 LocalTableInContext { hir_owner: self.hir_owner, data: &self.fru_field_types }
526 }
527
528 pub fn fru_field_types_mut(&mut self) -> LocalTableInContextMut<'_, Vec<Ty<'tcx>>> {
529 LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.fru_field_types }
530 }
531
532 pub fn is_coercion_cast(&self, hir_id: HirId) -> bool {
533 validate_hir_id_for_typeck_results(self.hir_owner, hir_id);
534 self.coercion_casts.contains(&hir_id.local_id)
535 }
536
537 pub fn set_coercion_cast(&mut self, id: ItemLocalId) {
538 self.coercion_casts.insert(id);
539 }
540
541 pub fn coercion_casts(&self) -> &ItemLocalSet {
542 &self.coercion_casts
543 }
544
545 pub fn offset_of_data(
546 &self,
547 ) -> LocalTableInContext<'_, (Ty<'tcx>, Vec<(VariantIdx, FieldIdx)>)> {
548 LocalTableInContext { hir_owner: self.hir_owner, data: &self.offset_of_data }
549 }
550
551 pub fn offset_of_data_mut(
552 &mut self,
553 ) -> LocalTableInContextMut<'_, (Ty<'tcx>, Vec<(VariantIdx, FieldIdx)>)> {
554 LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.offset_of_data }
555 }
556}
557
558#[inline]
566fn validate_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: HirId) {
567 if hir_id.owner != hir_owner {
568 invalid_hir_id_for_typeck_results(hir_owner, hir_id);
569 }
570}
571
572#[cold]
573#[inline(never)]
574fn invalid_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: HirId) {
575 ty::tls::with(|tcx| {
576 bug!(
577 "node {} cannot be placed in TypeckResults with hir_owner {:?}",
578 tcx.hir_id_to_string(hir_id),
579 hir_owner
580 )
581 });
582}
583
584pub struct LocalTableInContext<'a, V> {
585 hir_owner: OwnerId,
586 data: &'a ItemLocalMap<V>,
587}
588
589impl<'a, V> LocalTableInContext<'a, V> {
590 pub fn contains_key(&self, id: HirId) -> bool {
591 validate_hir_id_for_typeck_results(self.hir_owner, id);
592 self.data.contains_key(&id.local_id)
593 }
594
595 pub fn get(&self, id: HirId) -> Option<&'a V> {
596 validate_hir_id_for_typeck_results(self.hir_owner, id);
597 self.data.get(&id.local_id)
598 }
599
600 pub fn items(
601 &self,
602 ) -> UnordItems<(hir::ItemLocalId, &'a V), impl Iterator<Item = (hir::ItemLocalId, &'a V)>>
603 {
604 self.data.items().map(|(id, value)| (*id, value))
605 }
606
607 pub fn items_in_stable_order(&self) -> Vec<(ItemLocalId, &'a V)> {
608 self.data.items().map(|(&k, v)| (k, v)).into_sorted_stable_ord_by_key(|(k, _)| k)
609 }
610}
611
612impl<'a, V> ::std::ops::Index<HirId> for LocalTableInContext<'a, V> {
613 type Output = V;
614
615 fn index(&self, key: HirId) -> &V {
616 self.get(key).unwrap_or_else(|| {
617 bug!("LocalTableInContext({:?}): key {:?} not found", self.hir_owner, key)
618 })
619 }
620}
621
622pub struct LocalTableInContextMut<'a, V> {
623 hir_owner: OwnerId,
624 data: &'a mut ItemLocalMap<V>,
625}
626
627impl<'a, V> LocalTableInContextMut<'a, V> {
628 pub fn get_mut(&mut self, id: HirId) -> Option<&mut V> {
629 validate_hir_id_for_typeck_results(self.hir_owner, id);
630 self.data.get_mut(&id.local_id)
631 }
632
633 pub fn get(&mut self, id: HirId) -> Option<&V> {
634 validate_hir_id_for_typeck_results(self.hir_owner, id);
635 self.data.get(&id.local_id)
636 }
637
638 pub fn entry(&mut self, id: HirId) -> Entry<'_, hir::ItemLocalId, V> {
639 validate_hir_id_for_typeck_results(self.hir_owner, id);
640 self.data.entry(id.local_id)
641 }
642
643 pub fn insert(&mut self, id: HirId, val: V) -> Option<V> {
644 validate_hir_id_for_typeck_results(self.hir_owner, id);
645 self.data.insert(id.local_id, val)
646 }
647
648 pub fn remove(&mut self, id: HirId) -> Option<V> {
649 validate_hir_id_for_typeck_results(self.hir_owner, id);
650 self.data.remove(&id.local_id)
651 }
652
653 pub fn extend(&mut self, items: UnordItems<(HirId, V), impl Iterator<Item = (HirId, V)>>) {
654 self.data.extend_unord(items.map(|(id, value)| {
655 validate_hir_id_for_typeck_results(self.hir_owner, id);
656 (id.local_id, value)
657 }))
658 }
659}
660
661#[derive(Clone, Copy, Debug)]
662pub struct LocalSetInContext<'a> {
663 hir_owner: OwnerId,
664 data: &'a ItemLocalSet,
665}
666
667impl<'a> LocalSetInContext<'a> {
668 pub fn is_empty(&self) -> bool {
669 self.data.is_empty()
670 }
671
672 pub fn contains(&self, id: hir::HirId) -> bool {
673 validate_hir_id_for_typeck_results(self.hir_owner, id);
674 self.data.contains(&id.local_id)
675 }
676}
677
678#[derive(Debug)]
679pub struct LocalSetInContextMut<'a> {
680 hir_owner: OwnerId,
681 data: &'a mut ItemLocalSet,
682}
683
684impl<'a> LocalSetInContextMut<'a> {
685 pub fn is_empty(&self) -> bool {
686 self.data.is_empty()
687 }
688
689 pub fn contains(&self, id: hir::HirId) -> bool {
690 validate_hir_id_for_typeck_results(self.hir_owner, id);
691 self.data.contains(&id.local_id)
692 }
693 pub fn insert(&mut self, id: hir::HirId) -> bool {
694 validate_hir_id_for_typeck_results(self.hir_owner, id);
695 self.data.insert(id.local_id)
696 }
697
698 pub fn remove(&mut self, id: hir::HirId) -> bool {
699 validate_hir_id_for_typeck_results(self.hir_owner, id);
700 self.data.remove(&id.local_id)
701 }
702}
703
704rustc_index::newtype_index! {
705 #[derive(HashStable)]
706 #[encodable]
707 #[debug_format = "UserType({})"]
708 pub struct UserTypeAnnotationIndex {
709 const START_INDEX = 0;
710 }
711}
712
713pub type CanonicalUserTypeAnnotations<'tcx> =
715 IndexVec<UserTypeAnnotationIndex, CanonicalUserTypeAnnotation<'tcx>>;
716
717#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
718pub struct CanonicalUserTypeAnnotation<'tcx> {
719 #[type_foldable(identity)]
720 #[type_visitable(ignore)]
721 pub user_ty: Box<CanonicalUserType<'tcx>>,
722 pub span: Span,
723 pub inferred_ty: Ty<'tcx>,
724}
725
726pub type CanonicalUserType<'tcx> = Canonical<'tcx, UserType<'tcx>>;
728
729#[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable)]
730#[derive(Eq, Hash, HashStable, TypeFoldable, TypeVisitable)]
731pub struct UserType<'tcx> {
732 pub kind: UserTypeKind<'tcx>,
733 pub bounds: ty::Clauses<'tcx>,
734}
735
736impl<'tcx> UserType<'tcx> {
737 pub fn new(kind: UserTypeKind<'tcx>) -> UserType<'tcx> {
738 UserType { kind, bounds: ty::ListWithCachedTypeInfo::empty() }
739 }
740
741 pub fn new_with_bounds(kind: UserTypeKind<'tcx>, bounds: ty::Clauses<'tcx>) -> UserType<'tcx> {
744 UserType { kind, bounds }
745 }
746}
747
748#[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable)]
752#[derive(Eq, Hash, HashStable, TypeFoldable, TypeVisitable)]
753pub enum UserTypeKind<'tcx> {
754 Ty(Ty<'tcx>),
755
756 TypeOf(DefId, UserArgs<'tcx>),
759}
760
761pub trait IsIdentity {
762 fn is_identity(&self) -> bool;
763}
764
765impl<'tcx> IsIdentity for CanonicalUserType<'tcx> {
766 fn is_identity(&self) -> bool {
769 if !self.value.bounds.is_empty() {
770 return false;
771 }
772
773 match self.value.kind {
774 UserTypeKind::Ty(_) => false,
775 UserTypeKind::TypeOf(_, user_args) => {
776 if user_args.user_self_ty.is_some() {
777 return false;
778 }
779
780 iter::zip(user_args.args, BoundVar::ZERO..).all(|(kind, cvar)| {
781 match kind.unpack() {
782 GenericArgKind::Type(ty) => match ty.kind() {
783 ty::Bound(debruijn, b) => {
784 assert_eq!(*debruijn, ty::INNERMOST);
786 cvar == b.var
787 }
788 _ => false,
789 },
790
791 GenericArgKind::Lifetime(r) => match r.kind() {
792 ty::ReBound(debruijn, br) => {
793 assert_eq!(debruijn, ty::INNERMOST);
795 cvar == br.var
796 }
797 _ => false,
798 },
799
800 GenericArgKind::Const(ct) => match ct.kind() {
801 ty::ConstKind::Bound(debruijn, b) => {
802 assert_eq!(debruijn, ty::INNERMOST);
804 cvar == b
805 }
806 _ => false,
807 },
808 }
809 })
810 }
811 }
812 }
813}
814
815impl<'tcx> std::fmt::Display for UserType<'tcx> {
816 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
817 if self.bounds.is_empty() {
818 self.kind.fmt(f)
819 } else {
820 self.kind.fmt(f)?;
821 write!(f, " + ")?;
822 std::fmt::Debug::fmt(&self.bounds, f)
823 }
824 }
825}
826
827impl<'tcx> std::fmt::Display for UserTypeKind<'tcx> {
828 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
829 match self {
830 Self::Ty(arg0) => {
831 ty::print::with_no_trimmed_paths!(write!(f, "Ty({})", arg0))
832 }
833 Self::TypeOf(arg0, arg1) => write!(f, "TypeOf({:?}, {:?})", arg0, arg1),
834 }
835 }
836}
837
838#[derive(TyEncodable, TyDecodable, Debug, HashStable)]
841pub struct Rust2024IncompatiblePatInfo {
842 pub primary_labels: Vec<(Span, String)>,
844 pub bad_modifiers: bool,
846 pub bad_ref_pats: bool,
848 pub suggest_eliding_modes: bool,
850}