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